diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index 52d5d18f74a..78f7a69a302 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -751,6 +751,12 @@ impl Network { } /// Returns pre-NU6 funding streams for this network + /// + /// Commonly referred to as the "Dev Fund". + /// + /// Defined in [Zcash Protocol Specification §7.10.1][7.10.1] + /// + /// [7.10.1]: https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams pub fn pre_nu6_funding_streams(&self) -> &FundingStreams { if let Self::Testnet(params) = self { params.pre_nu6_funding_streams() @@ -760,6 +766,10 @@ impl Network { } /// Returns post-NU6 funding streams for this network + /// + /// Defined in [Zcash Protocol Specification §7.10.1][7.10.1] + /// + /// [7.10.1]: https://zips.z.cash/protocol/protocol.pdf#zip214fundingstreams pub fn post_nu6_funding_streams(&self) -> &FundingStreams { if let Self::Testnet(params) = self { params.post_nu6_funding_streams() diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 957b96de944..57165d0c760 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -89,8 +89,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 - // (block::Height(2_726_400), Nu6), + (block::Height(2_726_400), Nu6), ]; /// Fake mainnet network upgrade activation heights, used in tests. diff --git a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs index 626b983fac6..91faa923c93 100644 --- a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs +++ b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs @@ -1,199 +1,86 @@ //! Tests for funding streams. use color_eyre::Report; -use zebra_chain::parameters::{ - subsidy::FundingStreamReceiver, - testnet::{ - self, ConfiguredActivationHeights, ConfiguredFundingStreamRecipient, - ConfiguredFundingStreams, - }, - NetworkKind, -}; +use zebra_chain::parameters::{subsidy::FundingStreamReceiver, NetworkKind}; use crate::block::subsidy::general::block_subsidy; use super::*; -/// Check mainnet funding stream values are correct for the entire period. +/// Checks that the Mainnet funding stream values are correct. #[test] fn test_funding_stream_values() -> Result<(), Report> { let _init_guard = zebra_test::init(); let network = &Network::Mainnet; - // funding streams not active - let canopy_height_minus1 = (Canopy.activation_height(network).unwrap() - 1).unwrap(); + let canopy_activation_height = Canopy.activation_height(network).unwrap(); + let nu6_activation_height = Nu6.activation_height(network).unwrap(); - assert!(funding_stream_values( - canopy_height_minus1, - network, - block_subsidy(canopy_height_minus1, network)? - )? - .is_empty()); + let dev_fund_height_range = network.pre_nu6_funding_streams().height_range(); + let nu6_fund_height_range = network.post_nu6_funding_streams().height_range(); - // funding stream is active - let canopy_height = Canopy.activation_height(network).unwrap(); - let canopy_height_plus1 = (Canopy.activation_height(network).unwrap() + 1).unwrap(); - let canopy_height_plus2 = (Canopy.activation_height(network).unwrap() + 2).unwrap(); + let nu6_fund_end = Height(3_146_400); - let mut hash_map = HashMap::new(); - hash_map.insert(FundingStreamReceiver::Ecc, Amount::try_from(21_875_000)?); - hash_map.insert( - FundingStreamReceiver::ZcashFoundation, - Amount::try_from(15_625_000)?, - ); - hash_map.insert( - FundingStreamReceiver::MajorGrants, - Amount::try_from(25_000_000)?, - ); + assert_eq!(canopy_activation_height, Height(1_046_400)); + assert_eq!(nu6_activation_height, Height(2_726_400)); - assert_eq!( - funding_stream_values( - canopy_height, - network, - block_subsidy(canopy_height, network)? - ) - .unwrap(), - hash_map - ); - - assert_eq!( - funding_stream_values( - canopy_height_plus1, - network, - block_subsidy(canopy_height_plus1, network)? - ) - .unwrap(), - hash_map - ); + assert_eq!(dev_fund_height_range.start, canopy_activation_height); + assert_eq!(dev_fund_height_range.end, nu6_activation_height); - assert_eq!( - funding_stream_values( - canopy_height_plus2, - network, - block_subsidy(canopy_height_plus2, network)? - ) - .unwrap(), - hash_map - ); + assert_eq!(nu6_fund_height_range.start, nu6_activation_height); + assert_eq!(nu6_fund_height_range.end, nu6_fund_end); - // funding stream period is ending - let range = network.pre_nu6_funding_streams().height_range(); - let end = range.end; - let last = (end - 1).unwrap(); + assert_eq!(dev_fund_height_range.end, nu6_fund_height_range.start); - assert_eq!( - funding_stream_values(last, network, block_subsidy(last, network)?).unwrap(), - hash_map - ); + let mut expected_dev_fund = HashMap::new(); - assert!(funding_stream_values(end, network, block_subsidy(end, network)?)?.is_empty()); - - // TODO: Replace this with Mainnet once there's an NU6 activation height defined for Mainnet - let network = testnet::Parameters::build() - .with_activation_heights(ConfiguredActivationHeights { - blossom: Some(Blossom.activation_height(network).unwrap().0), - nu6: Some(POST_NU6_FUNDING_STREAMS_MAINNET.height_range().start.0), - ..Default::default() - }) - .with_post_nu6_funding_streams(ConfiguredFundingStreams { - // Start checking funding streams from block height 1 - height_range: Some(POST_NU6_FUNDING_STREAMS_MAINNET.height_range().clone()), - // Use default post-NU6 recipients - recipients: Some( - POST_NU6_FUNDING_STREAMS_TESTNET - .recipients() - .iter() - .map(|(&receiver, recipient)| ConfiguredFundingStreamRecipient { - receiver, - numerator: recipient.numerator(), - addresses: Some( - recipient - .addresses() - .iter() - .map(|addr| addr.to_string()) - .collect(), - ), - }) - .collect(), - ), - }) - .to_network(); - - let mut hash_map = HashMap::new(); - hash_map.insert( - FundingStreamReceiver::Deferred, - Amount::try_from(18_750_000)?, + expected_dev_fund.insert(FundingStreamReceiver::Ecc, Amount::try_from(21_875_000)?); + expected_dev_fund.insert( + FundingStreamReceiver::ZcashFoundation, + Amount::try_from(15_625_000)?, ); - hash_map.insert( + expected_dev_fund.insert( FundingStreamReceiver::MajorGrants, - Amount::try_from(12_500_000)?, + Amount::try_from(25_000_000)?, ); + let expected_dev_fund = expected_dev_fund; - let nu6_height = Nu6.activation_height(&network).unwrap(); - - for height in [ - nu6_height, - Height(nu6_height.0 + 1), - Height(nu6_height.0 + 1), - ] { - assert_eq!( - funding_stream_values(height, &network, block_subsidy(height, &network)?).unwrap(), - hash_map - ); - } - - // TODO: Replace this with Mainnet once there's an NU6 activation height defined for Mainnet - let network = testnet::Parameters::build() - .with_activation_heights(ConfiguredActivationHeights { - blossom: Some(Blossom.activation_height(&network).unwrap().0), - nu6: Some(POST_NU6_FUNDING_STREAMS_MAINNET.height_range().start.0), - ..Default::default() - }) - .with_post_nu6_funding_streams(ConfiguredFundingStreams { - // Start checking funding streams from block height 1 - height_range: Some(POST_NU6_FUNDING_STREAMS_MAINNET.height_range().clone()), - // Use default post-NU6 recipients - recipients: Some( - POST_NU6_FUNDING_STREAMS_TESTNET - .recipients() - .iter() - .map(|(&receiver, recipient)| ConfiguredFundingStreamRecipient { - receiver, - numerator: recipient.numerator(), - addresses: Some( - recipient - .addresses() - .iter() - .map(|addr| addr.to_string()) - .collect(), - ), - }) - .collect(), - ), - }) - .to_network(); - - let mut hash_map = HashMap::new(); - hash_map.insert( + let mut expected_nu6_fund = HashMap::new(); + expected_nu6_fund.insert( FundingStreamReceiver::Deferred, Amount::try_from(18_750_000)?, ); - hash_map.insert( + expected_nu6_fund.insert( FundingStreamReceiver::MajorGrants, Amount::try_from(12_500_000)?, ); - - let nu6_height = Nu6.activation_height(&network).unwrap(); + let expected_nu6_fund = expected_nu6_fund; for height in [ - nu6_height, - Height(nu6_height.0 + 1), - Height(nu6_height.0 + 1), + dev_fund_height_range.start.previous().unwrap(), + dev_fund_height_range.start, + dev_fund_height_range.start.next().unwrap(), + dev_fund_height_range.end.previous().unwrap(), + dev_fund_height_range.end, + dev_fund_height_range.end.next().unwrap(), + nu6_fund_height_range.start.previous().unwrap(), + nu6_fund_height_range.start, + nu6_fund_height_range.start.next().unwrap(), + nu6_fund_height_range.end.previous().unwrap(), + nu6_fund_height_range.end, + nu6_fund_height_range.end.next().unwrap(), ] { - assert_eq!( - funding_stream_values(height, &network, block_subsidy(height, &network)?).unwrap(), - hash_map - ); + let fsv = funding_stream_values(height, network, block_subsidy(height, network)?).unwrap(); + + if height < canopy_activation_height { + assert!(fsv.is_empty()); + } else if height < nu6_activation_height { + assert_eq!(fsv, expected_dev_fund); + } else if height < nu6_fund_end { + assert_eq!(fsv, expected_nu6_fund); + } else { + assert!(fsv.is_empty()); + } } Ok(()) diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index 07bca61d63a..a116fd63018 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -337,7 +337,10 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: u32 = 30 * 60; /// /// The current protocol version typically changes before Mainnet and Testnet /// network upgrades. -pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_110); +/// +/// This version of Zebra draws the current network protocol version from +/// [ZIP-253](https://zips.z.cash/zip-0253). +pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_120); /// The default RTT estimate for peer responses. /// @@ -393,6 +396,7 @@ lazy_static! { /// /// The minimum network protocol version typically changes after Mainnet and /// Testnet network upgrades. + // TODO: Change `Nu5` to `Nu6` after NU6 activation. // TODO: Move the value here to a field on `testnet::Parameters` (#8367) pub static ref INITIAL_MIN_NETWORK_PROTOCOL_VERSION: HashMap = { let mut hash_map = HashMap::new(); diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 1048f33e308..c6241ba4d78 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -72,12 +72,23 @@ impl Version { /// Returns the minimum specified network protocol version for `network` and /// `network_upgrade`. + /// + /// ## ZIP-253 + /// + /// > Nodes compatible with a network upgrade activation MUST advertise a network protocol + /// > version that is greater than or equal to the MIN_NETWORK_PROTOCOL_VERSION for that + /// > activation. + /// + /// + /// + /// ### Notes + /// + /// - The citation above is a generalization of a statement in ZIP-253 since that ZIP is + /// concerned only with NU6 on Mainnet and Testnet. pub(crate) fn min_specified_for_upgrade( network: &Network, network_upgrade: NetworkUpgrade, ) -> Version { - // TODO: Should we reject earlier protocol versions during our initial - // sync? zcashd accepts 170_002 or later during its initial sync. Version(match (network, network_upgrade) { (_, Genesis) | (_, BeforeOverwinter) => 170_002, (Testnet(params), Overwinter) if params.is_default_testnet() => 170_003, diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index 64663b86102..9986da0ec95 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -64,6 +64,11 @@ expression: info "name": "NU5", "activationheight": 1687104, "status": "pending" + }, + "c8e71055": { + "name": "NU6", + "activationheight": 2726400, + "status": "pending" } }, "consensus": {