def dict_to_spoof_transaction( chain: AsyncChainAPI, header: BlockHeaderAPI, transaction_dict: Dict[str, Any]) -> SignedTransactionAPI: """ 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.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 cast(SignedTransactionAPI, SpoofTransaction(unsigned, from_=sender))
async def state_at_block( chain: AsyncChainAPI, at_block: Union[str, int], read_only: bool = True) -> StateAPI: at_header = await get_header(chain, at_block) vm = chain.get_vm(at_header) return vm.state
async def get_header(chain: AsyncChainAPI, at_block: Union[str, int]) -> BlockHeaderAPI: 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(BlockNumber(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( BlockNumber(int(at_block))) at_header = block.header else: raise TypeError("Unrecognized block reference: %r" % at_block) return at_header
def block_to_dict(block: BlockAPI, chain: AsyncChainAPI, include_transactions: bool) -> RpcBlockResponse: # There doesn't seem to be a type safe way to initialize the RpcBlockResponse from # a RpcHeaderResponse + the extra fields hence the cast here. response = cast(RpcBlockResponse, header_to_dict(block.header)) if include_transactions: txs: Union[Sequence[str], Sequence[RpcBlockTransactionResponse]] = [ block_transaction_to_dict(tx, block.header) for tx in block.transactions ] else: txs = [encode_hex(tx.hash) for tx in block.transactions] response['totalDifficulty'] = hex(chain.get_score(block.hash)) response['uncles'] = [encode_hex(uncle.hash) for uncle in block.uncles] response['size'] = hex(len(rlp.encode(block))) response['transactions'] = txs return response
def block_to_dict( block: BlockAPI, chain: AsyncChainAPI, include_transactions: bool) -> Dict[str, Union[str, List[str]]]: header_dict = header_to_dict(block.header) block_dict: Dict[str, Union[str, List[str]]] = dict( header_dict, totalDifficulty=hex(chain.get_score(block.hash)), uncles=[encode_hex(uncle.hash) for uncle in block.uncles], size=hex(len(rlp.encode(block))), ) if include_transactions: # block_dict['transactions'] = map(transaction_to_dict, block.transactions) raise NotImplementedError( "Cannot return transaction object with block, yet") else: block_dict['transactions'] = [ encode_hex(tx.hash) for tx in block.transactions ] return block_dict
async def check_requested_block_age(chain: AsyncChainAPI, func: Func, params: Any) -> BlockHeaderAPI: """ :return: the reference header used for the data lookup. """ sig = inspect.signature(func) params = sig.bind(*params) try: at_block_name = getattr(func, AT_BLOCK_ATTRIBUTE_NAME) except AttributeError as e: raise Exception( "Function {func} was not decorated with @retryable") from e at_block = to_int_if_hex(params.arguments[at_block_name]) requested_header = await get_header(chain, at_block) requested_block = requested_header.block_number current_block = chain.get_canonical_head().block_number if requested_block < current_block - 64: raise Exception( f'block "{at_block}" is too old to be fetched over the network') else: return requested_header