def dict_to_spoof_transaction( chain: AsyncChain, header: BlockHeader, transaction_dict: Dict[str, Any]) -> SpoofTransaction: """ Convert dicts used in calls & gas estimates into a spoof transaction """ txn_dict = normalize_transaction_dict(transaction_dict) sender = txn_dict.get('from', ZERO_ADDRESS) if 'nonce' in txn_dict: nonce = txn_dict['nonce'] else: vm = chain.get_vm(header) nonce = vm.state.account_db.get_nonce(sender) gas_price = txn_dict.get('gasPrice', 0) gas = txn_dict.get('gas', header.gas_limit) unsigned = chain.get_vm_class(header).create_unsigned_transaction( nonce=nonce, gas_price=gas_price, gas=gas, to=txn_dict['to'], value=txn_dict['value'], data=txn_dict['data'], ) return SpoofTransaction(unsigned, from_=sender)
def receipt_to_dict(receipt: Receipt, tx_hash: Hash32, chain: AsyncChain) -> Dict[str, str]: dict_to_return = all_rlp_fields_to_dict_camel_case(receipt) block_hash, index, is_receive = chain.chaindb.get_transaction_index( tx_hash) dict_to_return['blockHash'] = to_hex(block_hash) dict_to_return['transactionHash'] = to_hex(tx_hash) dict_to_return['isReceive'] = to_hex(is_receive) dict_to_return['transactionIndex'] = to_hex(index) block_header = chain.get_block_header_by_hash(block_hash) dict_to_return['blockNumber'] = to_hex(block_header.block_number) for i in range(len(dict_to_return['logs'])): dict_to_return['logs'][i]['logIndex'] = to_hex(i) dict_to_return['logs'][i]['transactionIndex'] = to_hex(index) dict_to_return['logs'][i]['transactionHash'] = to_hex(tx_hash) dict_to_return['logs'][i]['blockHash'] = to_hex(block_hash) dict_to_return['logs'][i]['blockNumber'] = to_hex( block_header.block_number) dict_to_return['logs'][i]['topics'] = [ pad_hex(value, 32) for value in dict_to_return['logs'][i]['topics'] ] transaction = chain.get_canonical_transaction(tx_hash) if is_receive: dict_to_return['to'] = to_hex(block_header.chain_address) dict_to_return['sender'] = to_hex( chain.chaindb.get_chain_wallet_address_for_block_hash( transaction.sender_block_hash)) else: dict_to_return['to'] = to_hex(transaction.to) dict_to_return['sender'] = to_hex(transaction.sender) if transaction.to == CREATE_CONTRACT_ADDRESS: dict_to_return['contractAddress'] = to_hex( generate_contract_address(transaction.sender, transaction.nonce)) dict_to_return['cumulativeGasUsed'] = to_hex( chain.chaindb.get_cumulative_gas_used(tx_hash)) return dict_to_return
def receive_transaction_to_dict(transaction: BaseReceiveTransaction, chain: AsyncChain) -> Dict[str, str]: tx_hash = transaction.hash dict_to_return = all_rlp_fields_to_dict_camel_case(transaction) dict_to_return['isReceive'] = to_hex(True) dict_to_return['hash'] = encode_hex(tx_hash) from_address = chain.get_block_header_by_hash( transaction.sender_block_hash).chain_address dict_to_return['from'] = to_hex(from_address) originating_transaction = chain.chaindb.get_transaction_by_hash( transaction.send_transaction_hash, send_tx_class=chain.get_vm().get_transaction_class(), receive_tx_class=chain.get_vm().get_receive_transaction_class()) if transaction.is_refund: value = originating_transaction.remaining_refund else: value = originating_transaction.value dict_to_return['value'] = to_hex(value) dict_to_return['gasPrice'] = to_hex(originating_transaction.gas_price) dict_to_return['to'] = to_hex(originating_transaction.to) try: dict_to_return['gasUsed'] = to_hex( chain.chaindb.get_transaction_receipt(transaction.hash).gas_used) except TransactionNotFound: dict_to_return['gasUsed'] = to_hex(0) try: block_hash, receive_tx_index, _ = chain.chaindb.get_transaction_index( tx_hash) num_send_transactions = chain.chaindb.get_number_of_send_tx_in_block( block_hash) block_tx_index = num_send_transactions + receive_tx_index dict_to_return['transactionIndex'] = to_hex(block_tx_index) dict_to_return['blockHash'] = to_hex(block_hash) except TransactionNotFound: pass return dict_to_return
async def get_header(chain: AsyncChain, at_block: Union[str, int]) -> BlockHeader: if at_block == 'pending': raise NotImplementedError( "RPC interface does not support the 'pending' block at this time") elif at_block == 'latest': at_header = chain.get_canonical_head() elif at_block == 'earliest': # TODO find if genesis block can be non-zero. Why does 'earliest' option even exist? block = await chain.coro_get_canonical_block_by_number(0) at_header = block.header # mypy doesn't have user defined type guards yet # https://github.com/python/mypy/issues/5206 elif is_integer(at_block) and at_block >= 0: # type: ignore block = await chain.coro_get_canonical_block_by_number(0) at_header = block.header else: raise TypeError("Unrecognized block reference: %r" % at_block) return at_header
async def account_db_at_block(chain: AsyncChain, at_block: Union[str, int], read_only: bool = True) -> BaseAccountDB: at_header = await get_header(chain, at_block) vm = chain.get_vm(at_header) return vm.state.account_db