Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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')
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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)