Peercoin protocol rules

From Peercoin Wiki
Jump to: navigation, search

Data structures

The main data structures are transactions and blocks. Blocks are composed of the block header followed by transactions in the block. Transactions are identified by their hash; blocks by the hash of their header. Blocks have prev pointers that link them into a graph.

Conceptually, the client has the following data structures:

Transactions

There are two collections of transactions:

transaction pool
an unordered collection of transactions that are not in blocks in the main chain, but for which we have input transactions
orphan transactions
transactions that can't go into the pool due to one or more missing input transactions

Blocks

There are 3 categories of blocks:

blocks in the main branch
the transactions in these blocks are considered at least tentatively confirmed
blocks on side branches off the main branch
these blocks have at least tentatively lost the race to be in the main branch
orphan blocks
these are blocks which don't link into the main branch, normally because of a missing predecessor or nth-level predecessor

Tx messages

No Rule Source ppc
1 Check syntactic correctness
2 Make sure neither in or out lists are empty [1]
3 Size in bytes < MAX_BLOCK_SIZE [2]
4 Each output value, as well as the total, must be in legal money range [3]
1 Peercoin: enforce minimum output amount >= MIN_TXOUT_AMOUNT [4] pMHABKw.png
5 Make sure none of the inputs have hash=0, n=-1 (coinbase transactions)
6 Check that nLockTime <= INT_MAX (nLockTime must not exceed 31 bits, as some clients will interpret it incorrectly), size in bytes >= 100 (A valid transaction requires at least 100 bytes; if it's any less, the transaction is not valid), and sig opcount <= 2 (the number of signature operands in the signature (no, that is not redundant) for standard transactions will never exceed two)
7 Reject "nonstandard" transactions: scriptSig doing anything other than pushing numbers on the stack, or scriptPubkey not matching the two usual forms. Note that this is not a hard requirement on clients.
8 Reject if we already have matching tx in the pool, or in a block in the main branch
9 For each input, if the referenced output exists in any other tx in the pool, reject this transaction. Note that this is not a hard requirement on clients. The network-enforced rule is that only one transaction spending a particular output can be in the blockchain, thus preventing double-spending. Technically miners can choose which one they want to put into the block they're working on as long as no other transaction has spent that output either previously in the blockchain, or in the same block. The in-memory transaction pool can technically be managed in whatever way the miner is willing to implement.
10 For each input, look in the main branch and the transaction pool to find the referenced output transaction. If the output transaction is missing for any input, this will be an orphan transaction. Add to the orphan transactions, if a matching transaction is not in there already.
11 For each input, if the referenced output transaction is coinbase (i.e. only 1 input, with hash=0, n=-1) or coinstake (peercoin), it must have at least COINBASE_MATURITY_PPC confirmations; else reject this transaction. [5] pMHABKw.png
11.b For each input, if the referenced output transaction timestamp is after current transaction timestamp then reject this transaction. [6] pMHABKw.png
12 For each input, if the referenced output does not exist (e.g. never existed or has already been spent), reject this transaction. This is the protection against double-spending.
13 Using the referenced output transactions to get input values, check that each input value, as well as the sum, are in legal money range.
14 Reject if the sum of input values < sum of output values.
15.a Reject if transaction fee (defined as sum of input values minus sum of output values) would be too low to get into an empty block.
15.b If coinstake transaction, verify stake reward (peercoin) [7] pMHABKw.png
15.c Enforce minimum transaction fees (peercoin) [8] pMHABKw.png
16 Verify the scriptPubKey accepts for each input; reject if any are bad. [9]
17 Add to transaction pool.
18 "Add to wallet if mine".
19 Relay transaction to peers.
20 For each orphan transaction that uses this one as one of its inputs, run all these steps (including this one) recursively on that orphan.

Block messages

No Rule Source ppc
1 Check syntactic correctness
2.a Reject if duplicate of block we have in any of the three categories [10]
2.b Reject duplicate stake, only allowed when there is orphan child block [11] pMHABKw.png
3 Transaction list must be non-empty [12]
4.a PoW block hash must satisfy claimed nBits proof of work [13]
4.b PoS block: check kernel hash target and coinstake signature [14] pMHABKw.png
5 Block timestamp must not be more than two hours in the future [15]
6.a First transaction must be coinbase (i.e. only 1 input, with hash=0, n=-1), the rest must not be (except PoS block, cf. below) [16]
6.b For PoS block, second transaction must be coinstake, the rest must not be coinbase nor coinstake [17] pMHABKw.png
6.c For PoS block, coinbase output must be empty [18] pMHABKw.png
5.b Coinbase timestamp must not be more than two hours in the future [19]
5.c PoS block only: coinstake timestamp must not be more than two hours in the future [20] pMHABKw.png
7 For each transaction, apply "tx" checks 2-4 [21]
1 Check transaction timestamp > block timestamp (peercoin) [22] pMHABKw.png
8 For the coinbase (first) transaction, scriptSig length must be 2-100 [23]
9 Reject if sum of transaction sig opcounts > MAX_BLOCK_SIGOPS [24]
10 Verify Merkle hash [25]
10.b Check block signature (peercoin) [26] pMHABKw.png
11 Check if prev block (matching prev hash) is in main branch or side branches. If not, add this to orphan blocks, then query peer we got this from for 1st missing orphan block in prev chain; done with block
12 Check that nBits value matches the difficulty rules [27]
13 Reject if timestamp is the median time of the last 11 blocks or before [28]
14 For certain old blocks (i.e. on initial block download) check that hash matches known values [29]
15 Add block into the tree. There are three cases: 1. block further extends the main branch; 2. block extends a side branch but does not add enough difficulty to make it become the new main branch; 3. block extends a side branch and makes it the new main branch.
16 For case 1, adding to main branch:
1 For all but the coinbase transaction, apply the following:
1 For each input, look in the main branch to find the referenced output transaction. Reject if the output transaction is missing for any input.
2 For each input, if we are using the nth output of the earlier transaction, but it has fewer than n+1 outputs, reject.
3 For each input, if the referenced output transaction is coinbase (i.e. only 1 input, with hash=0, n=-1), it must have at least COINBASE_MATURITY (100) confirmations; else reject.
4 Verify crypto signatures for each input; reject if any are bad.
5 For each input, if the referenced output has already been spent by a transaction in the main branch, reject.
6 Using the referenced output transactions to get input values, check that each input value, as well as the sum, are in legal money range.
7 Reject if the sum of input values < sum of output values.
2 Reject if coinbase value > sum of block creation fee and transaction fees
3 (If we have not rejected):
4 For each transaction, "Add to wallet if mine"
5 For each transaction in the block, delete any matching transaction from the transaction pool
6 Relay block to our peers
7 If we rejected, the block is not counted as part of the main branch
17 For case 2, adding to a side branch, we don't do anything.
18 For case 3, a side branch becoming the main branch:
1 Find the fork block on the main branch which this side branch forks off of
2 Redefine the main branch to only go up to this fork block
3 For each block on the side branch, from the child of the fork block to the leaf, add to the main branch:
1 Do "branch" checks 3-11
2 For all but the coinbase transaction, apply the following:
1 For each input, look in the main branch to find the referenced output transaction. Reject if the output transaction is missing for any input.
2 For each input, if we are using the nth output of the earlier transaction, but it has fewer than n+1 outputs, reject.
3 For each input, if the referenced output transaction is coinbase (i.e. only 1 input, with hash=0, n=-1), it must have at least COINBASE_MATURITY (100) confirmations; else reject.
4 Verify crypto signatures for each input; reject if any are bad.
5 For each input, if the referenced output has already been spent by a transaction in the main branch, reject.
6 Using the referenced output transactions to get input values, check that each input value, as well as the sum, are in legal money range.
7 Reject if the sum of input values < sum of output values.
4 If we reject at any point, leave the main branch as what it was originally, done with block
5 For each block in the old main branch, from the leaf down to the child of the fork block:
1 For each non-coinbase transaction in the block:
1 Apply "tx" checks 2-9, except in step 8, only look in the transaction pool for duplicates, not the main branch
2 Add to transaction pool if accepted, else go on to next transaction
6 For each block in the new main branch, from the child of the fork node to the leaf:
1 For each transaction in the block, delete any matching transaction from the transaction pool
7 Relay block to our peers
19 For each orphan block for which this block is its prev, run all these steps (including this one) recursively on that orphan

Links