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)
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
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
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))
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)
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)
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")
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))