Each full node in the CICOIN network independently stores a block chain containing only blocks validated by that node. When several nodes all have the same blocks in their block chain, they are considered to be in consensus. The validation rules these nodes follow to maintain consensus are called consensus rules
A block of one or more new transactions is collected into the transaction data part of a block. Copies of each transaction are hashed, and the hashes are then paired, hashed, paired again, and hashed again until a single hash remains, the merkle root of a merkle tree.
The merkle root is stored in the block header. Each block also stores the hash of the previous block’s header, chaining the blocks together. This ensures a transaction cannot be modified without modifying the block that records it and all following blocks.
Transactions are also chained together. CICOIN wallet software gives the impression that coin are sent from and to wallets, but CICOINs really move from transaction to transaction. Each transaction spends the coin previously received in one or more earlier transactions, so the input of one transaction is the output of a previous transaction.
A single transaction can create multiple outputs, as would be the case when sending to multiple addresses, but each output of a particular transaction can only be used as an input once in the block chain. A
Outputs are tied to transaction identifiers (TXIDs), which are the hashes of signed transactions.
Because each output of a particular transaction can only be spent once, the outputs of all transactions included in the block chain can be categorized as either Unspent Transaction Outputs (UTXOs) or spent transaction outputs. For a payment to be valid, it must only use UTXOs as inputs.
OP_TRUE/OP_1
(0x51) and OP_2
through OP_16
(0x52–0x60), which push the values 1 through 16 to the stack.
OP_CHECKSIG
consumes a signature and a full public key, and pushes true onto the stack if the transaction data specified by the SIGHASH flag was converted into the signature using the same ECDSA private key that generated the public key. Otherwise, it pushes false onto the stack.
OP_DUP
pushes a copy of the topmost stack item on to the stack.
OP_HASH160
consumes the topmost item on the stack, computes the RIPEMD160(SHA256()) hash of that item, and pushes that hash onto the stack.
OP_EQUAL
consumes the top two items on the stack, compares them, and pushes true onto the stack if they are the same, false if not.
OP_VERIFY
consumes the topmost item on the stack. If that item is zero (false) it terminates the script in failure.
OP_EQUALVERIFY
runs OP_EQUAL
and then OP_VERIFY
in sequence.
OP_CHECKMULTISIG
consumes the value (n) at the top of the stack, consumes that many of the next stack levels (public keys), consumes the value (m) now at the top of the stack, and consumes that many of the next values (signatures) plus one extra value.The “one extra value” it consumes is the result of an off-by-one error in the CICOIN Core implementation. This value is not used, so signature scripts prefix the list of secp256k1 signatures with a single OP_0 (0x00). OP_CHECKMULTISIG
compares the first signature against each public key until it finds an ECDSA match. Starting with the subsequent public key, it compares the second signature against each remaining public key until it finds an ECDSA match. The process is repeated until all signatures have been checked or not enough public keys remain to produce a successful result.Because public keys are not checked again if they fail any signature comparison, signatures must be placed in the signature script using the same order as their corresponding public keys were placed in the pubkey script or redeem script. See the OP_CHECKMULTISIG
warning below for more details.
OP_RETURN
terminates the script in failure when executed.
The hashes used in P2PKH and P2SH outputs are commonly encoded as CICOIN addresses. This is the procedure to encode those hashes and decode the addresses.
First, get your hash. For P2PKH, you RIPEMD-160(SHA256()) hash a ECDSA public key derived from your 256-bit ECDSA private key (random data). For P2SH, you RIPEMD-160(SHA256()) hash a redeem script serialized in the format used in raw transactions (described in a following sub-section).
The raw transaction format and several peer-to-peer network messages use a type of variable-length integer to indicate the number of bytes in a following piece of data.
CICOIN Core code and this document refers to these variable length integers as compactSize. Many other documents refer to them as var_int or varInt, but this risks conflation with other variable-length integer encodings—such as the CVarInt class used in CICOIN Core for serializing data to disk. Because it’s used in the transaction format, the format of compactSize unsigned integers is part of the consensus rules.
For numbers from 0 to 252, compactSize unsigned integers look like regular unsigned integers. For other numbers up to 0xffffffffffffffff, a byte is prefixed to the number to indicate its length—but otherwise the numbers look like regular unsigned integers in little-endian order.
ssssValue | Bytes Used | Format |
---|---|---|
>= 0 && <= 252 | 1 | uint8_t |
>= 253 && <= 0xffff | 3 | 0xfd followed by the number as uint16_t |
>= 0x10000 && <= 0xffffffff | 5 | 0xfe followed by the number as uint32_t |
>= 0x100000000 && <= 0xffffffffffffffff | 9 | 0xff followed by the number as uint64_t |
getdata
message that requests the block with an inventory type of MSG_BLOCK
(provided the node has that block available for relay).block
messages broadcasting their newly-mined blocks to all of their peers. Many mining pools do the same thing, although some may be misconfigured to send the block from multiple nodes, possibly sending the same block to some peers more than once.
The getblocks
message requests an inv
message that provides block header hashes starting from a particular point in the block chain. It allows a peer which has been disconnected or started for the first time to get the data it needs to request the blocks it hasn’t seen.
Peers which have been disconnected may have stale blocks in their locally-stored block chain, so the getblocks
message allows the requesting peer to provide the receiving peer with multiple header hashes at various heights on their local chain. This allows the receiving peer to find, within that list, the last header hash they had in common and reply with all subsequent header hashes.
Note: the receiving peer itself may respond with an inv
message containing header hashes of stale blocks. It is up to the requesting peer to poll all of its peers to find the best block chain.
If the receiving peer does not find a common header hash within the list, it will assume the last common block was the genesis block (block zero), so it will reply with in inv
message containing header hashes starting with block one (the first block after the genesis block).
Bytes | Name | Data Type | Description |
---|---|---|---|
4 | version | uint32_t | The protocol version number; the same as sent in the version message. |
Varies | hash count | compactSize uint | The number of header hashes provided not including the stop hash. There is no limit except that the byte size of the entire message must be below the MAX_SIZE limit; typically from 1 to 200 hashes are sent. |
Varies | block header hashes | char[32] | One or more block header hashes (32 bytes each) in internal byte order. Hashes should be provided in reverse order of block height, so highest-height hashes are listed first and lowest-height hashes are listed last. |
32 | stop hash | char[32] | The header hash of the last header hash being requested; set to all zeroes to request an inv message with all subsequent header hashes (a maximum of 500 will be sent as a reply to this message; if you need more than 500, you will need to send another getblocks message with a higher-height header hash as the first entry in block header hash field). |
getblocks
message. (The message header has been omitted.)
71110100 ........................... Protocol version: 70001 02 ................................. Hash count: 2 d39f608a7775b537729884d4e6633bb2 105e55a16a14d31b0000000000000000 ... Hash #1 5c3e6403d40837110a2e8afb602b1c01 714bda7ce23bea0a0000000000000000 ... Hash #2 00000000000000000000000000000000 00000000000000000000000000000000 ... Stop hash
The getdata
message requests one or more data objects from another node. The objects are requested by an inventory, which the requesting node typically received previously by way of an inv message.
The response to a getdata
message can be a tx
message, block
message, merkleblock
message, cmpctblock
message, or notfound message.
This message cannot be used to request arbitrary data, such as historic transactions no longer in the memory pool or relay set. Full nodes may not even be able to provide older blocks if they’ve pruned old transactions from their block database. For this reason, the getdata
message should usually only be used to request data from a node which previously advertised it had that data by sending an inv
message.
The format and maximum size limitations of the getdata
message are identical to the inv message; only the message header differs.
The getheaders
message requests a headers
message that provides block headers starting from a particular point in the block chain. It allows a peer which has been disconnected or started for the first time to get the headers it hasn’t seen yet.
The getheaders
message is nearly identical to the getblocks
message, with one minor difference: the inv reply to the getblocks message will include no more than 500 block header hashes; the headers
reply to the getheaders
message will include as many as 2,000 block headers.
The headers
message sends block headers to a node which previously requested certain headers with a getheaders
message. A headers message can be empty.
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | count | compactSize uint | Number of block headers up to a maximum of 2,000. Note: headers-first sync assumes the sending node will send the maximum number of headers whenever possible. |
Varies | headers | block_header | Block headers: each 80-byte block header is in the format described in the block headers section with an additional 0x00 suffixed. This 0x00 is called the transaction count, but because the headers message doesn’t include any transactions, the transaction count is always zero. |
headers
message. (The message header has been omitted.)01 ................................. Header count: 1 02000000 ........................... Block version: 2 b6ff0b1b1680a2862a30ca44d346d9e8 910d334beb48ca0c0000000000000000 ... Hash of previous block's header 9d10aa52ee949386ca9385695f04ede2 70dda20810decd12bc9b048aaab31471 ... Merkle root 24d95a54 ........................... Unix time: 1415239972 30c31b18 ........................... Target (bits) fe9f0864 ........................... Nonce 00 ................................. Transaction count (0x00)
The inv
message (inventory message) transmits one or more inventories of objects known to the transmitting peer. It can be sent unsolicited to announce new transactions or blocks, or it can be sent in reply to a getblocks
message or mempool
message.
The receiving peer can compare the inventories from an inv
message against the inventories it has already seen, and then use a follow-up message to request unseen objects.
The mempool
message requests the TXIDs of transactions that the receiving node has verified as valid but which have not yet appeared in a block. That is, transactions which are in the receiving node’s memory pool. The response to the mempool
message is one or more inv
messages containing the TXIDs in the usual inventory format.
Sending the mempool
message is mostly useful when a program first connects to the network. Full nodes can use it to quickly gather most or all of the unconfirmed transactions available on the network; this is especially useful for miners trying to gather transactions for their transaction fees. SPV clients can set a filter before sending a mempool
to only receive transactions that match that filter; this allows a recently-started client to get most or all unconfirmed transactions related to its wallet.
There is no payload in a mempool
message. See the message header section for an example of a message without a payload.
The merkleblock
message is a reply to a getdata
message which requested a block using the inventory type MSG_MERKLEBLOCK
. It is only part of the reply: if any matching transactions are found, they will be sent separately as tx messages.
If a filter has been previously set with the filterload
message, the merkleblock
message will contain the TXIDs of any transactions in the requested block that matched the filter, as well as any parts of the block’s merkle tree necessary to connect those transactions to the block header’s merkle root. The message also contains a complete copy of the block header to allow the client to hash it and confirm its proof of work.
Bytes | Name | Data Type | Description |
---|---|---|---|
80 | block header | block_header | The block header in the format described in the block header section. |
4 | transaction count | uint32_t | The number of transactions in the block (including ones that don’t match the filter). |
Varies | hash count | compactSize uint | The number of hashes in the following field. |
Varies | hashes | char[32] | One or more hashes of both transactions and merkle nodes in internal byte order. Each hash is 32 bytes. |
Varies | flag byte count | compactSize uint | The number of flag bytes in the following field. |
Varies | flags | byte[] | A sequence of bits packed eight in a byte with the least significant bit first. May be padded to the nearest byte boundary but must not contain any more bits than that. Used to assign the hashes to particular nodes in the merkle tree as described below. |
merkleblock
message which corresponds to the examples below. (The message header has been omitted.)01000000 ........................... Block version: 1 82bb869cf3a793432a66e826e05a6fc3 7469f8efb7421dc88067010000000000 ... Hash of previous block's header 7f16c5962e8bd963659c793ce370d95f 093bc7e367117b3c30c1f8fdd0d97287 ... Merkle root 76381b4d ........................... Time: 1293629558 4c86041b ........................... nBits: 0x04864c * 256**(0x1b-3) 554b8529 ........................... Nonce 07000000 ........................... Transaction count: 7 04 ................................. Hash count: 4 3612262624047ee87660be1a707519a4 43b1c1ce3d248cbfc6c15870f6c5daa2 ... Hash #1 019f5b01d4195ecbc9398fbf3c3b1fa9 bb3183301d7a1fb3bd174fcfa40a2b65 ... Hash #2 41ed70551dd7e841883ab8f0b16bf041 76b7d1480e4f0af9f3d4c3595768d068 ... Hash #3 20d2a7bc994987302e5b1ac80fc425fe 25f8b63169ea78e68fbaaefa59379bbf ... Hash #4 01 ................................. Flag bytes: 1 1d ................................. Flags: 1 0 1 1 1 0 0 0
Note: when fully decoded, the above merkleblock
message provided the TXID for a single transaction that matched the filter. In the network traffic dump this output was taken from, the full transaction belonging to that TXID was sent immediately after the merkleblock
message as a tx
message.
As seen in the annotated hexdump above, the merkleblock
message provides three special data types: a transaction count, a list of hashes, and a list of one-bit flags.
You can use the transaction count to construct an empty merkle tree. We’ll call each entry in the tree a node; on the bottom are TXID nodes—the hashes for these nodes are TXIDs; the remaining nodes (including the merkle root) are non-TXID nodes—they may actually have the same hash as a TXID, but we treat them differently.
Keep the hashes and flags in the order they appear in the merkleblock
message. When we say “next flag” or “next hash”, we mean the next flag or hash on the list, even if it’s the first one we’ve used so far.
Start with the merkle root node and the first flag. The table below describes how to evaluate a flag based on whether the node being processed is a TXID node or a non-TXID node. Once you apply a flag to a node, never apply another flag to that same node or reuse that same flag again.
Flag | TXID Node | Non-TXID Node |
---|---|---|
0 | Use the next hash as this node’s TXID, but this transaction didn’t match the filter. | Use the next hash as this node’s hash. Don’t process any descendant nodes. |
1 | Use the next hash as this node’s TXID, and mark this transaction as matching the filter. | The hash needs to be computed. Process the left child node to get its hash; process the right child node to get its hash; then concatenate the two hashes as 64 raw bytes and hash them to get this node’s hash. |
Any time you begin processing a node for the first time, evaluate the next flag. Never use a flag at any other time.
When processing a child node, you may need to process its children (the grandchildren of the original node) or further-descended nodes before returning to the parent node. This is expected—keep processing depth first until you reach a TXID node or a non-TXID node with a flag of 0.
After you process a TXID node or a non-TXID node with a flag of 0, stop processing flags and begin to ascend the tree. As you ascend, compute the hash of any nodes for which you now have both child hashes or for which you now have the sole child hash. See the merkle tree section for hashing instructions. If you reach a node where only the left hash is known, descend into its right child (if present) and further descendants as necessary.
However, if you find a node whose left and right children both have the same hash, fail. This is related to CVE-2012-2459.
Continue descending and ascending until you have enough information to obtain the hash of the merkle root node. If you run out of flags or hashes before that condition is reached, fail. Then perform the following checks (order doesn’t matter):
For a detailed example of parsing a merkleblock
message, please see the corresponding merkle block examples section.
It’s easier to understand how to create a merkleblock
message after you understand how to parse an already-created message, so we recommend you read the parsing section above first.
Create a complete merkle tree with TXIDs on the bottom row and all the other hashes calculated up to the merkle root on the top row. For each transaction that matches the filter, track its TXID node and all of its ancestor nodes.
Start processing the tree with the merkle root node. The table below describes how to process both TXID nodes and non-TXID nodes based on whether the node is a match, a match ancestor, or neither a match nor a match ancestor.
TXID Node | Non-TXID Node | |
---|---|---|
Neither Match Nor Match Ancestor | Append a 0 to the flag list; append this node’s TXID to the hash list. | Append a 0 to the flag list; append this node’s hash to the hash list. Do not descend into its child nodes. |
Match Or Match Ancestor | Append a 1 to the flag list; append this node’s TXID to the hash list. | Append a 1 to the flag list; process the left child node. Then, if the node has a right child, process the right child. Do not append a hash to the hash list for this node. |
Any time you begin processing a node for the first time, a flag should be appended to the flag list. Never put a flag on the list at any other time, except when processing is complete to pad out the flag list to a byte boundary.
When processing a child node, you may need to process its children (the grandchildren of the original node) or further-descended nodes before returning to the parent node. This is expected—keep processing depth first until you reach a TXID node or a node which is neither a TXID nor a match ancestor.
After you process a TXID node or a node which is neither a TXID nor a match ancestor, stop processing and begin to ascend the tree until you find a node with a right child you haven’t processed yet. Descend into that right child and process it.
After you fully process the merkle root node according to the instructions in the table above, processing is complete. Pad your flag list to a byte boundary and construct the merkleblock message using the template near the beginning of this subsection.
The cmpctblock
message is a reply to a getdata
message which requested a block using the inventory type MSG_CMPCT_BLOCK
. If the requested block was recently announced and is close to the tip of the best chain of the receiver and after having sent the requesting peer a sendcmpct
message, nodes respond with a cmpctblock
message containing data for the block.
Upon receipt of a cmpctblock
message, after sending a sendcmpct
message, nodes should calculate the short transaction ID for each unconfirmed transaction they have available (ie in their mempool) and compare each to each short transaction ID in the cmpctblock
message. After finding already-available transactions, nodes which do not have all transactions available to reconstruct the full block should request the missing transactions using a getblocktxn
message.
A node must not send a cmpctblock
message unless they are able to respond to a getblocktxn
message which requests every transaction in the block. A node must not send a cmpctblock
message without having validated that the header properly commits to each transaction in the block, and properly builds on top of the existing, fully-validated chain with a valid proof-of-work either as a part of the current most-work valid chain, or building directly on top of it. A node may send a cmpctblock
message before validating that each transaction in the block validly spends existing UTXO set entries.
The cmpctblock
message contains a vector of PrefilledTransaction
whose structure is defined below.
Bytes | Name | Data Type | Description |
---|---|---|---|
1 | announce | bool | An integer representing a boolean value, must be 0x01 (true) or 0x00 (false). |
8 | version | uint64_t | A little-endian representation of a version number. Version 2 compact blocks should be specified by setting version to 2 |
The getblocktxn
message is defined as a message containing a serialized BlockTransactionsRequest
message. Upon receipt of a properly-formatted getblocktxn
message, nodes which recently provided the sender of such a message a cmpctblock
message for the block hash identified in this message must respond with either an appropriate blocktxn
message, or a full block message.
A blocktxn
message response must contain exactly and only each transaction which is present in the appropriate block at the index specified in the getblocktxn
message indexes list, in the order requested.
The structure of BlockTransactionsRequest
is defined below.
Bytes | Name | Data Type | Description |
---|---|---|---|
32 | block hash | binary blob | The blockhash of the block which the transactions being requested are in. |
Varies | indexes length | compactSize uint | The number of transactions being requested. |
Varies | indexes | compactSize uint[] | Vector of compactSize containing the indexes of the transactions being requested in the block. In version 2 of compact thblocks, the wtxid should be used instead of the txid as defined by BIP141 |
The blocktxn
message is defined as a message containing a serialized BlockTransactions
message. Upon receipt of a properly-formatted requested blocktxn
message, nodes should attempt to reconstruct the full block by taking the prefilledtxn transactions from the original cmpctblock
message and placing them in the marked positions, then for each short transaction ID from the original cmpctblock
message, in order, find the corresponding transaction either from the blocktxn
message or from other sources and place it in the first available position in the block then once the block has been reconstructed, it shall be processed as normal, keeping in mind that short transaction IDs are expected to occasionally collide, and that nodes must not be penalized for such collisions, wherever they appear.
The structure of BlockTransactions
is defined below.
Bytes | Name | Data Type | Description |
---|---|---|---|
32 | block hash | binary blob | The blockhash of the block which the transactions being provided are in. |
Varies | transactions length | compactSize uint | The number of transactions being provided. |
Varies | transactions | Transactions[] | Vector of transactions, for an example hexdump of the raw transaction format, see the raw transaction section. |
The notfound
message is a reply to a getdata
message which requested an object the receiving node does not have available for relay. (Nodes are not expected to relay historic transactions which are no longer in the memory pool or relay set. Nodes may also have pruned spent transactions from older blocks, making them unable to send those blocks.)
The format and maximum size limitations of the notfound
message are identical to the inv
message; only the message header differs.
The tx
message transmits a single transaction in the raw transaction format. It can be sent in a variety of situations;
getdata
message that requests the transaction with an inventory type of MSG_TX
.getdata
message that requests a merkle block with an inventory type of MSG_MERKLEBLOCK
. (This is in addition to sending a merkleblock
message.) Each tx message in this case provides a matched transaction from that block.
tx
message unsolicited for transactions it originates.
The following network messages all help control the connection between two peers or allow them to advise each other about the rest of the network.
The addr
(IP address) message relays connection information for peers on the network. Each peer which wants to accept incoming connections creates an addr
message providing its connection information and then sends that message to its peers unsolicited. Some of its peers send that information to their peers (also unsolicited), some of which further distribute it, allowing decentralized peer discovery for any program already on the network.
An addr
message may also be sent in response to a getaddr
message.
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | IP address count | compactSize uint | The number of IP address entries up to a maximum of 1,000. |
Varies | IP addresses | network IP address | IP address entries. See the table below for the format of a CICOIN network IP address. |
Each encapsulated network IP address currently uses the following structure:
Bytes | Name | Data Type | Description |
---|---|---|---|
4 | time | uint32 | A time in Unix epoch time format. Nodes advertising their own IP address set this to the current time. Nodes advertising IP addresses they’ve connected to set this to the last time they connected to that node. Other nodes just relaying the IP address should not change the time. Nodes can use the time field to avoid relaying old addr messages.Malicious nodes may change times or even set them in the future. |
8 | services | uint64_t | The services the node advertised in its version message. |
16 | IP address | char[16] | IPv6 address in big endian byte order. IPv4 addresses can be provided as IPv4-mapped IPv6 addresses |
2 | port | uint16_t | Port number in big endian byte order. Note that CICOIN Core will only connect to nodes with non-standard port numbers as a last resort for finding peers. This is to prevent anyone from trying to use the network to disrupt non-CICOIN services that run on other ports. |
The following annotated hexdump shows part of an addr
message. (The message header has been omitted and the actual IP address has been replaced with a RFC5737 reserved IP address.)
fde803 ............................. Address count: 1000 d91f4854 ........................... Epoch time: 1414012889 0100000000000000 ................... Service bits: 01 (network node) 00000000000000000000ffffc0000233 ... IP Address: ::ffff:192.0.2.51 208d ............................... Port: 8333 [...] .............................. (999 more addresses omitted)
The legacy p2p network alert messaging system has been retired; however, internal alerts, partition detection warnings and the -alertnotify
option features remain. See Alert System Retirement for details.
The feefilter
message is a request to the receiving peer to not relay any transaction inv messages to the sending peer where the fee rate for the transaction is below the fee rate specified in the feefilter message.
The feefilter
messages allows a node to inform its peers that it will not accept transactions below a specified fee rate into its mempool, and therefore that the peers can skip relaying inv messages for transactions below that fee rate to that node.
Bytes | Name | Data Type | Description |
---|---|---|---|
8 | feerate | uint64_t | which transactions should not be relayed to this peer. |
The receiving peer may choose to ignore the message and not filter transaction inv messages.
The fee filter is additive with bloom filters. If an SPV client loads a bloom filter and sends a feefilter message, transactions should only be relayed if they pass both filters.
Note however that feefilter has no effect on block propagation or responses to getdata messages. For example, if a node requests a merkleblock from its peer by sending a getdata message with inv type MSG_FILTERED_BLOCK and it has previously sent a feefilter to that peer, the peer should respond with a merkleblock containing all the transactions matching the bloom filter, even if they are below the feefilter fee rate.
inv messages generated from a mempool message are subject to a fee filter if it exists.
The annotated hexdump below shows a feefilter
message. (The message header has been omitted.)
The filteradd
message tells the receiving peer to add a single element to a previously-set bloom filter, such as a new public key. The element is sent directly to the receiving peer; the peer then uses the parameters set in the filterload
message to add the element to the bloom filter.
Because the element is sent directly to the receiving peer, there is no obfuscation of the element and none of the plausible-deniability privacy provided by the bloom filter. Clients that want to maintain greater privacy should recalculate the bloom filter themselves and send a new filterload
message with the recalculated bloom filter.
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | element bytes | compactSize uint | The number of bytes in the following element field. |
Varies | element | uint8_t[] | The element to add to the current filter. Maximum of 520 bytes, which is the maximum size of an element which can be pushed onto the stack in a pubkey or signature script. Elements must be sent in the byte order they would use when appearing in a raw transaction; for example, hashes should be sent in internal byte order. |
Note: a filteradd
message will not be accepted unless a filter was previously set with the filterload
message.
The annotated hexdump below shows a filteradd
message adding a TXID. (The message header has been omitted.) This TXID appears in the same block used for the example hexdump in the merkleblock
message; if that merkleblock
message is re-sent after sending this filteradd
message, six hashes are returned instead of four.
20 ................................. Element bytes: 32 fdacf9b3eb077412e7a968d2e4f11b9a 9dee312d666187ed77ee7d26af16cb0b ... Element (A TXID)
The filterclear
message tells the receiving peer to remove a previously-set bloom filter. This also undoes the effect of setting the relay field in the version
message to 0, allowing unfiltered access to inv
messages announcing new transactions.
CICOIN Core does not require a filterclear
message before a replacement filter is loaded with filterload
. It also doesn’t require a filterload
message before a filterclear
message.
There is no payload in a filterclear
message. See the message header section for an example of a message without a payload.
The filterload
message tells the receiving peer to filter all relayed transactions and requested merkle blocks through the provided filter. This allows clients to receive transactions relevant to their wallet plus a configurable rate of false positive transactions which can provide plausible-deniability privacy.
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | nFilterBytes | compactSize uint | Number of bytes in the following filter bit field. |
Varies | filter | uint8_t[] | A bit field of arbitrary byte-aligned size. The maximum size is 36,000 bytes. |
4 | nHashFuncs | uint32_t | The number of hash functions to use in this filter. The maximum value allowed in this field is 50. |
4 | nTweak | uint32_t | An arbitrary value to add to the seed value in the hash function used by the bloom filter. |
1 | nFlags | uint8_t | A set of flags that control how outpoints corresponding to a matched pubkey script are added to the filter. See the table in the Updating A Bloom Filter subsection below. |
The annotated hexdump below shows a filterload
message. (The message header has been omitted.) For an example of how this payload was created, see the filterload example.
02 ......... Filter bytes: 2 b50f ....... Filter: 1010 1101 1111 0000 0b000000 ... nHashFuncs: 11 00000000 ... nTweak: 0/none 00 ......... nFlags: BLOOM_UPDATE_NONE
The getaddr
message requests an addr
message from the receiving node, preferably one with lots of IP addresses of other receiving nodes. The transmitting node can use those IP addresses to quickly update its database of available nodes rather than waiting for unsolicited addr
messages to arrive over time.
There is no payload in a getaddr
message. See the message header section for an example of a message without a payload.
The ping
message helps confirm that the receiving peer is still connected. If a TCP/IP error is encountered when sending the ping
message (such as a connection timeout), the transmitting node can assume that the receiving node is disconnected. The response to a ping
message is the pong
message.
Before protocol version 60000, the ping
message had no payload. As of protocol version 60001 and all later versions, the message includes a single field, the nonce.
Bytes | Name | Data Type | Description |
---|---|---|---|
8 | nonce | uint64_t | Random nonce assigned to this ping message. The responding pong message will include this nonce to identify the ping message to which it is replying. |
The annotated hexdump below shows a ping
message. (The message header has been omitted.)
0094102111e2af4d ... Nonce
The pong
message replies to a ping
message, proving to the pinging node that the ponging node is still alive. CICOIN Core will, by default, disconnect from any clients which have not responded to a ping
message within 20 minutes.
To allow nodes to keep track of latency, the pong
message sends back the same nonce received in the ping
message it is replying to.
The format of the pong
message is identical to the ping
message; only the message header differs.
The reject
message informs the receiving node that one of its previous messages has been rejected.
Bytes | Name | Data Type | Description |
---|---|---|---|
Varies | message bytes | compactSize uint | The number of bytes in the following message field. |
Varies | message | string | The type of message rejected as ASCII text without null padding. For example: “tx”, “block”, or “version”. |
1 | code | char | The reject message code. See the table below. |
Varies | reason bytes | compactSize uint | The number of bytes in the following reason field. May be 0x00 if a text reason isn’t provided. |
Varies | reason | string | The reason for the rejection in ASCII text. This should not be displayed to the user; it is only for debugging purposes. |
Varies | extra data | varies | Optional additional data provided with the rejection. For example, most rejections of tx messages or block messages include the hash of the rejected transaction or block header. See the code table below. |
The following table lists message reject codes. Codes are tied to the type of message they reply to; for example there is a 0x10 reject code for transactions and a 0x10 reject code for blocks.
Code | In Reply To | Extra Bytes | Extra Type | Description |
---|---|---|---|---|
0x01 | any message | 0 | N/A | Message could not be decoded. Be careful of reject message feedback loops where two peers each don’t understand each other’s reject messages and so keep sending them back and forth forever. |
0x10 | block message |
32 | char[32] | Block is invalid for some reason (invalid proof-of-work, invalid signature, etc). Extra data may include the rejected block’s header hash. |
0x10 | tx message |
32 | char[32] | Transaction is invalid for some reason (invalid signature, output value greater than input, etc.). Extra data may include the rejected transaction’s TXID. |
0x11 | block message |
32 | char[32] | The block uses a version that is no longer supported. Extra data may include the rejected block’s header hash. |
0x11 | version message |
0 | N/A | Connecting node is using a protocol version that the rejecting node considers obsolete and unsupported. |
0x12 | tx message |
32 | char[32] | Duplicate input spend (double spend): the rejected transaction spends the same input as a previously-received transaction. Extra data may include the rejected transaction’s TXID. |
0x12 | version message |
0 | N/A | More than one version message received in this connection. |
0x40 | tx message |
32 | char[32] | The transaction will not be mined or relayed because the rejecting node considers it non-standard—a transaction type or version unknown by the server. Extra data may include the rejected transaction’s TXID. |
0x41 | tx message |
32 | char[32] | One or more output amounts are below the dust threshold. Extra data may include the rejected transaction’s TXID. |
0x42 | tx message |
char[32] | The transaction did not have a large enough fee or priority to be relayed or mined. Extra data may include the rejected transaction’s TXID. | |
0x43 | block message |
32 | char[32] | The block belongs to a block chain which is not the same block chain as provided by a compiled-in checkpoint. Extra data may include the rejected block’s header hash. |
The annotated hexdump below shows a reject
message. (The message header has been omitted.)
02 ................................. Number of bytes in message: 2 7478 ............................... Type of message rejected: tx 12 ................................. Reject code: 0x12 (duplicate) 15 ................................. Number of bytes in reason: 21 6261642d74786e732d696e707574732d 7370656e74 ......................... Reason: bad-txns-inputs-spent 394715fcab51093be7bfca5a31005972 947baf86a31017939575fb2354222821 ... TXID
The sendheaders
message tells the receiving peer to send new block announcements using a headers
message rather than an inv
message.
There is no payload in a sendheaders
message. See the message header section for an example of a message without a payload.
The verack
message acknowledges a previously-received version
message, informing the connecting node that it can begin to send other messages. The verack
message has no payload; for an example of a message with no payload, see the message headers section.
The version
message provides information about the transmitting node to the receiving node at the beginning of a connection. Until both peers have exchanged version
messages, no other messages will be accepted.
If a version
message is accepted, the receiving node should send a verack
message—but no node should send a verack
message before initializing its half of the connection by first sending a version
message.
Bytes | Name | Data Type | Required/Optional | Description |
---|---|---|---|---|
4 | version | int32_t | Required | The highest protocol version understood by the transmitting node. See the protocol version section. |
8 | services | uint64_t | Required | The services supported by the transmitting node encoded as a bitfield. See the list of service codes below. |
8 | timestamp | int64_t | Required | The current Unix epoch time according to the transmitting node’s clock. Because nodes will reject blocks with timestamps more than two hours in the future, this field can help other nodes to determine that their clock is wrong. |
8 | addr_recv services | uint64_t | Required | The services supported by the receiving node as perceived by the transmitting node. Same format as the ‘services’ field above. CICOIN Core will attempt to provide accurate information. CICOIN will, by default, always send 0. |
16 | addr_recv IP address | char[16] | Required | The IPv6 address of the receiving node as perceived by the transmitting node in big endian byte order. IPv4 addresses can be provided as IPv4-mapped IPv6 addresses. CICOIN Core will attempt to provide accurate information. CICOIN will, by default, always return ::ffff:127.0.0.1 |
2 | addr_recv port | uint16_t | Required | The port number of the receiving node as perceived by the transmitting node in big endian byte order. |
8 | addr_trans services | uint64_t | Required | The services supported by the transmitting node. Should be identical to the ‘services’ field above. |
16 | addr_trans IP address | char[16] | Required | The IPv6 address of the transmitting node in big endian byte order. IPv4 addresses can be provided as IPv4-mapped IPv6 addresses. Set to ::ffff:127.0.0.1 if unknown. |
2 | addr_trans port | uint16_t | Required | The port number of the transmitting node in big endian byte order. |
8 | nonce | uint64_t | Required | A random nonce which can help a node detect a connection to itself. If the nonce is 0, the nonce field is ignored. If the nonce is anything else, a node should terminate the connection on receipt of a version message with a nonce it previously sent. |
Varies | user_agent bytes | compactSize uint | Required | Number of bytes in following user_agent field. If 0x00, no user agent field is sent. |
Varies | user_agent | string | Required if user_agent bytes > 0 | User agent as defined by BIP14. Previously called subVer. |
4 | start_height | int32_t | Required | The height of the transmitting node’s best block chain or, in the case of an SPV client, best block header chain. |
1 | relay | bool | Optional | Transaction relay flag. If 0x00, no inv messages or tx messages announcing new transactions should be sent to this client until it sends a filterload message or filterclear message. If the relay field is not present or is set to 0x01, this node wants inv messages and tx messages announcing new transactions. |
The following service identifiers have been assigned.
Value | Name | Description |
---|---|---|
0x00 | Unnamed | This node is not a full node. It may not be able to provide any data except for the transactions it originates. |
0x01 | NODE_NETWORK | This is a full node and can be asked for full blocks. It should implement all protocol features available in its self-reported protocol version. |
0x02 | NODE_GETUTXO | This is a full node capable of responding to the getutxo protocol request. This is not supported by any currently-maintained CICOIN node. See BIP64 for details on how this is implemented. |
0x04 | NODE_BLOOM | This is a full node capable and willing to handle bloom-filtered connections. See BIP111 for details. |
0x08 | NODE_WITNESS | This is a full node that can be asked for blocks and transactions including witness data. See BIP144 for details. |
0x10 | NODE_XTHIN | This is a full node that supports Xtreme Thinblocks. This is not supported by any currently-maintained CICOIN node. |
0x0400 | NODE_NETWORK_LIMITED | This is the same as NODE_NETWORK but the node has at least the last 288 blocks (last 2 days). See BIP159 for details on how this is implemented. |
Note: Protocol version 70001 introduced the optional relay
field, adding the possibility of an additional byte to the version
message. This introduces an incompatibility with implementations of lower protocol versions which validate the version
message size. When implementing support for protocol versions less than 70001 you may want to handle the case of a peer potentially sending an extra byte, treating it as invalid only in the case of a requested protocol version less than 70001.
The following annotated hexdump shows a version
message. (The message header has been omitted and the actual IP addresses have been replaced with RFC5737 reserved IP addresses.)
72110100 ........................... Protocol version: 70002 0100000000000000 ................... Services: NODE_NETWORK bc8f5e5400000000 ................... Epoch time: 1415483324 0100000000000000 ................... Receiving node's services 00000000000000000000ffffc61b6409 ... Receiving node's IPv6 address 208d ............................... Receiving node's port number 0100000000000000 ................... Transmitting node's services 00000000000000000000ffffcb0071c0 ... Transmitting node's IPv6 address 208d ............................... Transmitting node's port number 128035cbc97953f8 ................... Nonce 0f ................................. Bytes in user agent string: 15 2f5361746f7368693a302e392e332f ..... cf050500 ........................... Start height: 329167 01 ................................. Relay flag: true
CICOIN Core provides a remote procedure call (RPC) interface for various administrative tasks, wallet operations, and queries about network and block chain data.
If you start CICOIN Core using cicoin-qt
, the RPC interface is disabled by default. To enable it, set server=1
in cicoin.conf
or supply the -server
argument when invoking the program. If you start CICOIN Core using cicoin, the RPC interface is enabled by default.
The interface requires the user to provide a password for authenticating RPC requests. This password can be set either using the rpcpassword
property in cicoin.conf
or by supplying the -rpcpassword
program argument. Optionally a username can be set using the rpcuser
configuration value. See the Examples Page for more information about setting CICOIN Core configuration values.
Open-source client libraries for the RPC interface are readily available in most modern programming languages, so you probably don’t need to write your own from scratch. CICOIN Core also ships with its own compiled C++ RPC client, cicoin-cli
, located in the bin
directory alongside cicoin and cicoin-qt
. The cicoin-cli
program can be used as a command-line interface (CLI) to CICOIN Core or for making RPC calls from applications written in languages lacking a suitable native client. The remainder of this section describes the CICOIN Core RPC protocol in detail.
The CICOIN Core RPC service listens for HTTP POST
requests on port 8332 in mainnet mode or 18332 in testnet or regtest mode. The port number can be changed by setting rpcport
in cicoin.conf
. By default the RPC service binds to your server’s localhost loopback network interface so it’s not accessible from other servers. Authentication is implemented using HTTP basic authentication. RPC HTTP requests must include a Content-Type
header set to text/plain
and a Content-Length
header set to the size of the request body.
The format of the request body and response data is based on version 1.0 of the JSON-RPC specification. Specifically, the HTTP POST
data of a request must be a JSON object with the following format:
Name | Type | Presence | Description |
---|---|---|---|
Request | object | Required (exactly 1) |
The JSON-RPC request object |
→ |
number (real) |
Optional (0 or 1) |
Version indicator for the JSON-RPC request. Currently ignored by CICOIN Core. |
→ |
string | Optional (0 or 1) |
An arbitrary string that will be returned with the response. May be omitted or set to an empty string (“”) |
→ |
string | Required (exactly 1) |
The RPC method name (e.g. getblock ). See the RPC section for a list of available methods. |
→ |
array | Optional (0 or 1) | An array containing positional parameter values for the RPC. May be an empty array or omitted for RPC calls that don’t have any required parameters. |
→ |
object | Optional (0 or 1) |
Starting from CICOIN Core 0.14.0 (replaces the params array above) An object containing named parameter values for the RPC. May be an empty object or omitted for RPC calls that don’t have any required parameters. |
→ → |
any | Optional (0 or more) |
A parameter. May be any JSON type allowed by the particular RPC method |
In the table above and in other tables describing RPC input and output, we use the following conventions
params
array which itself is a child of the Request object.params
are literal strings that appear in the JSON object.The HTTP response data for a RPC request is a JSON object with the following format:
Name | Type | Presence | Description |
---|---|---|---|
Response | object | Required (exactly 1) |
The JSON-RPC response object. |
→ |
any | Required (exactly 1) |
The RPC output whose type varies by call. Has value null if an error occurred. |
→ |
null/object | Required (exactly 1) |
An object describing the error if one occurred, otherwise null. |
→ → |
number (int) | Required (exactly 1) |
The error code returned by the RPC function call. See rpcprotocol.h for a full list of error codes and their meanings. |
→ → |
string | Required (exactly 1) |
A text description of the error. May be an empty string (“”). |
→ |
string | Required (exactly 1) |
The value of id provided with the request. Has value null if the id field was omitted in the request. |
As an example, here is the JSON-RPC request object for the hash of the genesis block:
{ "method": "getblockhash", "params": [0], "id": "foo" }
The command to send this request using cicoin-cli
is:
cicoin-cli getblockhash 0
Alternatively, we could POST
this request using the cURL command-line program as follows:
curl --user ':my_secret_password' --data-binary ''' { "method": "getblockhash", "params": [0], "id": "foo" }''' \ --header 'Content-Type: text/plain;' localhost:8332
The HTTP response data for this request would be:
{ "result": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", "error": null, "id": "foo" }
Note: In order to minimize its size, the raw JSON response from CICOIN Core doesn’t include any extraneous whitespace characters. Here we’ve added whitespace to make the object more readable. Speaking of which, cicoin-cli
also transforms the raw response to make it more human-readable. It:
\n
) into actual newlinesresult
field if there’s no errorresults
of type stringerror
field if there’s an errorContinuing with the example above, the output from the cicoin-cli
command would be simply:
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
If there’s an error processing a request, CICOIN Core sets the result
field to null
and provides information about the error
in the error field. For example, a request for the block hash at block height -1 would be met with the following response (again, whitespace added for clarity):
{ "result": null, "error": { "code": -8, "message": "Block height out of range" }, "id": "foo" }
If cicoin-cli
encounters an error
, it exits with a non-zero status code and outputs the error field as text to the process’s standard error stream:
error: {"code": -8, "message": "Block height out of range"}
Starting in CICOIN Core version 0.7.0, the RPC interface supports request batching as described in version 2.0 of the JSON-RPC specification. To initiate multiple RPC requests within a single HTTP request, a client can POST
a JSON array filled with Request objects. The HTTP response data is then a JSON array filled with the corresponding Response objects. Depending on your usage pattern, request batching may provide significant performance gains. The cicoin-cli
RPC client does not support batch requests.
To keep this documentation compact and readable, the examples for each of the available RPC calls will be given as cicoin-cli
commands:
cicoin-cli [options]...
This translates into an JSON-RPC Request object of the form:
{ "method": "<method name>", "params": [ "<param1>", "<param2>", "..." ], "id": "foo" }
[]proper money handling if you write programs using the JSON-RPC interface, you must ensure they handle high-precision real numbers correctly. See the Proper Money Handling CICOIN Wiki article for details and example code.