コード例 #1
0
ファイル: peer.py プロジェクト: smallbaby/py-evm
 async def process_p2p_handshake(
         self, cmd: protocol.Command, msg: protocol._DecodedMsgType) -> None:
     msg = cast(Dict[str, Any], msg)
     if not isinstance(cmd, Hello):
         await self.disconnect(DisconnectReason.bad_protocol)
         raise HandshakeFailure("Expected a Hello msg, got {}, disconnecting".format(cmd))
     remote_capabilities = msg['capabilities']
     try:
         self.sub_proto = self.select_sub_protocol(remote_capabilities)
     except NoMatchingPeerCapabilities:
         await self.disconnect(DisconnectReason.useless_peer)
         raise HandshakeFailure(
             "No matching capabilities between us ({}) and {} ({}), disconnecting".format(
                 self.capabilities, self.remote, remote_capabilities))
     self.logger.debug(
         "Finished P2P handshake with %s, using sub-protocol %s",
         self.remote, self.sub_proto)
コード例 #2
0
ファイル: server.py プロジェクト: tuxxy/py-evm
 async def do_handshake(self, peer: BasePeer) -> None:
     try:
         await peer.do_p2p_handshake(),
     except MalformedMessage as e:
         raise HandshakeFailure() from e
     await peer.do_sub_proto_handshake()
     await peer.ensure_same_side_on_dao_fork(self.chain.get_vm_configuration())
     self._start_peer(peer)
コード例 #3
0
    async def do_p2p_handshake(self):
        """Perform the handshake for the P2P base protocol.

        Raises HandshakeFailure if the handshake is not successful.
        """
        self.base_protocol.send_handshake()

        try:
            cmd, msg = await self.read_msg()
        except rlp.DecodingError:
            raise HandshakeFailure("Got invalid rlp data during handshake")

        if isinstance(cmd, Disconnect):
            # Peers sometimes send a disconnect msg before they send the initial P2P handshake.
            raise HandshakeFailure("{} disconnected before completing handshake: {}".format(
                self, msg['reason_name']))
        self.process_p2p_handshake(cmd, msg)
コード例 #4
0
    async def do_handshake(
            self, multiplexer: MultiplexerAPI,
            protocol: Union[LESProtocolV1,
                            LESProtocolV2]) -> LESHandshakeReceipt:
        """Perform the handshake for the sub-protocol agreed with the remote peer.

        Raises HandshakeFailure if the handshake is not successful.
        """

        protocol.send(protocol.status_command_type(self.handshake_params))

        async for cmd in multiplexer.stream_protocol_messages(protocol):
            if not isinstance(cmd, (StatusV1, StatusV2)):
                raise HandshakeFailure(
                    f"Expected a LES Status msg, got {cmd}, disconnecting")

            if cmd.payload.network_id != self.handshake_params.network_id:
                raise WrongNetworkFailure(
                    f"{multiplexer.remote} network "
                    f"({cmd.payload.network_id}) does not match ours "
                    f"({self.handshake_params.network_id}), disconnecting")

            if cmd.payload.genesis_hash != self.handshake_params.genesis_hash:
                raise WrongGenesisFailure(
                    f"{multiplexer.remote} genesis "
                    f"({encode_hex(cmd.payload.genesis_hash)}) does "
                    f"not match ours "
                    f"({encode_hex(self.handshake_params.genesis_hash)}), "
                    f"disconnecting")

            # Eventually we might want to keep connections to peers where we
            # are the only side serving data, but right now both our chain
            # syncer and the Peer.boot() method expect the remote to reply to
            # header requests, so if they don't we simply disconnect here.
            if cmd.payload.serve_headers is False:
                raise HandshakeFailure(
                    f"{multiplexer.remote} doesn't serve headers, disconnecting"
                )

            receipt = LESHandshakeReceipt(protocol, cmd.payload)
            break
        else:
            raise HandshakeFailure(
                "Message stream exited before finishing handshake")

        return receipt
コード例 #5
0
    async def do_handshake(self,
                           multiplexer: MultiplexerAPI,
                           protocol: ProtocolAPI) -> ETHHandshakeReceipt:
        """Perform the handshake for the sub-protocol agreed with the remote peer.

        Raises HandshakeFailure if the handshake is not successful.
        """
        protocol = cast(ETHProtocol, protocol)
        protocol.send_handshake(self.handshake_params)

        async for cmd, msg in multiplexer.stream_protocol_messages(protocol):
            if not isinstance(cmd, Status):
                raise HandshakeFailure(f"Expected a ETH Status msg, got {cmd}, disconnecting")

            msg = cast(Dict[str, Any], msg)

            remote_params = ETHHandshakeParams(
                version=msg['protocol_version'],
                network_id=msg['network_id'],
                total_difficulty=msg['td'],
                head_hash=msg['best_hash'],
                genesis_hash=msg['genesis_hash'],
            )
            receipt = ETHHandshakeReceipt(protocol, remote_params)

            if receipt.handshake_params.network_id != self.handshake_params.network_id:
                raise WrongNetworkFailure(
                    f"{multiplexer.remote} network "
                    f"({receipt.handshake_params.network_id}) does not match ours "
                    f"({self.handshake_params.network_id}), disconnecting"
                )

            if receipt.handshake_params.genesis_hash != self.handshake_params.genesis_hash:
                raise WrongGenesisFailure(
                    f"{multiplexer.remote} genesis "
                    f"({encode_hex(receipt.handshake_params.genesis_hash)}) does "
                    f"not match ours ({encode_hex(self.handshake_params.genesis_hash)}), "
                    f"disconnecting"
                )

            break
        else:
            raise HandshakeFailure("Message stream exited before finishing handshake")

        return receipt
コード例 #6
0
ファイル: packer.py プロジェクト: simulationcoin/trinity
 async def check_handshake_timeout(self, handshake_successful_event: trio.Event) -> None:
     try:
         with trio.fail_after(HANDSHAKE_TIMEOUT):
             # Only the timeout for successful handshakes has to be checked as a failure during
             # handshake will make the service as a whole fail.
             await handshake_successful_event.wait()
     except trio.TooSlowError as too_slow_error:
         self.logger.warning("Handshake with %s has timed out", encode_hex(self.remote_node_id))
         raise HandshakeFailure("Handshake has timed out") from too_slow_error
コード例 #7
0
 def process_sub_proto_handshake(self, cmd: protocol.Command,
                                 msg: protocol._DecodedMsgType) -> None:
     if not isinstance(cmd, eth.Status):
         self.disconnect(DisconnectReason.other)
         raise HandshakeFailure(
             "Expected a ETH Status msg, got {}, disconnecting".format(cmd))
     msg = cast(Dict[str, Any], msg)
     if msg['network_id'] != self.network_id:
         self.disconnect(DisconnectReason.other)
         raise HandshakeFailure(
             "{} network ({}) does not match ours ({}), disconnecting".
             format(self, msg['network_id'], self.network_id))
     if msg['genesis_hash'] != self.genesis.hash:
         self.disconnect(DisconnectReason.other)
         raise HandshakeFailure(
             "{} genesis ({}) does not match ours ({}), disconnecting".
             format(self, encode_hex(msg['genesis_hash']),
                    self.genesis.hex_hash))
コード例 #8
0
async def test_records_failures():
    connection_tracker = MemoryConnectionTracker()

    node = NodeFactory()
    assert await connection_tracker.should_connect_to(node) is True

    connection_tracker.record_failure(node, HandshakeFailure())

    assert await connection_tracker.should_connect_to(node) is False
    assert connection_tracker._record_exists(node.uri())
コード例 #9
0
ファイル: helpers.py プロジェクト: s0b0lev/trinity
async def process_v4_p2p_handshake(self: BasePeer, cmd: protocol.Command,
                                   msg: protocol.Payload) -> None:
    """
    This function is the replacement to the existing process_p2p_handshake
    function.
    This is used to simulate the v4 P2PProtocol node.
    The only change that has been made is to remove the snappy support irrespective
    of whether the other client supports it or not.
    """
    msg = cast(Dict[str, Any], msg)
    if not isinstance(cmd, Hello):
        await self.disconnect(DisconnectReason.bad_protocol)
        raise HandshakeFailure(
            f"Expected a Hello msg, got {cmd}, disconnecting")

    # As far as a v4 P2PProtocol client is concerned,
    # it never support snappy compression
    snappy_support = False

    remote_capabilities = msg['capabilities']
    matched_proto_classes = match_protocols_with_capabilities(
        self.supported_sub_protocols,
        remote_capabilities,
    )
    if len(matched_proto_classes) == 1:
        self.sub_proto = matched_proto_classes[0](
            self.transport,
            self.base_protocol.cmd_length,
            snappy_support,
        )
    elif len(matched_proto_classes) > 1:
        raise NotImplementedError(
            f"Peer {self.remote} connection matched on multiple protocols "
            f"{matched_proto_classes}.  Support for multiple protocols is not "
            f"yet supported")
    else:
        await self.disconnect(DisconnectReason.useless_peer)
        raise HandshakeFailure(
            f"No matching capabilities between us ({self.capabilities}) and {self.remote} "
            f"({remote_capabilities}), disconnecting")

    self.logger.debug("Finished P2P handshake with %s, using sub-protocol %s",
                      self.remote, self.sub_proto)
コード例 #10
0
    async def process_p2p_handshake(self, cmd: protocol.Command,
                                    msg: protocol.PayloadType) -> None:
        msg = cast(Dict[str, Any], msg)
        if not isinstance(cmd, Hello):
            await self.disconnect(DisconnectReason.bad_protocol)
            raise HandshakeFailure(
                f"Expected a Hello msg, got {cmd}, disconnecting")

        # limit number of chars to be displayed, and try to keep printable ones only
        # MAGIC 256: arbitrary, "should be enough for everybody"
        original_version = msg['client_version_string']
        client_version_string = original_version[:256] + (
            '...' if original_version[256:] else '')
        if client_version_string.isprintable():
            self.client_version_string = client_version_string.strip()
        else:
            self.client_version_string = repr(client_version_string)

        # Check whether to support Snappy Compression or not
        # based on other peer's p2p protocol version
        snappy_support = msg['version'] >= SNAPPY_PROTOCOL_VERSION

        if snappy_support:
            # Now update the base protocol to support snappy compression
            # This is needed so that Trinity is compatible with parity since
            # parity sends Ping immediately after Handshake
            self.base_protocol = P2PProtocol(self,
                                             snappy_support=snappy_support)

        remote_capabilities = msg['capabilities']
        try:
            self.sub_proto = self.select_sub_protocol(remote_capabilities,
                                                      snappy_support)
        except NoMatchingPeerCapabilities:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"No matching capabilities between us ({self.capabilities}) and {self.remote} "
                f"({remote_capabilities}), disconnecting")

        self.logger.debug(
            "Finished P2P handshake with %s, using sub-protocol %s",
            self.remote, self.sub_proto)
コード例 #11
0
ファイル: peer.py プロジェクト: caesarchad/py-evm
 async def process_sub_proto_handshake(
         self, cmd: protocol.Command, msg: protocol._DecodedMsgType) -> None:
     if not isinstance(cmd, (les.Status, les.StatusV2)):
         self.disconnect(DisconnectReason.subprotocol_error)
         raise HandshakeFailure(
             "Expected a LES Status msg, got {}, disconnecting".format(cmd))
     msg = cast(Dict[str, Any], msg)
     if msg['networkId'] != self.network_id:
         self.disconnect(DisconnectReason.useless_peer)
         raise HandshakeFailure(
             "{} network ({}) does not match ours ({}), disconnecting".format(
                 self, msg['networkId'], self.network_id))
     genesis = await self.genesis
     if msg['genesisHash'] != genesis.hash:
         self.disconnect(DisconnectReason.useless_peer)
         raise HandshakeFailure(
             "{} genesis ({}) does not match ours ({}), disconnecting".format(
                 self, encode_hex(msg['genesisHash']), genesis.hex_hash))
     # TODO: Disconnect if the remote doesn't serve headers.
     self.head_info = cmd.as_head_info(msg)
コード例 #12
0
ファイル: peer.py プロジェクト: wimel/py-evm
 async def process_sub_proto_handshake(
         self, cmd: Command, msg: _DecodedMsgType) -> None:
     if not isinstance(cmd, Status):
         await self.disconnect(DisconnectReason.subprotocol_error)
         raise HandshakeFailure(
             "Expected a ETH Status msg, got {}, disconnecting".format(cmd))
     msg = cast(Dict[str, Any], msg)
     if msg['network_id'] != self.network_id:
         await self.disconnect(DisconnectReason.useless_peer)
         raise HandshakeFailure(
             "{} network ({}) does not match ours ({}), disconnecting".format(
                 self, msg['network_id'], self.network_id))
     genesis = await self.genesis
     if msg['genesis_hash'] != genesis.hash:
         await self.disconnect(DisconnectReason.useless_peer)
         raise HandshakeFailure(
             "{} genesis ({}) does not match ours ({}), disconnecting".format(
                 self, encode_hex(msg['genesis_hash']), genesis.hex_hash))
     self.head_td = msg['td']
     self.head_hash = msg['best_hash']
コード例 #13
0
def test_timeout_for_failure():
    get_timeout = persistence.timeout_for_failure

    assert get_timeout(WrongGenesisFailure()) == 60 * 60 * 24
    assert get_timeout(HandshakeFailure()) == 10

    class UnknownException(Exception):
        pass

    with pytest.raises(Exception, match="Unknown failure type"):
        assert get_timeout(UnknownException()) is None
コード例 #14
0
ファイル: handshaker.py プロジェクト: wangroot/trinity
    async def do_handshake(self, multiplexer: MultiplexerAPI,
                           protocol: BaseETHProtocol) -> ETHHandshakeReceipt:
        """
        Perform the handshake for the sub-protocol agreed with the remote peer.

        Raise HandshakeFailure if the handshake is not successful.
        """

        self.logger.debug("Performing %s handshake with %s", protocol,
                          multiplexer.remote)
        protocol.send(Status(self.handshake_params))

        async for cmd in multiplexer.stream_protocol_messages(protocol):
            if not isinstance(cmd, Status):
                raise HandshakeFailure(
                    f"Expected a ETH Status msg, got {cmd}, disconnecting")

            receipt = ETHHandshakeReceipt(protocol, cmd.payload)

            validate_base_receipt(multiplexer.remote, receipt,
                                  self.handshake_params)

            try:
                validate_forkid(
                    receipt.fork_id,
                    self.handshake_params.genesis_hash,
                    self.head_number,
                    self.fork_blocks,
                )
            except BaseForkIDValidationError as exc:
                raise WrongForkIDFailure(
                    f"{multiplexer.remote} forkid "
                    f"({receipt.handshake_params.fork_id}) is incompatible to ours ({exc})"
                    f"({self.handshake_params.fork_id}), disconnecting")

            break
        else:
            raise HandshakeFailure(
                "Message stream exited before finishing handshake")

        return receipt
コード例 #15
0
    async def do_p2p_handshake(self) -> None:
        """Perform the handshake for the P2P base protocol.

        Raises HandshakeFailure if the handshake is not successful.
        """
        self.base_protocol.send_handshake()

        try:
            cmd, msg = await self.read_msg()
        except rlp.DecodingError:
            raise HandshakeFailure("Got invalid rlp data during handshake")
        except MalformedMessage as e:
            raise HandshakeFailure("Got malformed message during handshake") from e

        if isinstance(cmd, Disconnect):
            msg = cast(Dict[str, Any], msg)
            # Peers sometimes send a disconnect msg before they send the initial P2P handshake.
            raise HandshakeFailure(
                f"{self} disconnected before completing sub-proto handshake: {msg['reason_name']}"
            )
        await self.process_p2p_handshake(cmd, msg)
コード例 #16
0
async def test_records_failures():
    connection_tracker = MemoryConnectionTracker()

    node = NodeFactory()
    blacklisted_ids = await connection_tracker.get_blacklisted()
    assert node.id not in blacklisted_ids

    connection_tracker.record_failure(node, HandshakeFailure())

    blacklisted_ids = await connection_tracker.get_blacklisted()
    assert node.id in blacklisted_ids
    assert connection_tracker._record_exists(node.id)
コード例 #17
0
    def decrypt_and_validate_auth_response(
        self,
        auth_header_packet: AuthHeaderPacket,
        auth_response_key: AES128Key,
        id_nonce: IDNonce,
    ) -> Optional[ENR]:
        try:
            id_nonce_signature, enr = auth_header_packet.decrypt_auth_response(
                auth_response_key)
        except DecryptionError as error:
            raise HandshakeFailure(
                "Unable to decrypt auth response") from error
        except ValidationError as error:
            raise HandshakeFailure("Invalid auth response content") from error

        # validate ENR if present
        if enr is None:
            if self.remote_enr is None:
                raise HandshakeFailure("Peer failed to send their ENR")
            else:
                current_remote_enr = self.remote_enr
        else:
            try:
                enr.validate_signature()
            except ValidationError as error:
                raise HandshakeFailure(
                    "ENR in auth response contains invalid signature"
                ) from error

            if self.remote_enr is not None:
                if enr.sequence_number <= self.remote_enr.sequence_number:
                    raise HandshakeFailure(
                        "ENR in auth response is not newer than what we already have"
                    )

            if enr.node_id != self.remote_node_id:
                raise HandshakeFailure(
                    f"ENR received from peer belongs to different node ({encode_hex(enr.node_id)} "
                    f"instead of {encode_hex(self.remote_node_id)})")

            current_remote_enr = enr

        try:
            self.identity_scheme.validate_id_nonce_signature(
                signature=id_nonce_signature,
                id_nonce=id_nonce,
                ephemeral_public_key=auth_header_packet.auth_header.
                ephemeral_public_key,
                public_key=current_remote_enr.public_key,
            )
        except ValidationError as error:
            raise HandshakeFailure(
                "Invalid id nonce signature in auth response") from error

        return enr
コード例 #18
0
def test_memory_does_not_persist():
    node = random_node()

    peer_info = MemoryPeerInfo()
    assert peer_info.should_connect_to(node) is True
    peer_info.record_failure(node, HandshakeFailure())
    assert peer_info.should_connect_to(node) is False
    peer_info.close()

    # open a second instance
    peer_info = MemoryPeerInfo()
    # the second instance has no memory of the failure
    assert peer_info.should_connect_to(node) is True
コード例 #19
0
ファイル: peer.py プロジェクト: s0b0lev/trinity
    async def process_sub_proto_handshake(self, cmd: CommandAPI,
                                          msg: Payload) -> None:
        if not isinstance(cmd, Status):
            await self.disconnect(DisconnectReason.subprotocol_error)
            raise HandshakeFailure(
                f"Expected a BCC Status msg, got {cmd}, disconnecting")

        msg = cast(StatusMessage, msg)
        if msg['network_id'] != self.network_id:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} network ({msg['network_id']}) does not match ours "
                f"({self.network_id}), disconnecting")
        genesis_root = await self.get_genesis_root()

        if msg['genesis_root'] != genesis_root:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} genesis ({encode_hex(msg['genesis_root'])}) does not "
                f"match ours ({encode_hex(genesis_root)}), disconnecting")

        self.head_slot = msg['head_slot']
コード例 #20
0
    async def do_handshake(self, multiplexer: MultiplexerAPI,
                           protocol: ProtocolAPI) -> BCCHandshakeReceipt:
        """Perform the handshake for the sub-protocol agreed with the remote peer.

        Raises HandshakeFailure if the handshake is not successful.
        """
        protocol = cast(BCCProtocol, protocol)
        protocol.send_handshake(self.handshake_params)

        async for cmd, msg in multiplexer.stream_protocol_messages(protocol):
            if not isinstance(cmd, Status):
                raise HandshakeFailure(
                    f"Expected a BCC Status msg, got {cmd}, disconnecting")

            msg = cast(StatusMessage, msg)
            remote_params = BCCHandshakeParams(
                protocol_version=msg['protocol_version'],
                network_id=msg['network_id'],
                genesis_root=msg['genesis_root'],
                head_slot=msg['head_slot'],
            )

            if remote_params.network_id != self.handshake_params.network_id:
                raise HandshakeFailure(
                    f"{self} network ({remote_params.network_id}) does not match ours "
                    f"({self.handshake_params.network_id}), disconnecting")
            if remote_params.genesis_root != self.handshake_params.genesis_root:
                raise HandshakeFailure(
                    f"{self} genesis ({encode_hex(remote_params.genesis_root)}) does not "
                    f"match ours ({encode_hex(self.handshake_params.genesis_root)}), disconnecting"
                )

            receipt = BCCHandshakeReceipt(protocol, remote_params)
            break
        else:
            raise HandshakeFailure(
                "Message stream exited before finishing handshake")

        return receipt
コード例 #21
0
ファイル: peer.py プロジェクト: sriharikapu/py-evm
    async def process_sub_proto_handshake(self, cmd: Command, msg: _DecodedMsgType) -> None:
        if not isinstance(cmd, Status):
            await self.disconnect(DisconnectReason.subprotocol_error)
            raise HandshakeFailure(f"Expected a BCC Status msg, got {cmd}, disconnecting")

        msg = cast(Dict[str, Any], msg)
        if msg['network_id'] != self.network_id:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} network ({msg['network_id']}) does not match ours "
                f"({self.network_id}), disconnecting"
            )

        genesis_block = self.chain_db.get_canonical_block_by_slot(0)
        if msg['genesis_hash'] != genesis_block.hash:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} genesis ({encode_hex(msg['genesis_hash'])}) does not "
                f"match ours ({encode_hex(genesis_block.hash)}), disconnecting"
            )

        self.head_hash = msg['best_hash']
コード例 #22
0
async def test_sql_does_persist(tmpdir):
    db_path = Path(tmpdir.join("nodedb"))
    node = NodeFactory()

    connection_tracker_a = SQLiteConnectionTracker(get_tracking_database(db_path))
    assert await connection_tracker_a.should_connect_to(node) is True
    connection_tracker_a.record_failure(node, HandshakeFailure())
    assert await connection_tracker_a.should_connect_to(node) is False
    del connection_tracker_a

    # open a second instance
    connection_tracker_b = SQLiteConnectionTracker(get_tracking_database(db_path))
    # the second instance remembers the failure
    assert await connection_tracker_b.should_connect_to(node) is False
コード例 #23
0
async def test_memory_does_not_persist():
    node = NodeFactory()

    connection_tracker_a = MemoryConnectionTracker()
    assert await connection_tracker_a.should_connect_to(node) is True
    connection_tracker_a.record_failure(node, HandshakeFailure())
    assert await connection_tracker_a.should_connect_to(node) is False

    # open a second instance
    connection_tracker_b = MemoryConnectionTracker()

    # the second instance has no memory of the failure
    assert await connection_tracker_b.should_connect_to(node) is True
    assert await connection_tracker_a.should_connect_to(node) is False
コード例 #24
0
ファイル: peer.py プロジェクト: sunfinite/py-evm
    async def do_sub_proto_handshake(self):
        """Perform the handshake for the sub-protocol agreed with the remote peer.

        Raises HandshakeFailure if the handshake is not successful.
        """
        await self.send_sub_proto_handshake()
        cmd, msg = await self.read_msg()
        if isinstance(cmd, Disconnect):
            # Peers sometimes send a disconnect msg before they send the sub-proto handshake.
            raise HandshakeFailure(
                "{} disconnected before completing sub-proto handshake: {}".format(
                    self, msg['reason_name']))
        await self.process_sub_proto_handshake(cmd, msg)
        self.logger.debug("Finished %s handshake with %s", self.sub_proto, self.remote)
コード例 #25
0
async def _handshake(
    initiator: 'HandshakeInitiator',
    reader: asyncio.StreamReader,
    writer: asyncio.StreamWriter,
    token: CancelToken,
) -> Tuple[bytes, bytes, sha3.keccak_256, sha3.keccak_256]:
    """See the handshake() function above.

    This code was factored out into this helper so that we can create Peers with directly
    connected readers/writers for our tests.
    """
    initiator_nonce = keccak(os.urandom(HASH_LEN))
    auth_msg = initiator.create_auth_message(initiator_nonce)
    auth_init = initiator.encrypt_auth_message(auth_msg)

    if writer.transport.is_closing():
        raise HandshakeFailure(
            "Error during handshake with {initiator.remote!r}. Writer closed.")

    writer.write(auth_init)

    auth_ack = await token.cancellable_wait(
        reader.read(ENCRYPTED_AUTH_ACK_LEN), timeout=REPLY_TIMEOUT)

    if reader.at_eof():
        # This is what happens when Parity nodes have blacklisted us
        # (https://github.com/ethereum/py-evm/issues/901).
        raise HandshakeFailure(
            f"{initiator.remote!r} disconnected before sending auth ack")

    ephemeral_pubkey, responder_nonce = initiator.decode_auth_ack_message(
        auth_ack)
    aes_secret, mac_secret, egress_mac, ingress_mac = initiator.derive_secrets(
        initiator_nonce, responder_nonce, ephemeral_pubkey, auth_init,
        auth_ack)

    return aes_secret, mac_secret, egress_mac, ingress_mac
コード例 #26
0
    async def process_sub_proto_handshake(self, cmd: Command,
                                          msg: _DecodedMsgType) -> None:
        if not isinstance(cmd, Status):
            await self.disconnect(DisconnectReason.subprotocol_error)
            raise HandshakeFailure(
                f"Expected a BCC Status msg, got {cmd}, disconnecting")

        msg = cast(StatusMessage, msg)
        if msg['network_id'] != self.network_id:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} network ({msg['network_id']}) does not match ours "
                f"({self.network_id}), disconnecting")
        # TODO: pass accurate `block_class: Type[BaseBeaconBlock]` under per BeaconStateMachine fork
        genesis_block = self.chain_db.get_canonical_block_by_slot(
            0, BeaconBlock)
        if msg['genesis_hash'] != genesis_block.hash:
            await self.disconnect(DisconnectReason.useless_peer)
            raise HandshakeFailure(
                f"{self} genesis ({encode_hex(msg['genesis_hash'])}) does not "
                f"match ours ({encode_hex(genesis_block.hash)}), disconnecting"
            )

        self.head_slot = msg['head_slot']
コード例 #27
0
def test_sql_does_persist(temp_path):
    dbpath = temp_path / "nodedb"
    node = random_node()

    peer_info = SQLitePeerInfo(dbpath)
    assert peer_info.should_connect_to(node) is True
    peer_info.record_failure(node, HandshakeFailure())
    assert peer_info.should_connect_to(node) is False
    peer_info.close()

    # open a second instance
    peer_info = SQLitePeerInfo(dbpath)
    # the second instance remembers the failure
    assert peer_info.should_connect_to(node) is False
    peer_info.close()
コード例 #28
0
    async def do_handshake(self,
                           multiplexer: MultiplexerAPI,
                           protocol: ETHProtocolV63) -> ETHV63HandshakeReceipt:
        """
        Perform the handshake for the sub-protocol agreed with the remote peer.

        Raise HandshakeFailure if the handshake is not successful.
        """

        protocol.send(StatusV63(self.handshake_params))

        async for cmd in multiplexer.stream_protocol_messages(protocol):
            if not isinstance(cmd, StatusV63):
                raise HandshakeFailure(f"Expected a ETH Status msg, got {cmd}, disconnecting")

            receipt = ETHV63HandshakeReceipt(protocol, cmd.payload)

            validate_base_receipt(multiplexer.remote, receipt, self.handshake_params)

            break
        else:
            raise HandshakeFailure("Message stream exited before finishing handshake")

        return receipt
コード例 #29
0
async def test_timeout_works():
    node = NodeFactory()

    connection_tracker = MemoryConnectionTracker()
    assert await connection_tracker.should_connect_to(node) is True

    connection_tracker.record_failure(node, HandshakeFailure())
    assert await connection_tracker.should_connect_to(node) is False

    record = connection_tracker._get_record(node.uri())
    record.expires_at -= datetime.timedelta(seconds=120)
    connection_tracker.session.add(record)
    connection_tracker.session.commit()

    assert await connection_tracker.should_connect_to(node) is True
コード例 #30
0
    async def do_p2p_handshake(self) -> None:
        """Perform the handshake for the P2P base protocol.

        Raises HandshakeFailure if the handshake is not successful.
        """
        self.base_protocol.send_handshake()

        cmd, msg = await self.read_msg()

        if isinstance(cmd, Disconnect):
            msg = cast(Dict[str, Any], msg)
            # Peers sometimes send a disconnect msg before they send the initial P2P handshake.
            if msg['reason'] == DisconnectReason.too_many_peers.value:
                raise TooManyPeersFailure(f'{self} disconnected from us before handshake')
            raise HandshakeFailure(
                f"{self} disconnected before completing sub-proto handshake: {msg['reason_name']}"
            )
        await self.process_p2p_handshake(cmd, msg)