From f668e1f2c3231e89c652364cdbd18491ff913c2f Mon Sep 17 00:00:00 2001
From: Oscar Pepper <oscarpepper@zingolabs.org>
Date: Fri, 15 Mar 2024 13:39:58 +0000
Subject: [PATCH 1/2] zcash_protocol: Added constructors to `LocalNetwork`

---
 components/zcash_protocol/CHANGELOG.md        |  2 ++
 .../zcash_protocol/src/local_consensus.rs     | 31 +++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/components/zcash_protocol/CHANGELOG.md b/components/zcash_protocol/CHANGELOG.md
index 362b921850..6fc381ca11 100644
--- a/components/zcash_protocol/CHANGELOG.md
+++ b/components/zcash_protocol/CHANGELOG.md
@@ -10,6 +10,8 @@ and this library adheres to Rust's notion of
 ### Added
 - `zcash_protocol::memo`:
   - `impl TryFrom<&MemoBytes> for Memo`
+- `zcash_protocol::local_consensus`:
+  - `new`, `all_upgrades_active` and `canopy_active` constructors to `LocalNetwork`
 
 ### Removed
 - `unstable-nu6` and `zfuture` feature flags (use `--cfg zcash_unstable=\"nu6\"`
diff --git a/components/zcash_protocol/src/local_consensus.rs b/components/zcash_protocol/src/local_consensus.rs
index 5d277cf1be..213c2403a0 100644
--- a/components/zcash_protocol/src/local_consensus.rs
+++ b/components/zcash_protocol/src/local_consensus.rs
@@ -43,6 +43,37 @@ pub struct LocalNetwork {
     pub z_future: Option<BlockHeight>,
 }
 
+impl LocalNetwork {
+    pub fn new(
+        overwinter: u64,
+        sapling: u64,
+        blossom: u64,
+        heartwood: u64,
+        canopy: u64,
+        nu5: u64,
+    ) -> Self {
+        LocalNetwork {
+            overwinter: Some(BlockHeight::from_u32(overwinter as u32)),
+            sapling: Some(BlockHeight::from_u32(sapling as u32)),
+            blossom: Some(BlockHeight::from_u32(blossom as u32)),
+            heartwood: Some(BlockHeight::from_u32(heartwood as u32)),
+            canopy: Some(BlockHeight::from_u32(canopy as u32)),
+            nu5: Some(BlockHeight::from_u32(nu5 as u32)),
+        }
+    }
+
+    /// Creates a `LocalNetwork` with all network upgrades initially active.
+    pub fn all_upgrades_active() -> Self {
+        Self::new(1, 1, 1, 1, 1, 1)
+    }
+
+    /// Creates a `LocalNetwork` with all network upgrades up to and including canopy
+    /// initally active.
+    pub fn canopy_active(nu5_activation_height: u64) -> Self {
+        Self::new(1, 1, 1, 1, 1, nu5_activation_height)
+    }
+}
+
 /// Parameters implementation for `LocalNetwork`
 impl Parameters for LocalNetwork {
     fn network_type(&self) -> NetworkType {

From 68d2add2a62c879465adc6658e1b672ffec64582 Mon Sep 17 00:00:00 2001
From: Oscar Pepper <oscarpepper@zingolabs.org>
Date: Mon, 8 Apr 2024 22:25:07 +0100
Subject: [PATCH 2/2] Changes requested: Fixed and documented constructor and
 added panic if NU ordering is changed

---
 .../zcash_protocol/src/local_consensus.rs     | 21 +++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/components/zcash_protocol/src/local_consensus.rs b/components/zcash_protocol/src/local_consensus.rs
index 213c2403a0..6864bd25b2 100644
--- a/components/zcash_protocol/src/local_consensus.rs
+++ b/components/zcash_protocol/src/local_consensus.rs
@@ -44,6 +44,10 @@ pub struct LocalNetwork {
 }
 
 impl LocalNetwork {
+    /// Construct a new `LocalNetwork` where all network upgrade activation heights are specified.
+    ///
+    /// Sequential network upgrades may share the same activation height but this constructor will
+    /// panic if the order in which network upgrades activate is changed.
     pub fn new(
         overwinter: u64,
         sapling: u64,
@@ -52,6 +56,15 @@ impl LocalNetwork {
         canopy: u64,
         nu5: u64,
     ) -> Self {
+        assert!(
+            overwinter <= sapling
+                && sapling <= blossom
+                && blossom <= heartwood
+                && heartwood <= canopy
+                && canopy <= nu5,
+            "Network upgrade activation heights must be in ascending order"
+        );
+
         LocalNetwork {
             overwinter: Some(BlockHeight::from_u32(overwinter as u32)),
             sapling: Some(BlockHeight::from_u32(sapling as u32)),
@@ -59,15 +72,19 @@ impl LocalNetwork {
             heartwood: Some(BlockHeight::from_u32(heartwood as u32)),
             canopy: Some(BlockHeight::from_u32(canopy as u32)),
             nu5: Some(BlockHeight::from_u32(nu5 as u32)),
+            #[cfg(zcash_unstable = "nu6")]
+            nu6: None,
+            #[cfg(zcash_unstable = "zfuture")]
+            z_future: None,
         }
     }
 
-    /// Creates a `LocalNetwork` with all network upgrades initially active.
+    /// Construct a new `LocalNetwork` with all network upgrades initially active.
     pub fn all_upgrades_active() -> Self {
         Self::new(1, 1, 1, 1, 1, 1)
     }
 
-    /// Creates a `LocalNetwork` with all network upgrades up to and including canopy
+    /// Construct a new `LocalNetwork` with all network upgrades up to and including canopy
     /// initally active.
     pub fn canopy_active(nu5_activation_height: u64) -> Self {
         Self::new(1, 1, 1, 1, 1, nu5_activation_height)