added RoutedHost and updated new_node to support it

This commit is contained in:
Alex Haynes 2019-04-20 17:35:05 -04:00
parent 367a939087
commit e7424d3673
6 changed files with 85 additions and 15 deletions

View File

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

View File

@ -15,8 +15,7 @@ class KadPeerInfo(PeerInfo):
def __init__(self, peer_id, peer_data=None): def __init__(self, peer_id, peer_data=None):
super(KadPeerInfo, self).__init__(peer_id, peer_data) super(KadPeerInfo, self).__init__(peer_id, peer_data)
# pylint: disable=protected-access self.peer_id = peer_id.get_raw_id()
self.peer_id = peer_id._id_str
self.long_id = int(digest(peer_id._id_str).hex(), 16) self.long_id = int(digest(peer_id._id_str).hex(), 16)
self.addrs = peer_data.get_addrs() if peer_data else None 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 # pylint: disable=too-many-instance-attributes
class Server: class KademliaServer:
""" """
High level view of a node instance. This is the object that should be 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. created to start listening as an active node on the network.

View File

@ -0,0 +1,35 @@
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 kad_listen(self, port, interface='0.0.0.0'):
return self.kad_network.listen(port, interface)
def kad_get(self, key):
return self.kad_network.get(key)
def kad_set(self, key, value):
return self.kad_network.set(key, value)
def kad_set_digest(self, dkey, value):
return self.kad_network.set_digest(dkey, value)
def check_dht_value_type(value):
"""
Checks to see if the type of the value is a valid type for
placing in the dht.
"""
typeset = [
int,
float,
bool,
str,
bytes
]
return type(value) in typeset # pylint: disable=unidiomatic-typecheck

View File

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

View File

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