def create_minor_block(self, root_block: RootBlock, full_shard_id: int, evm_state: EvmState) -> MinorBlock: """ Create genesis block for shard. Genesis block's hash_prev_root_block is set to the genesis root block. Genesis state will be committed to the given evm_state. Based on ALLOC, genesis_token will be added to initial accounts. """ branch = Branch(full_shard_id) shard_config = self._qkc_config.shards[full_shard_id] genesis = shard_config.GENESIS for address_hex, alloc_amount in genesis.ALLOC.items(): address = Address.create_from(bytes.fromhex(address_hex)) check( self._qkc_config.get_full_shard_id_by_full_shard_key( address.full_shard_key) == full_shard_id) evm_state.full_shard_key = address.full_shard_key if isinstance(alloc_amount, dict): for k, v in alloc_amount.items(): evm_state.delta_token_balance(address.recipient, token_id_encode(k), v) else: evm_state.delta_token_balance(address.recipient, self._qkc_config.genesis_token, alloc_amount) evm_state.commit() meta = MinorBlockMeta( hash_merkle_root=bytes.fromhex(genesis.HASH_MERKLE_ROOT), hash_evm_state_root=evm_state.trie.root_hash, ) local_fee_rate = 1 - self._qkc_config.reward_tax_rate # type: Fraction coinbase_tokens = { self._qkc_config.genesis_token: shard_config.COINBASE_AMOUNT * local_fee_rate.numerator // local_fee_rate.denominator } coinbase_address = Address.create_empty_account(full_shard_id) header = MinorBlockHeader( version=genesis.VERSION, height=genesis.HEIGHT, branch=branch, hash_prev_minor_block=bytes.fromhex(genesis.HASH_PREV_MINOR_BLOCK), hash_prev_root_block=root_block.header.get_hash(), evm_gas_limit=genesis.GAS_LIMIT, hash_meta=sha3_256(meta.serialize()), coinbase_amount_map=TokenBalanceMap(coinbase_tokens), coinbase_address=coinbase_address, create_time=genesis.TIMESTAMP, difficulty=genesis.DIFFICULTY, extra_data=bytes.fromhex(genesis.EXTRA_DATA), ) return ( MinorBlock(header=header, meta=meta, tx_list=[]), TokenBalanceMap(coinbase_tokens), )
def create_minor_block(self, root_block: RootBlock, shard_id: int, evm_state: EvmState) -> MinorBlock: """ Create genesis block for shard. Genesis block's hash_prev_root_block is set to the genesis root block. Genesis state will be committed to the given evm_state. """ branch = Branch.create(self._qkc_config.SHARD_SIZE, shard_id) shard_config = self._qkc_config.SHARD_LIST[shard_id] genesis = shard_config.GENESIS for address_hex, amount_in_wei in genesis.ALLOC.items(): address = Address.create_from(bytes.fromhex(address_hex)) check( address.get_shard_id(self._qkc_config.SHARD_SIZE) == shard_id) evm_state.full_shard_id = address.full_shard_id evm_state.delta_balance(address.recipient, amount_in_wei) evm_state.commit() meta = MinorBlockMeta( hash_merkle_root=bytes.fromhex(genesis.HASH_MERKLE_ROOT), hash_evm_state_root=evm_state.trie.root_hash, ) local_fee_rate = 1 - self._qkc_config.reward_tax_rate # type: Fraction coinbase_amount = (shard_config.COINBASE_AMOUNT * local_fee_rate.numerator // local_fee_rate.denominator) coinbase_address = Address.create_empty_account(shard_id) header = MinorBlockHeader( version=genesis.VERSION, height=genesis.HEIGHT, branch=branch, hash_prev_minor_block=bytes.fromhex(genesis.HASH_PREV_MINOR_BLOCK), hash_prev_root_block=root_block.header.get_hash(), evm_gas_limit=genesis.GAS_LIMIT, hash_meta=sha3_256(meta.serialize()), coinbase_amount=coinbase_amount, coinbase_address=coinbase_address, create_time=genesis.TIMESTAMP, difficulty=genesis.DIFFICULTY, extra_data=bytes.fromhex(genesis.EXTRA_DATA), ) return MinorBlock(header=header, meta=meta, tx_list=[])
async def handle_get_transaction_request(self, req): minor_block, i = self.slave_server.get_transaction_by_hash( req.tx_hash, req.branch ) if not minor_block: empty_block = MinorBlock(MinorBlockHeader(), MinorBlockMeta()) return GetTransactionResponse( error_code=1, minor_block=empty_block, index=0 ) return GetTransactionResponse(error_code=0, minor_block=minor_block, index=i)
def test_get_minor_block_by_hash(self): db = ShardDbOperator(InMemoryDb(), DEFAULT_ENV, Branch(2)) block = MinorBlock(MinorBlockHeader(), MinorBlockMeta()) block_hash = block.header.get_hash() db.put_minor_block(block, []) self.assertEqual(db.get_minor_block_by_hash(block_hash), block) self.assertIsNone(db.get_minor_block_by_hash(b"")) self.assertEqual(db.get_minor_block_header_by_hash(block_hash), block.header) self.assertIsNone(db.get_minor_block_header_by_hash(b""))
async def handle_get_transaction_receipt_request(self, req): resp = self.slave_server.get_transaction_receipt(req.tx_hash, req.branch) if not resp: empty_block = MinorBlock(MinorBlockHeader(), MinorBlockMeta()) empty_receipt = TransactionReceipt.create_empty_receipt() return GetTransactionReceiptResponse( error_code=1, minor_block=empty_block, index=0, receipt=empty_receipt ) minor_block, i, receipt = resp return GetTransactionReceiptResponse( error_code=0, minor_block=minor_block, index=i, receipt=receipt )
async def handle_get_minor_block_request(self, req): if req.minor_block_hash != bytes(32): block = self.slave_server.get_minor_block_by_hash( req.minor_block_hash, req.branch) else: block = self.slave_server.get_minor_block_by_height( req.height, req.branch) if not block: empty_block = MinorBlock(MinorBlockHeader(), MinorBlockMeta()) return GetMinorBlockResponse(error_code=1, minor_block=empty_block) return GetMinorBlockResponse(error_code=0, minor_block=block)
def create_minor_block( self, root_block: RootBlock, full_shard_id: int, evm_state: EvmState) -> Tuple[MinorBlock, TokenBalanceMap]: """ Create genesis block for shard. Genesis block's hash_prev_root_block is set to the genesis root block. Genesis state will be committed to the given evm_state. Based on ALLOC, genesis_token will be added to initial accounts. """ branch = Branch(full_shard_id) shard_config = self._qkc_config.shards[full_shard_id] genesis = shard_config.GENESIS for address_hex, alloc_data in genesis.ALLOC.items(): address = Address.create_from(bytes.fromhex(address_hex)) check( self._qkc_config.get_full_shard_id_by_full_shard_key( address.full_shard_key) == full_shard_id) evm_state.full_shard_key = address.full_shard_key recipient = address.recipient if "code" in alloc_data: code = decode_hex(remove_0x_head(alloc_data["code"])) evm_state.set_code(recipient, code) evm_state.set_nonce(recipient, 1) if "storage" in alloc_data: for k, v in alloc_data["storage"].items(): evm_state.set_storage_data( recipient, big_endian_to_int(decode_hex(k[2:])), big_endian_to_int(decode_hex(v[2:])), ) # backward compatible: # v1: {addr: {QKC: 1234}} # v2: {addr: {balances: {QKC: 1234}, code: 0x, storage: {0x12: 0x34}}} balances = alloc_data if "balances" in alloc_data: balances = alloc_data["balances"] for k, v in balances.items(): if k in ("code", "storage"): continue evm_state.delta_token_balance(recipient, token_id_encode(k), v) evm_state.commit() meta = MinorBlockMeta( hash_merkle_root=bytes.fromhex(genesis.HASH_MERKLE_ROOT), hash_evm_state_root=evm_state.trie.root_hash, xshard_tx_cursor_info=XshardTxCursorInfo(root_block.header.height, 0, 0), ) local_fee_rate = 1 - self._qkc_config.reward_tax_rate # type: Fraction coinbase_tokens = { self._qkc_config.genesis_token: shard_config.COINBASE_AMOUNT * local_fee_rate.numerator // local_fee_rate.denominator } coinbase_address = Address.create_empty_account(full_shard_id) header = MinorBlockHeader( version=genesis.VERSION, height=genesis.HEIGHT, branch=branch, hash_prev_minor_block=bytes.fromhex(genesis.HASH_PREV_MINOR_BLOCK), hash_prev_root_block=root_block.header.get_hash(), evm_gas_limit=genesis.GAS_LIMIT, hash_meta=sha3_256(meta.serialize()), coinbase_amount_map=TokenBalanceMap(coinbase_tokens), coinbase_address=coinbase_address, create_time=genesis.TIMESTAMP, difficulty=genesis.DIFFICULTY, extra_data=bytes.fromhex(genesis.EXTRA_DATA), ) return ( MinorBlock(header=header, meta=meta, tx_list=[]), TokenBalanceMap(coinbase_tokens), )