async def get_receipts(self, block_hash: Hash32) -> List[Receipt]: peer = cast(LESPeer, self.peer_pool.highest_td_peer) self.logger.debug("Fetching %s receipts from %s", encode_hex(block_hash), peer) request_id = gen_request_id() peer.sub_proto.send_get_receipts(block_hash, request_id) reply = await self._wait_for_reply(request_id) if not reply['receipts']: raise BlockNotFound("No block with hash {} found".format(block_hash)) return reply['receipts'][0]
async def get_block_body_by_hash(self, block_hash: Hash32) -> BlockBody: peer = cast(LESPeer, self.peer_pool.highest_td_peer) self.logger.debug("Fetching block %s from %s", encode_hex(block_hash), peer) request_id = gen_request_id() peer.sub_proto.send_get_block_bodies([block_hash], request_id) reply = await self._wait_for_reply(request_id) if not reply['bodies']: raise BlockNotFound("Peer {} has no block with hash {}".format(peer, block_hash)) return reply['bodies'][0]
async def _get_proof(self, peer: LESPeer, block_hash: bytes, account_key: bytes, key: bytes, from_level: int = 0) -> List[bytes]: request_id = gen_request_id() peer.sub_proto.send_get_proof(block_hash, account_key, key, from_level, request_id) reply = await self._wait_for_reply(request_id) return reply['proof']
async def _handle_new_collation_hashes(self, peer: ShardingPeer, msg: Dict[str, Any]) -> None: """Request those collations.""" # Request all collations for now, no matter if we now about them or not, as there's no way # to header existence at the moment. In the future we won't transfer collations anyway but # only collation bodies (headers are retrieved from the main chain), so there's no need to # add this at the moment. from trinity.utils.les import gen_request_id collation_hashes = set( collation_hash for collation_hash, _ in msg["collation_hashes_and_periods"] ) if collation_hashes: peer.sub_proto = cast(ShardingProtocol, peer.sub_proto) peer.sub_proto.send_get_collations(gen_request_id(), list(collation_hashes))
async def __call__(self, # type: ignore block_number_or_hash: BlockIdentifier, max_headers: int = None, skip: int = 0, reverse: bool = True, timeout: int = None) -> Tuple[BlockHeader, ...]: request_id = gen_request_id() request = HeaderRequest( block_number_or_hash, max_headers, skip, reverse, request_id, ) return await self._request_and_wait(request, timeout)
async def get_collations(self, collation_hashes: List[Hash32], cancel_token: CancelToken) -> Set[Collation]: from trinity.utils.les import gen_request_id # Don't send empty request if len(collation_hashes) == 0: return set() request_id = gen_request_id() pending_reply: asyncio.Future[Tuple[ Command, protocol._DecodedMsgType]] = asyncio.Future() self._pending_replies[request_id] = pending_reply cast(ShardingProtocol, self.sub_proto).send_get_collations(request_id, collation_hashes) cmd, msg = await cancel_token.cancellable_wait(pending_reply) msg = cast(Dict[str, Any], msg) if not isinstance(cmd, Collations): raise UnexpectedMessage( "Expected Collations as response to GetCollations, but got %s", cmd.__class__.__name__) return set(msg["collations"])
async def _get_contract_code_from_peer(self, block_hash: Hash32, address: Address, code_hash: Hash32, peer: LESPeer) -> bytes: """ A single attempt to get the contract code from the given peer :raise BadLESResponse: if the peer replies with contract code that does not match the account's code hash """ # request contract code request_id = gen_request_id() peer.sub_proto.send_get_contract_code(block_hash, keccak(address), request_id) reply = await self._wait_for_reply(request_id) if not reply['codes']: bytecode = b'' else: bytecode = reply['codes'][0] # validate bytecode against a proven account if code_hash == keccak(bytecode): return bytecode elif bytecode == b'': await self._raise_for_empty_code(block_hash, address, code_hash, peer) # The following is added for mypy linting: raise RuntimeError( "Unreachable, _raise_for_empty_code must raise its own exception" ) else: # a bad-acting peer sent an invalid non-empty bytecode raise BadLESResponse( "Peer %s sent code %s that did not match hash %s in account %s" % ( peer, encode_hex(bytecode), encode_hex(code_hash), encode_hex(address), ))
async def __call__( # type: ignore self, block_number_or_hash: BlockIdentifier, max_headers: int = None, skip: int = 0, reverse: bool = True, timeout: int = None) -> Tuple[BlockHeader, ...]: original_request_args = (block_number_or_hash, max_headers, skip, reverse) validator = GetBlockHeadersValidator(*original_request_args) command_args = original_request_args + (gen_request_id(), ) request = GetBlockHeadersRequest(*command_args) return await self.get_result( request, self._normalizer, validator, match_payload_request_id, timeout, )
async def _get_block_header_by_hash(self, block_hash: Hash32, peer: LESPeer) -> BlockHeader: """ A single attempt to get the block header from the given peer. :raise BadLESResponse: if the peer replies with a header that has a different hash """ self.logger.debug("Fetching header %s from %s", encode_hex(block_hash), peer) request_id = gen_request_id() max_headers = 1 peer.sub_proto.send_get_block_headers(block_hash, max_headers, 0, False, request_id) reply = await self._wait_for_reply(request_id) if not reply['headers']: raise HeaderNotFound("Peer {} has no block with hash {}".format( peer, block_hash)) header = reply['headers'][0] if header.hash != block_hash: raise BadLESResponse( "Received header hash (%s) does not match what we requested (%s)", header.hex_hash, encode_hex(block_hash)) return header