Merge pull request #153 from libp2p/routed-host

Added RoutedHost
This commit is contained in:
Alex Haynes 2019-04-24 21:12:15 -04:00 committed by GitHub
commit fc4fc74b87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 17 deletions

View File

@ -6,8 +6,10 @@ from .peer.peerstore import PeerStore
from .peer.id import id_from_public_key
from .network.swarm import Swarm
from .host.basic_host import BasicHost
from .kademlia.routed_host import RoutedHost
from .transport.upgrader import TransportUpgrader
from .transport.tcp.tcp import TCP
from .kademlia.network import KademliaServer
async def cleanup_done_tasks():
@ -23,6 +25,30 @@ async def cleanup_done_tasks():
# Some sleep necessary to context switch
await asyncio.sleep(3)
def generate_id():
new_key = RSA.generate(2048, e=65537)
new_id = id_from_public_key(new_key.publickey())
# private_key = new_key.exportKey("PEM")
return new_id
def initialize_default_kademlia(
ksize=20, alpha=3, id_opt=None, storage=None):
"""
initialize swam when no swarm is passed in
:param ksize: The k parameter from the paper
:param alpha: The alpha parameter from the paper
:param id_opt: optional id for host
:param storage: An instance that implements
:interface:`~kademlia.storage.IStorage`
:return: return a default kademlia instance
"""
if not id_opt:
id_opt = generate_id()
node_id = id_opt.get_raw_id()
return KademliaServer(ksize=ksize, alpha=alpha,
node_id=node_id, storage=storage)
def initialize_default_swarm(
id_opt=None, transport_opt=None,
@ -37,10 +63,9 @@ def initialize_default_swarm(
:return: return a default swarm instance
"""
# pylint: disable=too-many-arguments, unused-argument
if not id_opt:
new_key = RSA.generate(2048, e=65537)
id_opt = id_from_public_key(new_key.publickey())
# private_key = new_key.exportKey("PEM")
id_opt = generate_id()
transport_opt = transport_opt or ["/ip4/127.0.0.1/tcp/8001"]
transport = [multiaddr.Multiaddr(t) for t in transport_opt]
@ -58,7 +83,8 @@ def initialize_default_swarm(
async def new_node(
swarm_opt=None, id_opt=None, transport_opt=None,
muxer_opt=None, sec_opt=None, peerstore_opt=None):
muxer_opt=None, sec_opt=None, peerstore_opt=None,
disc_opt=None):
"""
create new libp2p node
:param id_opt: optional id for host
@ -69,6 +95,10 @@ async def new_node(
:return: return a default swarm instance
"""
# pylint: disable=too-many-arguments
if not id_opt:
id_opt = generate_id()
if not swarm_opt:
swarm_opt = initialize_default_swarm(
id_opt=id_opt, transport_opt=transport_opt,
@ -77,7 +107,10 @@ async def new_node(
# TODO enable support for other host type
# TODO routing unimplemented
host = BasicHost(swarm_opt)
if not disc_opt:
host = BasicHost(swarm_opt)
else:
host = RoutedHost(swarm_opt, disc_opt)
# Kick off cleanup job
asyncio.ensure_future(cleanup_done_tasks())

View File

@ -15,9 +15,8 @@ class KadPeerInfo(PeerInfo):
def __init__(self, peer_id, peer_data=None):
super(KadPeerInfo, self).__init__(peer_id, peer_data)
# pylint: disable=protected-access
self.peer_id = peer_id._id_str
self.long_id = int(digest(peer_id._id_str).hex(), 16)
self.peer_id = peer_id.get_raw_id()
self.long_id = int(digest(peer_id.get_raw_id()).hex(), 16)
self.addrs = peer_data.get_addrs() if peer_data else None

View File

@ -16,7 +16,7 @@ log = logging.getLogger(__name__) # pylint: disable=invalid-name
# pylint: disable=too-many-instance-attributes
class Server:
class KademliaServer:
"""
High level view of a node instance. This is the object that should be
created to start listening as an active node on the network.
@ -219,7 +219,7 @@ class Server:
log.info("Loading state from %s", fname)
with open(fname, 'rb') as file:
data = pickle.load(file)
svr = Server(data['ksize'], data['alpha'], data['id'])
svr = KademliaServer(data['ksize'], data['alpha'], data['id'])
if data['neighbors']:
svr.bootstrap(data['neighbors'])
return svr

View File

@ -0,0 +1,21 @@
from libp2p.host.basic_host import BasicHost
class RoutedHost(BasicHost):
def __init__(self, _network, _kad_network):
super(RoutedHost, self).__init__(_network)
self.kad_network = _kad_network
def get_kad_network(self):
return self.kad_network
def routed_listen(self, port, interface='0.0.0.0'):
return self.kad_network.listen(port, interface)
def routed_get(self, key):
return self.kad_network.get(key)
def routed_set(self, key, value):
return self.kad_network.set(key, value)
def routed_set_digest(self, dkey, value):
return self.kad_network.set_digest(dkey, value)

View File

@ -15,6 +15,9 @@ class ID:
def __init__(self, id_str):
self._id_str = id_str
def get_raw_id(self):
return self._id_str
def pretty(self):
return base58.b58encode(self._id_str).decode()

View File

@ -1,13 +1,13 @@
import pytest
from libp2p.kademlia.network import Server
from libp2p.kademlia.network import KademliaServer
@pytest.mark.asyncio
async def test_example():
node_a = Server()
node_a = KademliaServer()
await node_a.listen(5678)
node_b = Server()
node_b = KademliaServer()
await node_b.listen(5679)
# Bootstrap the node by connecting to other known nodes, in this case
@ -29,12 +29,12 @@ async def test_example():
@pytest.mark.asyncio
async def test_multiple_nodes_bootstrap_set_get(nodes_nr):
node_bootstrap = Server()
node_bootstrap = KademliaServer()
await node_bootstrap.listen(3000 + nodes_nr * 2)
nodes = []
for i in range(nodes_nr):
node = Server()
node = KademliaServer()
addrs = [("127.0.0.1", 3000 + nodes_nr * 2)]
await node.listen(3001 + i + nodes_nr * 2)
await node.bootstrap(addrs)
@ -56,12 +56,12 @@ async def test_multiple_nodes_bootstrap_set_get(nodes_nr):
@pytest.mark.parametrize("nodes_nr", [(2**i) for i in range(2, 5)])
@pytest.mark.asyncio
async def test_multiple_nodes_set_bootstrap_get(nodes_nr):
node_bootstrap = Server()
node_bootstrap = KademliaServer()
await node_bootstrap.listen(2000 + nodes_nr * 2)
nodes = []
for i in range(nodes_nr):
node = Server()
node = KademliaServer()
addrs = [("127.0.0.1", 2000 + nodes_nr * 2)]
await node.listen(2001 + i + nodes_nr * 2)
await node.bootstrap(addrs)