示例#1
0
    def test_current_contacts_joins_mn_seed_adds_table_to_joiner(self):
        n1 = '/tmp/n1'
        make_ipc(n1)

        mnw1 = Wallet()
        mn1 = Network(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}')

        mn1.peer_service.table = {'a': 'b', 'c': 'd', 'e': 'f'}

        mnw2 = Wallet()
        n2 = '/tmp/n2'
        make_ipc(n2)
        mn2 = Network(wallet=mnw2,
                      ctx=self.ctx,
                      socket_base=f'ipc://{n2}',
                      mn_seed='ipc:///tmp/n1')

        tasks = asyncio.gather(mn1.peer_service.start(),
                               mn2.discovery_server.serve(),
                               stop_server(mn2.discovery_server, 0.3),
                               stop_server(mn1.peer_service, 0.3),
                               mn2.get_current_contacts())

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)

        self.assertDictEqual(mn1.peer_service.table, mn2.peer_service.table)
示例#2
0
    def test_start_and_stopping_destroys_servers(self):
        # Create Network service
        w1 = Wallet()
        n1 = NetworkParameters(peer_port=10001, event_port=10002)
        p1 = Network(wallet=w1,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n1)

        # Create Network service
        w2 = Wallet()
        n2 = NetworkParameters(peer_port=10003, event_port=10004)
        p2 = Network(wallet=w2,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n2)

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        tasks = asyncio.gather(p1.peer_service.start(),
                               p2.peer_service.start(), stop(p1, 0.3),
                               stop(p2, 0.3))

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)
示例#3
0
    def test_start_and_stopping_destroys_servers_ipc(self):
        # Create Network service
        w1 = Wallet()
        n1 = NetworkParameters(peer_ipc='peers1',
                               event_ipc='events1',
                               discovery_ipc='discovery1')
        p1 = Network(wallet=w1,
                     ctx=self.ctx,
                     socket_base='ipc:///tmp',
                     params=n1)

        # Create Network service
        w2 = Wallet()
        n2 = NetworkParameters(peer_ipc='peers2', event_port='events2')
        p2 = Network(wallet=w2,
                     ctx=self.ctx,
                     socket_base='ipc:///tmp',
                     params=n2)

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        tasks = asyncio.gather(p1.peer_service.start(),
                               p2.peer_service.start(), stop(p1, 0.3),
                               stop(p2, 0.3))

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)
示例#4
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)
    def test_get_sockets_with_service(self):
        constitution = self.get_vkbook_args()
        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=self.client)
        sync.submit_node_election_contracts(
            initial_masternodes=constitution['masternodes'],
            boot_mns=constitution['masternode_min_quorum'],
            initial_delegates=constitution['delegates'],
            boot_dels=constitution['delegate_min_quorum'],
            client=self.client)

        PhoneBook = VKBook(client=self.client)

        w1 = Wallet()

        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1')

        # 'tcp://127.0.0.1:10003'

        raw = {'stu': 'tcp://127.0.0.1', 'raghu': 'tcp://127.0.0.2'}
        p1.peer_service.table = raw

        expected = {
            'stu': _socket('tcp://127.0.0.1:19003'),
            'raghu': _socket('tcp://127.0.0.2:19003')
        }

        # CHANGE CLIENT TO SOCKET
        masternodes = Parameters(socket_base='tcp://127.0.0.1',
                                 wallet=w1,
                                 contacts=MockContacts(['stu'],
                                                       delegates=['raghu']),
                                 ctx=self.ctx)

        self.assertDictEqual(masternodes.sockets, {})

        async def late_refresh():
            await asyncio.sleep(0.3)
            await masternodes.refresh()

        async def stop():
            await asyncio.sleep(0.5)
            p1.stop()

        tasks = asyncio.gather(p1.start(discover=False), late_refresh(),
                               stop())

        self.loop.run_until_complete(tasks)

        self.assertEqual(
            masternodes.get_all_sockets(service=ServiceType.EVENT), expected)
示例#6
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)
示例#7
0
    def test_ask_returns_table(self):
        n1 = '/tmp/n1'
        make_ipc(n1)

        mnw1 = Wallet()
        mn1 = Network(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}')

        mn1.peer_service.table = {'a': 'b', 'c': 'd', 'e': 'f'}

        ask_message = ['ask', '']
        ask_message = json.dumps(ask_message).encode()

        async def get():
            return await services.get(_socket('ipc:///tmp/n1/peers'),
                                      msg=ask_message,
                                      ctx=self.ctx,
                                      timeout=500)

        tasks = asyncio.gather(mn1.peer_service.start(),
                               stop_server(mn1.peer_service, 0.3), get())

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        self.assertDictEqual(json.loads(res[-1]), mn1.peer_service.table)
示例#8
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')
示例#9
0
    def test_peer_server_returns_all_peers_if_doesnt_have_it_or_more_than_response_amount_ipc(
            self):
        w1 = Wallet()
        p1 = Network(wallet=w1, socket_base='ipc:///tmp', ctx=self.ctx)

        test_dict = {'test': 'value', 'another': 'one', 'something': 'else'}

        p1.peer_service.table = test_dict

        find_message = ['find', 'baloney']
        find_message = json.dumps(find_message).encode()

        tasks = asyncio.gather(
            p1.peer_service.serve(), stop_server(p1.peer_service, 0.3),
            services.get(_socket('ipc:///tmp/peers'),
                         msg=find_message,
                         ctx=self.ctx,
                         timeout=300))

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        response = res[-1]
        response = response.decode()
        response = json.loads(response)

        self.assertDictEqual(test_dict, response)
示例#10
0
    def test_peer_server_returns_peer_when_asked_ipc(self):
        w1 = Wallet()
        p1 = Network(wallet=w1, socket_base='ipc:///tmp', ctx=self.ctx)

        w2 = Wallet()

        p1.peer_service.table[w2.verifying_key().hex()] = 'inproc://goodtimes'

        find_message = ['find', w2.verifying_key().hex()]
        find_message = json.dumps(find_message).encode()

        tasks = asyncio.gather(
            p1.peer_service.serve(), stop_server(p1.peer_service, 0.3),
            services.get(_socket('ipc:///tmp/peers'),
                         msg=find_message,
                         ctx=self.ctx,
                         timeout=300))

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        response = res[-1]
        response = response.decode()
        response = json.loads(response)

        self.assertEqual(response.get(w2.verifying_key().hex()),
                         'inproc://goodtimes')
示例#11
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)
示例#12
0
    def test_find_node_requests_from_others_and_returns_key_if_they_have_it_ipc(
            self):
        # Create Network service
        w1 = Wallet()
        n1 = NetworkParameters(peer_ipc='peers1',
                               event_ipc='events1',
                               discovery_ipc='discovery1')
        p1 = Network(wallet=w1,
                     ctx=self.ctx,
                     socket_base='ipc:///tmp',
                     params=n1)

        # Create Network service
        w2 = Wallet()
        n2 = NetworkParameters(peer_ipc='peers2', event_port='events2')
        p2 = Network(wallet=w2,
                     ctx=self.ctx,
                     socket_base='ipc:///tmp',
                     params=n2)

        async def get():
            return await p1.find_node(_socket('ipc:///tmp/peers2'),
                                      w2.verifying_key().hex())

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        tasks = asyncio.gather(
            p1.peer_service.start(),
            p2.peer_service.start(),
            get(),
            stop(p1, 0.3),
            stop(p2, 0.3),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        self.assertEqual(res[2].get(w2.verifying_key().hex()), 'ipc:///tmp')
示例#13
0
    def test_find_node_fails_if_cant_find_and_retries_are_up(self):
        # Create Network service
        w1 = Wallet()
        n1 = NetworkParameters(peer_port=10001, event_port=10002)
        p1 = Network(wallet=w1,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n1)

        # Create Network service
        w2 = Wallet()
        n2 = NetworkParameters(peer_port=10003, event_port=10004)
        p2 = Network(wallet=w2,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n2)

        w3 = Wallet()

        async def get():
            return await p1.find_node(_socket('tcp://127.0.0.1:10003'),
                                      w3.verifying_key().hex(),
                                      retries=1)

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        tasks = asyncio.gather(
            p1.peer_service.start(),
            p2.peer_service.start(),
            get(),
            stop(p1, 0.3),
            stop(p2, 0.3),
        )

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        self.assertIsNone(res[2])
示例#14
0
    def test_contacts_added_if_network_starts_up_and_mn_seed_provided(self):
        n1 = '/tmp/n1'
        make_ipc(n1)

        mnw1 = Wallet()
        mn1 = Network(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}')

        mn1.peer_service.table = {'a': 'b', 'c': 'd', 'e': 'f'}

        mnw2 = Wallet()
        n2 = '/tmp/n2'
        make_ipc(n2)
        mn2 = Network(wallet=mnw2,
                      ctx=self.ctx,
                      socket_base=f'ipc://{n2}',
                      mn_seed='ipc:///tmp/n1')

        tasks = asyncio.gather(mn1.peer_service.start(), mn2.start(),
                               stop_server(mn1.peer_service, 1))

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)
示例#15
0
    def test_find_node_returns_self_if_asked_on_peer_address_and_self_is_the_value_ipc(
            self):
        # Create Network service
        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp')

        async def get():
            return await p1.find_node(p1.peer_service_address,
                                      w1.verifying_key().hex())

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(get())

        self.assertEqual(res.get(w1.verifying_key().hex()), 'ipc:///tmp')
示例#16
0
    def test_find_node_gets_node_from_self_if_asked_from_self_and_has_it_as_peer_ipc(
            self):
        # Create Network service
        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp')

        w2 = Wallet()
        p1.peer_service.table[w2.verifying_key().hex()] = 'ipc:///tmp123'

        async def get():
            return await p1.find_node(p1.peer_service_address,
                                      w2.verifying_key().hex())

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(get())

        self.assertEqual(res.get(w2.verifying_key().hex()), 'ipc:///tmp123')
示例#17
0
    def test_peer_server_returns_self_when_asked(self):
        w1 = Wallet()
        p1 = Network(wallet=w1, socket_base='tcp://127.0.0.1', ctx=self.ctx)

        find_message = ['find', w1.verifying_key().hex()]
        find_message = json.dumps(find_message).encode()

        tasks = asyncio.gather(
            p1.peer_service.serve(), stop_server(p1.peer_service, 0.3),
            services.get(_socket('tcp://127.0.0.1:19002'),
                         msg=find_message,
                         ctx=self.ctx,
                         timeout=300))

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        response = res[-1]
        response = response.decode()
        response = json.loads(response)

        self.assertEqual(response.get(w1.verifying_key().hex()),
                         'tcp://127.0.0.1')
示例#18
0
    def test_event_service_publisher_starts_up_on_init_ipc(self):
        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='ipc:///tmp')

        test_subscriber = self.ctx.socket(zmq.SUB)
        test_subscriber.setsockopt(zmq.SUBSCRIBE, b'')
        test_subscriber.connect('ipc:///tmp/events')

        # TCP takes a bit longer to bind and is prone to dropping messages...
        sleep(0.1)

        async def send():
            await p1.peer_service.event_publisher.send(b'waaaa')

        async def recv():
            return await test_subscriber.recv()

        tasks = asyncio.gather(send(), recv(),
                               stop_server(p1.peer_service, 0.1))

        loop = asyncio.get_event_loop()
        res = loop.run_until_complete(tasks)

        self.assertEqual(res[1], b'waaaa')
示例#19
0
    def test_refresh_remove_old_nodes(self):
        vkbook_args = self.get_vkbook_args()
        sync.submit_vkbook(vkbook_args, overwrite=True)

        PhoneBook = VKBook()

        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1')

        peeps = {
            'stu': 'tcp://127.0.0.1',
            'raghu': 'tcp://127.0.0.8',
            'tejas': 'tcp://127.0.2.1',
            'steve': 'tcp://127.0.54.6'
        }

        p1.peer_service.table.peers = peeps

        ctx2 = zmq.asyncio.Context()

        masternodes = SocketBook(
            socket_base='tcp://127.0.0.1',
            service_type=ServiceType.EVENT,
            ctx=ctx2,
            phonebook_function=PhoneBook.contract.get_masternodes)

        self.assertDictEqual(masternodes.sockets, {})

        async def late_refresh():
            await asyncio.sleep(0.3)
            await masternodes.refresh()

        async def stop():
            await asyncio.sleep(0.5)
            p1.stop()

        tasks = asyncio.gather(p1.start(discover=False), late_refresh(),
                               stop())

        self.loop.run_until_complete(tasks)

        expected = {
            'stu': _socket('tcp://127.0.0.1:{}'.format(EVENT_PORT)),
            'raghu': _socket('tcp://127.0.0.8:{}'.format(EVENT_PORT))
        }

        self.assertDictEqual(masternodes.sockets, expected)

        self.ctx.destroy()
        self.loop.close()

        self.ctx = zmq.asyncio.Context()
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1')

        peeps = {
            'stu': 'tcp://127.0.2.1',
            'raghu': 'tcp://127.0.0.8',
            'tejas': 'tcp://127.0.2.1',
            'steve': 'tcp://127.0.54.6'
        }

        p1.peer_service.table.peers = peeps

        vkbook_args = self.get_vkbook_args(mns=['stu', 'tejas'])
        sync.submit_vkbook(vkbook_args, overwrite=True)

        async def late_refresh():
            await asyncio.sleep(0.3)
            await masternodes.refresh()

        async def stop():
            await asyncio.sleep(1)
            p1.stop()

        tasks = asyncio.gather(p1.start(discover=False), late_refresh(),
                               stop())

        self.loop.run_until_complete(tasks)

        expected = {
            'stu': _socket('tcp://127.0.2.1:{}'.format(EVENT_PORT)),
            'tejas': _socket('tcp://127.0.2.1:{}'.format(EVENT_PORT)),
        }

        self.assertDictEqual(masternodes.sockets, expected)
示例#20
0
    def __init__(self,
                 socket_base,
                 ctx: zmq.asyncio.Context,
                 wallet,
                 constitution: dict,
                 overwrite=False,
                 bootnodes=[],
                 network_parameters=NetworkParameters(),
                 driver=BlockchainDriver(),
                 mn_seed=None,
                 debug=True,
                 store=False):

        self.driver = driver
        self.store = store

        self.blocks = None
        if self.store:
            self.blocks = MasterStorage()

        self.waiting_for_confirmation = False

        self.log = get_logger('NODE')
        self.log.propagate = debug
        self.log.info(constitution)
        self.socket_base = socket_base
        self.wallet = wallet
        self.ctx = ctx
        self.ctx.max_sockets = 50_000

        self.client = ContractingClient(
            driver=self.driver,
            submission_filename=cilantro_ee.contracts.__path__[0] +
            '/submission.s.py')

        # Sync contracts

        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=self.client)
        sync.submit_node_election_contracts(
            initial_masternodes=constitution['masternodes'],
            boot_mns=constitution['masternode_min_quorum'],
            initial_delegates=constitution['delegates'],
            boot_dels=constitution['delegate_min_quorum'],
            client=self.client)

        self.driver.commit()
        self.driver.clear_pending_state()

        self.contacts = VKBook(
            client=self.client,
            boot_mn=constitution['masternode_min_quorum'],
            boot_del=constitution['delegate_min_quorum'],
        )

        self.current_masters = deepcopy(self.contacts.masternodes)
        self.current_delegates = deepcopy(self.contacts.delegates)

        self.parameters = Parameters(socket_base,
                                     ctx,
                                     wallet,
                                     contacts=self.contacts)

        self.socket_authenticator = SocketAuthenticator(ctx=self.ctx)

        self.elect_masternodes = self.client.get_contract('elect_masternodes')
        self.elect_delegates = self.client.get_contract('elect_delegates')

        self.masternode_contract = self.client.get_contract('masternodes')
        self.delegate_contract = self.client.get_contract('delegates')

        self.update_sockets()

        # Cilantro version / upgrade

        self.version_state = self.client.get_contract('upgrade')
        self.active_upgrade = self.version_state.quick_read('upg_lock')

        self.tol_mn = self.version_state.quick_read('tol_mn')
        self.tot_dl = self.version_state.quick_read('tot_dl')

        if self.tol_mn is None:
            self.tol_mn = 0

        if self.tot_dl is None:
            self.tot_dl = 0

        self.all_votes = self.tol_mn + self.tot_dl
        self.mn_votes = self.version_state.quick_read('mn_vote')
        self.dl_votes = self.version_state.quick_read('dl_vote')
        # self.pending_cnt = self.all_votes - self.vote_cnt
        # stuff

        self.network_parameters = network_parameters

        self.bootnodes = bootnodes
        self.constitution = constitution
        self.overwrite = overwrite

        # Should have a function to get the current NBN
        self.block_fetcher = BlockFetcher(
            wallet=self.wallet,
            ctx=self.ctx,
            parameters=self.parameters,
        )

        self.network = Network(
            wallet=self.wallet,
            ctx=self.ctx,
            socket_base=socket_base,
            bootnodes=self.bootnodes,
            params=self.network_parameters,
            initial_del_quorum=deepcopy(self.contacts.delegate_quorum_min),
            initial_mn_quorum=deepcopy(self.contacts.masternode_quorum_min),
            mn_to_find=deepcopy(self.contacts.masternodes),
            del_to_find=deepcopy(self.contacts.delegates),
            mn_seed=mn_seed)

        self.nbn_inbox = NBNInbox(socket_id=self.network_parameters.resolve(
            self.socket_base,
            service_type=ServiceType.BLOCK_NOTIFICATIONS,
            bind=True),
                                  ctx=self.ctx,
                                  driver=self.driver,
                                  contacts=self.contacts,
                                  wallet=wallet)

        self.reward_manager = RewardManager(driver=self.driver, debug=True)

        self.running = False
示例#21
0
class Node:
    def __init__(self,
                 socket_base,
                 ctx: zmq.asyncio.Context,
                 wallet,
                 constitution: dict,
                 overwrite=False,
                 bootnodes=[],
                 network_parameters=NetworkParameters(),
                 driver=BlockchainDriver(),
                 mn_seed=None,
                 debug=True,
                 store=False):

        self.driver = driver
        self.store = store

        self.blocks = None
        if self.store:
            self.blocks = MasterStorage()

        self.waiting_for_confirmation = False

        self.log = get_logger('NODE')
        self.log.propagate = debug
        self.log.info(constitution)
        self.socket_base = socket_base
        self.wallet = wallet
        self.ctx = ctx
        self.ctx.max_sockets = 50_000

        self.client = ContractingClient(
            driver=self.driver,
            submission_filename=cilantro_ee.contracts.__path__[0] +
            '/submission.s.py')

        # Sync contracts

        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=self.client)
        sync.submit_node_election_contracts(
            initial_masternodes=constitution['masternodes'],
            boot_mns=constitution['masternode_min_quorum'],
            initial_delegates=constitution['delegates'],
            boot_dels=constitution['delegate_min_quorum'],
            client=self.client)

        self.driver.commit()
        self.driver.clear_pending_state()

        self.contacts = VKBook(
            client=self.client,
            boot_mn=constitution['masternode_min_quorum'],
            boot_del=constitution['delegate_min_quorum'],
        )

        self.current_masters = deepcopy(self.contacts.masternodes)
        self.current_delegates = deepcopy(self.contacts.delegates)

        self.parameters = Parameters(socket_base,
                                     ctx,
                                     wallet,
                                     contacts=self.contacts)

        self.socket_authenticator = SocketAuthenticator(ctx=self.ctx)

        self.elect_masternodes = self.client.get_contract('elect_masternodes')
        self.elect_delegates = self.client.get_contract('elect_delegates')

        self.masternode_contract = self.client.get_contract('masternodes')
        self.delegate_contract = self.client.get_contract('delegates')

        self.update_sockets()

        # Cilantro version / upgrade

        self.version_state = self.client.get_contract('upgrade')
        self.active_upgrade = self.version_state.quick_read('upg_lock')

        self.tol_mn = self.version_state.quick_read('tol_mn')
        self.tot_dl = self.version_state.quick_read('tot_dl')

        if self.tol_mn is None:
            self.tol_mn = 0

        if self.tot_dl is None:
            self.tot_dl = 0

        self.all_votes = self.tol_mn + self.tot_dl
        self.mn_votes = self.version_state.quick_read('mn_vote')
        self.dl_votes = self.version_state.quick_read('dl_vote')
        # self.pending_cnt = self.all_votes - self.vote_cnt
        # stuff

        self.network_parameters = network_parameters

        self.bootnodes = bootnodes
        self.constitution = constitution
        self.overwrite = overwrite

        # Should have a function to get the current NBN
        self.block_fetcher = BlockFetcher(
            wallet=self.wallet,
            ctx=self.ctx,
            parameters=self.parameters,
        )

        self.network = Network(
            wallet=self.wallet,
            ctx=self.ctx,
            socket_base=socket_base,
            bootnodes=self.bootnodes,
            params=self.network_parameters,
            initial_del_quorum=deepcopy(self.contacts.delegate_quorum_min),
            initial_mn_quorum=deepcopy(self.contacts.masternode_quorum_min),
            mn_to_find=deepcopy(self.contacts.masternodes),
            del_to_find=deepcopy(self.contacts.delegates),
            mn_seed=mn_seed)

        self.nbn_inbox = NBNInbox(socket_id=self.network_parameters.resolve(
            self.socket_base,
            service_type=ServiceType.BLOCK_NOTIFICATIONS,
            bind=True),
                                  ctx=self.ctx,
                                  driver=self.driver,
                                  contacts=self.contacts,
                                  wallet=wallet)

        self.reward_manager = RewardManager(driver=self.driver, debug=True)

        self.running = False

    async def catchup(self, mn_seed):
        current = self.driver.get_latest_block_num()
        latest = await self.block_fetcher.get_latest_block_height(mn_seed)

        if current == 0:
            current = 1

        for i in range(current, latest):
            block = await self.block_fetcher.get_block_from_master(i, mn_seed)
            block = block.to_dict()
            self.process_block(block)

        while len(self.nbn_inbox.q) > 0:
            block = self.nbn_inbox.q.pop(0)
            self.process_block(block)

    def should_process(self, block):
        if self.waiting_for_confirmation:
            return self.driver.latest_block_num <= block['blockNum'] and block[
                'hash'] != 'f' * 64
        else:
            return self.driver.latest_block_num < block['blockNum'] and block[
                'hash'] != 'f' * 64

    def process_block(self, block):
        # self.driver.reads.clear()
        # self.driver.cache.clear()
        #
        # self.log.info(f'PENDING WRITES :{self.driver.pending_writes}')
        # self.driver.pending_writes.clear()

        if self.should_process(block):
            self.log.info('Processing new block...')
            self.driver.update_with_block(block)
            self.reward_manager.issue_rewards(block=block)
            self.update_sockets()

            if self.store:
                self.blocks.store_block(block)
                #self.reward_manager.issue_rewards(block=block)
                #self.update_sockets()
        else:
            self.log.error('Could not store block...')
            if self.driver.latest_block_num >= block['blockNum']:
                self.log.error(
                    f'Latest block num = {self.driver.latest_block_num}')
                self.log.error(f'New block num = {block["blockNum"]}')
            if block['hash'] == 'f' * 64:
                self.log.error(f'Block hash = {block["hash"]}')
            self.driver.delete_pending_nonces()

        self.driver.cache.clear()
        self.nbn_inbox.clean()
        self.nbn_inbox.update_signers()

        self.version_check()

    async def start(self):
        await self.network.start()

        # Start block server
        asyncio.ensure_future(self.nbn_inbox.serve())

        # Catchup when joining the network
        if self.network.mn_seed is not None:
            await self.catchup(
                self.network_parameters.resolve(self.network.mn_seed,
                                                ServiceType.BLOCK_SERVER))

            self.log.info(self.network.peers())

            self.parameters.sockets.update(self.network.peers())

        # Start block server
        #asyncio.ensure_future(self.nbn_inbox.serve())

        self.running = True

    def stop(self):
        self.network.stop()
        self.nbn_inbox.stop()
        self.running = False

    def update_sockets(self):
        od_mn = self.elect_masternodes.quick_read('top_candidate')
        od_dl = self.elect_delegates.quick_read('top_candidate')

        masternodes = self.masternode_contract.quick_read('S', 'members')
        delegates = self.delegate_contract.quick_read('S', 'members')

        self.socket_authenticator.add_governance_sockets(
            masternode_list=masternodes,
            delegate_list=delegates,
            on_deck_masternode=od_mn,
            on_deck_delegate=od_dl)

    def version_check(self):

        # check for trigger
        self.version_state = self.client.get_contract('upgrade')
        self.mn_votes = self.version_state.quick_read('mn_vote')
        self.dl_votes = self.version_state.quick_read('dl_vote')

        if self.version_state:
            self.log.info('Waiting for Consensys on vote')
            self.log.info('num masters voted -> {}'.format(self.mn_votes))
            self.log.info('num delegates voted -> {}'.format(self.dl_votes))

            # Given node is either master or delegate default assumes it to be valid
            # delegate

            node_type = False

            for key in self.contacts.masternodes:
                if self.wallet.verifying_key().hex() == key:
                    self.log.info("Node Type : Master")
                    node_type = True

            # check for vote consensys
            vote_consensus = self.version_state.quick_read('upg_consensus')
            if vote_consensus:
                self.log.error('Rebooting Node with new version')
                version_reboot(bn=self.bootnodes, is_master=node_type)
            else:
                self.log.info(
                    '{} waiting for vote on upgrade'.format(node_type))

    def get_update_state(self):
        self.active_upgrade = self.version_state.quick_read('upg_lock')
        start_time = self.version_state.quick_read('upg_init_time')
        window = self.version_state.quick_read('upg_window')
        pepper = self.version_state.quick_read('upg_pepper')
        self.mn_votes = self.version_state.quick_read('mn_vote')
        self.dl_votes = self.version_state.quick_read('dl_vote')
        consensus = self.version_state.quick_read('upg_consensus')

        print("Upgrade -> {} Cil Pepper   -> {}\n"
              "Init time -> {}, Time Window -> {}\n"
              "Masters      -> {}\n"
              "Delegates    -> {}\n"
              "Votes        -> {}\n "
              "MN-Votes     -> {}\n "
              "DL-Votes     -> {}\n "
              "Consensus    -> {}\n".format(self.active_upgrade, pepper,
                                            start_time, window, self.tol_mn,
                                            self.tot_dl, self.all_votes,
                                            self.mn_votes, self.dl_votes,
                                            consensus))
    def test_refresh_remove_old_nodes(self):
        constitution = self.get_vkbook_args()
        sync.submit_from_genesis_json_file(cilantro_ee.contracts.__path__[0] +
                                           '/genesis.json',
                                           client=self.client)
        sync.submit_node_election_contracts(
            initial_masternodes=constitution['masternodes'],
            boot_mns=constitution['masternode_min_quorum'],
            initial_delegates=constitution['delegates'],
            boot_dels=constitution['delegate_min_quorum'],
            client=self.client)

        PhoneBook = VKBook(client=self.client)

        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1')

        peeps = {
            'stu': 'tcp://127.0.0.1',
            'raghu': 'tcp://127.0.0.8',
            'tejas': 'tcp://127.0.2.1',
            'steve': 'tcp://127.0.54.6'
        }

        p1.peer_service.table = peeps

        ctx2 = zmq.asyncio.Context()

        masternodes = Parameters(socket_base='tcp://127.0.0.1',
                                 wallet=w1,
                                 contacts=MockContacts(['stu', 'raghu'],
                                                       ['tejas', 'steve']),
                                 ctx=ctx2)

        self.assertDictEqual(masternodes.sockets, {})

        async def late_refresh():
            await asyncio.sleep(0.3)
            await masternodes.refresh()

        async def stop():
            await asyncio.sleep(0.5)
            p1.stop()

        tasks = asyncio.gather(p1.start(discover=False), late_refresh(),
                               stop())

        self.loop.run_until_complete(tasks)

        expected = {'stu': 'tcp://127.0.0.1', 'raghu': 'tcp://127.0.0.8'}

        self.assertDictEqual(masternodes.sockets, expected)

        self.ctx.destroy()
        self.loop.close()

        self.ctx = zmq.asyncio.Context()
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        w1 = Wallet()
        p1 = Network(wallet=w1, ctx=self.ctx, socket_base='tcp://127.0.0.1')

        peeps = {
            'stu': 'tcp://127.0.2.1',
            'raghu': 'tcp://127.0.0.8',
            'tejas': 'tcp://127.0.2.1',
            'steve': 'tcp://127.0.54.6'
        }

        p1.peer_service.table.peers = peeps

        vkbook_args = self.get_vkbook_args(mns=['stu', 'tejas'])
        sync.submit_vkbook(vkbook_args, overwrite=True)

        async def late_refresh():
            await asyncio.sleep(0.3)
            await masternodes.refresh()

        async def stop():
            await asyncio.sleep(1)
            p1.stop()

        tasks = asyncio.gather(p1.start(discover=False), late_refresh(),
                               stop())

        self.loop.run_until_complete(tasks)

        expected = {
            'stu': 'tcp://127.0.2.1',
            'tejas': 'tcp://127.0.2.1',
        }

        self.assertDictEqual(masternodes.sockets, expected)
    def test_network_start(self):
        # 4 nodes
        # 2 bootnodes
        # 2 mns, 2 delegates

        bootnodes = ['ipc:///tmp/n1', 'ipc:///tmp/n3']

        mnw1 = Wallet()
        mnw2 = Wallet()
        masternodes = [mnw1.verifying_key().hex(), mnw2.verifying_key().hex()]

        dw1 = Wallet()
        dw2 = Wallet()
        delegates = [dw1.verifying_key().hex(), dw2.verifying_key().hex()]

        constitution = {
            "masternodes": [
                    mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()
                ],
            "masternode_min_quorum": 1,
            "delegates": [
                    dw1.verifying_key().hex(),
                    dw2.verifying_key().hex()
                ],
            "delegate_min_quorum": 1,
            "witnesses": {},
            "schedulers": {},
            "notifiers": {},
            "enable_stamps": False,
            "enable_nonces": False
        }

        n1 = '/tmp/n1'
        make_ipc(n1)
        mn1 = Masternode(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}', bootnodes=bootnodes,
                         constitution=constitution, webserver_port=8080)

        n2 = '/tmp/n2'
        make_ipc(n2)
        mn2 = Masternode(wallet=mnw2, ctx=self.ctx, socket_base=f'ipc://{n2}', bootnodes=bootnodes,
                         constitution=constitution, webserver_port=8081)

        n3 = '/tmp/n3'
        make_ipc(n3)
        d1 = Network(wallet=dw1, ctx=self.ctx, socket_base=f'ipc://{n3}',
                     bootnodes=bootnodes, mn_to_find=masternodes, del_to_find=delegates)

        n4 = '/tmp/n4'
        make_ipc(n4)
        d2 = Network(wallet=dw2, ctx=self.ctx, socket_base=f'ipc://{n4}',
                     bootnodes=bootnodes, mn_to_find=masternodes, del_to_find=delegates)


        # should test to see all ready signals are recieved
        tasks = asyncio.gather(
            mn1.start(),
            mn2.start(),
            d1.start(),
            d2.start()
        )

        async def run():
            await tasks
            await asyncio.sleep(5)
            mn1.stop()
            mn2.stop()
            d1.stop()
            d2.stop()

        loop = asyncio.get_event_loop()
        loop.run_until_complete(run())
示例#24
0
    def test_wait_for_quorum_to_succeed_only_one_master_ipc(self):
        # 0 tries
        n1 = '/tmp/n1'
        try:
            os.mkdir('/tmp/n1')
        except:
            pass
        mnw1 = Wallet()
        mn1 = Network(wallet=mnw1, ctx=self.ctx, socket_base=f'ipc://{n1}')

        n2 = '/tmp/n2'
        try:
            os.mkdir('/tmp/n2')
        except:
            pass
        mnw2 = Wallet()
        mn2 = Network(wallet=mnw2, ctx=self.ctx, socket_base=f'ipc://{n2}')

        n3 = '/tmp/n3'
        try:
            os.mkdir('/tmp/n3')
        except:
            pass
        dw1 = Wallet()
        d1 = Network(wallet=dw1, ctx=self.ctx, socket_base=f'ipc://{n3}')

        n4 = '/tmp/n4'
        try:
            os.mkdir('/tmp/n4')
        except:
            pass
        dw2 = Wallet()
        d2 = Network(wallet=dw2, ctx=self.ctx, socket_base=f'ipc://{n4}')

        async def get():
            return await mn1.wait_for_quorum(
                1,
                0, [mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()],
                [dw1.verifying_key().hex(),
                 dw2.verifying_key().hex()],
                initial_peers=[_socket('ipc:///tmp/n2/peers')])

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        timeout = 0.3

        tasks = asyncio.gather(
            mn1.peer_service.start(),
            mn2.peer_service.start(),
            d1.peer_service.start(),
            d2.peer_service.start(),
            get(),
            stop(mn1, timeout),
            stop(mn2, timeout),
            stop(d1, timeout),
            stop(d1, timeout),
        )

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)

        self.assertIn(mnw2.verifying_key().hex(), mn1.peer_service.table)
示例#25
0
    def test_wait_for_quorum_to_succeed_only_one_master(self):
        # 0 tries
        mnw1 = Wallet()
        n1 = NetworkParameters(peer_port=10001, event_port=10002)
        mn1 = Network(wallet=mnw1,
                      ctx=self.ctx,
                      socket_base='tcp://127.0.0.1',
                      params=n1)

        # 1 try
        mnw2 = Wallet()
        n2 = NetworkParameters(peer_port=10003, event_port=10004)
        mn2 = Network(wallet=mnw2,
                      ctx=self.ctx,
                      socket_base='tcp://127.0.0.1',
                      params=n2)

        dw1 = Wallet()
        n3 = NetworkParameters(peer_port=10005, event_port=10006)
        d1 = Network(wallet=dw1,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n3)

        # 2 tries <- info in this node should be returned
        dw2 = Wallet()
        n4 = NetworkParameters(peer_port=10007, event_port=10008)
        d2 = Network(wallet=dw2,
                     ctx=self.ctx,
                     socket_base='tcp://127.0.0.1',
                     params=n4)

        async def get():
            return await mn1.wait_for_quorum(
                1,
                0, [mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()],
                [dw1.verifying_key().hex(),
                 dw2.verifying_key().hex()],
                initial_peers=[_socket('tcp://127.0.0.1:10003')])

        async def stop(n: Network, s):
            await asyncio.sleep(s)
            n.peer_service.stop()

        timeout = 0.3

        tasks = asyncio.gather(
            mn1.peer_service.start(),
            mn2.peer_service.start(),
            d1.peer_service.start(),
            d2.peer_service.start(),
            get(),
            stop(mn1, timeout),
            stop(mn2, timeout),
            stop(d1, timeout),
            stop(d1, timeout),
        )

        loop = asyncio.get_event_loop()
        loop.run_until_complete(tasks)

        self.assertIn(mnw2.verifying_key().hex(), mn1.peer_service.table)