Пример #1
0
    def test_send_work_sends_tx_batch_properly(self):
        make_ipc('/tmp/n2')
        m = Masternode(wallet=mnw1,
                       ctx=self.ctx,
                       socket_base='ipc:///tmp/n2',
                       bootnodes=bootnodes,
                       constitution=constitution,
                       webserver_port=8080,
                       overwrite=True)

        d = MockDelegate(self.ctx)

        m.parameters.sockets = {dw1.verifying_key().hex(): 'ipc:///tmp/n1'}

        tasks = asyncio.gather(m.send_work(), d.recv_work())

        tx = make_tx(mnw1.verifying_key().hex(),
                     contract_name='howdy',
                     function_name='yoohoo')

        m.tx_batcher.queue.append(tx)

        _, msg = self.loop.run_until_complete(tasks)

        self.assertEqual(msg.transactions[0].to_dict(), tx.to_dict())
    def test_new_blockchain_boot_sends_genesis_block_if_tx_batch(self):
        m = Masternode(
            wallet=mnw1,
            ctx=self.ctx,
            socket_base='ipc:///tmp/n1',
            bootnodes=bootnodes,
            constitution=constitution,
            webserver_port=8080,
            overwrite=True
        )

        m.parameters.sockets = {
            dw1.verifying_key().hex(): 'ipc:///tmp/n2'
        }

        # For mocking
        async def add_tx_batch():
            m.tx_batcher.queue.append(b'123')

        async def recv_tx_batch():
            socket = self.ctx.socket(zmq.ROUTER)
            socket.bind('ipc:///tmp/n2/block_notifications')
            _id, msg = await socket.recv_multipart()
            return msg

        tasks = asyncio.gather(
            m.new_blockchain_boot(),
            add_tx_batch(),
            recv_tx_batch()
        )

        _, _, msg = self.loop.run_until_complete(tasks)

        self.assertEqual(msg, canonical.dict_to_msg_block(canonical.get_genesis_block()))
    def test_join_quorum_updates_with_block_if_nbn_has_block(self):
        m = Masternode(
            wallet=mnw1,
            ctx=self.ctx,
            socket_base='ipc:///tmp/n1',
            bootnodes=bootnodes,
            constitution=constitution,
            webserver_port=8080,
            overwrite=True
        )

        block = random_txs.random_block()

        m.nbn_inbox.q.append(block.to_dict())

        k = block.subBlocks[0].transactions[0].state[0].key
        v = block.subBlocks[0].transactions[0].state[0].value

        self.assertIsNone(m.client.raw_driver.get_direct(k))

        async def add_tx_queue():
            await asyncio.sleep(0.3)
            m.tx_batcher.queue.append(b'blah')
            m.nbn_inbox.q.append(block.to_dict())

        tasks = asyncio.gather(
            m.join_quorum(),
            add_tx_queue()
        )

        self.loop.run_until_complete(tasks)

        self.assertEqual(m.client.raw_driver.get_direct(k), v)
    def test_new_blockchain_boot_completes_if_nbn_inbox_recieved(self):
        m = Masternode(
            wallet=mnw1,
            ctx=self.ctx,
            socket_base='ipc:///tmp/n1',
            bootnodes=bootnodes,
            constitution=constitution,
            webserver_port=8080,
            overwrite=True
        )

        # For mocking
        m.nbn_inbox.verify = False

        async def send_nbn():
            await asyncio.sleep(0.3)
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('ipc:///tmp/n1/block_notifications')
            await socket.send(b'123')
            await asyncio.sleep(0.3)
            m.nbn_inbox.stop()

        tasks = asyncio.gather(
            m.nbn_inbox.serve(),
            m.new_blockchain_boot(),
            send_nbn()
        )

        self.loop.run_until_complete(tasks)
Пример #5
0
    def test_send_work_returns_none_if_no_one_online(self):
        m = Masternode(wallet=mnw1,
                       ctx=self.ctx,
                       socket_base='ipc:///tmp/n1',
                       bootnodes=bootnodes,
                       constitution=constitution,
                       webserver_port=8080,
                       overwrite=True)

        r = self.loop.run_until_complete(m.send_work())

        self.assertIsNone(r)
Пример #6
0
    def test_wait_for_work_does_not_block_if_skip_block_and_tx_batcher_not_empty(
            self):
        make_ipc('/tmp/n2')
        m = Masternode(wallet=mnw1,
                       ctx=self.ctx,
                       socket_base='ipc:///tmp/n2',
                       bootnodes=bootnodes,
                       constitution=constitution,
                       webserver_port=8080,
                       overwrite=True)

        skip = {'subBlocks': [{'transactions': []}]}

        m.tx_batcher.queue.append(b'work')

        async def wait_then_put_in_work():
            await asyncio.sleep(0.1)
            return time.time()

        async def wait_for_work_wrapped():
            await m.wait_for_work(skip)
            return time.time()

        tasks = asyncio.gather(wait_then_put_in_work(),
                               wait_for_work_wrapped())

        r, r2 = self.loop.run_until_complete(tasks)

        # Wait for work should finish after wait then put in work
        self.assertGreater(r, r2)
    def test_retreived_subblocks_serialize_to_block_properly_single_block(self):
        bootnodes = ['ipc:///tmp/n2', 'ipc:///tmp/n3']

        mnw1 = Wallet()

        dw1 = Wallet()

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

        n1 = '/tmp/n1'
        make_ipc(n1)

        m = Masternode(
            wallet=mnw1,
            ctx=self.ctx,
            socket_base=f'ipc://{n1}',
            bootnodes=bootnodes,
            constitution=constitution,
            webserver_port=8080,
            overwrite=True
        )

        input_hash = secrets.token_bytes(32)
        sbc = random_txs.sbc_from_txs(input_hash, b'\x00' * 32, w=dw1, idx=0, poisoned_sig=b'\x00' * 64)
        b = m.sbcs_to_block([sbc])

        print(b)
def make_network(masternodes,
                 delegates,
                 ctx,
                 mn_min_quorum=2,
                 del_min_quorum=2):
    mn_wallets = [Wallet() for _ in range(masternodes)]
    dl_wallets = [Wallet() for _ in range(delegates)]

    constitution = {
        'masternodes': [mn.verifying_key().hex() for mn in mn_wallets],
        'delegates': [dl.verifying_key().hex() for dl in dl_wallets],
        'masternode_min_quorum': mn_min_quorum,
        'delegate_min_quorum': del_min_quorum,
    }

    mns = []
    dls = []
    bootnodes = None
    node_count = 0
    for wallet in mn_wallets:
        driver = BlockchainDriver(driver=InMemDriver())
        # driver = IsolatedDriver()
        ipc = f'/tmp/n{node_count}'
        make_ipc(ipc)

        if bootnodes is None:
            bootnodes = [f'ipc://{ipc}']

        mn = Masternode(wallet=wallet,
                        ctx=ctx,
                        socket_base=f'ipc://{ipc}',
                        bootnodes=bootnodes,
                        constitution=deepcopy(constitution),
                        webserver_port=18080 + node_count,
                        driver=driver)

        mns.append(mn)
        node_count += 1

    for wallet in dl_wallets:
        driver = BlockchainDriver(driver=InMemDriver())
        # driver = IsolatedDriver()
        ipc = f'/tmp/n{node_count}'
        make_ipc(ipc)

        dl = Delegate(wallet=wallet,
                      ctx=ctx,
                      socket_base=f'ipc://{ipc}',
                      constitution=deepcopy(constitution),
                      bootnodes=bootnodes,
                      driver=driver)

        dls.append(dl)
        node_count += 1

    return mns, dls
def join_network(args):
    assert args.node_type == 'masternode' or args.node_type == 'delegate', \
        'Provide node type as "masternode" or "delegate"'

    sk = bytes.fromhex(args.key)

    wallet = Wallet(seed=sk)

    const = resolve_constitution(args.constitution)

    mn_seed = f'tcp://{args.mn_seed}'

    ip_str = requests.get('http://api.ipify.org').text
    socket_base = f'tcp://{ip_str}'

    # Setup Environment
    # CURR_DIR = pathlib.Path(os.getcwd())
    # os.environ['PKG_ROOT'] = str(CURR_DIR.parent)
    # os.environ['CIL_PATH'] = os.getenv('PKG_ROOT') + '/cilantro_ee'

    if args.node_type == 'masternode':
        # Start mongo
        start_mongo()

        n = Masternode(wallet=wallet,
                       ctx=zmq.asyncio.Context(),
                       socket_base=socket_base,
                       constitution=const,
                       webserver_port=args.webserver_port,
                       mn_seed=mn_seed)
    elif args.node_type == 'delegate':
        start_mongo()
        n = Delegate(wallet=wallet,
                     ctx=zmq.asyncio.Context(),
                     socket_base=socket_base,
                     constitution=const,
                     mn_seed=mn_seed)

    loop = asyncio.get_event_loop()
    asyncio. async (n.start())
    loop.run_forever()
Пример #10
0
    def test_send_work_returns_sends_if_successful(self):
        make_ipc('/tmp/n2')
        m = Masternode(wallet=mnw1,
                       ctx=self.ctx,
                       socket_base='ipc:///tmp/n2',
                       bootnodes=bootnodes,
                       constitution=constitution,
                       webserver_port=8080,
                       overwrite=True)

        d = MockDelegate(self.ctx)

        m.parameters.sockets = {dw1.verifying_key().hex(): 'ipc:///tmp/n1'}

        tasks = asyncio.gather(m.send_work(), d.recv_work())

        r, _ = self.loop.run_until_complete(tasks)

        status, socket = r[0]
        self.assertTrue(status)
        self.assertEqual(socket, 'ipc:///tmp/n1/incoming_work')
    def test_new_blockchain_boot_completes_if_tx_batch_filled(self):
        m = Masternode(
            wallet=mnw1,
            ctx=self.ctx,
            socket_base='ipc:///tmp/n1',
            bootnodes=bootnodes,
            constitution=constitution,
            webserver_port=8080,
            overwrite=True
        )

        # For mocking
        async def add_tx_batch():
            m.tx_batcher.queue.append(b'123')

        tasks = asyncio.gather(
            m.new_blockchain_boot(),
            add_tx_batch()
        )

        self.loop.run_until_complete(tasks)
Пример #12
0
def setup_node():
    node_type = ''
    while node_type not in ['M', 'D']:
        node_type = input('(M)asternode or (D)elegate: ').upper()

    while True:
        sk = getpass('Signing Key in Hex Format: ')

        try:
            wallet = Wallet(seed=bytes.fromhex(sk))
            break
        except:
            print('Invalid format! Try again.')

    join_or_start = ''
    while join_or_start not in ['J', 'S']:
        join_or_start = input('(J)oin or (S)tart: ').upper()

    bootnodes = []
    mn_seed = None
    if join_or_start == 'S':
        bootnode = ''
        while len(bootnodes) < 1 or bootnode != '':
            bootnode = input(
                'Enter bootnodes as IP string. Press Enter twice to continue: '
            )
            if is_valid_ip(bootnode):
                print(f'Added {bootnode}.')
                bootnodes.append(bootnode)
            elif bootnode != '':
                print(f'Invalid IP string: {bootnode}')
    else:
        while mn_seed is None:
            mn_ip = input('Enter masternode as IP string: ')
            if is_valid_ip(mn_ip):
                mn_seed = mn_ip
            else:
                print(f'Invalid IP string: {mn_seed}')

    ip_str = requests.get('http://api.ipify.org').text
    socket_base = f'tcp://{ip_str}'
    mn_seed_str = f'tcp://{mn_seed}'
    const_url = input('URL of constitution: ')
    c = requests.get(const_url)
    const = resolve_raw_constitution(c.text)

    # start_rocks()

    if node_type == 'M':
        # Start mongo
        start_mongo()

        n = Masternode(wallet=wallet,
                       ctx=zmq.asyncio.Context(),
                       socket_base=socket_base,
                       bootnodes=bootnodes,
                       constitution=const,
                       webserver_port=18080,
                       mn_seed=mn_seed_str)
    elif node_type == 'D':
        n = Delegate(wallet=wallet,
                     ctx=zmq.asyncio.Context(),
                     socket_base=socket_base,
                     bootnodes=bootnodes,
                     constitution=const,
                     mn_seed=mn_seed_str)

    loop = asyncio.get_event_loop()
    asyncio. async (n.start())
    loop.run_forever()
Пример #13
0
def start_node(args):
    # sleep for restart module for ppid to be killed
    time.sleep(5)

    assert args.node_type == 'masternode' or args.node_type == 'delegate', \
        'Provide node type as "masternode" or "delegate"'

    sk = bytes.fromhex(args.key)

    wallet = Wallet(seed=sk)

    bootnodes = []

    for node in args.boot_nodes:
        assert is_valid_ip(
            node), 'Invalid IP string provided to boot node argument.'
        bootnodes.append(f'tcp://{node}')

    assert len(bootnodes) > 0, 'Must provide at least one bootnode.'

    const = resolve_constitution(args.constitution)

    ip_str = requests.get('http://api.ipify.org').text
    socket_base = f'tcp://{ip_str}'

    # Setup Environment
    copyfile('/root/cilantro-enterprise/scripts/cil.service',
             '/etc/systemd/system/cil.service')

    # Enable Auto Restart
    # key, config = read_cfg()  #use restart logic to start the node again

    # if key is None or config is None:
    #     # booting for 1st time
    #     enable = ask(question='Authorize auto restart for cilantro')
    #
    #     if enable:
    #         validate_key(restart=enable, key = args.key)
    #     else:
    #         print("Auto Restart is disabled manual intervention to restart CIL")

    if args.node_type == 'masternode':
        # Start mongo
        start_mongo()

        n = Masternode(
            wallet=wallet,
            ctx=zmq.asyncio.Context(),
            socket_base=socket_base,
            bootnodes=bootnodes,
            constitution=const,
            webserver_port=args.webserver_port,
        )
    elif args.node_type == 'delegate':
        n = Delegate(
            wallet=wallet,
            ctx=zmq.asyncio.Context(),
            socket_base=socket_base,
            bootnodes=bootnodes,
            constitution=const,
        )

    loop = asyncio.get_event_loop()
    asyncio. async (n.start())
    loop.run_forever()
    def test_send_to_delegates_doesnt_hang_if_one_is_not_online(self):
        bootnodes = ['ipc:///tmp/n2', 'ipc:///tmp/n3']

        mnw1 = Wallet()
        mnw2 = Wallet()

        dw1 = Wallet()
        dw2 = Wallet()
        dw3 = Wallet()
        dw4 = Wallet()

        constitution = {
            "masternodes": {
                "vk_list": [
                    mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "delegates": {
                "vk_list": [
                    dw1.verifying_key().hex(),
                    dw2.verifying_key().hex(),
                    dw3.verifying_key().hex(),
                    dw4.verifying_key().hex()
                ],
                "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, overwrite=True)

        masternodes = [mnw1.verifying_key().hex(), mnw2.verifying_key().hex()]
        delegates = [dw1.verifying_key().hex(), dw2.verifying_key().hex(), dw3.verifying_key().hex(),
                     dw4.verifying_key().hex()]

        contacts = MockContacts(
            masters=masternodes,
            delegates=delegates
        )

        d1 = '/tmp/d1'
        make_ipc(d1)
        wi1 = WorkInbox(socket_id=_socket(f'ipc://{d1}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d2 = '/tmp/d2'
        make_ipc(d2)
        wi2 = WorkInbox(socket_id=_socket(f'ipc://{d2}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d3 = '/tmp/d3'
        make_ipc(d3)
        #wi3 = WorkInbox(socket_id=_socket(f'ipc://{d3}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        d4 = '/tmp/d4'
        make_ipc(d4)
        wi4 = WorkInbox(socket_id=_socket(f'ipc://{d4}/incoming_work'), ctx=self.ctx, contacts=contacts, verify=False)

        w = Wallet()
        batch = TransactionBuilder(
            sender=w.verifying_key(),
            contract='test',
            function='testing',
            kwargs={},
            stamps=1_000_000,
            processor=mnw1.verifying_key(),
            nonce=0
        )

        batch.sign(w.signing_key())
        b = batch.serialize()

        tx = transaction_capnp.Transaction.from_bytes_packed(b)

        currency_contract = 'currency'
        balances_hash = 'balances'

        balances_key = '{}{}{}{}{}'.format(currency_contract,
                                           config.INDEX_SEPARATOR,
                                           balances_hash,
                                           config.DELIMITER,
                                           w.verifying_key().hex())

        driver = BlockchainDriver()
        driver.set(balances_key, 1_000_000)
        driver.commit()

        mn1.tx_batcher.queue.append(tx)

        mn1.network.peer_service.table.peers = {
            dw1.verifying_key().hex(): f'ipc://{d1}',
            dw2.verifying_key().hex(): f'ipc://{d2}',
            dw3.verifying_key().hex(): f'ipc://{d3}',
            dw4.verifying_key().hex(): f'ipc://{d4}'
        }

        async def late_send():
            await asyncio.sleep(0.3)
            await mn1.parameters.refresh()
            return await mn1.send_batch_to_delegates()

        async def stop():
            await asyncio.sleep(0.5)
            wi1.stop()
            wi2.stop()
            wi4.stop()
            mn1.network.stop()

        tasks = asyncio.gather(
            mn1.network.start(False),
            wi1.serve(),
            wi2.serve(),
            wi4.serve(),
            late_send(),
            stop()
        )

        _, _, _, _, r, _ = self.loop.run_until_complete(tasks)

        # Make sure the right socket failed
        for rr in r:
            if not rr[0]:
                self.assertEqual(rr[1], f'ipc://{d3}/incoming_work')

        self.assertTrue(wi1.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi2.work[mnw1.verifying_key().hex()])
        self.assertTrue(wi4.work[mnw1.verifying_key().hex()])
    def test_send_nbn_to_everyone_except_one_doesnt_block(self):
        bootnodes = ['ipc:///tmp/n2', 'ipc:///tmp/n3']

        mnw1 = Wallet()
        mnw2 = Wallet()

        dw1 = Wallet()
        dw2 = Wallet()
        dw3 = Wallet()
        dw4 = Wallet()

        constitution = {
            "masternodes": {
                "vk_list": [
                    mnw1.verifying_key().hex(),
                    mnw2.verifying_key().hex()
                ],
                "min_quorum": 1
            },
            "delegates": {
                "vk_list": [
                    dw1.verifying_key().hex(),
                    dw2.verifying_key().hex(),
                    dw3.verifying_key().hex(),
                    dw4.verifying_key().hex()
                ],
                "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,
            overwrite=True
        )

        masternodes = [mnw1.verifying_key().hex(), mnw2.verifying_key().hex()]
        delegates = [dw1.verifying_key().hex(), dw2.verifying_key().hex(), dw3.verifying_key().hex(),
                     dw4.verifying_key().hex()]

        contacts = MockContacts(
            masters=masternodes,
            delegates=delegates
        )

        d1 = '/tmp/d1'
        make_ipc(d1)
        wi1 = NBNInbox(socket_id=_socket(f'ipc://{d1}/block_notifications'), ctx=self.ctx, contacts=contacts, verify=False)

        d2 = '/tmp/d2'
        make_ipc(d2)
        #wi2 = NBNInbox(socket_id=_socket(f'ipc://{d2}/block_notifications'), ctx=self.ctx, contacts=contacts, verify=False)

        d3 = '/tmp/d3'
        make_ipc(d3)
        wi3 = NBNInbox(socket_id=_socket(f'ipc://{d3}/block_notifications'), ctx=self.ctx, contacts=contacts, verify=False)

        d4 = '/tmp/d4'
        make_ipc(d4)
        wi4 = NBNInbox(socket_id=_socket(f'ipc://{d4}/block_notifications'), ctx=self.ctx, contacts=contacts, verify=False)

        n2 = '/tmp/n2'
        make_ipc(n2)
        mn2 = NBNInbox(socket_id=_socket(f'ipc://{n2}/block_notifications'), ctx=self.ctx, contacts=contacts, verify=False)

        mn1.network.peer_service.table.peers = {
            dw1.verifying_key().hex(): f'ipc://{d1}',
            dw2.verifying_key().hex(): f'ipc://{d2}',
            dw3.verifying_key().hex(): f'ipc://{d3}',
            dw4.verifying_key().hex(): f'ipc://{d4}',
            mnw2.verifying_key().hex(): f'ipc://{n2}'
        }

        mn1.current_nbn = b'hello'

        async def late_send():
            await asyncio.sleep(0.3)
            await mn1.parameters.refresh()
            return await mn1.send_nbn_to_everyone()

        async def stop():
            await asyncio.sleep(0.5)
            wi1.stop()
            wi3.stop()
            wi4.stop()
            mn2.stop()
            mn1.network.stop()

        tasks = asyncio.gather(
            mn1.network.start(False),
            wi1.serve(),
            wi3.serve(),
            wi4.serve(),
            mn2.serve(),
            late_send(),
            stop()
        )

        self.loop.run_until_complete(tasks)

        _, _, _, _, _, r, _ = self.loop.run_until_complete(tasks)

        # Make sure the right socket failed
        for rr in r:
            if not rr[0]:
                self.assertEqual(rr[1], f'ipc://{d2}/block_notifications')

        self.assertEqual(wi1.q[0], b'hello')
        #self.assertEqual(wi2.q[0], b'hello')
        self.assertEqual(wi3.q[0], b'hello')
        self.assertEqual(wi4.q[0], b'hello')
        self.assertEqual(mn2.q[0], b'hello')
    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())