From 3dc05a69eb691eaaf401813c7a35032b1e4317e9 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Tue, 11 May 2021 10:10:21 -0600 Subject: [PATCH] Add Nu5 NetworkUpgrade variant. --- components/zcash_note_encryption/src/lib.rs | 1 - zcash_primitives/src/consensus.rs | 107 +++++++++++++++++++- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/components/zcash_note_encryption/src/lib.rs b/components/zcash_note_encryption/src/lib.rs index 481ee1e81..3bece34f2 100644 --- a/components/zcash_note_encryption/src/lib.rs +++ b/components/zcash_note_encryption/src/lib.rs @@ -445,7 +445,6 @@ pub fn try_compact_note_decryption>( /// /// Implements part of section 4.19.3 of the /// [Zcash Protocol Specification](https://zips.z.cash/protocol/nu5.pdf#decryptovk) -/// For decryption using a Full Viewing Key see [`try_sapling_output_recovery`]. pub fn try_output_recovery_with_ock>( domain: &D, ock: &OutgoingCipherKey, diff --git a/zcash_primitives/src/consensus.rs b/zcash_primitives/src/consensus.rs index 4e5c49dd4..02e3913f7 100644 --- a/zcash_primitives/src/consensus.rs +++ b/zcash_primitives/src/consensus.rs @@ -3,7 +3,7 @@ use std::cmp::{Ord, Ordering}; use std::convert::TryFrom; use std::fmt; -use std::ops::{Add, Sub}; +use std::ops::{Add, Bound, RangeBounds, Sub}; use crate::constants; @@ -195,6 +195,7 @@ impl Parameters for MainNetwork { NetworkUpgrade::Blossom => Some(BlockHeight(653_600)), NetworkUpgrade::Heartwood => Some(BlockHeight(903_000)), NetworkUpgrade::Canopy => Some(BlockHeight(1_046_400)), + NetworkUpgrade::Nu5 => None, #[cfg(feature = "zfuture")] NetworkUpgrade::ZFuture => None, } @@ -239,6 +240,7 @@ impl Parameters for TestNetwork { NetworkUpgrade::Blossom => Some(BlockHeight(584_000)), NetworkUpgrade::Heartwood => Some(BlockHeight(903_800)), NetworkUpgrade::Canopy => Some(BlockHeight(1_028_500)), + NetworkUpgrade::Nu5 => None, #[cfg(feature = "zfuture")] NetworkUpgrade::ZFuture => None, } @@ -352,6 +354,10 @@ pub enum NetworkUpgrade { /// /// [Canopy]: https://z.cash/upgrade/canopy/ Canopy, + /// The [Nu5] network upgrade. + /// + /// [Nu5]: https://z.cash/upgrade/nu5/ + Nu5, /// The ZFUTURE network upgrade. /// /// This upgrade is expected never to activate on mainnet; @@ -369,6 +375,7 @@ impl fmt::Display for NetworkUpgrade { NetworkUpgrade::Blossom => write!(f, "Blossom"), NetworkUpgrade::Heartwood => write!(f, "Heartwood"), NetworkUpgrade::Canopy => write!(f, "Canopy"), + NetworkUpgrade::Nu5 => write!(f, "Nu5"), #[cfg(feature = "zfuture")] NetworkUpgrade::ZFuture => write!(f, "ZFUTURE"), } @@ -383,6 +390,7 @@ impl NetworkUpgrade { NetworkUpgrade::Blossom => BranchId::Blossom, NetworkUpgrade::Heartwood => BranchId::Heartwood, NetworkUpgrade::Canopy => BranchId::Canopy, + NetworkUpgrade::Nu5 => BranchId::Nu5, #[cfg(feature = "zfuture")] NetworkUpgrade::ZFuture => BranchId::ZFuture, } @@ -399,6 +407,7 @@ const UPGRADES_IN_ORDER: &[NetworkUpgrade] = &[ NetworkUpgrade::Blossom, NetworkUpgrade::Heartwood, NetworkUpgrade::Canopy, + NetworkUpgrade::Nu5, ]; pub const ZIP212_GRACE_PERIOD: u32 = 32256; @@ -430,6 +439,8 @@ pub enum BranchId { Heartwood, /// The consensus rules deployed by [`NetworkUpgrade::Canopy`]. Canopy, + /// The consensus rules deployed by [`NetworkUpgrade::Nu5`]. + Nu5, /// Candidates for future consensus rules; this branch will never /// activate on mainnet. #[cfg(feature = "zfuture")] @@ -447,6 +458,7 @@ impl TryFrom for BranchId { 0x2bb4_0e60 => Ok(BranchId::Blossom), 0xf5b9_230b => Ok(BranchId::Heartwood), 0xe9ff_75a6 => Ok(BranchId::Canopy), + 0xf919_a198 => Ok(BranchId::Nu5), #[cfg(feature = "zfuture")] 0xffff_ffff => Ok(BranchId::ZFuture), _ => Err("Unknown consensus branch ID"), @@ -463,6 +475,7 @@ impl From for u32 { BranchId::Blossom => 0x2bb4_0e60, BranchId::Heartwood => 0xf5b9_230b, BranchId::Canopy => 0xe9ff_75a6, + BranchId::Nu5 => 0xf919_a198, #[cfg(feature = "zfuture")] BranchId::ZFuture => 0xffff_ffff, } @@ -484,6 +497,94 @@ impl BranchId { // Sprout rules apply before any network upgrade BranchId::Sprout } + + /// Returns the range of heights for the consensus epoch associated with this branch id. + /// + /// The resulting tuple implements the [`RangeBounds`] trait. + pub fn height_range(&self, params: &P) -> Option> { + self.height_bounds(params).map(|(lower, upper)| { + ( + Bound::Included(lower), + upper.map_or(Bound::Unbounded, Bound::Excluded), + ) + }) + } + + /// Returns the range of heights for the consensus epoch associated with this branch id. + /// + /// The return type of this value is slightly more precise than [`Self::height_range`]. + pub fn height_bounds( + &self, + params: &P, + ) -> Option<(BlockHeight, Option)> { + match self { + BranchId::Sprout => params + .activation_height(NetworkUpgrade::Overwinter) + .map(|upper| (BlockHeight(0), Some(upper))), + BranchId::Overwinter => params + .activation_height(NetworkUpgrade::Overwinter) + .map(|lower| (lower, params.activation_height(NetworkUpgrade::Sapling))), + BranchId::Sapling => params + .activation_height(NetworkUpgrade::Sapling) + .map(|lower| (lower, params.activation_height(NetworkUpgrade::Blossom))), + BranchId::Blossom => params + .activation_height(NetworkUpgrade::Blossom) + .map(|lower| (lower, params.activation_height(NetworkUpgrade::Heartwood))), + BranchId::Heartwood => params + .activation_height(NetworkUpgrade::Heartwood) + .map(|lower| (lower, params.activation_height(NetworkUpgrade::Canopy))), + BranchId::Canopy => params + .activation_height(NetworkUpgrade::Canopy) + .map(|lower| (lower, params.activation_height(NetworkUpgrade::Nu5))), + BranchId::Nu5 => params.activation_height(NetworkUpgrade::Nu5).map(|lower| { + #[cfg(feature = "zfuture")] + let upper = params.activation_height(NetworkUpgrade::ZFuture); + #[cfg(not(feature = "zfuture"))] + let upper = None; + (lower, upper) + }), + #[cfg(feature = "zfuture")] + BranchId::ZFuture => params + .activation_height(NetworkUpgrade::ZFuture) + .map(|lower| (lower, None)), + } + } +} + +#[cfg(any(test, feature = "test-dependencies"))] +pub mod testing { + use proptest::sample::select; + use proptest::strategy::{Just, Strategy}; + + use super::{BlockHeight, BranchId, Parameters}; + + pub fn arb_branch_id() -> impl Strategy { + select(vec![ + BranchId::Sprout, + BranchId::Overwinter, + BranchId::Sapling, + BranchId::Blossom, + BranchId::Heartwood, + BranchId::Canopy, + BranchId::Nu5, + #[cfg(feature = "zfuture")] + BranchId::ZFuture, + ]) + } + + pub fn arb_height( + branch_id: BranchId, + params: &P, + ) -> impl Strategy> { + branch_id + .height_bounds(params) + .map_or(Strategy::boxed(Just(None)), |(lower, upper)| { + Strategy::boxed( + (lower.0..upper.map_or(std::u32::MAX, |u| u.0)) + .prop_map(|h| Some(BlockHeight(h))), + ) + }) + } } #[cfg(test)] @@ -503,7 +604,9 @@ mod tests { MAIN_NETWORK.activation_height(nu_a), MAIN_NETWORK.activation_height(nu_b), ) { - (a, b) if a < b => (), + (Some(a), Some(b)) if a < b => (), + (Some(_), None) => (), + (None, None) => (), _ => panic!( "{} should not be before {} in UPGRADES_IN_ORDER", nu_a, nu_b