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¶
-
coroutine
-
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.DiscoveryProtocol(privkey: eth_keys.datatypes.PrivateKey, address: evm.p2p.kademlia.Address, bootstrap_nodes: typing.List[evm.p2p.kademlia.Node]) → None¶ Bases:
asyncio.protocols.DatagramProtocolA 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¶
-
coroutine
-
exception
evm.p2p.discovery.WrongMAC¶
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
- generate shared-secret = kdf( ecdhAgree(myPrivKey, msg[1:65]) )
- verify tag
- 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
- generate r = random value
- generate shared-secret = kdf( ecdhAgree(r, P) )
- generate R = rG [same op as generating a public key]
- 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¶
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()¶
-
classmethod
-
class
evm.p2p.kademlia.KBucket(start: int, end: int) → None¶ Bases:
collections.abc.SizedA 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.
-
coroutine
-
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¶
-
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()¶
-
coroutine
-
class
evm.p2p.lightchain.PeerPool(chaindb: evm.db.chain.BaseChainDB, network_id: int, privkey: eth_keys.datatypes.PrivateKey, min_peers: int = 2) → None¶ Bases:
objectPeerPool 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()¶
-
coroutine
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.EnumAn 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¶
-
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.link_transports(proto1, proto2)¶
-
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_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.LESPeerA 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¶