def get_root_block_by_hash(self, h, consistency_check=True):
        if consistency_check and h not in self.r_header_pool:
            return None

        raw_block = self.db.get(b"rblock_" + h, None)
        if not raw_block:
            return None
        return RootBlock.deserialize(raw_block)
예제 #2
0
 def get_root_block_by_hash(self, h) -> Optional[RootBlock]:
     key = b"rblock_" + h
     if key in self.rblock_cache:
         return self.rblock_cache[key]
     raw_block = self.db.get(key, None)
     block = raw_block and RootBlock.deserialize(raw_block)
     if block is not None:
         self.rblock_cache[key] = block
     return block
예제 #3
0
    def __recover_from_db(self):
        """ Recover the best chain from local database.
        """
        Logger.info("Recovering root chain from local database...")

        if b"tipHash" not in self.db:
            return None

        r_hash = self.db.get(b"tipHash")
        r_block = RootBlock.deserialize(self.db.get(b"rblock_" + r_hash))
        if r_block.header.height <= 0:
            return None
        # use the parent of the tipHash block as the new tip
        # since it's guaranteed to have been accepted by all the shards
        # while shards might not have seen the block of tipHash
        r_hash = r_block.header.hash_prev_block
        r_block = RootBlock.deserialize(self.db.get(b"rblock_" + r_hash))
        self.tip_header = r_block.header  # type: RootBlockHeader
예제 #4
0
    def __recover_from_db(self):
        """ Recover the best chain from local database.
        """
        Logger.info("Recovering root chain from local database...")

        if b"tipHash" not in self.db:
            return None

        r_hash = self.db.get(b"tipHash")
        r_block = RootBlock.deserialize(self.db.get(b"rblock_" + r_hash))
        self.tip_header = r_block.header

        while len(self.r_header_pool) < self.max_num_blocks_to_recover:
            self.r_header_pool[r_hash] = r_block.header
            for m_header in r_block.minor_block_header_list:
                self.m_hash_set.add(m_header.get_hash())

            if r_block.header.height <= 0:
                break

            r_hash = r_block.header.hash_prev_block
            r_block = RootBlock.deserialize(self.db.get(b"rblock_" + r_hash))
예제 #5
0
    def get_root_block_by_hash(self, h, consistency_check=True):
        """
        Consistency check being true means whatever in memory should already have enough
        information (no missing root block, minor block etc). Skipping the check by reading
        directly from database may have unwanted consequences.
        """
        if consistency_check and h not in self.r_header_pool:
            return None

        raw_block = self.db.get(b"rblock_" + h, None)
        if not raw_block:
            return None
        return RootBlock.deserialize(raw_block)
예제 #6
0
 async def addBlock(self, branch, block_data):
     if branch == 0:
         block = RootBlock.deserialize(block_data)
         return await self.master.add_root_block_from_miner(block)
     return await self.master.add_raw_minor_block(Branch(branch),
                                                  block_data)
예제 #7
0
    def test_getNextBlockToMine_and_addBlock(self):
        id1 = Identity.create_random_identity()
        acc1 = Address.create_from_identity(id1, full_shard_id=0)
        acc3 = Address.create_random_account(full_shard_id=1)

        with ClusterContext(1, acc1) as clusters, jrpc_server_context(
                clusters[0].master):
            slaves = clusters[0].slave_list

            # Expect to mine root that confirms the genesis minor blocks
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertTrue(response["isRootBlock"])
            block = RootBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))

            self.assertEqual(block.header.height, 1)
            self.assertEqual(len(block.minor_block_header_list), 2)
            self.assertEqual(block.minor_block_header_list[0].height, 0)
            self.assertEqual(block.minor_block_header_list[1].height, 0)

            send_request("addBlock", "0x0", response["blockData"])

            tx = create_transfer_transaction(
                shard_state=clusters[0].get_shard_state(0),
                key=id1.get_key(),
                from_address=acc1,
                to_address=acc3,
                value=14,
                gas=opcodes.GTXXSHARDCOST + opcodes.GTXCOST,
            )
            self.assertTrue(slaves[0].add_tx(tx))

            # Expect to mine shard 0 since it has one tx
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block1 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block1.header.branch.value, 0b10)

            self.assertTrue(
                send_request("addBlock", "0x2", response["blockData"]))
            self.assertEqual(
                clusters[0].get_shard_state(1).get_balance(acc3.recipient, 0),
                0)

            # Expect to mine shard 1 due to proof-of-progress
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block2 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block2.header.branch.value, 0b11)

            self.assertTrue(
                send_request("addBlock", "0x3", response["blockData"]))

            # Expect to mine root
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertTrue(response["isRootBlock"])
            block = RootBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))

            self.assertEqual(block.header.height, 2)
            self.assertEqual(len(block.minor_block_header_list), 2)
            self.assertEqual(block.minor_block_header_list[0], block1.header)
            self.assertEqual(block.minor_block_header_list[1], block2.header)

            send_request("addBlock", "0x0", response["blockData"])
            self.assertEqual(
                clusters[0].get_shard_state(1).get_balance(acc3.recipient, 0),
                0)

            # Expect to mine shard 1 for the gas on xshard tx to acc3
            response = send_request("getNextBlockToMine",
                                    "0x" + acc1.serialize().hex(), "0x0")
            self.assertFalse(response["isRootBlock"])
            block3 = MinorBlock.deserialize(
                bytes.fromhex(response["blockData"][2:]))
            self.assertEqual(block3.header.branch.value, 0b11)

            self.assertTrue(
                send_request("addBlock", "0x3", response["blockData"]))
            # Expect withdrawTo is included in acc3's balance
            resp = send_request("getBalance", "0x" + acc3.serialize().hex())
            self.assertEqual(resp["branch"], "0x3")
            self.assertEqual(resp["balance"], "0xe")
예제 #8
0
 def get_root_block_by_hash(self, h):
     if h not in self.r_header_pool:
         return None
     return RootBlock.deserialize(self.db.get(b"rblock_" + h))