diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index a9b3b133..18d60606 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -102,13 +102,13 @@ impl Block { /// Check if the `network_upgrade` fields from each transaction in the block matches /// the network upgrade calculated from the `network` and block height. /// - /// # Consensus rule: + /// # Consensus /// - /// The nConsensusBranchId field MUST match the consensus branch ID used for - /// SIGHASH transaction hashes, as specified in [ZIP-244] ([7.1]). + /// > [NU5 onward] The nConsensusBranchId field MUST match the consensus branch ID used + /// > for SIGHASH transaction hashes, as specified in [ZIP-244]. /// + /// /// [ZIP-244]: https://zips.z.cash/zip-0244 - /// [7.1]: https://zips.z.cash/protocol/nu5.pdf#txnencodingandconsensus pub fn check_transaction_network_upgrade_consistency( &self, network: Network, diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 0aa653a1..9997c2ca 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -544,10 +544,38 @@ impl ZcashDeserialize for Transaction { (header & LOW_31_BITS, header >> 31 != 0) }; - // Consensus rules: + // # Consensus + // + // The next rules apply for different transaction versions as follows: + // + // [Pre-Overwinter]: Transactions version 1 and 2. + // [Overwinter onward]: Transactions version 3 and above. + // [Overwinter only, pre-Sapling]: Transactions version 3. + // [Sapling to Canopy inclusive, pre-NU5]: Transactions version 4. + // [NU5 onward]: Transactions version 4 and above. + // // > The transaction version number MUST be greater than or equal to 1. - // > - // > The overwintered flag MUST NOT be set for version 1 and 2 transactions. + // + // > [Pre-Overwinter] The fOverwintered fag MUST NOT be set. + // + // > [Overwinter onward] The version group ID MUST be recognized. + // + // > [Overwinter onward] The fOverwintered flag MUST be set. + // + // > [Overwinter only, pre-Sapling] The transaction version number MUST be 3, + // > and the version group ID MUST be 0x03C48270. + // + // > [Sapling to Canopy inclusive, pre-NU5] The transaction version number MUST be 4, + // > and the version group ID MUST be 0x892F2085. + // + // > [NU5 onward] The transaction version number MUST be 4 or 5. + // > If the transaction version number is 4 then the version group ID MUST be 0x892F2085. + // > If the transaction version number is 5 then the version group ID MUST be 0x26A7270A. + // + // Note: Zebra checkpoints until Canopy blocks, this means only transactions versions + // 4 and 5 get fully verified. This satisfies "The transaction version number MUST be 4" + // and "The transaction version number MUST be 4 or 5" from the last two rules above. + // This is done in the zebra-consensus crate, in the transactions checks. // // https://zips.z.cash/protocol/protocol.pdf#txnconsensus match (version, overwintered) { @@ -568,10 +596,6 @@ impl ZcashDeserialize for Transaction { } (3, true) => { let id = limited_reader.read_u32::()?; - // Consensus rule: - // > [Overwinter only, pre-Sapling] The transaction version number MUST be 3, and the version group ID MUST be 0x03C48270. - // - // https://zips.z.cash/protocol/protocol.pdf#txnconsensus if id != OVERWINTER_VERSION_GROUP_ID { return Err(SerializationError::Parse( "expected OVERWINTER_VERSION_GROUP_ID", @@ -589,13 +613,6 @@ impl ZcashDeserialize for Transaction { } (4, true) => { let id = limited_reader.read_u32::()?; - // Consensus rules: - // > [Sapling to Canopy inclusive, pre-NU5] The transaction version number MUST be 4, and the version group ID MUST be 0x892F2085. - // > - // > [NU5 onward] The transaction version number MUST be 4 or 5. - // > If the transaction version number is 4 then the version group ID MUST be 0x892F2085. - // - // https://zips.z.cash/protocol/protocol.pdf#txnconsensus if id != SAPLING_VERSION_GROUP_ID { return Err(SerializationError::Parse( "expected SAPLING_VERSION_GROUP_ID", @@ -666,13 +683,6 @@ impl ZcashDeserialize for Transaction { }) } (5, true) => { - // header - // - // Consensus rule: - // > [NU5 onward] The transaction version number MUST be 4 or 5. ... - // > If the transaction version number is 5 then the version group ID MUST be 0x26A7270A. - // - // https://zips.z.cash/protocol/protocol.pdf#txnconsensus let id = limited_reader.read_u32::()?; if id != TX_V5_VERSION_GROUP_ID { return Err(SerializationError::Parse("expected TX_V5_VERSION_GROUP_ID")); diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index dfbdb4dd..5449813a 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -231,8 +231,6 @@ pub fn time_is_valid_at( /// /// # Consensus rules: /// -/// - The nConsensusBranchId field MUST match the consensus branch ID used for -/// SIGHASH transaction hashes, as specified in [ZIP-244] ([7.1]). /// - A SHA-256d hash in internal byte order. The merkle root is derived from the /// hashes of all transactions included in this block, ensuring that none of /// those transactions can be modified without modifying the header. [7.6] diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 2a8c8490..69e95cea 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -544,12 +544,19 @@ where match network_upgrade { // Supports V4 transactions // - // Consensus rules: - // > [Sapling to Canopy inclusive, pre-NU5] The transaction version number MUST be 4, ... - // > + // # Consensus + // + // > [Sapling to Canopy inclusive, pre-NU5] The transaction version number MUST be 4, + // > and the version group ID MUST be 0x892F2085. + // // > [NU5 onward] The transaction version number MUST be 4 or 5. + // > If the transaction version number is 4 then the version group ID MUST be 0x892F2085. + // > If the transaction version number is 5 then the version group ID MUST be 0x26A7270A. // // https://zips.z.cash/protocol/protocol.pdf#txnconsensus + // + // Note: Here we verify the transaction version number of the above two rules, the group + // id is checked in zebra-chain crate, in the transaction serialize. NetworkUpgrade::Sapling | NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood @@ -633,10 +640,16 @@ where match network_upgrade { // Supports V5 transactions // - // Consensus rules: + // # Consensus + // // > [NU5 onward] The transaction version number MUST be 4 or 5. + // > If the transaction version number is 4 then the version group ID MUST be 0x892F2085. + // > If the transaction version number is 5 then the version group ID MUST be 0x26A7270A. // // https://zips.z.cash/protocol/protocol.pdf#txnconsensus + // + // Note: Here we verify the transaction version number of the above rule, the group + // id is checked in zebra-chain crate, in the transaction serialize. NetworkUpgrade::Nu5 => Ok(()), // Does not support V5 transactions diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index c7d1e746..86a0761c 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -319,8 +319,12 @@ pub fn coinbase_expiry_height( } return Ok(()); } - // Consensus rule: [Overwinter to Canopy inclusive, pre-NU5] nExpiryHeight - // MUST be less than or equal to 499999999. + // # Consensus + // + // > [Overwinter to Canopy inclusive, pre-NU5] `nExpiryHeight` MUST be less than + // > or equal to 499999999. + // + // https://zips.z.cash/protocol/protocol.pdf#txnconsensus validate_expiry_height_max(expiry_height, true, block_height, coinbase) } } @@ -338,6 +342,19 @@ pub fn non_coinbase_expiry_height( if transaction.is_overwintered() { let expiry_height = transaction.expiry_height(); + // # Consensus + // + // > [Overwinter to Canopy inclusive, pre-NU5] nExpiryHeight MUST be + // > less than or equal to 499999999. + // + // > [NU5 onward] nExpiryHeight MUST be less than or equal to 499999999 + // > for non-coinbase transactions. + // + // > [Overwinter onward] If a transaction is not a coinbase transaction and its + // > nExpiryHeight field is nonzero, then it MUST NOT be mined at a block height + // > greater than its nExpiryHeight. + // + // https://zips.z.cash/protocol/protocol.pdf#txnconsensus validate_expiry_height_max(expiry_height, false, block_height, transaction)?; validate_expiry_height_mined(expiry_height, block_height, transaction)?; }