From 9837f306981037a9824e850235ead5d0c1bbcc71 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Sun, 24 Nov 2019 16:52:46 +0800 Subject: [PATCH 01/14] Rename `peer_map` to `peer_data_map` --- libp2p/peer/peerstore.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 65f6eb7..6d6b1f1 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -10,35 +10,35 @@ from .peerstore_interface import IPeerStore class PeerStore(IPeerStore): - peer_map: Dict[ID, PeerData] + peer_data_map: Dict[ID, PeerData] def __init__(self) -> None: IPeerStore.__init__(self) - self.peer_map = {} + self.peer_data_map = {} def __create_or_get_peer(self, peer_id: ID) -> PeerData: """ Returns the peer data for peer_id or creates a new peer data (and - stores it in peer_map) if peer data for peer_id does not yet exist. + stores it in peer_data_map) if peer data for peer_id does not yet exist. :param peer_id: peer ID :return: peer data """ - if peer_id in self.peer_map: - return self.peer_map[peer_id] + if peer_id in self.peer_data_map: + return self.peer_data_map[peer_id] data = PeerData() - self.peer_map[peer_id] = data - return self.peer_map[peer_id] + self.peer_data_map[peer_id] = data + return self.peer_data_map[peer_id] def peer_info(self, peer_id: ID) -> Optional[PeerInfo]: - if peer_id in self.peer_map: - peer_data = self.peer_map[peer_id] + if peer_id in self.peer_data_map: + peer_data = self.peer_data_map[peer_id] return PeerInfo(peer_id, peer_data.addrs) return None def get_protocols(self, peer_id: ID) -> List[str]: - if peer_id in self.peer_map: - return self.peer_map[peer_id].get_protocols() + if peer_id in self.peer_data_map: + return self.peer_data_map[peer_id].get_protocols() raise PeerStoreError("peer ID not found") def add_protocols(self, peer_id: ID, protocols: Sequence[str]) -> None: @@ -50,12 +50,12 @@ class PeerStore(IPeerStore): peer.set_protocols(list(protocols)) def peer_ids(self) -> List[ID]: - return list(self.peer_map.keys()) + return list(self.peer_data_map.keys()) def get(self, peer_id: ID, key: str) -> Any: - if peer_id in self.peer_map: + if peer_id in self.peer_data_map: try: - val = self.peer_map[peer_id].get_metadata(key) + val = self.peer_data_map[peer_id].get_metadata(key) except PeerDataError as error: raise PeerStoreError(error) return val @@ -76,21 +76,21 @@ class PeerStore(IPeerStore): peer.add_addrs(list(addrs)) def addrs(self, peer_id: ID) -> List[Multiaddr]: - if peer_id in self.peer_map: - return self.peer_map[peer_id].get_addrs() + if peer_id in self.peer_data_map: + return self.peer_data_map[peer_id].get_addrs() raise PeerStoreError("peer ID not found") def clear_addrs(self, peer_id: ID) -> None: # Only clear addresses if the peer is in peer map - if peer_id in self.peer_map: - self.peer_map[peer_id].clear_addrs() + if peer_id in self.peer_data_map: + self.peer_data_map[peer_id].clear_addrs() def peers_with_addrs(self) -> List[ID]: # Add all peers with addrs at least 1 to output output: List[ID] = [] - for peer_id in self.peer_map: - if len(self.peer_map[peer_id].get_addrs()) >= 1: + for peer_id in self.peer_data_map: + if len(self.peer_data_map[peer_id].get_addrs()) >= 1: output.append(peer_id) return output From 144d93a02370679b44d20c2624a842bb4d96592b Mon Sep 17 00:00:00 2001 From: NIC619 Date: Sun, 24 Nov 2019 18:04:00 +0800 Subject: [PATCH 02/14] Add pubkey/privkey info to `PeerStore` --- libp2p/peer/peerstore.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 6d6b1f1..8a19a3c 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -1,7 +1,9 @@ -from typing import Any, Dict, List, Optional, Sequence +from typing import Any, Dict, List, Optional, Sequence, Tuple from multiaddr import Multiaddr +from libp2p.crypto.keys import PrivateKey, PublicKey + from .id import ID from .peerdata import PeerData, PeerDataError from .peerinfo import PeerInfo @@ -10,10 +12,14 @@ from .peerstore_interface import IPeerStore class PeerStore(IPeerStore): + peer_pubkey_map: Dict[ID, PublicKey] + peer_privkey_map: Dict[ID, PrivateKey] peer_data_map: Dict[ID, PeerData] def __init__(self) -> None: IPeerStore.__init__(self) + self.peer_pubkey_map = {} + self.peer_privkey_map = {} self.peer_data_map = {} def __create_or_get_peer(self, peer_id: ID) -> PeerData: @@ -94,6 +100,29 @@ class PeerStore(IPeerStore): output.append(peer_id) return output + def add_pubkey(self, peer_id: ID, pubkey: PublicKey) -> None: + if peer_id in self.peer_pubkey_map: + raise PeerStoreError(f"peer ID already has pubkey: {self.peer_pubkey_map[peer_id]}") + self.peer_pubkey_map[peer_id] = pubkey + + def pubkey(self, peer_id: ID) -> PublicKey: + if peer_id in self.peer_pubkey_map: + return self.peer_pubkey_map[peer_id] + raise PeerStoreError("peer ID not found") + + def add_privkey(self, peer_id: ID, privkey: PrivateKey) -> None: + if peer_id in self.peer_privkey_map: + raise PeerStoreError(f"peer ID already has privkey: {self.peer_privkey_map[peer_id]}") + self.peer_privkey_map[peer_id] = privkey + + def privkey(self, peer_id: ID) -> PrivateKey: + if peer_id in self.peer_pubkey_map: + return self.peer_privkey_map[peer_id] + raise PeerStoreError("peer ID not found") + + def peers_with_keys(self) -> Tuple[ID]: + return set(self.peer_pubkey_map.keys()).union(self.peer_privkey_map.keys()) + class PeerStoreError(KeyError): """Raised when peer ID is not found in peer store.""" From a63f00d8f8287d34c82c1d39c998d265be827e61 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 16:55:55 +0800 Subject: [PATCH 03/14] Store our pubkey/privkey info during `initialize_default_swarm` --- libp2p/__init__.py | 8 ++++++-- libp2p/host/basic_host.py | 5 +---- libp2p/host/routed_host.py | 5 ++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index a1dca53..75b6764 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -105,6 +105,10 @@ def initialize_default_swarm( ) peerstore = peerstore_opt or PeerStore() + # Store our key pair in peerstore + peerstore.add_pubkey(id_opt, key_pair.public_key) + peerstore.add_privkey(id_opt, key_pair.private_key) + # TODO: Initialize discovery if not presented return Swarm(id_opt, peerstore, upgrader, transport) @@ -151,9 +155,9 @@ async def new_node( # TODO routing unimplemented host: IHost # If not explicitly typed, MyPy raises error if disc_opt: - host = RoutedHost(key_pair.public_key, swarm_opt, disc_opt) + host = RoutedHost(swarm_opt, disc_opt) else: - host = BasicHost(key_pair.public_key, swarm_opt) + host = BasicHost(swarm_opt) # Kick off cleanup job asyncio.ensure_future(cleanup_done_tasks()) diff --git a/libp2p/host/basic_host.py b/libp2p/host/basic_host.py index 7469d33..cd0d289 100644 --- a/libp2p/host/basic_host.py +++ b/libp2p/host/basic_host.py @@ -39,7 +39,6 @@ class BasicHost(IHost): right after a stream is initialized. """ - _public_key: PublicKey _network: INetwork peerstore: IPeerStore @@ -48,11 +47,9 @@ class BasicHost(IHost): def __init__( self, - public_key: PublicKey, network: INetwork, default_protocols: "OrderedDict[TProtocol, StreamHandlerFn]" = None, ) -> None: - self._public_key = public_key self._network = network self._network.set_stream_handler(self._swarm_stream_handler) self.peerstore = self._network.peerstore @@ -68,7 +65,7 @@ class BasicHost(IHost): return self._network.get_peer_id() def get_public_key(self) -> PublicKey: - return self._public_key + return self.peerstore.pubkey(self.get_id()) def get_network(self) -> INetwork: """ diff --git a/libp2p/host/routed_host.py b/libp2p/host/routed_host.py index e253ce1..78b6fa5 100644 --- a/libp2p/host/routed_host.py +++ b/libp2p/host/routed_host.py @@ -1,4 +1,3 @@ -from libp2p.crypto.keys import PublicKey from libp2p.host.basic_host import BasicHost from libp2p.host.exceptions import ConnectionFailure from libp2p.network.network_interface import INetwork @@ -11,8 +10,8 @@ from libp2p.routing.interfaces import IPeerRouting class RoutedHost(BasicHost): _router: IPeerRouting - def __init__(self, public_key: PublicKey, network: INetwork, router: IPeerRouting): - super().__init__(public_key, network) + def __init__(self, network: INetwork, router: IPeerRouting): + super().__init__(network) self._router = router async def connect(self, peer_info: PeerInfo) -> None: From e49de15227c1b39678227129e260d5c61267c339 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 16:57:00 +0800 Subject: [PATCH 04/14] Add `get_private_key` to `Host` --- libp2p/host/basic_host.py | 3 +++ libp2p/host/host_interface.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/libp2p/host/basic_host.py b/libp2p/host/basic_host.py index cd0d289..48c322b 100644 --- a/libp2p/host/basic_host.py +++ b/libp2p/host/basic_host.py @@ -67,6 +67,9 @@ class BasicHost(IHost): def get_public_key(self) -> PublicKey: return self.peerstore.pubkey(self.get_id()) + def get_private_key(self) -> PublicKey: + return self.peerstore.privkey(self.get_id()) + def get_network(self) -> INetwork: """ :return: network instance of host diff --git a/libp2p/host/host_interface.py b/libp2p/host/host_interface.py index cfba82c..5e28fda 100644 --- a/libp2p/host/host_interface.py +++ b/libp2p/host/host_interface.py @@ -24,6 +24,12 @@ class IHost(ABC): :return: the public key belonging to the peer """ + @abstractmethod + def get_private_key(self) -> PublicKey: + """ + :return: the private key belonging to the peer + """ + @abstractmethod def get_network(self) -> INetwork: """ From 8b4022328d5530531f70536bfa4cbea54fd6c793 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 17:16:47 +0800 Subject: [PATCH 05/14] Update peer store interface --- libp2p/peer/addrbook_interface.py | 3 - libp2p/peer/peermetadata_interface.py | 3 - libp2p/peer/peerstore.py | 76 +++++++++++++++++- libp2p/peer/peerstore_interface.py | 106 +++++++++++++++++++++++--- 4 files changed, 172 insertions(+), 16 deletions(-) diff --git a/libp2p/peer/addrbook_interface.py b/libp2p/peer/addrbook_interface.py index a4045a7..849600e 100644 --- a/libp2p/peer/addrbook_interface.py +++ b/libp2p/peer/addrbook_interface.py @@ -7,9 +7,6 @@ from .id import ID class IAddrBook(ABC): - def __init__(self) -> None: - pass - @abstractmethod def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None: """ diff --git a/libp2p/peer/peermetadata_interface.py b/libp2p/peer/peermetadata_interface.py index 22a690e..6273a71 100644 --- a/libp2p/peer/peermetadata_interface.py +++ b/libp2p/peer/peermetadata_interface.py @@ -5,9 +5,6 @@ from .id import ID class IPeerMetadata(ABC): - def __init__(self) -> None: - pass - @abstractmethod def get(self, peer_id: ID, key: str) -> Any: """ diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 8a19a3c..7dc367f 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -17,7 +17,6 @@ class PeerStore(IPeerStore): peer_data_map: Dict[ID, PeerData] def __init__(self) -> None: - IPeerStore.__init__(self) self.peer_pubkey_map = {} self.peer_privkey_map = {} self.peer_data_map = {} @@ -37,28 +36,54 @@ class PeerStore(IPeerStore): return self.peer_data_map[peer_id] def peer_info(self, peer_id: ID) -> Optional[PeerInfo]: + """ + :param peer_id: peer ID to get info for + :return: peer info object + """ if peer_id in self.peer_data_map: peer_data = self.peer_data_map[peer_id] return PeerInfo(peer_id, peer_data.addrs) return None def get_protocols(self, peer_id: ID) -> List[str]: + """ + :param peer_id: peer ID to get protocols for + :return: protocols (as list of strings) + :raise PeerStoreError: if peer ID not found + """ if peer_id in self.peer_data_map: return self.peer_data_map[peer_id].get_protocols() raise PeerStoreError("peer ID not found") def add_protocols(self, peer_id: ID, protocols: Sequence[str]) -> None: + """ + :param peer_id: peer ID to add protocols for + :param protocols: protocols to add + """ peer = self.__create_or_get_peer(peer_id) peer.add_protocols(list(protocols)) def set_protocols(self, peer_id: ID, protocols: Sequence[str]) -> None: + """ + :param peer_id: peer ID to set protocols for + :param protocols: protocols to set + """ peer = self.__create_or_get_peer(peer_id) peer.set_protocols(list(protocols)) def peer_ids(self) -> List[ID]: + """ + :return: all of the peer IDs stored in peer store + """ return list(self.peer_data_map.keys()) def get(self, peer_id: ID, key: str) -> Any: + """ + :param peer_id: peer ID to get peer data for + :param key: the key to search value for + :return: value corresponding to the key + :raise PeerStoreError: if peer ID or value not found + """ if peer_id in self.peer_data_map: try: val = self.peer_data_map[peer_id].get_metadata(key) @@ -68,30 +93,56 @@ class PeerStore(IPeerStore): raise PeerStoreError("peer ID not found") def put(self, peer_id: ID, key: str, val: Any) -> None: + """ + :param peer_id: peer ID to put peer data for + :param key: + :param value: + """ # <> # This can output an error, not sure what the possible errors are peer = self.__create_or_get_peer(peer_id) peer.put_metadata(key, val) def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None: + """ + :param peer_id: peer ID to add address for + :param addr: + :param ttl: time-to-live for the this record + """ self.add_addrs(peer_id, [addr], ttl) def add_addrs(self, peer_id: ID, addrs: Sequence[Multiaddr], ttl: int) -> None: + """ + :param peer_id: peer ID to add address for + :param addrs: + :param ttl: time-to-live for the this record + """ # Ignore ttl for now peer = self.__create_or_get_peer(peer_id) peer.add_addrs(list(addrs)) def addrs(self, peer_id: ID) -> List[Multiaddr]: + """ + :param peer_id: peer ID to get addrs for + :return: list of addrs + :raise PeerStoreError: if peer ID not found + """ if peer_id in self.peer_data_map: return self.peer_data_map[peer_id].get_addrs() raise PeerStoreError("peer ID not found") def clear_addrs(self, peer_id: ID) -> None: + """ + :param peer_id: peer ID to clear addrs for + """ # Only clear addresses if the peer is in peer map if peer_id in self.peer_data_map: self.peer_data_map[peer_id].clear_addrs() def peers_with_addrs(self) -> List[ID]: + """ + :return: all of the peer IDs which has addrs stored in peer store + """ # Add all peers with addrs at least 1 to output output: List[ID] = [] @@ -101,26 +152,49 @@ class PeerStore(IPeerStore): return output def add_pubkey(self, peer_id: ID, pubkey: PublicKey) -> None: + """ + :param peer_id: peer ID to add public key for + :param pubkey: + :raise PeerStoreError: if peer ID already has pubkey set + """ if peer_id in self.peer_pubkey_map: raise PeerStoreError(f"peer ID already has pubkey: {self.peer_pubkey_map[peer_id]}") self.peer_pubkey_map[peer_id] = pubkey def pubkey(self, peer_id: ID) -> PublicKey: + """ + :param peer_id: peer ID to get public key for + :return: public key of the peer + :raise PeerStoreError: if peer ID not found + """ if peer_id in self.peer_pubkey_map: return self.peer_pubkey_map[peer_id] raise PeerStoreError("peer ID not found") def add_privkey(self, peer_id: ID, privkey: PrivateKey) -> None: + """ + :param peer_id: peer ID to add private key for + :param privkey: + :raise PeerStoreError: if peer ID already has privkey set + """ if peer_id in self.peer_privkey_map: raise PeerStoreError(f"peer ID already has privkey: {self.peer_privkey_map[peer_id]}") self.peer_privkey_map[peer_id] = privkey def privkey(self, peer_id: ID) -> PrivateKey: + """ + :param peer_id: peer ID to get private key for + :return: private key of the peer + :raise PeerStoreError: if peer ID not found + """ if peer_id in self.peer_pubkey_map: return self.peer_privkey_map[peer_id] raise PeerStoreError("peer ID not found") def peers_with_keys(self) -> Tuple[ID]: + """ + :return: all of the peer IDs which has pubkey/privkey stored in peer store + """ return set(self.peer_pubkey_map.keys()).union(self.peer_privkey_map.keys()) diff --git a/libp2p/peer/peerstore_interface.py b/libp2p/peer/peerstore_interface.py index 3ffd9a2..fbd1a2e 100644 --- a/libp2p/peer/peerstore_interface.py +++ b/libp2p/peer/peerstore_interface.py @@ -1,5 +1,9 @@ from abc import abstractmethod -from typing import List, Sequence +from typing import Any, List, Sequence, Tuple + +from multiaddr import Multiaddr + +from libp2p.crypto.keys import PrivateKey, PublicKey from .addrbook_interface import IAddrBook from .id import ID @@ -8,10 +12,6 @@ from .peermetadata_interface import IPeerMetadata class IPeerStore(IAddrBook, IPeerMetadata): - def __init__(self) -> None: - IPeerMetadata.__init__(self) - IAddrBook.__init__(self) - @abstractmethod def peer_info(self, peer_id: ID) -> PeerInfo: """ @@ -23,8 +23,8 @@ class IPeerStore(IAddrBook, IPeerMetadata): def get_protocols(self, peer_id: ID) -> List[str]: """ :param peer_id: peer ID to get protocols for - :return: protocols (as strings) - :raise Exception: peer ID not found exception + :return: protocols (as list of strings) + :raise PeerStoreError: if peer ID not found """ @abstractmethod @@ -32,7 +32,6 @@ class IPeerStore(IAddrBook, IPeerMetadata): """ :param peer_id: peer ID to add protocols for :param protocols: protocols to add - :raise Exception: peer ID not found """ @abstractmethod @@ -40,7 +39,6 @@ class IPeerStore(IAddrBook, IPeerMetadata): """ :param peer_id: peer ID to set protocols for :param protocols: protocols to set - :raise Exception: peer ID not found """ @abstractmethod @@ -48,3 +46,93 @@ class IPeerStore(IAddrBook, IPeerMetadata): """ :return: all of the peer IDs stored in peer store """ + + @abstractmethod + def get(self, peer_id: ID, key: str) -> Any: + """ + :param peer_id: peer ID to get peer data for + :param key: the key to search value for + :return: value corresponding to the key + :raise PeerStoreError: if peer ID or value not found + """ + + @abstractmethod + def put(self, peer_id: ID, key: str, val: Any) -> None: + """ + :param peer_id: peer ID to put peer data for + :param key: + :param value: + """ + + @abstractmethod + def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None: + """ + :param peer_id: peer ID to add address for + :param addr: + :param ttl: time-to-live for the this record + """ + + @abstractmethod + def add_addrs(self, peer_id: ID, addrs: Sequence[Multiaddr], ttl: int) -> None: + """ + :param peer_id: peer ID to add address for + :param addrs: + :param ttl: time-to-live for the this record + """ + + @abstractmethod + def addrs(self, peer_id: ID) -> List[Multiaddr]: + """ + :param peer_id: peer ID to get addrs for + :return: list of addrs + """ + + @abstractmethod + def clear_addrs(self, peer_id: ID) -> None: + """ + :param peer_id: peer ID to clear addrs for + """ + + @abstractmethod + def peers_with_addrs(self) -> List[ID]: + """ + :return: all of the peer IDs which has addrs stored in peer store + """ + + @abstractmethod + def add_pubkey(self, peer_id: ID, pubkey: PublicKey) -> None: + """ + :param peer_id: peer ID to add public key for + :param pubkey: + :raise PeerStoreError: if peer ID already has pubkey set + """ + + @abstractmethod + def pubkey(self, peer_id: ID) -> PublicKey: + """ + :param peer_id: peer ID to get public key for + :return: public key of the peer + :raise PeerStoreError: if peer ID not found + """ + + @abstractmethod + def add_privkey(self, peer_id: ID, privkey: PrivateKey) -> None: + """ + :param peer_id: peer ID to add private key for + :param privkey: + :raise PeerStoreError: if peer ID already has privkey set + """ + + @abstractmethod + def privkey(self, peer_id: ID) -> PrivateKey: + """ + :param peer_id: peer ID to get private key for + :return: private key of the peer + :raise PeerStoreError: if peer ID not found + """ + + @abstractmethod + def peers_with_keys(self) -> Tuple[ID]: + """ + :return: all of the peer IDs which has pubkey/privkey stored in peer store + """ From e28a9744257a23a16f9bc431572c3e7640363d6f Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 17:17:09 +0800 Subject: [PATCH 06/14] Update peer store initialization in host factory --- libp2p/tools/factories.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libp2p/tools/factories.py b/libp2p/tools/factories.py index 2b63544..341d691 100644 --- a/libp2p/tools/factories.py +++ b/libp2p/tools/factories.py @@ -10,6 +10,7 @@ from libp2p.host.basic_host import BasicHost from libp2p.network.connection.swarm_connection import SwarmConn from libp2p.network.stream.net_stream_interface import INetStream from libp2p.network.swarm import Swarm +from libp2p.peer.id import ID from libp2p.peer.peerstore import PeerStore from libp2p.pubsub.floodsub import FloodSub from libp2p.pubsub.gossipsub import GossipSub @@ -33,6 +34,13 @@ from .constants import ( from .utils import connect, connect_swarm +def initialize_peerstore_with_our_keypair(self_id: ID, key_pair: KeyPair): + peer_store = PeerStore() + peer_store.add_pubkey(self_id, key_pair.public_key) + peer_store.add_privkey(self_id, key_pair.private_key) + return peer_store + + def security_transport_factory( is_secure: bool, key_pair: KeyPair ) -> Dict[TProtocol, BaseSecureTransport]: @@ -52,7 +60,9 @@ class SwarmFactory(factory.Factory): muxer_opt = {MPLEX_PROTOCOL_ID: Mplex} peer_id = factory.LazyAttribute(lambda o: generate_peer_id_from(o.key_pair)) - peerstore = factory.LazyFunction(PeerStore) + peerstore = factory.LazyAttribute( + lambda o: initialize_peerstore_with_our_keypair(o.peer_id, o.key_pair) + ) upgrader = factory.LazyAttribute( lambda o: TransportUpgrader( security_transport_factory(o.is_secure, o.key_pair), o.muxer_opt @@ -97,7 +107,6 @@ class HostFactory(factory.Factory): is_secure = False key_pair = factory.LazyFunction(generate_new_rsa_identity) - public_key = factory.LazyAttribute(lambda o: o.key_pair.public_key) network = factory.LazyAttribute( lambda o: SwarmFactory(is_secure=o.is_secure, key_pair=o.key_pair) ) @@ -113,10 +122,7 @@ class HostFactory(factory.Factory): for key_pair in key_pairs ] ) - return tuple( - BasicHost(key_pair.public_key, swarm) - for key_pair, swarm in zip(key_pairs, swarms) - ) + return tuple(BasicHost(swarm) for swarm in swarms) class FloodsubFactory(factory.Factory): From 566e4c080dd50a9d533b83398e35a3fba101c12a Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 17:32:53 +0800 Subject: [PATCH 07/14] Fix lint --- libp2p/host/basic_host.py | 4 ++-- libp2p/host/host_interface.py | 4 ++-- libp2p/peer/peerstore.py | 15 ++++++++++----- libp2p/peer/peerstore_interface.py | 4 ++-- libp2p/tools/factories.py | 2 +- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/libp2p/host/basic_host.py b/libp2p/host/basic_host.py index 48c322b..253394e 100644 --- a/libp2p/host/basic_host.py +++ b/libp2p/host/basic_host.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, List, Sequence import multiaddr -from libp2p.crypto.keys import PublicKey +from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.host.defaults import get_default_protocols from libp2p.host.exceptions import StreamFailure from libp2p.network.network_interface import INetwork @@ -67,7 +67,7 @@ class BasicHost(IHost): def get_public_key(self) -> PublicKey: return self.peerstore.pubkey(self.get_id()) - def get_private_key(self) -> PublicKey: + def get_private_key(self) -> PrivateKey: return self.peerstore.privkey(self.get_id()) def get_network(self) -> INetwork: diff --git a/libp2p/host/host_interface.py b/libp2p/host/host_interface.py index 5e28fda..43f4ac4 100644 --- a/libp2p/host/host_interface.py +++ b/libp2p/host/host_interface.py @@ -3,7 +3,7 @@ from typing import Any, List, Sequence import multiaddr -from libp2p.crypto.keys import PublicKey +from libp2p.crypto.keys import PrivateKey, PublicKey from libp2p.network.network_interface import INetwork from libp2p.network.stream.net_stream_interface import INetStream from libp2p.peer.id import ID @@ -25,7 +25,7 @@ class IHost(ABC): """ @abstractmethod - def get_private_key(self) -> PublicKey: + def get_private_key(self) -> PrivateKey: """ :return: the private key belonging to the peer """ diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 7dc367f..4cff54e 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Sequence, Tuple +from typing import Any, Dict, List, Optional, Sequence, Set from multiaddr import Multiaddr @@ -24,7 +24,8 @@ class PeerStore(IPeerStore): def __create_or_get_peer(self, peer_id: ID) -> PeerData: """ Returns the peer data for peer_id or creates a new peer data (and - stores it in peer_data_map) if peer data for peer_id does not yet exist. + stores it in peer_data_map) if peer data for peer_id does not yet + exist. :param peer_id: peer ID :return: peer data @@ -158,7 +159,9 @@ class PeerStore(IPeerStore): :raise PeerStoreError: if peer ID already has pubkey set """ if peer_id in self.peer_pubkey_map: - raise PeerStoreError(f"peer ID already has pubkey: {self.peer_pubkey_map[peer_id]}") + raise PeerStoreError( + f"peer ID already has pubkey: {self.peer_pubkey_map[peer_id]}" + ) self.peer_pubkey_map[peer_id] = pubkey def pubkey(self, peer_id: ID) -> PublicKey: @@ -178,7 +181,9 @@ class PeerStore(IPeerStore): :raise PeerStoreError: if peer ID already has privkey set """ if peer_id in self.peer_privkey_map: - raise PeerStoreError(f"peer ID already has privkey: {self.peer_privkey_map[peer_id]}") + raise PeerStoreError( + f"peer ID already has privkey: {self.peer_privkey_map[peer_id]}" + ) self.peer_privkey_map[peer_id] = privkey def privkey(self, peer_id: ID) -> PrivateKey: @@ -191,7 +196,7 @@ class PeerStore(IPeerStore): return self.peer_privkey_map[peer_id] raise PeerStoreError("peer ID not found") - def peers_with_keys(self) -> Tuple[ID]: + def peers_with_keys(self) -> Set[ID]: """ :return: all of the peer IDs which has pubkey/privkey stored in peer store """ diff --git a/libp2p/peer/peerstore_interface.py b/libp2p/peer/peerstore_interface.py index fbd1a2e..8ebe1cc 100644 --- a/libp2p/peer/peerstore_interface.py +++ b/libp2p/peer/peerstore_interface.py @@ -1,5 +1,5 @@ from abc import abstractmethod -from typing import Any, List, Sequence, Tuple +from typing import Any, List, Sequence, Set from multiaddr import Multiaddr @@ -132,7 +132,7 @@ class IPeerStore(IAddrBook, IPeerMetadata): """ @abstractmethod - def peers_with_keys(self) -> Tuple[ID]: + def peers_with_keys(self) -> Set[ID]: """ :return: all of the peer IDs which has pubkey/privkey stored in peer store """ diff --git a/libp2p/tools/factories.py b/libp2p/tools/factories.py index 341d691..405e6ed 100644 --- a/libp2p/tools/factories.py +++ b/libp2p/tools/factories.py @@ -34,7 +34,7 @@ from .constants import ( from .utils import connect, connect_swarm -def initialize_peerstore_with_our_keypair(self_id: ID, key_pair: KeyPair): +def initialize_peerstore_with_our_keypair(self_id: ID, key_pair: KeyPair) -> PeerStore: peer_store = PeerStore() peer_store.add_pubkey(self_id, key_pair.public_key) peer_store.add_privkey(self_id, key_pair.private_key) From 076dae50f364844635dfbba7b18c83dd2638c77e Mon Sep 17 00:00:00 2001 From: NIC619 Date: Mon, 25 Nov 2019 22:05:33 +0800 Subject: [PATCH 08/14] Fix missing `BasicHost` interface update --- tests/host/test_basic_host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/host/test_basic_host.py b/tests/host/test_basic_host.py index f25f4e7..1eec04a 100644 --- a/tests/host/test_basic_host.py +++ b/tests/host/test_basic_host.py @@ -7,7 +7,7 @@ from libp2p.host.defaults import get_default_protocols def test_default_protocols(): key_pair = create_new_key_pair() swarm = initialize_default_swarm(key_pair) - host = BasicHost(key_pair.public_key, swarm) + host = BasicHost(swarm) mux = host.get_mux() handlers = mux.handlers From 828ae69c66c8c6fe6964c98f1bfb5624a4ff0501 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 11:52:31 +0800 Subject: [PATCH 09/14] Apply PR feedback: `add_key_pair` --- libp2p/__init__.py | 3 +-- libp2p/peer/peerstore.py | 13 +++++++++++-- libp2p/peer/peerstore_interface.py | 10 +++++++++- libp2p/tools/factories.py | 3 +-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libp2p/__init__.py b/libp2p/__init__.py index 75b6764..291b3a5 100644 --- a/libp2p/__init__.py +++ b/libp2p/__init__.py @@ -106,8 +106,7 @@ def initialize_default_swarm( peerstore = peerstore_opt or PeerStore() # Store our key pair in peerstore - peerstore.add_pubkey(id_opt, key_pair.public_key) - peerstore.add_privkey(id_opt, key_pair.private_key) + peerstore.add_key_pair(id_opt, key_pair) # TODO: Initialize discovery if not presented return Swarm(id_opt, peerstore, upgrader, transport) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 4cff54e..c011e3e 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -2,7 +2,7 @@ from typing import Any, Dict, List, Optional, Sequence, Set from multiaddr import Multiaddr -from libp2p.crypto.keys import PrivateKey, PublicKey +from libp2p.crypto.keys import KeyPair, PrivateKey, PublicKey from .id import ID from .peerdata import PeerData, PeerDataError @@ -34,7 +34,7 @@ class PeerStore(IPeerStore): return self.peer_data_map[peer_id] data = PeerData() self.peer_data_map[peer_id] = data - return self.peer_data_map[peer_id] + return data def peer_info(self, peer_id: ID) -> Optional[PeerInfo]: """ @@ -196,6 +196,15 @@ class PeerStore(IPeerStore): return self.peer_privkey_map[peer_id] raise PeerStoreError("peer ID not found") + def add_key_pair(self, peer_id: ID, key_pair: KeyPair) -> None: + """ + :param peer_id: peer ID to add private key for + :param key_pair: + :raise PeerStoreError: if peer ID already has pubkey or privkey set + """ + self.add_pubkey(peer_id, key_pair.public_keypubkey) + self.add_privkey(peer_id, key_pair.private_key) + def peers_with_keys(self) -> Set[ID]: """ :return: all of the peer IDs which has pubkey/privkey stored in peer store diff --git a/libp2p/peer/peerstore_interface.py b/libp2p/peer/peerstore_interface.py index 8ebe1cc..618bbf5 100644 --- a/libp2p/peer/peerstore_interface.py +++ b/libp2p/peer/peerstore_interface.py @@ -3,7 +3,7 @@ from typing import Any, List, Sequence, Set from multiaddr import Multiaddr -from libp2p.crypto.keys import PrivateKey, PublicKey +from libp2p.crypto.keys import KeyPair, PrivateKey, PublicKey from .addrbook_interface import IAddrBook from .id import ID @@ -131,6 +131,14 @@ class IPeerStore(IAddrBook, IPeerMetadata): :raise PeerStoreError: if peer ID not found """ + @abstractmethod + def add_key_pair(self, peer_id: ID, key_pair: KeyPair) -> None: + """ + :param peer_id: peer ID to add private key for + :param key_pair: + :raise PeerStoreError: if peer ID already has pubkey or privkey set + """ + @abstractmethod def peers_with_keys(self) -> Set[ID]: """ diff --git a/libp2p/tools/factories.py b/libp2p/tools/factories.py index 405e6ed..b5c16b8 100644 --- a/libp2p/tools/factories.py +++ b/libp2p/tools/factories.py @@ -36,8 +36,7 @@ from .utils import connect, connect_swarm def initialize_peerstore_with_our_keypair(self_id: ID, key_pair: KeyPair) -> PeerStore: peer_store = PeerStore() - peer_store.add_pubkey(self_id, key_pair.public_key) - peer_store.add_privkey(self_id, key_pair.private_key) + peer_store.add_key_pair(self_id, key_pair) return peer_store From 0bfbdf7fab77a15562b32bf892cd23d5d9a5c16d Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 12:27:59 +0800 Subject: [PATCH 10/14] Move keypair into `PeerData` --- libp2p/peer/peerdata.py | 59 ++++++++++++++++++++++ libp2p/peer/peerdata_interface.py | 33 +++++++++++-- libp2p/peer/peerstore.py | 81 ++++++++++++++----------------- 3 files changed, 126 insertions(+), 47 deletions(-) diff --git a/libp2p/peer/peerdata.py b/libp2p/peer/peerdata.py index 9273079..f26ddd6 100644 --- a/libp2p/peer/peerdata.py +++ b/libp2p/peer/peerdata.py @@ -2,11 +2,15 @@ from typing import Any, Dict, List, Sequence from multiaddr import Multiaddr +from libp2p.crypto.keys import PrivateKey, PublicKey + from .peerdata_interface import IPeerData class PeerData(IPeerData): + pubkey: PublicKey + privkey: PrivateKey metadata: Dict[Any, Any] protocols: List[str] addrs: List[Multiaddr] @@ -17,31 +21,86 @@ class PeerData(IPeerData): self.addrs = [] def get_protocols(self) -> List[str]: + """ + :return: all protocols associated with given peer + """ return self.protocols def add_protocols(self, protocols: Sequence[str]) -> None: + """ + :param protocols: protocols to add + """ self.protocols.extend(list(protocols)) def set_protocols(self, protocols: Sequence[str]) -> None: + """ + :param protocols: protocols to set + """ self.protocols = list(protocols) def add_addrs(self, addrs: Sequence[Multiaddr]) -> None: + """ + :param addrs: multiaddresses to add + """ self.addrs.extend(addrs) def get_addrs(self) -> List[Multiaddr]: + """ + :return: all multiaddresses + """ return self.addrs def clear_addrs(self) -> None: + """Clear all addresses.""" self.addrs = [] def put_metadata(self, key: str, val: Any) -> None: + """ + :param key: key in KV pair + :param val: val to associate with key + """ self.metadata[key] = val def get_metadata(self, key: str) -> Any: + """ + :param key: key in KV pair + :return: val for key + :raise PeerDataError: key not found + """ if key in self.metadata: return self.metadata[key] raise PeerDataError("key not found") + def add_pubkey(self, pubkey: PublicKey) -> None: + """ + :param pubkey: + """ + self.pubkey = pubkey + + def get_pubkey(self) -> PublicKey: + """ + :return: public key of the peer + :raise PeerDataError: if public key not found + """ + if self.pubkey is None: + raise PeerDataError("public key not found") + return self.pubkey + + def add_privkey(self, privkey: PrivateKey) -> None: + """ + :param privkey: + """ + self.privkey = privkey + + def get_privkey(self) -> PrivateKey: + """ + :return: private key of the peer + :raise PeerDataError: if private key not found + """ + if self.privkey is None: + raise PeerDataError("private key not found") + return self.privkey + class PeerDataError(KeyError): """Raised when a key is not found in peer metadata.""" diff --git a/libp2p/peer/peerdata_interface.py b/libp2p/peer/peerdata_interface.py index e842acb..ab9016e 100644 --- a/libp2p/peer/peerdata_interface.py +++ b/libp2p/peer/peerdata_interface.py @@ -3,6 +3,8 @@ from typing import Any, List, Sequence from multiaddr import Multiaddr +from libp2p.crypto.keys import PrivateKey, PublicKey + from .peermetadata_interface import IPeerMetadata @@ -22,7 +24,7 @@ class IPeerData(ABC): @abstractmethod def set_protocols(self, protocols: Sequence[str]) -> None: """ - :param protocols: protocols to add + :param protocols: protocols to set """ @abstractmethod @@ -46,7 +48,6 @@ class IPeerData(ABC): """ :param key: key in KV pair :param val: val to associate with key - :raise Exception: unsuccesful put """ @abstractmethod @@ -54,5 +55,31 @@ class IPeerData(ABC): """ :param key: key in KV pair :return: val for key - :raise Exception: key not found + :raise PeerDataError: key not found + """ + + @abstractmethod + def add_pubkey(self, pubkey: PublicKey) -> None: + """ + :param pubkey: + """ + + @abstractmethod + def get_pubkey(self) -> PublicKey: + """ + :return: public key of the peer + :raise PeerDataError: if public key not found + """ + + @abstractmethod + def add_privkey(self, privkey: PrivateKey) -> None: + """ + :param privkey: + """ + + @abstractmethod + def get_privkey(self) -> PrivateKey: + """ + :return: private key of the peer + :raise PeerDataError: if private key not found """ diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index c011e3e..572a7af 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Sequence, Set +from typing import Any, Dict, List, Sequence from multiaddr import Multiaddr @@ -12,16 +12,12 @@ from .peerstore_interface import IPeerStore class PeerStore(IPeerStore): - peer_pubkey_map: Dict[ID, PublicKey] - peer_privkey_map: Dict[ID, PrivateKey] peer_data_map: Dict[ID, PeerData] def __init__(self) -> None: - self.peer_pubkey_map = {} - self.peer_privkey_map = {} self.peer_data_map = {} - def __create_or_get_peer(self, peer_id: ID) -> PeerData: + def __create_or_get_peer_data(self, peer_id: ID) -> PeerData: """ Returns the peer data for peer_id or creates a new peer data (and stores it in peer_data_map) if peer data for peer_id does not yet @@ -36,15 +32,15 @@ class PeerStore(IPeerStore): self.peer_data_map[peer_id] = data return data - def peer_info(self, peer_id: ID) -> Optional[PeerInfo]: + def peer_info(self, peer_id: ID) -> PeerInfo: """ :param peer_id: peer ID to get info for :return: peer info object """ if peer_id in self.peer_data_map: peer_data = self.peer_data_map[peer_id] - return PeerInfo(peer_id, peer_data.addrs) - return None + return PeerInfo(peer_id, peer_data.get_addrs()) + raise PeerStoreError("peer ID not found") def get_protocols(self, peer_id: ID) -> List[str]: """ @@ -61,16 +57,16 @@ class PeerStore(IPeerStore): :param peer_id: peer ID to add protocols for :param protocols: protocols to add """ - peer = self.__create_or_get_peer(peer_id) - peer.add_protocols(list(protocols)) + peer_data = self.__create_or_get_peer_data(peer_id) + peer_data.add_protocols(list(protocols)) def set_protocols(self, peer_id: ID, protocols: Sequence[str]) -> None: """ :param peer_id: peer ID to set protocols for :param protocols: protocols to set """ - peer = self.__create_or_get_peer(peer_id) - peer.set_protocols(list(protocols)) + peer_data = self.__create_or_get_peer_data(peer_id) + peer_data.set_protocols(list(protocols)) def peer_ids(self) -> List[ID]: """ @@ -101,8 +97,8 @@ class PeerStore(IPeerStore): """ # <> # This can output an error, not sure what the possible errors are - peer = self.__create_or_get_peer(peer_id) - peer.put_metadata(key, val) + peer_data = self.__create_or_get_peer_data(peer_id) + peer_data.put_metadata(key, val) def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None: """ @@ -119,8 +115,8 @@ class PeerStore(IPeerStore): :param ttl: time-to-live for the this record """ # Ignore ttl for now - peer = self.__create_or_get_peer(peer_id) - peer.add_addrs(list(addrs)) + peer_data = self.__create_or_get_peer_data(peer_id) + peer_data.add_addrs(list(addrs)) def addrs(self, peer_id: ID) -> List[Multiaddr]: """ @@ -156,60 +152,57 @@ class PeerStore(IPeerStore): """ :param peer_id: peer ID to add public key for :param pubkey: - :raise PeerStoreError: if peer ID already has pubkey set """ - if peer_id in self.peer_pubkey_map: - raise PeerStoreError( - f"peer ID already has pubkey: {self.peer_pubkey_map[peer_id]}" - ) - self.peer_pubkey_map[peer_id] = pubkey + peer_data = self.__create_or_get_peer_data(peer_id) + # TODO: Check if pubkey matches peer ID + peer_data.add_pubkey(pubkey) def pubkey(self, peer_id: ID) -> PublicKey: """ :param peer_id: peer ID to get public key for :return: public key of the peer - :raise PeerStoreError: if peer ID not found + :raise PeerStoreError: if peer ID or peer pubkey not found """ - if peer_id in self.peer_pubkey_map: - return self.peer_pubkey_map[peer_id] + if peer_id in self.peer_data_map: + peer_data = self.peer_data_map[peer_id] + try: + pubkey = peer_data.get_pubkey() + except PeerDataError: + raise PeerStoreError("peer pubkey not found") + return pubkey raise PeerStoreError("peer ID not found") def add_privkey(self, peer_id: ID, privkey: PrivateKey) -> None: """ :param peer_id: peer ID to add private key for :param privkey: - :raise PeerStoreError: if peer ID already has privkey set """ - if peer_id in self.peer_privkey_map: - raise PeerStoreError( - f"peer ID already has privkey: {self.peer_privkey_map[peer_id]}" - ) - self.peer_privkey_map[peer_id] = privkey + peer_data = self.__create_or_get_peer_data(peer_id) + # TODO: Check if privkey matches peer ID + peer_data.add_privkey(privkey) def privkey(self, peer_id: ID) -> PrivateKey: """ :param peer_id: peer ID to get private key for :return: private key of the peer - :raise PeerStoreError: if peer ID not found + :raise PeerStoreError: if peer ID or peer privkey not found """ - if peer_id in self.peer_pubkey_map: - return self.peer_privkey_map[peer_id] + if peer_id in self.peer_data_map: + peer_data = self.peer_data_map[peer_id] + try: + privkey = peer_data.get_privkey() + except PeerDataError: + raise PeerStoreError("peer privkey not found") + return privkey raise PeerStoreError("peer ID not found") def add_key_pair(self, peer_id: ID, key_pair: KeyPair) -> None: """ :param peer_id: peer ID to add private key for :param key_pair: - :raise PeerStoreError: if peer ID already has pubkey or privkey set """ - self.add_pubkey(peer_id, key_pair.public_keypubkey) - self.add_privkey(peer_id, key_pair.private_key) - - def peers_with_keys(self) -> Set[ID]: - """ - :return: all of the peer IDs which has pubkey/privkey stored in peer store - """ - return set(self.peer_pubkey_map.keys()).union(self.peer_privkey_map.keys()) + self.add_pubkey(key_pair.public_key) + self.add_privkey(key_pair.private_key) class PeerStoreError(KeyError): From ffa73f56493dea5fd4f8805ed3aaa9aba9527824 Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 12:33:55 +0800 Subject: [PATCH 11/14] Check if pubkey matches peer ID before add --- libp2p/peer/peerstore.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 572a7af..8111f08 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -95,8 +95,6 @@ class PeerStore(IPeerStore): :param key: :param value: """ - # <> - # This can output an error, not sure what the possible errors are peer_data = self.__create_or_get_peer_data(peer_id) peer_data.put_metadata(key, val) @@ -152,9 +150,11 @@ class PeerStore(IPeerStore): """ :param peer_id: peer ID to add public key for :param pubkey: + :raise PeerStoreError: if peer ID and pubkey does not match """ peer_data = self.__create_or_get_peer_data(peer_id) - # TODO: Check if pubkey matches peer ID + if ID.from_pubkey(pubkey) != peer_id: + raise PeerStoreError("peer ID and pubkey does not match") peer_data.add_pubkey(pubkey) def pubkey(self, peer_id: ID) -> PublicKey: @@ -176,9 +176,11 @@ class PeerStore(IPeerStore): """ :param peer_id: peer ID to add private key for :param privkey: + :raise PeerStoreError: if peer ID or peer privkey not found """ peer_data = self.__create_or_get_peer_data(peer_id) - # TODO: Check if privkey matches peer ID + if ID.from_pubkey(privkey.get_public_key()) != peer_id: + raise PeerStoreError("peer ID and privkey does not match") peer_data.add_privkey(privkey) def privkey(self, peer_id: ID) -> PrivateKey: From fab27b03579635faea047dd5606abbf7418f7aca Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 12:35:50 +0800 Subject: [PATCH 12/14] Fix lint --- libp2p/peer/peerstore.py | 4 ++-- libp2p/peer/peerstore_interface.py | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 8111f08..03edffb 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -203,8 +203,8 @@ class PeerStore(IPeerStore): :param peer_id: peer ID to add private key for :param key_pair: """ - self.add_pubkey(key_pair.public_key) - self.add_privkey(key_pair.private_key) + self.add_pubkey(peer_id, key_pair.public_key) + self.add_privkey(peer_id, key_pair.private_key) class PeerStoreError(KeyError): diff --git a/libp2p/peer/peerstore_interface.py b/libp2p/peer/peerstore_interface.py index 618bbf5..a9790b0 100644 --- a/libp2p/peer/peerstore_interface.py +++ b/libp2p/peer/peerstore_interface.py @@ -1,5 +1,5 @@ from abc import abstractmethod -from typing import Any, List, Sequence, Set +from typing import Any, List, Sequence from multiaddr import Multiaddr @@ -138,9 +138,3 @@ class IPeerStore(IAddrBook, IPeerMetadata): :param key_pair: :raise PeerStoreError: if peer ID already has pubkey or privkey set """ - - @abstractmethod - def peers_with_keys(self) -> Set[ID]: - """ - :return: all of the peer IDs which has pubkey/privkey stored in peer store - """ From 94c7a0bca472b7c0756565ba755a68a4ba44240c Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 14:04:28 +0800 Subject: [PATCH 13/14] Apply PR feedback and fix --- libp2p/peer/peerdata.py | 2 ++ tests/libp2p/test_libp2p.py | 7 ++++--- tests/peer/test_peerstore.py | 9 +++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libp2p/peer/peerdata.py b/libp2p/peer/peerdata.py index f26ddd6..02df07e 100644 --- a/libp2p/peer/peerdata.py +++ b/libp2p/peer/peerdata.py @@ -16,6 +16,8 @@ class PeerData(IPeerData): addrs: List[Multiaddr] def __init__(self) -> None: + self.pubkey = None + self.privkey = None self.metadata = {} self.protocols = [] self.addrs = [] diff --git a/tests/libp2p/test_libp2p.py b/tests/libp2p/test_libp2p.py index 330250c..541c173 100644 --- a/tests/libp2p/test_libp2p.py +++ b/tests/libp2p/test_libp2p.py @@ -328,18 +328,19 @@ async def test_host_connect(): transport_opt_list = [["/ip4/127.0.0.1/tcp/0"], ["/ip4/127.0.0.1/tcp/0"]] (node_a, node_b) = await set_up_nodes_by_transport_opt(transport_opt_list) - assert not node_a.get_peerstore().peer_ids() + # Only our peer ID is stored in peer store + assert len(node_a.get_peerstore().peer_ids()) == 1 addr = node_b.get_addrs()[0] info = info_from_p2p_addr(addr) await node_a.connect(info) - assert len(node_a.get_peerstore().peer_ids()) == 1 + assert len(node_a.get_peerstore().peer_ids()) == 2 await node_a.connect(info) # make sure we don't do double connection - assert len(node_a.get_peerstore().peer_ids()) == 1 + assert len(node_a.get_peerstore().peer_ids()) == 2 assert node_b.get_id() in node_a.get_peerstore().peer_ids() ma_node_b = multiaddr.Multiaddr("/p2p/%s" % node_b.get_id().pretty()) diff --git a/tests/peer/test_peerstore.py b/tests/peer/test_peerstore.py index ffb7b2d..4a45651 100644 --- a/tests/peer/test_peerstore.py +++ b/tests/peer/test_peerstore.py @@ -1,13 +1,14 @@ -from libp2p.peer.peerstore import PeerStore +import pytest + +from libp2p.peer.peerstore import PeerStore, PeerStoreError # Testing methods from IPeerStore base class. def test_peer_info_empty(): store = PeerStore() - info = store.peer_info("peer") - - assert not info + with pytest.raises(PeerStoreError): + store.peer_info("peer") def test_peer_info_basic(): From 9f3f2c53da9ebd96114370e4fa2d97456b71676f Mon Sep 17 00:00:00 2001 From: NIC619 Date: Tue, 26 Nov 2019 16:18:15 +0800 Subject: [PATCH 14/14] Apply PR feedback: use defaultdict for peer data map --- libp2p/peer/peerstore.py | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/libp2p/peer/peerstore.py b/libp2p/peer/peerstore.py index 03edffb..f9a9fbd 100644 --- a/libp2p/peer/peerstore.py +++ b/libp2p/peer/peerstore.py @@ -1,3 +1,4 @@ +from collections import defaultdict from typing import Any, Dict, List, Sequence from multiaddr import Multiaddr @@ -15,22 +16,7 @@ class PeerStore(IPeerStore): peer_data_map: Dict[ID, PeerData] def __init__(self) -> None: - self.peer_data_map = {} - - def __create_or_get_peer_data(self, peer_id: ID) -> PeerData: - """ - Returns the peer data for peer_id or creates a new peer data (and - stores it in peer_data_map) if peer data for peer_id does not yet - exist. - - :param peer_id: peer ID - :return: peer data - """ - if peer_id in self.peer_data_map: - return self.peer_data_map[peer_id] - data = PeerData() - self.peer_data_map[peer_id] = data - return data + self.peer_data_map = defaultdict(PeerData) def peer_info(self, peer_id: ID) -> PeerInfo: """ @@ -57,7 +43,7 @@ class PeerStore(IPeerStore): :param peer_id: peer ID to add protocols for :param protocols: protocols to add """ - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] peer_data.add_protocols(list(protocols)) def set_protocols(self, peer_id: ID, protocols: Sequence[str]) -> None: @@ -65,7 +51,7 @@ class PeerStore(IPeerStore): :param peer_id: peer ID to set protocols for :param protocols: protocols to set """ - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] peer_data.set_protocols(list(protocols)) def peer_ids(self) -> List[ID]: @@ -95,7 +81,7 @@ class PeerStore(IPeerStore): :param key: :param value: """ - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] peer_data.put_metadata(key, val) def add_addr(self, peer_id: ID, addr: Multiaddr, ttl: int) -> None: @@ -113,7 +99,7 @@ class PeerStore(IPeerStore): :param ttl: time-to-live for the this record """ # Ignore ttl for now - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] peer_data.add_addrs(list(addrs)) def addrs(self, peer_id: ID) -> List[Multiaddr]: @@ -152,7 +138,7 @@ class PeerStore(IPeerStore): :param pubkey: :raise PeerStoreError: if peer ID and pubkey does not match """ - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] if ID.from_pubkey(pubkey) != peer_id: raise PeerStoreError("peer ID and pubkey does not match") peer_data.add_pubkey(pubkey) @@ -178,7 +164,7 @@ class PeerStore(IPeerStore): :param privkey: :raise PeerStoreError: if peer ID or peer privkey not found """ - peer_data = self.__create_or_get_peer_data(peer_id) + peer_data = self.peer_data_map[peer_id] if ID.from_pubkey(privkey.get_public_key()) != peer_id: raise PeerStoreError("peer ID and privkey does not match") peer_data.add_privkey(privkey)