Features
P2p Encrypted Network

Introduction

P2p Encrypted Network is a network of nodes that communicate with each other using a secure, encrypted protocol.
The network is designed to be decentralized, with no central authority or single point of failure.
It is also designed to be lightweight for low devices, but also resistant to censorship and surveillance, with strong privacy and security guarantees.

Seed nodes are used to help nodes find each other and are connected by default when no peerlist available.

XELIS use ChaCha20-Poly1305 AEAD cipher for symmetric encryption with key rotation happening every 1 GB data transferred.

All transfered data are using a custom serializer / deserializer made by hand to transform a struct representation in raw bytes directly.
This serialization is done using the fixed position of each fields and their corresponding bits size.

Before sending a packet to the peer, we encrypt it completely to prevent network traffic analysis and authenticate each transfered data.

Every data transfered is done following the protocol which allow ease to read & transfer data and doing the whole serialization itself.

Protocol

Protocol has a simple design with a packet system that allow to transfer data between peers.

To create a connection between with a potential peer, the party that initiated the connection must send its symetric encryption key first.
The other party will wait on it and will send its own key after receiving the first one.

Once both parties have received the other's symetric encryption key, they can start the handshake and send / receive data encrypted.

The client that initiated the connection will send a handshake packet to the other party to be upgraded as a Peer, and the other party will respond with a handshake packet to confirm the upgrade.

In the handshake packet, a peer can inform others peers if he accept that its IP is shared to extend peerlist of others and / or to be returned in RPC API.

To reduce overall bandwidth of network, nodes shouldn't:

  • send twice a transaction during propagation time to the same peer.
  • send twice a block during propagation time to the same peer.

For blocks and transactions propagation, we keep in cache last N elements sent or received from a peer to not send the same data twice during propagation.

Implementation

As a note, the connection for a new peer (took from the queue or a new incoming connections) is executed through a unique tokio task with the same allocated buffer for handshake. This prevents any DoS attack on creating multiple task and verifying connection.

When the peer is verified and valid, we create him its own two tasks. One is for reading incoming packets and one for writing packets to him. By separating both directions in two differents task it prevents blocking the communication of opposed side.

Chain Sync

We select randomly a peer which is higher in height from the peers list than us and send him a chain request.

The chain request includes last CHAIN_SYNC_REQUEST_MAX_BLOCKS blocks hashes of our chain with theirs topoheight espaced exponentially. This data is used by the select peer to try to find a common point with our chain and his own (block hash must be at same topoheight as other peer). If selected peer found a common point, he add up to CHAIN_SYNC_RESPONSE_MAX_BLOCKS blocks hashes ordered by block height.

Through the "ask and await" request object system, we ask the complete block (block header with transactions included) and add it to chain directly.

Chain sync is requested with a minimum interval of CHAIN_SYNC_DELAY seconds.

Packets

This parts explains all packets used in XELIS network to communicate over the P2p network.

Key Exchange

Key Exchange is the real first packet to be sent when creating a new connection. This allow to exchange symetric encryption keys between peer to establish an encrypted communication channel over TCP.

Currently, we are using ChaCha20-Poly1305 algorithm to encrypt / decrypt every packets.

This packet can be sent later to rotate the key of a peer. This is currently done every 1 GB of data sent.

We're using two different symetric keys for encryption per Peer. One key is from us, to encrypt our packet, and the other key is to decrypt peer's packets.

Handshake

Handshake packet must be the first packet sent with the blockchain state inside to upgrade a connection to a peer. If valid, the peer will send the same packet with is own blockchain state.

Except at beginning, this packet should never be sent again.

Transaction Propagation

Transaction propagation packet contains the hash only to prevent sending the TX. Its also backed by a cache per peer to knows if the transaction was already received from him / send to him.

Block Propagation

Block propagation packet contains the block header only. Its sent to all peers who have theirs height minus our height less than STABLE_LIMIT. To build the block, we retrieve transactions from mempool. If a transaction is not found in the mempool, we request it from the same peer in order to build it.

Chain Request

TODO

Chain Response

TODO

Ping

Ping packet is sent at an regular interval and inform peers of the our blockchain state. Every 15 minutes, the packet can contains up to MAX_LEN sockets addresses (IPv4 or IPv6) to help others nodes to extends theirs peers list.

Object Request

TODO

Object Response

TODO

Notify Inventory Request

TODO

Notify Inventory Response

TODO

Bootstrap Chain Request

TODO

Bootstrap Chain Response

TODO

Disconnect

Disconnect packet is sent when a peer is disconnected from us and we have it in common with another peer.

This is used to keep synced the "propagation map predicate".