Repository: ZcashFoundation/zebra (rust)

Issue:
Add NU6 network upgrade variant
### Scope

Add an NU6 network upgrade variant with a random consensus branch ID for testing.


Pull request:
add(chain): Add an NU6 network upgrade variant
## Motivation

Close #7958.

## Solution

- Add an `Nu6` variant to the `NetworkUpgrade` enum.
- Update docs.

### Tests

- Fix failing tests.

### PR Author's Checklist

- [x] The PR name will make sense to users.
- [ ] The PR provides a CHANGELOG summary.
- [x] The solution is tested.
- [x] The documentation is up to date.
- [x] The PR has a priority label.

### PR Reviewer's Checklist

<!-- If you are a reviewer of the PR, check the boxes below before approving it. -->

- [ ] The PR Author's checklist is complete.
- [ ] The PR resolves the issue.

Patch:
diff --git a/zebra-chain/src/block/commitment.rs b/zebra-chain/src/block/commitment.rs
index 2071773ff..2cb09e75b 100644
--- a/zebra-chain/src/block/commitment.rs
+++ b/zebra-chain/src/block/commitment.rs
@@ -123,9 +123,9 @@ impl Commitment {
                 }
             }
             // NetworkUpgrade::current() returns the latest network upgrade that's activated at the provided height, so
-            // on Regtest for heights above height 0, it returns NU5, and it's possible for the current network upgrade
-            // to be NU5 (or Canopy, or any network upgrade above Heartwood) at the Heartwood activation height.
-            (Canopy | Nu5, activation_height)
+            // on Regtest for heights above height 0, it could return NU6, and it's possible for the current network upgrade
+            // to be NU6 (or Canopy, or any network upgrade above Heartwood) at the Heartwood activation height.
+            (Canopy | Nu5 | Nu6, activation_height)
                 if height == activation_height
                     && Some(height) == Heartwood.activation_height(network) =>
             {
@@ -136,7 +136,7 @@ impl Commitment {
                 }
             }
             (Heartwood | Canopy, _) => Ok(ChainHistoryRoot(ChainHistoryMmrRootHash(bytes))),
-            (Nu5, _) => Ok(ChainHistoryBlockTxAuthCommitment(
+            (Nu5 | Nu6, _) => Ok(ChainHistoryBlockTxAuthCommitment(
                 ChainHistoryBlockTxAuthCommitmentHash(bytes),
             )),
         }
diff --git a/zebra-chain/src/history_tree.rs b/zebra-chain/src/history_tree.rs
index 59dcb13a6..91fa3a176 100644
--- a/zebra-chain/src/history_tree.rs
+++ b/zebra-chain/src/history_tree.rs
@@ -102,7 +102,7 @@ impl NonEmptyHistoryTree {
                 )?;
                 InnerHistoryTree::PreOrchard(tree)
             }
-            NetworkUpgrade::Nu5 => {
+            NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => {
                 let tree = Tree::<OrchardOnward>::new_from_cache(
                     network,
                     network_upgrade,
@@ -156,7 +156,7 @@ impl NonEmptyHistoryTree {
                 )?;
                 (InnerHistoryTree::PreOrchard(tree), entry)
             }
-            NetworkUpgrade::Nu5 => {
+            NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => {
                 let (tree, entry) = Tree::<OrchardOnward>::new_from_block(
                     network,
                     block,
diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs
index f4f575069..5de204ba7 100644
--- a/zebra-chain/src/parameters/network_upgrade.rs
+++ b/zebra-chain/src/parameters/network_upgrade.rs
@@ -15,7 +15,7 @@ use hex::{FromHex, ToHex};
 use proptest_derive::Arbitrary;
 
 /// A list of network upgrades in the order that they must be activated.
-pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 8] = [
+pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 9] = [
     Genesis,
     BeforeOverwinter,
     Overwinter,
@@ -24,12 +24,13 @@ pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 8] = [
     Heartwood,
     Canopy,
     Nu5,
+    Nu6,
 ];
 
 /// A Zcash network upgrade.
 ///
-/// Network upgrades can change the Zcash network protocol or consensus rules in
-/// incompatible ways.
+/// Network upgrades change the Zcash network protocol or consensus rules. Note that they have no
+/// designated codenames from NU5 onwards.
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
 #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
 pub enum NetworkUpgrade {
@@ -54,12 +55,11 @@ pub enum NetworkUpgrade {
     Heartwood,
     /// The Zcash protocol after the Canopy upgrade.
     Canopy,
-    /// The Zcash protocol after the Nu5 upgrade.
-    ///
-    /// Note: Network Upgrade 5 includes the Orchard Shielded Protocol, non-malleable transaction
-    /// IDs, and other changes. There is no special code name for Nu5.
+    /// The Zcash protocol after the NU5 upgrade.
     #[serde(rename = "NU5")]
     Nu5,
+    /// The Zcash protocol after the NU6 upgrade.
+    Nu6,
 }
 
 impl fmt::Display for NetworkUpgrade {
@@ -88,6 +88,7 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)]
     (block::Height(903_000), Heartwood),
     (block::Height(1_046_400), Canopy),
     (block::Height(1_687_104), Nu5),
+    // TODO: Add NU6.
 ];
 
 /// Fake mainnet network upgrade activation heights, used in tests.
@@ -101,6 +102,7 @@ const FAKE_MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[
     (block::Height(25), Heartwood),
     (block::Height(30), Canopy),
     (block::Height(35), Nu5),
+    (block::Height(40), Nu6),
 ];
 
 /// Testnet network upgrade activation heights.
@@ -122,6 +124,7 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)]
     (block::Height(903_800), Heartwood),
     (block::Height(1_028_500), Canopy),
     (block::Height(1_842_420), Nu5),
+    // TODO: Add NU6.
 ];
 
 /// Fake testnet network upgrade activation heights, used in tests.
@@ -135,6 +138,7 @@ const FAKE_TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[
     (block::Height(25), Heartwood),
     (block::Height(30), Canopy),
     (block::Height(35), Nu5),
+    (block::Height(40), Nu6),
 ];
 
 /// The Consensus Branch Id, used to bind transactions and blocks to a
@@ -210,6 +214,8 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] =
     (Heartwood, ConsensusBranchId(0xf5b9230b)),
     (Canopy, ConsensusBranchId(0xe9ff75a6)),
     (Nu5, ConsensusBranchId(0xc2d6d0b4)),
+    // TODO: Use the real consensus branch ID once it's specified.
+    (Nu6, ConsensusBranchId(0xdeadc0de)),
 ];
 
 /// The target block spacing before Blossom.
@@ -313,7 +319,8 @@ impl NetworkUpgrade {
             Blossom => Some(Heartwood),
             Heartwood => Some(Canopy),
             Canopy => Some(Nu5),
-            Nu5 => None,
+            Nu5 => Some(Nu6),
+            Nu6 => None,
         }
     }
 
@@ -390,7 +397,7 @@ impl NetworkUpgrade {
     pub fn target_spacing(&self) -> Duration {
         let spacing_seconds = match self {
             Genesis | BeforeOverwinter | Overwinter | Sapling => PRE_BLOSSOM_POW_TARGET_SPACING,
-            Blossom | Heartwood | Canopy | Nu5 => POST_BLOSSOM_POW_TARGET_SPACING.into(),
+            Blossom | Heartwood | Canopy | Nu5 | Nu6 => POST_BLOSSOM_POW_TARGET_SPACING.into(),
         };
 
         Duration::seconds(spacing_seconds)
diff --git a/zebra-chain/src/primitives/zcash_history.rs b/zebra-chain/src/primitives/zcash_history.rs
index e43b9478f..e8ca97d63 100644
--- a/zebra-chain/src/primitives/zcash_history.rs
+++ b/zebra-chain/src/primitives/zcash_history.rs
@@ -273,22 +273,23 @@ impl Version for zcash_history::V1 {
             }
             // Nu5 is included because this function is called by the V2 implementation
             // since the V1::NodeData is included inside the V2::NodeData.
-            NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy | NetworkUpgrade::Nu5 => {
-                zcash_history::NodeData {
-                    consensus_branch_id: branch_id.into(),
-                    subtree_commitment: block_hash,
-                    start_time: time,
-                    end_time: time,
-                    start_target: target,
-                    end_target: target,
-                    start_sapling_root: sapling_root,
-                    end_sapling_root: sapling_root,
-                    subtree_total_work: work,
-                    start_height: height.0 as u64,
-                    end_height: height.0 as u64,
-                    sapling_tx: sapling_tx_count,
-                }
-            }
+            NetworkUpgrade::Heartwood
+            | NetworkUpgrade::Canopy
+            | NetworkUpgrade::Nu5
+            | NetworkUpgrade::Nu6 => zcash_history::NodeData {
+                consensus_branch_id: branch_id.into(),
+                subtree_commitment: block_hash,
+                start_time: time,
+                end_time: time,
+                start_target: target,
+                end_target: target,
+                start_sapling_root: sapling_root,
+                end_sapling_root: sapling_root,
+                subtree_total_work: work,
+                start_height: height.0 as u64,
+                end_height: height.0 as u64,
+                sapling_tx: sapling_tx_count,
+            },
         }
     }
 }
diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs
index 432b83b2b..cf4aa7a95 100644
--- a/zebra-chain/src/transaction/arbitrary.rs
+++ b/zebra-chain/src/transaction/arbitrary.rs
@@ -778,7 +778,7 @@ impl Arbitrary for Transaction {
             NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => {
                 Self::v4_strategy(ledger_state)
             }
-            NetworkUpgrade::Nu5 => prop_oneof![
+            NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => prop_oneof![
                 Self::v4_strategy(ledger_state.clone()),
                 Self::v5_strategy(ledger_state)
             ]
diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs
index 95cd13ed7..1c3030036 100644
--- a/zebra-consensus/src/transaction.rs
+++ b/zebra-consensus/src/transaction.rs
@@ -677,7 +677,8 @@ where
             | NetworkUpgrade::Blossom
             | NetworkUpgrade::Heartwood
             | NetworkUpgrade::Canopy
-            | NetworkUpgrade::Nu5 => Ok(()),
+            | NetworkUpgrade::Nu5
+            | NetworkUpgrade::Nu6 => Ok(()),
 
             // Does not support V4 transactions
             NetworkUpgrade::Genesis
@@ -765,7 +766,7 @@ where
             //
             // 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(()),
+            NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => Ok(()),
 
             // Does not support V5 transactions
             NetworkUpgrade::Genesis
diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs
index f15275d3b..7ac76d767 100644
--- a/zebra-network/src/protocol/external/types.rs
+++ b/zebra-network/src/protocol/external/types.rs
@@ -93,6 +93,8 @@ impl Version {
             (Mainnet, Canopy) => 170_013,
             (Testnet(params), Nu5) if params.is_default_testnet() => 170_050,
             (Mainnet, Nu5) => 170_100,
+            (Testnet(params), Nu6) if params.is_default_testnet() => 170_050,
+            (Mainnet, Nu6) => 170_100,
 
             // It should be fine to reject peers with earlier network protocol versions on custom testnets for now.
             (Testnet(_params), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0,
diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs
index 386b81da7..ccb33a35f 100644
--- a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs
+++ b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs
@@ -212,7 +212,9 @@ pub fn proposal_block_from_template(
         | NetworkUpgrade::Blossom
         | NetworkUpgrade::Heartwood => panic!("pre-Canopy block templates not supported"),
         NetworkUpgrade::Canopy => chain_history_root.bytes_in_serialized_order().into(),
-        NetworkUpgrade::Nu5 => block_commitments_hash.bytes_in_serialized_order().into(),
+        NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => {
+            block_commitments_hash.bytes_in_serialized_order().into()
+        }
     };
 
     Ok(Block {


Test patch:
diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs
index 391f7eae4..7ba180223 100644
--- a/zebra-chain/src/parameters/network/testnet.rs
+++ b/zebra-chain/src/parameters/network/testnet.rs
@@ -61,6 +61,8 @@ pub struct ConfiguredActivationHeights {
     /// Activation height for `NU5` network upgrade.
     #[serde(rename = "NU5")]
     pub nu5: Option<u32>,
+    /// Activation height for `NU6` network upgrade.
+    pub nu6: Option<u32>,
 }
 
 /// Builder for the [`Parameters`] struct.
@@ -174,6 +176,7 @@ impl ParametersBuilder {
             heartwood,
             canopy,
             nu5,
+            nu6,
         }: ConfiguredActivationHeights,
     ) -> Self {
         use NetworkUpgrade::*;
@@ -191,6 +194,7 @@ impl ParametersBuilder {
             .chain(heartwood.into_iter().map(|h| (h, Heartwood)))
             .chain(canopy.into_iter().map(|h| (h, Canopy)))
             .chain(nu5.into_iter().map(|h| (h, Nu5)))
+            .chain(nu6.into_iter().map(|h| (h, Nu6)))
             .map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu))
             .collect();
 
diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs
index 88aa19b40..33f0bd06b 100644
--- a/zebra-chain/src/parameters/network/tests/vectors.rs
+++ b/zebra-chain/src/parameters/network/tests/vectors.rs
@@ -103,7 +103,7 @@ fn activates_network_upgrades_correctly() {
     let expected_activation_height = 1;
     let network = testnet::Parameters::build()
         .with_activation_heights(ConfiguredActivationHeights {
-            nu5: Some(expected_activation_height),
+            nu6: Some(expected_activation_height),
             ..Default::default()
         })
         .to_network();
diff --git a/zebra-consensus/src/transaction/tests/prop.rs b/zebra-consensus/src/transaction/tests/prop.rs
index e5e790059..99a093068 100644
--- a/zebra-consensus/src/transaction/tests/prop.rs
+++ b/zebra-consensus/src/transaction/tests/prop.rs
@@ -344,7 +344,7 @@ fn sanitize_transaction_version(
             BeforeOverwinter => 2,
             Overwinter => 3,
             Sapling | Blossom | Heartwood | Canopy => 4,
-            Nu5 => 5,
+            Nu5 | Nu6 => 5,
         }
     };