def test_bootstrap_nodes_ipc(self): w = Wallet() w1 = Wallet() w2 = Wallet() w3 = Wallet() w4 = Wallet() bootnodes = [ _socket('ipc:///tmp/n1/discovery'), _socket('ipc:///tmp/n2/discovery'), _socket('ipc:///tmp/n3/discovery'), _socket('ipc:///tmp/n4/discovery') ] d1 = DiscoveryServer(socket_id=bootnodes[0], wallet=w1, pepper=PEPPER.encode(), ctx=self.ctx, linger=1000, poll_timeout=1000) d2 = DiscoveryServer(socket_id=bootnodes[1], wallet=w2, pepper=PEPPER.encode(), ctx=self.ctx, linger=1000, poll_timeout=1000) d3 = DiscoveryServer(socket_id=bootnodes[2], wallet=w3, pepper=PEPPER.encode(), ctx=self.ctx, linger=1000, poll_timeout=1000) d4 = DiscoveryServer(socket_id=bootnodes[3], wallet=w4, pepper=PEPPER.encode(), ctx=self.ctx, linger=1000, poll_timeout=1000) n = Network(wallet=w, ctx=self.ctx, bootnodes=bootnodes) tasks = asyncio.gather(d1.serve(), d2.serve(), d3.serve(), d4.serve(), stop_server(d1, 1), stop_server(d2, 1), stop_server(d3, 1), stop_server(d4, 1), n.discover_bootnodes(bootnodes)) loop = asyncio.get_event_loop() loop.run_until_complete(tasks) expected_dict = { w.verifying_key().hex(): 'tcp://0.0.0.0', w1.verifying_key().hex(): 'ipc:///tmp/n1', w2.verifying_key().hex(): 'ipc:///tmp/n2', w3.verifying_key().hex(): 'ipc:///tmp/n3', w4.verifying_key().hex(): 'ipc:///tmp/n4' } self.assertDictEqual(n.peer_service.table, expected_dict)
async def discover_bootnodes(self, nodes): responses = await discovery.discover_nodes(nodes, pepper=PEPPER.encode(), ctx=self.ctx, timeout=1000) for ip, vk in responses.items(): self.peer_service.table[vk] = struct.strip_service( ip) # Should be stripped of port and tcp self.log.error(f'Added {struct.strip_service(ip)} for {vk}') #if not self.discovery_server.running: # asyncio.ensure_future(self.discovery_server.serve()) # Ping everyone discovered that you've joined current_nodes = deepcopy(self.peer_service.table) for vk, ip in current_nodes.items(): join_message = [ 'join', (self.wallet.verifying_key().hex(), self.ip) ] join_message = json.dumps(join_message, cls=struct.SocketEncoder).encode() peer = self.params.resolve(ip, service_type=ServiceType.PEER) self.log.error(peer) await services.get(peer, msg=join_message, ctx=self.ctx, timeout=1000)
def test_peer_table_updated_on_join_command(self): # Network params issue w1 = Wallet() p1 = Network(wallet=w1, socket_base='tcp://127.0.0.1', ctx=self.ctx) w2 = Wallet() d = DiscoveryServer(wallet=w2, socket_id=_socket('tcp://127.0.0.1:19000'), pepper=PEPPER.encode(), ctx=self.ctx, linger=200) # 1. start network # 2. start discovery of other side # 3. send join request # 4. check to see if the data has been added join_message = ['join', (w2.verifying_key().hex(), 'tcp://127.0.0.1')] join_message = json.dumps(join_message).encode() tasks = asyncio.gather( p1.peer_service.serve(), d.serve(), services.get(_socket('tcp://127.0.0.1:10002'), msg=join_message, ctx=self.ctx, timeout=1000), stop_server(p1.peer_service, 0.3), stop_server(d, 0.3)) loop = asyncio.get_event_loop() loop.run_until_complete(tasks) self.assertEqual(p1.peer_service.table[w2.verifying_key().hex()], 'tcp://127.0.0.1')
def test_event_service_triggered_when_new_node_added_ipc(self): # Create Network service w1 = Wallet() p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp') n1 = '/tmp/n1' try: os.mkdir('/tmp/n1') except: pass # Create Discovery Server w2 = Wallet() d = DiscoveryServer(wallet=w2, socket_id=_socket('ipc:///tmp/n1/discovery'), pepper=PEPPER.encode(), ctx=self.ctx, poll_timeout=2000, linger=200) # Create raw subscriber subscriber = self.ctx.socket(zmq.SUB) subscriber.setsockopt(zmq.SUBSCRIBE, b'') subscriber.connect('ipc:///tmp/events') # TCP takes a bit longer to bind and is prone to dropping messages... sleep(0.3) # Construct the join RPC message join_message = ['join', (w2.verifying_key().hex(), 'ipc:///tmp/n1')] join_message = json.dumps(join_message).encode() # Wrap recv() in an async async def recv(): msg = await subscriber.recv() return msg tasks = asyncio.gather( p1.peer_service.start( ), # Start the PeerService which will process RPC and emit events d.serve( ), # Start Discovery so PeerService can verify they are online services.get(_socket('ipc:///tmp/peers'), msg=join_message, ctx=self.ctx, timeout=3000), # Push out a join request stop_server(p1.peer_service, 1), stop_server(d, 1), recv() # Collect the subscription result ) loop = asyncio.get_event_loop() res = loop.run_until_complete(tasks) expected_list = ['join', [w2.verifying_key().hex(), 'ipc:///tmp/n1']] got_list = json.loads(res[-1].decode()) self.assertListEqual(expected_list, got_list)
def test_other_peers_add_new_nodes_when_join_event_occurs_ipc(self): # N3 runs discovery server and pings N1 # N1 checks to see if N3 is valid, and if so, adds to their table and pings N2 about the new join # Create Network service w1 = Wallet() p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp/n1') # Create Network service w2 = Wallet() p2 = Network(wallet=w2, ctx=self.ctx, socket_base='ipc:///tmp/n2') p2.peer_service.event_service.add_subscription( _socket('ipc:///tmp/n1/events')) # Create Discovery Server w3 = Wallet() d = DiscoveryServer(wallet=w3, socket_id=_socket('ipc:///tmp/n3/discovery'), pepper=PEPPER.encode(), ctx=self.ctx, poll_timeout=2000, linger=2000) # TCP takes a bit longer to bind and is prone to dropping messages... sleep(1) # Construct the join RPC message join_message = ['join', (w3.verifying_key().hex(), 'ipc:///tmp/n3')] join_message = json.dumps(join_message).encode() tasks = asyncio.gather( p1.peer_service.start(), p2.peer_service.start(), d.serve(), services.get(_socket('ipc:///tmp/n1/peers'), msg=join_message, ctx=self.ctx, timeout=1000), stop_server(p1.peer_service, 2), stop_server(p2.peer_service, 2), stop_server(d, 2), ) loop = asyncio.get_event_loop() loop.run_until_complete(tasks) self.assertTrue(w3.verifying_key().hex() in p2.peer_service.table)
def __init__(self, wallet, params=NetworkParameters(), ctx=zmq.asyncio.Context(), bootnodes=[], initial_mn_quorum=1, initial_del_quorum=1, mn_to_find=[], del_to_find=[], socket_base='tcp://0.0.0.0', poll_timeout=200, linger=1000, debug=True, mn_seed=None): self.log = get_logger('NetworkService') self.log.propagate = debug self.mn_seed = mn_seed # Set this to a single masternode if you are joining the network!! # General Instance Variables self.wallet = wallet self.ctx = ctx self.bootnodes = bootnodes self.ip = socket_base # Peer Service Constants self.params = params self.socket_base = socket_base self.peer_service_address = self.params.resolve(socket_base, ServiceType.PEER, bind=True) self.event_server_address = self.params.resolve(socket_base, ServiceType.EVENT, bind=True) self.peer_service = PeerServer( self.peer_service_address, event_address=self.event_server_address, table={self.wallet.verifying_key().hex(): socket_base}, wallet=self.wallet, ctx=self.ctx, poll_timeout=poll_timeout, linger=linger) self.discovery_server_address = self.params.resolve( self.socket_base, ServiceType.DISCOVERY, bind=True) self.discovery_server = discovery.DiscoveryServer( pepper=PEPPER.encode(), socket_id=self.discovery_server_address, wallet=self.wallet, ctx=self.ctx, poll_timeout=poll_timeout, linger=linger) # Quorum Constants self.initial_mn_quorum = initial_mn_quorum self.initial_del_quorum = initial_del_quorum self.mn_to_find = mn_to_find self.del_to_find = del_to_find self.ready = False self.outbox = services.Outbox(self.ctx)