Files
carrotcoin/docs/protocol-v0.md

6.3 KiB

The carrotcoin protocol

There are two ways of communication:

  • Node to Node
  • Client to Node

General

Node to Node communication happens over IPv6 only.

When starting a node process, it tries to claim udp port 62039. If this port is not free, any other port is chosen.

Node behaviour

Peers

A node keeps a list of "peers". (IPv6 address + port number)

Each peer has a lifetime counter.

A node may drop a peer at any time by ignoring it.

A node may add new peers passively, when it gets contacted from a previously unknown address.

Within one minute, a node contacts all its peers and decrements the lifetime counter by one.

  • When the counter reaches -1, the node is dropped from the peer list.
  • Otherwise, a "heartbeat" message is sent to the peer.

When a node receives a "heartbeat" message from a peer, this peers lifetime counter is reset to 10.

At the beginning of each minute, the node creates a random "pairing" of all known peers with a lifetime counter >= 8.

The "heartbeat" message of a "paired" node includes the address and port number of the partner.

When a node receives a "heartbeat" message with an included partner, it adds this partner address to its peer list with a lifetime counter of 3.

Transactions

Each node keeps a list of up to 1024 open transactions. (That are valid but not yet part of the blockchain.)

The list is sorted by the following criteria:

  • transaction fee, decreasing
  • sender pubkey, increasing
  • id, increasing

These sorting criteria form a 3-tuple.

Only one transaction per (sender pubkey, id) tuple stays in the list. If a transaction with the same tuple but greater transaction fee is received, it replaces the current transaction. If the transaction fee is equal or smaller, the new transaction is ignored.

If one sender created multiple transactions, it must have a large enough balance for all transactions, otherwise the excess ones (as defined by the sorting criteria above) are removed from the list.

If the list grows above 1024 entries, a node may either remove excess ones or keep them in a local list. Within the Node to Node communication, only the first 1024 entries will be synced.

Open transactions are hashed in a chain.
The hash of each open transaction is a SHA256, calculated over the following datastructure:

content length
previous hash 32
transaction fee (BE) 8
sender pubkey 32
id 4

The "previous hash" consists of 32 nullbytes for the first transaction in the list. For all other entries, it is the calculated hash value of the open transaction entry directly before in the list.

If the list contains less than 1024 entries, set "transaction fee", "sender pubkey" and "id" to nullbytes for the hash calculation of all following entries.

Node to Node message packet formats

heartbeat message

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 0 (BE) 1
difficulty sum of second last known block (BE) 32
hash value of open transaction # 1023 32
partner IPv6 16
partner port (BE) 2

The difficulty sum is sent as 2^28 if only one block is known or as 0 if no block is known.

partner IPv6 and partner port may be nullbytes (no partner included).

block request

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 1 (BE) 1
block hash 32

A block request is sent from node A to node B in order to transfer a block from node B to node A.
Node B should answer with a "block transfer" message that includes the requested block (as given by "block hash")

If "block hash" consists of 32 nullbytes, node A wants node B to send the newest block of B's blockchain.

block transfer

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 2 (BE) 1
block 292

A "block transfer" message is sent back in response to a "block request" message.

open transaction list hash request

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 3 (BE) 1
list position (0 <= x < 1024) (BE) 2

open transaction list hash response

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 4 (BE) 1
list position (0 <= x < 1024) (BE) 2
"open transaction" hash value 32

open transaction request

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 5 (BE) 1
list position (0 <= x < 1024) (BE) 2

open transaction response

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 6 (BE) 1
list position (0 <= x < 1024) (BE) 2
transaction 148

Client to Node message packet formats

Mining task request (Client -> Node)

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 7 (BE) 1

The node should answer to a "Mining task request" with a "Mining task response"

Mining task response (Node -> Client)

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 8 (BE) 1
transaction (optional) 148
previous hash 32
timestamp (unix time in seconds, BE) 8
difficulty sum (BE) 32

The node tells the miner "timestamp", "previous hash", "difficulty sum" and "transaction" for the new block.

The miner fills "nonce", "message" and "miner pubkey" on its own.

When a miner finds a block, it sends a "block transfer" message to the node.

Payment request (Client -> Node)

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 9 (BE) 1
transaction 148

The node should answer to a "Payment request" with a "Payment request received" if the contained transaction is formally correct (see "validity / transaction" in the blockchain specification).

A response is always sent back in this case, even if the transaction cannot be applied to the blockchain right now.

Payment request received (Node -> Client)

content size (bytes)
protocol version = 0 (BE) 2
capable version = 0 (BE) 2
type = 10 (BE) 1