예제 #1
0
    def test_get_block_blob_by_block_data_request(self):
        block = random_txs.random_block()
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode().hex())
        c.drop_collections()

        d = canonical.block_from_subblocks([s for s in block.subBlocks],
                                           previous_hash=b'x/00' * 32,
                                           block_num=0)

        d['blockOwners'] = [secrets.token_bytes(32) for _ in range(12)]

        c.put(d)

        del d['_id']
        del d['blockOwners']

        m = BlockServer(w,
                        'tcp://127.0.0.1',
                        self.ctx,
                        linger=500,
                        poll_timeout=500,
                        driver=c)

        async def get(msg):
            socket = self.ctx.socket(zmq.DEALER)
            socket.connect('tcp://127.0.0.1:10004')

            await socket.send(msg)

            res = await socket.recv()

            return res

        message = Message.get_signed_message_packed_2(
            wallet=w, msg_type=MessageType.BLOCK_DATA_REQUEST, blockNum=0)

        tasks = asyncio.gather(
            m.serve(),
            get(message),
            stop_server(m, 0.2),
        )

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

        msg_type, msg, sender, timestamp, is_verified = Message.unpack_message_2(
            res[1])

        dd = canonical.block_from_subblocks([s for s in msg.subBlocks],
                                            previous_hash=b'x/00' * 32,
                                            block_num=0)

        self.assertDictEqual(d, dd)
    def test_block_from_subblocks_verify_works(self):
        sbs = random_txs.random_block().subBlocks

        block = canonical.block_from_subblocks(subblocks=sbs, previous_hash=b'\x00' * 32, block_num=0)

        prev_hash = block['prevBlockHash']
        prop_hash = block['hash']

        valid = canonical.verify_block(sbs, prev_hash, prop_hash)

        self.assertTrue(valid)
    def test_fetch_block_from_master(self):
        # Setup Mongo
        #sync.seed_vkbook()
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode())
        c.drop_collections()

        # Store 20 blocks
        self.store_blocks(c, 1)

        w1 = Wallet()
        m1 = BlockServer(socket_base='tcp://127.0.0.1',
                         wallet=w1,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=500,
                         driver=FakeTopBlockManager(101, 'abcd'))

        class FakeParameters:
            async def refresh(self):
                await asyncio.sleep(0.1)

            def get_masternode_sockets(self, *args):
                return ['tcp://127.0.0.1:10004']

        f = BlockFetcher(wallet=Wallet(),
                         ctx=self.ctx,
                         parameters=FakeParameters())

        tasks = asyncio.gather(
            m1.serve(),
            f.get_block_from_master(
                0,
                cilantro_ee.sockets.struct._socket('tcp://127.0.0.1:10004')),
            stop_server(m1, 0.3),
        )

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

        block_dict = c.get_block(0)

        del block_dict['blockOwners']

        got_block = res[1]

        got = canonical.block_from_subblocks([s for s in got_block.subBlocks],
                                             previous_hash=b'\x00' * 32,
                                             block_num=0)

        self.assertDictEqual(block_dict, got)
    def store_blocks(self, c, i, initial_hash=(b'\x00' * 32).hex()):
        current_hash = initial_hash
        for _i in range(i):
            block = random_txs.random_block(block_num=_i)
            d = canonical.block_from_subblocks([s for s in block.subBlocks],
                                               previous_hash=current_hash,
                                               block_num=_i)

            d['blockOwners'] = [secrets.token_bytes(32) for _ in range(12)]

            c.put(d)

            del d['_id']
            del d['blockOwners']

            current_hash = d['hash']
예제 #5
0
    async def gather_subblocks(self,
                               total_contacts,
                               quorum_ratio=0.66,
                               adequate_ratio=0.5,
                               expected_subblocks=4):
        self.sbc_inbox.expected_subblocks = expected_subblocks

        self.log.info(f'''
========
Gathering subblocks:
Total Contacts: {total_contacts}, Expected SBs: {expected_subblocks}
Quorum Ratio: {quorum_ratio}, Adequate Ratio: {adequate_ratio}
========
        ''')

        contenders = BlockContender(total_contacts=total_contacts,
                                    required_consensus=quorum_ratio,
                                    total_subblocks=expected_subblocks,
                                    acceptable_consensus=adequate_ratio)

        # Add timeout condition.
        started = time.time()
        while (not contenders.block_has_consensus() and contenders.responses < contenders.total_contacts) and \
                time.time() - started < self.seconds_to_timeout:

            if self.sbc_inbox.has_sbc():
                sbcs = await self.sbc_inbox.receive_sbc(
                )  # Can probably make this raw sync code
                contenders.add_sbcs(sbcs)
            await asyncio.sleep(0)

        if time.time() - started > self.seconds_to_timeout:
            self.log.error('BLOCK TIMEOUT!')

        self.log.info('Done aggregating new block.')

        block = contenders.get_current_best_block()

        return canonical.block_from_subblocks(
            block,
            previous_hash=self.driver.latest_block_hash,
            block_num=self.driver.latest_block_num + 1)
예제 #6
0
    def get_block_dict(self, sub_blocks, kind):
        last_block = self.get_last_n(1, self.INDEX)

        if len(last_block) > 0:
            last_block = last_block[0]
            last_hash = last_block.get('hash')
            current_block_num = last_block.get('blockNum')
        else:
            last_hash = GENESIS_HASH
            current_block_num = 0

        if kind == 0:
            current_block_num += 1

        block_dict = block_from_subblocks(subblocks=sub_blocks,
                                          previous_hash=last_hash,
                                          block_num=current_block_num)
        block_dict['blockOwners'] = [m for m in self.vkbook.masternodes],

        return block_dict
    def test_fetch_multiple_blocks_works_with_good_actors(self):
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode())
        c.drop_collections()

        # Store 20 blocks
        self.store_blocks(c, 10)

        # Good one
        w1 = Wallet()
        n1 = '/tmp/n1'
        make_ipc(n1)
        m1 = BlockServer(socket_base=f'ipc://{n1}',
                         wallet=w1,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=500,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=c)

        w2 = Wallet()
        n2 = '/tmp/n2'
        make_ipc(n2)
        m2 = BlockServer(socket_base=f'ipc://{n2}',
                         wallet=w2,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=100,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=c)

        w3 = Wallet()
        n3 = '/tmp/n3'
        make_ipc(n3)
        m3 = BlockServer(socket_base=f'ipc://{n3}',
                         wallet=w3,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=100,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=c)

        fake_driver = FakeBlockReciever()

        class FakeParameters:
            async def refresh(self):
                await asyncio.sleep(0.1)

            def get_masternode_sockets(self, *args):
                return [
                    f'ipc://{n1}/blocks',
                    f'ipc://{n2}/blocks',
                    f'ipc://{n3}/blocks',
                ]

        f = BlockFetcher(wallet=Wallet(),
                         ctx=self.ctx,
                         parameters=FakeParameters(),
                         blocks=fake_driver)

        tasks = asyncio.gather(
            m1.serve(),
            m2.serve(),
            m3.serve(),
            f.fetch_blocks(latest_block_available=9),
            stop_server(m1, 3),
            stop_server(m2, 3),
            stop_server(m3, 3),
        )

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

        last_hash = b'\x00' * 32
        for i in range(10):
            block_dict = c.get_block(i)

            del block_dict['blockOwners']

            got = canonical.block_from_subblocks(
                [s for s in fake_driver.blocks[i]['subBlocks']],
                previous_hash=last_hash,
                block_num=i)

            last_hash = block_dict['hash']

            self.assertDictEqual(block_dict, got)
    def test_fetch_block_from_multiple_masters_where_some_are_corrupted(self):
        w = Wallet()
        c = CilantroStorageDriver(key=w.sk.encode())
        c.drop_collections()

        # Store 20 blocks
        self.store_blocks(c, 1)

        # Good one
        w1 = Wallet()
        n1 = '/tmp/n1'
        make_ipc(n1)
        m1 = BlockServer(socket_base=f'ipc://{n1}',
                         wallet=w1,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=500,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=c)

        # Bad Ones
        bad_block = canonical.block_from_subblocks(
            [s for s in random_txs.random_block().subBlocks],
            previous_hash=b'\x01' * 32,
            block_num=0)

        bad_block['blockOwners'] = [secrets.token_bytes(32) for _ in range(30)]

        d = FakeBlockDriver(bad_block)
        w2 = Wallet()
        n2 = '/tmp/n2'
        make_ipc(n2)
        m2 = BlockServer(socket_base=f'ipc://{n2}',
                         wallet=w2,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=100,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=d)

        w3 = Wallet()
        n3 = '/tmp/n3'
        make_ipc(n3)
        m3 = BlockServer(socket_base=f'ipc://{n3}',
                         wallet=w3,
                         ctx=self.ctx,
                         linger=500,
                         poll_timeout=100,
                         driver=FakeTopBlockManager(101, 'abcd'),
                         blocks=d)

        class FakeParameters:
            async def refresh(self):
                await asyncio.sleep(0.1)

            def get_masternode_sockets(self, *args):
                return [
                    f'ipc://{n1}/blocks',
                    f'ipc://{n2}/blocks',
                    f'ipc://{n3}/blocks',
                ]

        f = BlockFetcher(wallet=Wallet(),
                         ctx=self.ctx,
                         parameters=FakeParameters())

        tasks = asyncio.gather(
            m1.serve(),
            m2.serve(),
            m3.serve(),
            f.find_valid_block(0, latest_hash=b'\x00' * 32, timeout=3000),
            stop_server(m1, 2),
            stop_server(m2, 2),
            stop_server(m3, 2),
        )

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

        block_dict = c.get_block(0)

        del block_dict['blockOwners']

        got_block = res[3]

        got = canonical.block_from_subblocks([s for s in got_block.subBlocks],
                                             previous_hash=b'\x00' * 32,
                                             block_num=0)

        self.assertDictEqual(block_dict, got)