diff --git a/docs/protocol.md b/docs/protocol.md index 96f364b..5430b7c 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -10,16 +10,15 @@ Blocks are hashed with SHA256 and need to start with a certain number of zeros ( ed25519 keys are used to validate transactions. - ## block datastructure | content | size (bytes) | |---|---| -| previous hash | 32 | -| message (arbitrary) | 32 | | nonce | 8 | | timestamp (unix time in seconds, BE) | 8 | -| block id (BE) | 4 | +| previous hash | 32 | +| message (arbitrary) | 32 | +| difficulty sum (BE) | 32 | | miner pubkey | 32 | | transaction (optional) | 148 | @@ -49,3 +48,60 @@ If a transaction is included, the following happens additionally: - The sender needs to pay "amount" + "transaction fee" - The receiver gets "amount" - The miner gets "transaction fee" on top of the reward. + +## calculating difficulty + +The "difficulty sum" field (included in each block) is the cumulative sum of all block difficulty values, beginning with the first block. + +The block difficulty value is not directly stated in each block but can be calculated by subtracting the "difficulty sum" of the previous block from the "difficulty sum" of the current block. + +To calculate the block difficulty value, the following blocks are relevant: + +- The current block for which to calculate the difficulty: [B-0] +- The previous block: [B-1] +- The block that is 10 steps back in the chain: [B-10] + +Then apply the following formula: (The slash / means integer division) +``` +D = [B-1].difficulty_sum - [B-10].difficulty_sum +T = [B-1].timestamp - [B-10].timestamp +calculated_difficulty = D * 300 / T + +block_difficulty = max(calculated_difficulty, 2^28) + +[B-0].difficulty_sum = [B-1].difficulty_sum + block_difficulty +``` + +Note the max() operation: A difficulty can never be lower than 2^28 (=268435456). This is a strict lower bound. + +For the first block, the "difficulty sum" value is set to 0. + +Early in the chain, when less than 11 blocks have been mined, we take assumptions for blocks "before" the first block: +- Each of these "before" blocks had a block difficulty of exactly 2^28 +- The timestamp difference between each two blocks before the first block is exactly 300 seconds. + +## validity + +### transaction + +A transaction is valid if its signature is valid. +The "signature" field must be an ed25519 signature over the concatenation of all previous fields (id + sender pubkey + receiver pubkey + amount + transaction fee), and must be valid when validated with the "sender" pubkey. + +### transaction in a block + +A transaction that is stored in a block must fulfill the following criteria (in addition to the valid signature): + +- There was never another transaction with the same ("id", "sender") pair anywhere in the block chain before. +- Following the balances in the block chain, the "sender" key has enough money for both payments. (amount + transaction fee) + +### block + +A block is valid if all of the following criteria are fulfilled: + +- The "previous hash" field contains a SHA256 hash value of a previous valid block. (Or is completely filled with nullbytes, in case of the first block.) +- The "timestamp" field is greater than the timestamp of the previous block (if there is any). Equal timestamps are not allowed. +- The "timestamp" field is less than or equal to the current time. This needs to be decided by each node based on the local clock. +- The "difficulty sum" must be precisely calculated, as specified in `calculating difficulty` +- The "transaction" is either: + - Completely empty (148 nullbytes) + - or: A valid `transaction in a block` as described above.