Beispiel #1
0
 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]
Beispiel #2
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]
Beispiel #3
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']
Beispiel #4
0
    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))
Beispiel #5
0
 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)
Beispiel #6
0
    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"])
Beispiel #7
0
    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),
                ))
Beispiel #8
0
    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,
        )
Beispiel #9
0
    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