def compute_state_test_unit(state, txdata, indices, konfig): state.env.config = konfig s = state.snapshot() try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata['nonce'] or b"0"), gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"), startgas=parse_int_or_hex(txdata['gasLimit'][indices["gas"]] or b"0"), to=decode_hex(remove_0x_head(txdata['to'])), value=parse_int_or_hex(txdata['value'][indices["value"]] or b"0"), data=decode_hex(remove_0x_head(txdata['data'][indices["data"]]))) if 'secretKey' in txdata: tx.sign(decode_hex(remove_0x_head(txdata['secretKey']))) else: tx.v = parse_int_or_hex(txdata['v']) # Run it prev = state.to_dict() success, output = apply_transaction(state, tx) print("Applied tx") except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b'' # state.set_code('0x3e180b1862f9d158abb5e519a6d8605540c23682', b'') state.commit() post = state.to_dict() # print('pozt', post) output_decl = { "hash": '0x' + encode_hex(state.trie.root_hash), "indexes": indices, "diff": mk_state_diff(prev, post) } state.revert(s) return output_decl
def init_state(env, pre, is_qkc_state, qkc_env=None): # Setup env db = InMemoryDb() state_env = Env(config=konfig) state_env.db = db state = State( env=state_env, block_prevhash=decode_hex(remove_0x_head(env["previousHash"])), prev_headers=[ mk_fake_header(i) for i in range( parse_int_or_hex(env["currentNumber"]) - 1, max(-1, parse_int_or_hex(env["currentNumber"]) - 257), -1, ) ], block_number=parse_int_or_hex(env["currentNumber"]), block_coinbase=decode_hex(remove_0x_head(env["currentCoinbase"])), block_difficulty=parse_int_or_hex(env["currentDifficulty"]), gas_limit=parse_int_or_hex(env["currentGasLimit"]), timestamp=parse_int_or_hex(env["currentTimestamp"]), qkc_config=qkc_env.quark_chain_config, # If testing QuarkChain states, should not use mock account use_mock_evm_account=not is_qkc_state, ) seen_token_ids = set() # Fill up pre for address, h in list(pre.items()): assert len(address) in (40, 42) address = decode_hex(remove_0x_head(address)) state.set_nonce(address, parse_int_or_hex(h["nonce"])) if is_qkc_state and "balances" in h: # In QuarkChain state tests, can either specify balance map or single balance for token_id, balance in h["balances"].items(): parsed_token_id = parse_int_or_hex(token_id) state.set_token_balance( address, parsed_token_id, parse_int_or_hex(balance) ) seen_token_ids.add(parsed_token_id) else: state.set_balance(address, parse_int_or_hex(h["balance"])) state.set_code(address, decode_hex(remove_0x_head(h["code"]))) for k, v in h["storage"].items(): state.set_storage_data( address, big_endian_to_int(decode_hex(k[2:])), big_endian_to_int(decode_hex(v[2:])), ) # Update allowed token IDs if seen_token_ids: state.qkc_config._allowed_token_ids = seen_token_ids state.commit(allow_empties=True) return state
def compute_state_test_unit(state, txdata, indices, konfig, is_qkc_state, qkc_env=None): state.env.config = konfig s = state.snapshot() if "transferTokenId" in txdata: transfer_token_id = parse_int_or_hex( txdata["transferTokenId"][indices["transferTokenId"]]) else: transfer_token_id = token_id_encode("QKC") try: # Create the transaction tx = transactions.Transaction( nonce=parse_int_or_hex(txdata["nonce"] or b"0"), gasprice=parse_int_or_hex(txdata["gasPrice"] or b"0"), startgas=parse_int_or_hex(txdata["gasLimit"][indices["gas"]] or b"0"), to=decode_hex(remove_0x_head(txdata["to"])), value=parse_int_or_hex(txdata["value"][indices["value"]] or b"0"), data=decode_hex(remove_0x_head(txdata["data"][indices["data"]])), gas_token_id=token_id_encode("QKC"), transfer_token_id=transfer_token_id, # Should not set testing flag if testing QuarkChain state is_testing=not is_qkc_state, ) tx.set_quark_chain_config(qkc_env.quark_chain_config) if "secretKey" in txdata: tx.sign(decode_hex(remove_0x_head(txdata["secretKey"]))) else: tx._in_mutable_context = True tx.v = parse_int_or_hex(txdata["v"]) tx._in_mutable_context = False # Run it prev = state.to_dict() success, output = apply_transaction(state, tx, tx_wrapper_hash=bytes(32)) except InvalidTransaction as e: print("Exception: %r" % e) success, output = False, b"" # touch coinbase, make behavior consistent with go-ethereum state.delta_token_balance(state.block_coinbase, token_id_encode("QKC"), 0) state.commit() post = state.to_dict() output_decl = { "hash": "0x" + encode_hex(state.trie.root_hash), "indexes": indices, "diff": mk_state_diff(prev, post), } state.revert(s) return output_decl
def coinbase(self): """Return the address that should be used as coinbase for new blocks. The coinbase address is given by the config field pow.coinbase_hex. If this does not exist or is `None`, the address of the first account is used instead. If there are no accounts, the coinbase is `DEFAULT_COINBASE`. :raises: :exc:`ValueError` if the coinbase is invalid (no string, wrong length) or there is no account for it and the config flag `accounts.check_coinbase` is set (does not apply to the default coinbase) """ cb_hex = self.app.config.get('pow', {}).get('coinbase_hex') if cb_hex is None: if not self.accounts_with_address: return DEFAULT_COINBASE cb = self.accounts_with_address[0].address else: # [NOTE]: check it! # if not is_string(cb_hex): if not isinstance(cb_hex, str): raise ValueError('coinbase must be string') try: cb = decode_hex(remove_0x_head(cb_hex)) except (ValueError, TypeError): raise ValueError('invalid coinbase') if len(cb) != 20: raise ValueError('wrong coinbase length') if self.config['accounts']['must_include_coinbase']: if cb not in (acct.address for acct in self.accounts): raise ValueError('no account for coinbase') return cb
def init_state(env, pre): # Setup env db = InMemoryDb() stateEnv = Env(config=konfig) stateEnv.db = db state = State( env=stateEnv, block_prevhash=decode_hex(remove_0x_head(env["previousHash"])), prev_headers=[ mk_fake_header(i) for i in range( parse_int_or_hex(env["currentNumber"]) - 1, max(-1, parse_int_or_hex(env["currentNumber"]) - 257), -1, ) ], block_number=parse_int_or_hex(env["currentNumber"]), block_coinbase=decode_hex(remove_0x_head(env["currentCoinbase"])), block_difficulty=parse_int_or_hex(env["currentDifficulty"]), gas_limit=parse_int_or_hex(env["currentGasLimit"]), timestamp=parse_int_or_hex(env["currentTimestamp"]), ) # Fill up pre for address, h in list(pre.items()): assert len(address) in (40, 42) address = decode_hex(remove_0x_head(address)) assert set(h.keys()) == set(["code", "nonce", "balance", "storage"]) state.set_nonce(address, parse_int_or_hex(h["nonce"])) state.set_balance(address, parse_int_or_hex(h["balance"])) state.set_code(address, decode_hex(remove_0x_head(h["code"]))) for k, v in h["storage"].items(): state.set_storage_data( address, big_endian_to_int(decode_hex(k[2:])), big_endian_to_int(decode_hex(v[2:])), ) state.commit(allow_empties=True) # state.commit() return state
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), )