evm.p2p package

Submodules

evm.p2p.auth module

class evm.p2p.auth.HandshakeBase(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey) → None

Bases: object

coroutine connect() → typing.Tuple[asyncio.streams.StreamReader, asyncio.streams.StreamWriter]
derive_secrets(initiator_nonce: bytes, responder_nonce: bytes, remote_ephemeral_pubkey: eth_keys.datatypes.PublicKey, auth_init_ciphertext: bytes, auth_ack_ciphertext: bytes) → typing.Tuple[bytes, bytes, _pysha3.keccak_256, _pysha3.keccak_256]

Derive base secrets from ephemeral key agreement.

ephemeral_pubkey
got_eip8_auth = False
logger = <logging.Logger object>
pubkey
class evm.p2p.auth.HandshakeInitiator(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey) → None

Bases: evm.p2p.auth.HandshakeBase

create_auth_message(nonce: bytes) → bytes
decode_auth_ack_message(ciphertext: bytes) → typing.Tuple[eth_keys.datatypes.PublicKey, bytes]
encrypt_auth_message(auth_message: bytes) → bytes
class evm.p2p.auth.HandshakeResponder(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey) → None

Bases: evm.p2p.auth.HandshakeBase

create_auth_ack_message(nonce: bytes) → bytes
decode_authentication(ciphertext: bytes) → typing.Tuple[eth_keys.datatypes.PublicKey, bytes]

Decrypts and decodes the auth_init message.

Returns the initiator’s ephemeral pubkey and nonce.

encrypt_auth_ack_message(ack_message: bytes) → bytes
evm.p2p.auth.decode_ack_eip8(ciphertext: bytes, privkey: eth_keys.datatypes.PrivateKey) → typing.Tuple[eth_keys.datatypes.PublicKey, bytes, int]

Decrypts and decodes a EIP-8 auth ack message.

Returns the remote’s ephemeral pubkey, nonce and protocol version.

evm.p2p.auth.decode_ack_plain(ciphertext: bytes, privkey: eth_keys.datatypes.PrivateKey) → typing.Tuple[eth_keys.datatypes.PublicKey, bytes, int]

Decrypts and decodes a legacy pre-EIP-8 auth ack message.

Returns the remote’s ephemeral pubkey, nonce and protocol version.

evm.p2p.auth.decode_auth_eip8(ciphertext: bytes, privkey: eth_keys.datatypes.PrivateKey) → typing.Tuple[eth_keys.datatypes.Signature, eth_keys.datatypes.PublicKey, bytes, int]

Decode EIP-8 auth message format

evm.p2p.auth.decode_auth_plain(ciphertext: bytes, privkey: eth_keys.datatypes.PrivateKey) → typing.Tuple[eth_keys.datatypes.Signature, eth_keys.datatypes.PublicKey, bytes, int]

Decode legacy pre-EIP-8 auth message format

coroutine evm.p2p.auth.handshake(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey) → typing.Tuple[bytes, bytes, _pysha3.keccak_256, _pysha3.keccak_256, asyncio.streams.StreamReader, asyncio.streams.StreamWriter]

Perform the auth handshake with given remote.

Returns the established secrets and the StreamReader/StreamWriter pair already connected to the remote.

evm.p2p.constants module

evm.p2p.discovery module

The Node Discovery protocol provides a way to find RLPx nodes that can be connected to. It uses a Kademlia-like protocol to maintain a distributed database of the IDs and endpoints of all listening nodes.

More information at https://github.com/ethereum/devp2p/blob/master/rlpx.md#node-discovery

class evm.p2p.discovery.Command(name: str, id: int, elem_count: int) → None

Bases: object

exception evm.p2p.discovery.DefectiveMessage

Bases: Exception

class evm.p2p.discovery.DiscoveryProtocol(privkey: eth_keys.datatypes.PrivateKey, address: evm.p2p.kademlia.Address, bootstrap_nodes: typing.List[evm.p2p.kademlia.Node]) → None

Bases: asyncio.protocols.DatagramProtocol

A Kademlia-like protocol to discover RLPx nodes.

coroutine bootstrap()
connection_made(transport)
datagram_received(data: AnyStr, addr: typing.Tuple[str, int]) → None
error_received(exc: Exception) → None
coroutine listen(loop: asyncio.events.AbstractEventLoop) → typing.Tuple[asyncio.transports.BaseTransport, asyncio.protocols.BaseProtocol]
logger = <logging.Logger object>
pubkey
receive(address: evm.p2p.kademlia.Address, message: AnyStr) → None
recv_find_node(node: evm.p2p.kademlia.Node, payload: typing.List[typing.Any], _: AnyStr) → None
recv_neighbours(node: evm.p2p.kademlia.Node, payload: typing.List[typing.Any], _: AnyStr) → None
recv_ping(node: evm.p2p.kademlia.Node, _, message_hash: AnyStr) → None
recv_pong(node: evm.p2p.kademlia.Node, payload: typing.List[typing.Any], _: AnyStr) → None
send(node: evm.p2p.kademlia.Node, message: bytes) → None
send_find_node(node: evm.p2p.kademlia.Node, target_node_id: int) → None
send_neighbours(node: evm.p2p.kademlia.Node, neighbours: typing.List[evm.p2p.kademlia.Node]) → None
send_ping(node: evm.p2p.kademlia.Node) → bytes
send_pong(node: evm.p2p.kademlia.Node, token: AnyStr) → None
stop()
transport = None
exception evm.p2p.discovery.WrongMAC

Bases: evm.p2p.discovery.DefectiveMessage

evm.p2p.ecies module

evm.p2p.ecies.decrypt(data: bytes, privkey: eth_keys.datatypes.PrivateKey, shared_mac_data: bytes = b'')

Decrypt data with ECIES method using the given private key

  1. generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
  2. verify tag
  3. decrypt

ecdhAgree(r, recipientPublic) == ecdhAgree(recipientPrivate, R) [where R = r*G, and recipientPublic = recipientPrivate*G]

evm.p2p.ecies.ecdh_agree(privkey: eth_keys.datatypes.PrivateKey, pubkey: eth_keys.datatypes.PublicKey) → bytes

Performs a key exchange operation using the ECDH algorithm.

evm.p2p.ecies.encrypt(data: bytes, pubkey: eth_keys.datatypes.PublicKey, shared_mac_data: bytes = b'') → bytes

Encrypt data with ECIES method to the given public key

  1. generate r = random value
  2. generate shared-secret = kdf( ecdhAgree(r, P) )
  3. generate R = rG [same op as generating a public key]
  4. 0x04 || R || AsymmetricEncrypt(shared-secret, plaintext) || tag
evm.p2p.ecies.generate_privkey()

Generate a new SECP256K1 private key and return it

evm.p2p.ecies.hmac_sha256(key, msg)
evm.p2p.ecies.kdf(key_material)

NIST SP 800-56a Concatenation Key Derivation Function (see section 5.8.1).

Pretty much copied from geth’s implementation: https://github.com/ethereum/go-ethereum/blob/673007d7aed1d2678ea3277eceb7b55dc29cf092/crypto/ecies/ecies.go#L167

evm.p2p.exceptions module

exception evm.p2p.exceptions.AuthenticationError

Bases: Exception

exception evm.p2p.exceptions.DecryptionError

Bases: Exception

exception evm.p2p.exceptions.EmptyGetBlockHeadersReply

Bases: Exception

exception evm.p2p.exceptions.PeerConnectionLost

Bases: Exception

exception evm.p2p.exceptions.PeerDisconnected

Bases: Exception

exception evm.p2p.exceptions.UnknownProtocolCommand

Bases: Exception

exception evm.p2p.exceptions.UnreachablePeer

Bases: Exception

exception evm.p2p.exceptions.UselessPeer

Bases: Exception

evm.p2p.kademlia module

class evm.p2p.kademlia.Address(ip: str, udp_port: int, tcp_port: int = 0) → None

Bases: object

classmethod from_endpoint(ip: str, udp_port: str, tcp_port: str = '\x00\x00')
ip
to_endpoint()
exception evm.p2p.kademlia.AlreadyWaiting

Bases: Exception

class evm.p2p.kademlia.KBucket(start: int, end: int) → None

Bases: collections.abc.Sized

A bucket of nodes whose IDs fall between the bucket’s start and end.

The bucket is kept sorted by time last seen—least-recently seen node at the head, most-recently seen at the tail.

add(node: evm.p2p.kademlia.Node) → evm.p2p.kademlia.Node

Try to add the given node to this bucket.

If the node is already present, it is moved to the tail of the list, and we return None.

If the node is not already present and the bucket has fewer than k entries, it is inserted at the tail of the list, and we return None.

If the bucket is full, we add the node to the bucket’s replacement cache and return the node at the head of the list (i.e. the least recently seen), which should be evicted if it fails to respond to a ping.

distance_to(id) → int
head

Least recently seen

in_range(node: evm.p2p.kademlia.Node) → bool
is_full
k = 16
midpoint
nodes_by_distance_to(id) → typing.List[evm.p2p.kademlia.Node]
remove_node(node: evm.p2p.kademlia.Node) → None
split() → typing.Tuple[typing.KBucket, typing.KBucket]

Split at the median id

class evm.p2p.kademlia.KademliaProtocol

Bases: object

coroutine bond(node: evm.p2p.kademlia.Node) → bool

Bond with the given node.

Bonding consists of pinging the node, waiting for a pong and maybe a ping as well. It is necessary to do this at least once before we send find_node requests to a node.

coroutine bootstrap(bootstrap_nodes: typing.List[evm.p2p.kademlia.Node]) → None
logger = <logging.Logger object>
coroutine lookup(node_id: int) → typing.List[evm.p2p.kademlia.Node]

Lookup performs a network search for nodes close to the given target.

It approaches the target by querying nodes that are closer to it on each iteration. The given target does not need to be an actual node identifier.

ping(node: evm.p2p.kademlia.Node) → bytes
coroutine populate_not_full_buckets()

Go through all buckets that are not full and try to fill them.

For every node in the replacement cache of every non-full bucket, try to bond. When the bonding succeeds the node is automatically added to the bucket.

recv_find_node(remote: evm.p2p.kademlia.Node, targetid: int) → None
recv_neighbours(remote: evm.p2p.kademlia.Node, neighbours: typing.List[evm.p2p.kademlia.Node]) → None

Process a neighbours response.

Neighbours responses should only be received as a reply to a find_node, and that is only done as part of node lookup, so the actual processing is left to the callback from neighbours_callbacks, which is added (and removed after it’s done or timed out) in wait_neighbours().

recv_ping(remote: evm.p2p.kademlia.Node, hash_: AnyStr) → None

Process a received ping packet.

A ping packet may come any time, unrequested, or may be prompted by us bond()ing with a new node. In the former case we’ll just update the sender’s entry in our routing table and reply with a pong, whereas in the latter we’ll also fire a callback from ping_callbacks.

recv_pong(remote: evm.p2p.kademlia.Node, token: AnyStr) → None

Process a pong packet.

Pong packets should only be received as a response to a ping, so the actual processing is left to the callback from pong_callbacks, which is added (and removed after it’s done or timed out) in wait_pong().

refresh_idle_buckets()
update_routing_table(node: evm.p2p.kademlia.Node) → None

Update the routing table entry for the given node.

coroutine wait_neighbours(remote: evm.p2p.kademlia.Node) → typing.List[evm.p2p.kademlia.Node]

Wait for a neihgbours packet from the given node.

Returns the list of neighbours received.

coroutine wait_ping(remote: evm.p2p.kademlia.Node) → bool

Wait for a ping from the given remote.

This coroutine adds a callback to ping_callbacks and yields control until that callback is called or a timeout (k_request_timeout) occurs. At that point it returns whether or not a ping was received from the given node.

coroutine wait_pong(pingid: bytes) → bool

Wait for a pong with the given pingid.

This coroutine adds a callback to pong_callbacks and yields control until that callback is called or a timeout (k_request_timeout) occurs. At that point it returns whether or not a pong was received with the given pingid.

class evm.p2p.kademlia.Node(pubkey: eth_keys.datatypes.PublicKey, address: evm.p2p.kademlia.Address) → None

Bases: object

distance_to(id)
classmethod from_uri(uri: bytes) → evm.p2p.kademlia.Node
class evm.p2p.kademlia.RoutingTable(node: evm.p2p.kademlia.Node) → None

Bases: object

add_node(node: evm.p2p.kademlia.Node) → evm.p2p.kademlia.Node
buckets_by_distance_to(id: int) → typing.List[evm.p2p.kademlia.KBucket]
get_bucket_for_node(node: evm.p2p.kademlia.Node) → evm.p2p.kademlia.KBucket
idle_buckets
neighbours(node_id: int, k: int = 16) → typing.List[evm.p2p.kademlia.Node]

Return up to k neighbours of the given node.

not_full_buckets
remove_node(node: evm.p2p.kademlia.Node) → None
split_bucket(index: int) → None
evm.p2p.kademlia.binary_get_bucket_for_node(buckets: typing.List[evm.p2p.kademlia.KBucket], node: evm.p2p.kademlia.Node) → evm.p2p.kademlia.KBucket

Given a list of ordered buckets, returns the bucket for a given node.

evm.p2p.kademlia.enc_port(p)
evm.p2p.kademlia.host_port_pubkey_from_uri(uri)
evm.p2p.kademlia.int_to_big_endian4(integer)

4 bytes big endian integer

evm.p2p.kademlia.sort_by_distance(nodes: typing.List[evm.p2p.kademlia.Node], target_id: int) → typing.List[evm.p2p.kademlia.Node]

evm.p2p.les module

class evm.p2p.les.Announce(id_offset: int) → None

Bases: evm.p2p.protocol.Command

structure = [('head_hash', <rlp.sedes.binary.Binary object>), ('head_number', <rlp.sedes.big_endian_int.BigEndianInt object>), ('head_td', <rlp.sedes.big_endian_int.BigEndianInt object>), ('reorg_depth', <rlp.sedes.big_endian_int.BigEndianInt object>), ('params', <rlp.sedes.lists.CountableList object>)]
class evm.p2p.les.BlockBodies(id_offset: int) → None

Bases: evm.p2p.protocol.Command

structure = [('request_id', <rlp.sedes.big_endian_int.BigEndianInt object>), ('buffer_value', <rlp.sedes.big_endian_int.BigEndianInt object>), ('bodies', <rlp.sedes.lists.CountableList object>)]
class evm.p2p.les.BlockHeaders(id_offset: int) → None

Bases: evm.p2p.protocol.Command

structure = [('request_id', <rlp.sedes.big_endian_int.BigEndianInt object>), ('buffer_value', <rlp.sedes.big_endian_int.BigEndianInt object>), ('headers', <rlp.sedes.lists.CountableList object>)]
class evm.p2p.les.GetBlockBodies(id_offset: int) → None

Bases: evm.p2p.protocol.Command

structure = [('request_id', <rlp.sedes.big_endian_int.BigEndianInt object>), ('block_hashes', <rlp.sedes.lists.CountableList object>)]
class evm.p2p.les.GetBlockHeaders(id_offset: int) → None

Bases: evm.p2p.protocol.Command

structure = [('request_id', <rlp.sedes.big_endian_int.BigEndianInt object>), ('query', <class 'evm.p2p.les.GetBlockHeadersQuery'>)]
class evm.p2p.les.GetBlockHeadersQuery(*args, **kwargs)

Bases: rlp.sedes.lists.Serializable

fields = [('block', <rlp.sedes.big_endian_int.BigEndianInt object>), ('max_headers', <rlp.sedes.big_endian_int.BigEndianInt object>), ('skip', <rlp.sedes.big_endian_int.BigEndianInt object>), ('reverse', <rlp.sedes.big_endian_int.BigEndianInt object>)]
class evm.p2p.les.LESBlockBody(*args, **kwargs)

Bases: rlp.sedes.lists.Serializable

fields = [('transactions', <rlp.sedes.lists.CountableList object>), ('uncles', <rlp.sedes.lists.CountableList object>)]
class evm.p2p.les.LESProtocol

Bases: evm.p2p.protocol.Protocol

cmd_length = 15
handshake_msg_type

alias of Status

name = b'les'
process_handshake(decoded_msg: typing.Dict[str, typing.Any]) → None
send_get_block_bodies(block_hashes: typing.List[bytes], request_id: int) → None
send_get_block_headers(block_number: int, max_headers: int, request_id: int, reverse: bool = True) → None

Send a GetBlockHeaders msg to the remote.

This requests that the remote send us up to max_headers, starting from block_number if reverse is False or ending at block_number if reverse is True.

send_handshake(head_info)
version = 1
class evm.p2p.les.Status(id_offset: int) → None

Bases: evm.p2p.protocol.Command

decode_payload(rlp_data)
decode_strict = False
encode_payload(data)
items_sedes = {'genesisHash': <rlp.sedes.binary.Binary object>, 'protocolVersion': <rlp.sedes.big_endian_int.BigEndianInt object>, 'serveChainSince': <rlp.sedes.big_endian_int.BigEndianInt object>, 'networkId': <rlp.sedes.big_endian_int.BigEndianInt object>, 'serveHeaders': None, 'serveStateSince': <rlp.sedes.big_endian_int.BigEndianInt object>, 'flowControl/MRC': <rlp.sedes.lists.CountableList object>, 'headHash': <rlp.sedes.binary.Binary object>, 'flowControl/MRR': <rlp.sedes.big_endian_int.BigEndianInt object>, 'flowControl/BL': <rlp.sedes.big_endian_int.BigEndianInt object>, 'txRelay': None, 'headTd': <rlp.sedes.big_endian_int.BigEndianInt object>, 'headNum': <rlp.sedes.big_endian_int.BigEndianInt object>}
structure = <rlp.sedes.lists.CountableList object>

evm.p2p.lightchain module

class evm.p2p.lightchain.LightChain(chaindb: evm.db.chain.BaseChainDB) → None

Bases: evm.chains.chain.Chain

coroutine get_block_by_hash(block_hash: bytes) → evm.rlp.blocks.BaseBlock
coroutine get_canonical_block_by_number(block_number: int) → evm.rlp.blocks.BaseBlock
privkey = '0x975638098a8b38ed61f0d36eca5b98ebec273e6a3265cd57f3a6be2001e4d2e7'
coroutine run()
coroutine stop()
class evm.p2p.lightchain.PeerPool(chaindb: evm.db.chain.BaseChainDB, network_id: int, privkey: eth_keys.datatypes.PrivateKey, min_peers: int = 2) → None

Bases: object

PeerPool attempts to keep connections to at least min_peers on the given network.

coroutine connect(remote: evm.p2p.kademlia.Node) → evm.p2p.peer.LESPeer

Connect to the given remote and return a Peer instance when successful.

Returns None if the remote is unreachable, times out or is useless.

coroutine get_best_peer() → evm.p2p.peer.LESPeer

Return the peer with the highest announced block height.

coroutine get_nodes_to_connect() → typing.List[evm.p2p.kademlia.Node]
logger = <logging.Logger object>
coroutine maybe_connect_to_more_peers()

Connect to more peers if we’re not yet connected to at least self.min_peers.

peer_class

alias of LESPeer

coroutine run()
coroutine stop()
coroutine stop_all_peers()

evm.p2p.p2p_proto module

class evm.p2p.p2p_proto.Disconnect(id_offset: int) → None

Bases: evm.p2p.protocol.Command

decode(data)
get_reason_name(reason_id)
handle(proto, data)
structure = [('reason', <rlp.sedes.big_endian_int.BigEndianInt object>)]
class evm.p2p.p2p_proto.DisconnectReason

Bases: enum.Enum

An enumeration.

already_connected = 5
bad_protocol = 2
client_quitting = 8
connected_to_self = 10
disconnect_requested = 0
incompatible_p2p_version = 6
null_node_identity_received = 7
other = 16
subprotocol_error = 12
tcp_sub_system_error = 1
timeout = 11
too_many_peers = 4
unexpected_identity = 9
useless_peer = 3
class evm.p2p.p2p_proto.Hello(id_offset: int) → None

Bases: evm.p2p.protocol.Command

decode_strict = False
handle(proto, data)
structure = [('version', <rlp.sedes.big_endian_int.BigEndianInt object>), ('client_version_string', <rlp.sedes.binary.Binary object>), ('capabilities', <rlp.sedes.lists.CountableList object>), ('listen_port', <rlp.sedes.big_endian_int.BigEndianInt object>), ('remote_pubkey', <rlp.sedes.binary.Binary object>)]
class evm.p2p.p2p_proto.P2PProtocol(peer)

Bases: evm.p2p.protocol.Protocol

cmd_length = 16
handshake_msg_type

alias of Hello

name = b'p2p'
process_handshake(decoded_msg)
send_disconnect(reason)
send_handshake(head_info=None)
send_pong()
version = 4
class evm.p2p.p2p_proto.Ping(id_offset: int) → None

Bases: evm.p2p.protocol.Command

handle(proto, data)
class evm.p2p.p2p_proto.Pong(id_offset: int) → None

Bases: evm.p2p.protocol.Command

handle(proto, data)

evm.p2p.peer module

class evm.p2p.peer.BasePeer(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey, reader: asyncio.streams.StreamReader, writer: asyncio.streams.StreamWriter, aes_secret: bytes, mac_secret: bytes, egress_mac: _pysha3.keccak_256, ingress_mac: _pysha3.keccak_256, chaindb: evm.db.chain.BaseChainDB, network_id: int) → None

Bases: object

capabilities
close()

Close this peer’s reader/writer streams.

This will cause the peer to stop in case it is running.

conn_idle_timeout = 30
decrypt_body(data: bytes, body_size: int) → bytes
decrypt_header(data: bytes) → bytes
disconnect(reason: evm.p2p.p2p_proto.DisconnectReason) → None

Send a disconnect msg to the remote node and stop this Peer.

Parameters:reason – An item from the DisconnectReason enum.
encrypt(header: bytes, frame: bytes) → bytes
get_frame_size(header: bytes) → int
get_protocol_for(cmd_id: int) → evm.p2p.protocol.Protocol

Return the protocol to which the cmd_id belongs.

Every sub-protocol enabled for a peer defines a cmd ID offset, which is agreed on by both sides during the base protocol’s handshake. Here we use that to look up the protocol to which cmd_id belongs. See the match_protocols() method for the details on how the peers agree on which sub protocols to enable and what cmd ID offsets to use for them.

handle_msg(cmd: evm.p2p.protocol.Command, msg: typing.Dict[str, typing.Any]) → None

Peer-specific handling of incoming messages.

This method is called once the sub-protocol’s process() method is done, so that custom Peer implementations can appy extra processing to incoming messages.

head_info
listen_port = 30303
logger = <logging.Logger object>
match_protocols(remote_capabilities: typing.List[typing.Tuple[bytes, int]])

Match the sub-protocols supported by this Peer with the given remote capabilities.

Every sub-protocol and remote-capability are defined by a protocol name and version. This method will get the match with the highest version for every protocol, sort them in ascending alphabetical order and add a Protocol instance for the protocol with that name/version to this peer’s list of enabled sub protocols. Each Protocol instance will also have a cmd ID offset, defined as the offset of the previous item (0 for the base protocol) plus the protocol’s cmd length (i.e. number of commands).

max_headers_fetch = 192
process_msg(msg: bytes) → typing.Dict[str, typing.Any]
process_p2p_handshake(decoded_msg: typing.Dict[str, typing.Any]) → None
coroutine read(n: int) → bytes
coroutine read_loop()
coroutine read_msg() → bytes
reply_timeout = 3
send(header: bytes, body: bytes) → None
coroutine start(finished_callback: typing.Union[typing.Callable[[typing.BasePeer], NoneType], NoneType] = None) → None
coroutine stop_and_wait_until_finished()
coroutine wait_for_reply(request_id)
class evm.p2p.peer.HeadInfo(block_number, block_hash, total_difficulty, genesis_hash)

Bases: object

class evm.p2p.peer.LESPeer(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey, reader: asyncio.streams.StreamReader, writer: asyncio.streams.StreamWriter, aes_secret: bytes, mac_secret: bytes, egress_mac: _pysha3.keccak_256, ingress_mac: _pysha3.keccak_256, chaindb: evm.db.chain.BaseChainDB, network_id: int) → None

Bases: evm.p2p.peer.BasePeer

handle_announce(msg: typing.Dict[str, typing.Any]) → None
handle_msg(cmd: evm.p2p.protocol.Command, msg: typing.Dict[str, typing.Any]) → None
handle_status(msg: typing.Dict[str, typing.Any]) → None
les_proto

Return the LESProtocol available for this peer.

The available LESProtocol will be the highest version supported by this class and the remote peer. It is available only after the initial P2P handshake.

coroutine sync(head_hash, head_number, reorg_depth=0)
coroutine evm.p2p.peer.handshake(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey, peer_class: typing.Type[evm.p2p.peer.BasePeer], chaindb: evm.db.chain.BaseChainDB, network_id: int) → evm.p2p.peer.BasePeer

Perform the auth and P2P handshakes with the given remote.

Return an instance of the given peer_class (must be a subclass of BasePeer) connected to that remote in case both handshakes are successful and at least one of the sub-protocols supported by peer_class is also supported by the remote.

Raises UnreachablePeer if we cannot connect to the peer or UselessPeer if none of the sub-protocols supported by us is also supported by the remote.

evm.p2p.protocol module

class evm.p2p.protocol.Command(id_offset: int) → None

Bases: object

cmd_id
decode(data: bytes) → typing.Dict[str, typing.Any]
decode_payload(rlp_data: bytes) → typing.Dict[str, typing.Any]
decode_strict = True
encode(data: typing.Dict[str, typing.Any]) → typing.Tuple[bytes, bytes]
encode_payload(data: typing.Union[typing.Dict[str, typing.Any], rlp.sedes.lists.CountableList]) → bytes
handle(proto: evm.p2p.protocol.Protocol, data: bytes)
structure = []
class evm.p2p.protocol.Protocol

Bases: object

cmd_length = None
handshake_msg_type = None
logger = <logging.Logger object>
name = None
process(cmd_id: int, msg: bytes) → typing.Dict[str, typing.Any]
process_handshake(decoded_msg: typing.Dict[str, typing.Any]) → None

Process the handshake msg for this protocol.

send(header: bytes, body: bytes) → None
send_handshake()

Send the handshake msg for this protocol.

version = None

evm.p2p.test_auth module

evm.p2p.test_auth.test_eip8_hello()
coroutine evm.p2p.test_auth.test_handshake()
evm.p2p.test_auth.test_handshake_eip8()

evm.p2p.test_discovery module

evm.p2p.test_discovery.get_discovery_protocol(seed=b'seed')
evm.p2p.test_discovery.random_address()
evm.p2p.test_discovery.random_node()
evm.p2p.test_discovery.remove_chars(s, chars)
evm.p2p.test_discovery.test_find_node_neighbours()
evm.p2p.test_discovery.test_get_max_neighbours_per_packet()
evm.p2p.test_discovery.test_pack()
evm.p2p.test_discovery.test_ping_pong()
evm.p2p.test_discovery.test_unpack_eip8_packets()

evm.p2p.test_ecies module

evm.p2p.test_ecies.test_decrypt_known_good_handshake()
evm.p2p.test_ecies.test_ecdh(privkey_hex, pubkey_hex, ecdh_expected)
evm.p2p.test_ecies.test_encrypt_decrypt()
evm.p2p.test_ecies.test_hmac_sha256()
evm.p2p.test_ecies.test_kdf()

evm.p2p.test_kademlia module

class evm.p2p.test_kademlia.WireMock(sender)

Bases: object

messages = []
send_find_node(node, nodeid)
send_neighbours(node, neighbours)
send_ping(node)
send_pong(node, echo)
evm.p2p.test_kademlia.get_wired_protocol()
evm.p2p.test_kademlia.random_node(nodeid=None)
evm.p2p.test_kademlia.random_pubkey()
evm.p2p.test_kademlia.short_timeout(monkeypatch)
evm.p2p.test_kademlia.test_binary_get_bucket_for_node(bucket_list, node_id, correct_position)
evm.p2p.test_kademlia.test_binary_get_bucket_for_node_error(bucket_list, node_id)
coroutine evm.p2p.test_kademlia.test_bond()
evm.p2p.test_kademlia.test_bucket_ordering()
evm.p2p.test_kademlia.test_compute_shared_prefix_bits()
evm.p2p.test_kademlia.test_kbucket_add()
evm.p2p.test_kademlia.test_kbucket_split()
coroutine evm.p2p.test_kademlia.test_protocol_bootstrap()
evm.p2p.test_kademlia.test_routingtable_add_node()
evm.p2p.test_kademlia.test_routingtable_add_node_error()
evm.p2p.test_kademlia.test_routingtable_neighbours()
evm.p2p.test_kademlia.test_routingtable_remove_node()
evm.p2p.test_kademlia.test_routingtable_split_bucket()
evm.p2p.test_kademlia.test_update_routing_table()
coroutine evm.p2p.test_kademlia.test_update_routing_table_triggers_bond_if_eviction_candidate()
coroutine evm.p2p.test_kademlia.test_wait_neighbours()
coroutine evm.p2p.test_kademlia.test_wait_ping()
coroutine evm.p2p.test_kademlia.test_wait_pong()

evm.p2p.test_lightchain module

evm.p2p.test_peer module

class evm.p2p.test_peer.ETHProtocol63

Bases: evm.p2p.protocol.Protocol

cmd_length = 15
name = b'eth'
send_handshake()
version = 63
class evm.p2p.test_peer.LESPeerServing(remote: evm.p2p.kademlia.Node, privkey: eth_keys.datatypes.PrivateKey, reader: asyncio.streams.StreamReader, writer: asyncio.streams.StreamWriter, aes_secret: bytes, mac_secret: bytes, egress_mac: _pysha3.keccak_256, ingress_mac: _pysha3.keccak_256, chaindb: evm.db.chain.BaseChainDB, network_id: int) → None

Bases: evm.p2p.peer.LESPeer

A LESPeer that can send announcements and responds to GetBlockHeaders msgs.

Used to test our LESPeer implementation. Tests should call .send_announce(), optionally specifying a block number to use as the chain’s head and then use the helper function wait_for_head() to wait until the client peer has synced all headers up to the announced head.

conn_idle_timeout = 2
handle_get_block_headers(msg)
handle_msg(cmd, msg)
head_number
max_headers_fetch = 20
reply_timeout = 1
send_announce(head_number=None, reorg_depth=0)
class evm.p2p.test_peer.LESProtocolFull

Bases: evm.p2p.les.LESProtocol

send_announce(block_hash, block_number, total_difficulty, reorg_depth)
send_block_headers(headers, buffer_value, request_id)
class evm.p2p.test_peer.LESProtocolV2

Bases: evm.p2p.les.LESProtocol

send_handshake()
version = 2
class evm.p2p.test_peer.LESProtocolV3

Bases: evm.p2p.les.LESProtocol

send_handshake()
version = 3
class evm.p2p.test_peer.MockP2PProtocol(peer)

Bases: evm.p2p.p2p_proto.P2PProtocol

send_handshake()
class evm.p2p.test_peer.ProtoMatchingPeer(supported_sub_protocols)

Bases: evm.p2p.peer.LESPeer

evm.p2p.test_peer.assert_canonical_chains_are_equal(chaindb1, chaindb2, block_number=None)

Assert that the canonical chains in both DBs are identical up to block_number.

evm.p2p.test_peer.chaindb_mainnet_100()

Return a chaindb with mainnet headers numbered from 0 to 100.

coroutine evm.p2p.test_peer.get_directly_linked_peers(chaindb1=None, chaindb2=None)

Create two LESPeers with their readers/writers connected directly.

The first peer’s reader will write directly to the second’s writer, and vice-versa.

coroutine evm.p2p.test_peer.get_linked_and_running_peers(request, event_loop, chaindb1=None, chaindb2=None)
coroutine evm.p2p.test_peer.test_directly_linked_peers()
coroutine evm.p2p.test_peer.test_full_header_sync_and_reorg(request, event_loop, chaindb_mainnet_100)
coroutine evm.p2p.test_peer.test_header_sync_with_multi_peers(request, event_loop, chaindb_mainnet_100)
coroutine evm.p2p.test_peer.test_incremental_header_sync(request, event_loop, chaindb_mainnet_100)
coroutine evm.p2p.test_peer.test_les_handshake()
evm.p2p.test_peer.test_sub_protocol_matching()
coroutine evm.p2p.test_peer.wait_for_head(chaindb, header)

evm.p2p.utils module

evm.p2p.utils.gen_request_id()
evm.p2p.utils.get_devp2p_cmd_id(msg: bytes) → int

Return the cmd_id for the given devp2p msg.

The cmd_id, also known as the payload type, is always the first entry of the RLP, interpreted as an integer.

evm.p2p.utils.roundup_16(x)

Rounds up the given value to the next multiple of 16.

evm.p2p.utils.sxor(s1: bytes, s2: bytes) → bytes

Module contents