node — NEO network node

A NeoNode in the networking context is considered an P2P endpoint with which NEO specific network messages can be exchanged. It is not to be confused with the generic node term commonly used to refer to a client application that participates in the blockchain network. A node in the generic term would consist of a NeoNode for the network layer, a virtual machine for transaction processing, a persistence layer for storing data and optionally an interface like a GUI or CLI.

Connecting

Establishing a connection to a node requires just 3 pieces of information.

  1. a network magic to select the right network (MainNet, TestNet, private net).

  2. an IP address.

  3. a port number.

With this information at hand we can establish a basic connection as follows.

import asyncio
from neo3 import settings
from neo3.network import node

async def main():
    # set network magic to NEO MainNet
    settings.network.magic = 5195086

    node_client, error = await node.NeoNode.connect_to('127.0.0.1', 40333)
    if node_client:
        print(f"Connected to {node_client.version.user_agent} @ {node_client.address}")
        # send and receive messages

if __name__ == "__main__":
    asyncio.run(main())

The connect_to() function establishes a network connection and performs the initial handshake. Under the hood it uses asyncio.loop.create_connection with a NeoProtocol as the factory.

Once a connection is established it is up to the caller to implement a message loop for handling incoming messages. Such a loop can be started via the convenience start_message_handler() method. This loop reads network messages and dispatches them to their associates handlers.

Connect and disconnect events are broadcasted using Events via on_node_connected(client_instance) and on_node_disconnected(client_instance, reason). You can listen to these events as follows:

from neo3.core import msgrouter

def node_connected(node_client):
    print(f"Connected to node {node_client.version.user_agent} @ {node_client.address}")

def node_disconnected(node_client, reason):
   print(f"Disconnected from node {node_client.version.user_agent} @ {node_client.address} for reason {reason}")

msgrouter.on_node_connected += node_connected
msgrouter.on_node_disconnected += node_disconnected

When connected you likely want to exchange data.

Exchanging data

At the most basic level you have the send_message() and read_message() commands. These respectivily take or provide you a network Message and a payload.

A handfull of convenience functions are present for common requests and responses. Specifically:

Finally, in conjunction with the convenience message loop (started via start_message_handler()) a list of message handlers are available that can be overwritten by updating the dispatch_table dictionary to set your own handler. All handlers start with handler_<name> and take a Message as parameter.

class neo3.network.node.NeoNode(protocol)
async static connect_to(host=None, port=None, timeout=3, loop=None, socket=None)

Establish a connection to a Neo node

Note: performs the initial connection handshake and validation.

Parameters
  • host (Optional[str]) – remote address in IPv4 format

  • port (Optional[int]) – remote port

  • timeout – maximum time establishing a connection may take

  • loop – custom loop

Raises

ValueError – if host/port and the socket argument as specified as the same time or none are specified.

Returns

  • (Node instance, None) - if a connection was successfully established

  • (None, (ip address, error reason)) - if a connection failed to establish . Reasons include connection timeout, connection full and handshake errors. # noqa

Return type

Tuple

async connection_lost(exc)

Event called by the base protocol.

Return type

None

async connection_made(transport)

Event called by the base protocol.

Return type

None

async disconnect(reason)

Close the connection to remote endpoint.

Parameters

reason (DisconnectReason) – reason for disconnecting.

Return type

None

classmethod get_address_new()

Utility function to return the first address with the state NEW.

Return type

Optional[NetworkAddress]

handler_addr(msg)

Handler for a message with the ADDR type.

Parameters

msg (Message) –

Return type

None

handler_block(msg)

Handler for a message with the BLOCK type.

Parameters

msg (Message) –

Return type

None

handler_consensus(msg)

Handler for a message with the CONSENSUS type.

Parameters

msg (Message) –

Return type

None

handler_filteradd(msg)

Handler for a message with the FILTERADD type.

Parameters

msg (Message) –

Return type

None

handler_filterclear(msg)

Handler for a message with the FILTERCLEAR type.

Parameters

msg (Message) –

Return type

None

handler_filterload(msg)

Handler for a message with the FILTERLOAD type.

Parameters

msg (Message) –

Return type

None

handler_getaddr(msg)

Handler for a message with the GETADDR type.

Parameters

msg (Message) –

Return type

None

handler_getblockdata(msg)

Handler for a message with the GETBLOCKBYINDEX type.

Parameters

msg (Message) –

Return type

None

handler_getblocks(msg)

Handler for a message with the GETBLOCKS type.

Parameters

msg (Message) –

Return type

None

handler_getdata(msg)

Handler for a message with the GETDATA type.

Parameters

msg (Message) –

Return type

None

handler_getheaders(msg)

Handler for a message with the GETHEADERS type.

Parameters

msg (Message) –

Return type

None

handler_headers(msg)

Handler for a message with the HEADERS type.

Parameters

msg (Message) –

Return type

None

handler_inv(msg)

Handler for a message with the INV type.

Parameters

msg (Message) –

Return type

None

handler_mempool(msg)

Handler for a message with the MEMPOOL type.

Parameters

msg (Message) –

Return type

None

handler_merkleblock(msg)

Handler for a message with the MERKLEBLOCK type.

Parameters

msg (Message) –

Return type

None

handler_ping(msg)

Handler for a message with the PING type.

Parameters

msg (Message) –

Return type

None

handler_pong(msg)

Handler for a message with the PONG type.

Parameters

msg (Message) –

Return type

None

handler_transaction(msg)

Handler for a message with the TRANSACTION type.

Parameters

msg (Message) –

Return type

None

async read_message(timeout=30)

Read a Message from the wire.

Parameters

timeout (int) – maximum time to wait in trying to deserialize a message from the wire.

Return type

Optional[Message]

Returns

Message, if enough data was found and successfully deserialized. None otherwise.

async relay(inventory)

Relay the inventory to the network

Parameters

inventory (IInventory) – should be of type Block, Transaction or Consensus. See: InventoryType. # noqa

Return type

bool

async request_address_list()

Send a request for receiving known network addresses.

Return type

None

async request_block_data(index_start, count)

Send a request for count blocks starting from index_start.

Count cannot exceed MAX_BLOCKS_COUNT.

See also

request_blocks() to only request block hashes.

Parameters
  • index_start – block index to start from.

  • count – number of blocks to return.

Return type

None

async request_blocks(hash_start, count=None)

Send a request for retrieving block hashes from hash_start to hash_start`+`count.

Not specifying a count results in requesting at most 500 blocks.

Note

The remote node is expected to reply with a Message with the INV type containing the hashes of the requested blocks. Use request_data() in combination with these hashes to return the actual Block objects.

See also

request_block_data() to immediately retrieve Block objects.

Parameters
Return type

None

async request_data(type, hashes)

Send a request for receiving the specified inventory data.

Parameters
Return type

None

async request_headers(index_start, count=2000)

Send a request for headers from index_start to index_start`+`count.

Not specifying a count results in requesting at most 2000 headers.

Parameters
  • index_start (int) –

  • count (int) –

Return type

None

async send_address_list(network_addresses)

Send network addresses.

Parameters

network_addresses (List[NetworkAddress]) –

Return type

None

async send_headers(headers)

Send a list of Header objects.

Parameters

headers (List[Header]) –

Return type

None

async send_inventory(inv_type, inv_hash)

Send an inventory to the network

Parameters
Return type

None

async send_message(message)

Send a Message over the wire.

Parameters

message (Message) –

Return type

None

async send_ping()

Send a Ping message and expecting a Pong response

Return type

None

start_message_handler()

A convenience function to start a message reading loop and forward the messages to their respective handlers as configured in dispatch_table.

Return type

None

address

Address of the remote endpoint.

Type

payloads.NetworkAddress

addresses: List[neo3.network.payloads.address.NetworkAddress] = []

a list of known network addresses (class attribute).

Type

List[payloads.NetworkAddress]

best_height: int

Best block height of node.

Type

int

disconnecting: bool

Whether the node is in the process of disconnecting and shutting down its tasks.

Type

bool

dispatch_table: Dict[neo3.network.message.MessageType, Callable[[neo3.network.message.Message], None]]

A table matching message types to handler functions.

Type

Dict[message.MessageType, Callable[[message.Message], None]]

nodeid: int

Unique identifier.

Type

int

nodeid_human: str

Human readable id.

Type

str