P2P¶
This section describes how peers are discovered in the SonoCoin network and how information is shared between nodes. SonoCoin’s P2P network layer is based on Ethereum’s well established RLPx protocol and can be divided into the following three parts:
- Discovery Protocol (UDP)
- Base Protocol (TCP)
- SonoCoin Protocol (Base Protocol)
Any number of protocols can be built on top of the base protocol and can be used side by side with the SonoCoin Protocol.
Discovery Protocol¶
SonoCoin uses a variant of the Kademlia distributed hash table (DHT) to form a structured p2p overlay network. This UDP based DHT represents the base layer of the SonoCoin network, allowing for a highly scalable ( for node lookup and space complexity) and general decentralized network infrastructure.
The following table summarizes the parametrization of Kademlia used in SonoCoin’s reference implementation:
Parameter Name | Value |
---|---|
hash bits | 256 |
k (bucket size) | 16 |
α (Concurrency Factor) | 3 |
For node distance calculations using Kademlia’s XOR metric the sha256 hash of the nodeID is used.
Packet header¶
All packets are prefixed with a header of the following structure:
Size | Name | Type | comment |
---|---|---|---|
32 | PublicKey | [32]byte | The node’s public key |
64 | signature | [64]byte | sig(packet-type || packet-data) |
1 | packetType | uint | packet identifier |
Note
The || operator stands for concatenation
Data Structures¶
The following data structure will be reused in the packet definitions:
Size | Name | Type | Comment |
---|---|---|---|
4 / 16 | IPAddress | []byte | Little endian encoded IPV4 / IPV6 address |
2 | UDP | uint16 | UDP port number |
2 | TCP | uint16 | TCP port number |
Packet Types¶
SonoCoin’s discovery protocol defines the following 4 RPC packet types. Packet size is limited to 1280 bytes. Larger packets are discarded.
All packet contents are serialized using Recursive Length Prefix (RLP) encoding.
Ping Packet (packet-type = 0x01)¶
Size | Name | Type | comment |
---|---|---|---|
4 | Version | uint32 | For Forward compatibility (Current Version = 1) |
8 / 20 | From | rpcEndpoint | |
8 / 20 | To | rpcEndpoint | |
8 | Expiration | uint64 | Unix timestamp after which packet is considered expired |
Pong Packet (packet-type = 0x02)¶
Size | Name | Type | comment |
---|---|---|---|
8 / 20 | To | rpcEnpoint | |
32 | ping-hash | [32]byte | hash of corresponding ping packet |
8 | Expiration | uint64 | Unix timestamp after which packet is considered expired |
FindNode Packet (packet-type = 0x03)¶
Size | Name | Type | comment |
---|---|---|---|
32 | Target | [32]byte | The identifier of the node |
8 | Expiration | uint64 | Unix timestamp after which packet is considered expired |
Neighbors Packet (packet-type = 0x04)¶
Size | Name | Type | comment |
---|---|---|---|
var. | Nodes | []rpcEndpoint | |
8 | Expiration | uint64 | Unix timestamp after which packet is considered expired |
Neighbors packets are split up into multiple packets to stay below the 1280 byte limit.
Base Protocol¶
The TCP-based base protocol is used to authenticate nodes and upgrade to a higher layer protocol (eg. SonoCoin Protocol).
Message structure¶
All messages are structured as follows:
Size | Name | Type | Comment |
---|---|---|---|
3 | StartSymbol | [3]byte | [0x73, 0x63, 0x6d] (“scm”) |
4 | Magic | uint32 | 1 = MainNet, 2 = TestNet |
8 | Command | uint64 | command |
8 | Length | uint64 | Length of payload in number of bytes |
4 | Checksum | uint32 | First 4 bytes of sha256(sha256(payload)) |
16 | UUID | [16]byte | Unique Packet Identifier |
var. | Payload | []byte | Payload Data |
Available Commands¶
Command Name | Command ID |
---|---|
cmdEncHandshake | 0x00 |
cmdHandshake | 0x01 |
cmdDisc | 0x02 |
cmdPing | 0x03 |
cmdPong | 0x04 |
Handshakes¶
After a peer is discovered by the discovery protocol, two handshakes are performed to authenticate peers and communicate protocol capabilities. The described process is illustrated in the following sequence diagram:
Data Structures¶
The following data structure will be reused in the packet definitions:
Size | Name | Type | Comment |
---|---|---|---|
var. | Name | string | Protocol name (“SNC” for SonoCoin Protocol) |
4 | Version | uint32 | For forward Compatibility (current version = 1 ) |
Commands in Detail¶
cmdEncHandshake¶
The Encryption Handshake (0x00) authenticates the nodes and establishes a shared secret between them.
Warning
Shared secret isn’t used for encrypted communication yet.
The payload is different for the initiating peer and the target peer.
Request Payload¶
The initiator generates a random key pair and a random nonce and signs the nonce with the generated private key.
Size | Name | Type | comment |
---|---|---|---|
64 | Signature | [64]byte | Signed Nonce |
32 | InitiatorPubKey | [32]byte | Randomly generated public key |
32 | Nonce | [32]byte | Randomly generated nonce |
4 | Version | uint32 | For forward compatibility (Current Version = 1) |
Response Payload¶
Size | Name | Type | comment |
---|---|---|---|
32 | random_pub_key | [32]byte | Randomly generated public key |
32 | Nonce | [32]byte | Randomly generated nonce |
4 | Version | uint32 | For forward compatibility (Current Version = 1) |
cmdHandshake¶
The protocol handshake (0x01) determines the capability of the nodes and is the same for the initiator and the target.
Size | Name | Type | comment |
---|---|---|---|
32 | NodeID | [32]byte | |
8 | Version | uint64 | |
var. | Name | string | |
var. | Caps | []Cap | |
8 | ListenPort | uint64 |
cmdDisc¶
cmdDisc is used when disconnecting from a peer. It lets the peer know why the TCP connection will be dropped.
Size | Name | Type | comment |
---|---|---|---|
4 | Reason | uint32 | Reason for disconnecting. Valid reasons Listed in the following table |
Reason List¶
Name | Code | Description |
---|---|---|
DiscRequested | 0x00 | |
DiscNetworkError | 0x01 | |
DiscProtocolError | 0x02 | |
DiscUselessPeer | 0x03 | |
DiscTooManyPeers | 0x04 | |
DiscAlreadyConnected | 0x05 | |
DiscIncompatibleVersion | 0x06 | |
DiscInvalidIdentity | 0x07 | |
DiscQuitting | 0x08 | |
DiscUnexpectedIdentity | 0x09 | |
DiscSelf | 0x0a | |
DiscReadTimeout | 0x0b | |
DiscSubprotocolError | 0x10 |
Warning
TODO: define which disconnect reason is used when.
cmdPing¶
No payload.
cmdPong¶
Response to ping. No payload.
SonoCoin Protocol V1¶
The SonoCoin Protocol defines how blockchain related information is exchanged. Nodes that implement Version 1 of the SonoCoin protocol communicate this, by adding [“SNC”,1] to their capability list in the base protocol handshake.
Available Commands¶
Command Name | Command ID |
---|---|
cmdStatus | 0x10 |
cmdPing | 0x11 |
cmdPong | 0x12 |
cmdMsg | 0x13 |
cmdTx | 0x14 |
cmdNewBlockHashes | 0x15 |
cmdGetBlockHeaders | 0x16 |
cmdBlockHeaders | 0x17 |
cmdGetBlockBodies | 0x18 |
cmdBlockBodies | 0x19 |
cmdNewBlock | 0x1a |
cmdGetNodeData | 0x1d |
cmdGetReceipts | 0x1f |
Handshake¶
The SonoCoin Protocol Handshake involves both peers sending a cmdStatus (0x00) Message that communicates the current state of each peer’s blockchain. The process is illustrated in the following sequence diagram:
Peers that haven’t partaken in a handshake but send commands from the SonoCoin Protocol should be dropped (cmdDisc 0x02).
Commands in Detail¶
cmdStatus¶
Handshake for the SonoCoin Protocol. Informs peer of blockchain state.
Size | Name | Type | Comment |
---|---|---|---|
4 | ProtocolVersion | uint32 | For forward compatibility (Current version = 1 ) |
8 | NetworkID | uint64 | Mainnet = 1, Testnet = 2 |
32 | CurrentBlock | [32]byte | Hash of last known block in local blockchain |
32 | GenesisBlock | [32]byte | Hash of genesis block in local blockchain |
cmdPing¶
No Payload.
cmdPong¶
Response to cmdPing. No Payload.
cmdNewBlockHashes¶
Announces the availability of a number of blocks through a hash notification.
Size | Name | Type | Comment |
---|---|---|---|
var. | NewBlockHashes | []newBlockHashesData |
The newBlockHashesData type is defined as follows:
Size | Name | Type | Comment |
---|---|---|---|
32 | Hash | [32]byte | |
4 | Height | uint32 |
cmdGetBlockHeaders¶
Requests block headers starting at hash or height.
Size | Name | Type | Comment |
---|---|---|---|
32 / 4 | Origin | [32]byte / uint32 | Block hash or block height |
4 | Amount | uint32 | Amount of blocks |
4 | Skip | uint32 | Amount of block to skip after origin |
1 | Reverse | bool | Block header order (1 = towards genesis, 0 = towards leaf ) |
Note
currently in the json version “reverse”: true, “reverse”: false instead of 1, 0
cmdGetBlockBodies¶
Requests block bodies specified by a list of hashes.
Size | Name | Type | Comment |
---|---|---|---|
var. | hashes | [][32]byte | Block hashes |
cmdNewBlock¶
cmdNewBlock propagates a newly discovered block to a remote peer.
Size | Name | Type | Comment |
---|---|---|---|
var. | block | Block |
cmdGetNodeData¶
Warning
not implemented!
cmdGetReceipts¶
Warning
not implemented!
Node Bootstrapping¶
A new node wanting to join the network needs at least one seed node to connect to. It is recommended to optain seed nodes in one of the following ways:
- Receiving a list of seed nodes from a trusted source and connecting to them directly.
- Calling the SonoCoin bootstrap API (https://api.sono.money/v1/nodes).