add(consensus): Add `slow_start_{interval/shift}` fields to `testnet::Parameters` (#8477)

* - Adds `slow_start_interval` field to `testnet::Parameters`
- Moves SLOW_START_INTERVAL/SLOW_START_SHIFT constants to zebra-chain

* Apply suggestions from code review

Co-authored-by: Marek <mail@marek.onl>

---------

Co-authored-by: Marek <mail@marek.onl>
This commit is contained in:
Arya 2024-05-08 13:14:54 -04:00 committed by GitHub
parent 15e1096826
commit d2d1a18d81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 43 deletions

View File

@ -12,6 +12,7 @@
//! Typically, consensus parameters are accessed via a function that takes a
//! `Network` and `block::Height`.
pub mod constants;
mod genesis;
mod network;
mod network_upgrade;

View File

@ -0,0 +1,17 @@
//! Definitions of Zebra chain constants, including:
//! - slow start interval,
//! - slow start shift
use crate::block::Height;
/// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining]
///
/// [slow-mining]: https://z.cash/support/faq/#what-is-slow-start-mining
pub const SLOW_START_INTERVAL: Height = Height(20_000);
/// `SlowStartShift()` as described in [protocol specification §7.8][7.8]
///
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
///
/// This calculation is exact, because `SLOW_START_INTERVAL` is divisible by 2.
pub const SLOW_START_SHIFT: Height = Height(SLOW_START_INTERVAL.0 / 2);

View File

@ -189,14 +189,6 @@ impl Network {
}
}
/// Returns true if proof-of-work validation should be disabled for this network
pub fn disable_pow(&self) -> bool {
if let Self::Testnet(params) = self {
params.disable_pow()
} else {
false
}
}
/// Returns the [`NetworkKind`] for this network.
pub fn kind(&self) -> NetworkKind {
match self {

View File

@ -6,8 +6,9 @@ use zcash_primitives::constants as zp_constants;
use crate::{
block::{self, Height},
parameters::{
network_upgrade::TESTNET_ACTIVATION_HEIGHTS, Network, NetworkUpgrade,
NETWORK_UPGRADES_IN_ORDER,
constants::{SLOW_START_INTERVAL, SLOW_START_SHIFT},
network_upgrade::TESTNET_ACTIVATION_HEIGHTS,
Network, NetworkUpgrade, NETWORK_UPGRADES_IN_ORDER,
},
};
@ -76,6 +77,8 @@ pub struct ParametersBuilder {
hrp_sapling_extended_full_viewing_key: String,
/// Sapling payment address human-readable prefix for this network
hrp_sapling_payment_address: String,
/// Slow start interval for this network
slow_start_interval: Height,
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
disable_pow: bool,
}
@ -98,6 +101,7 @@ impl Default for ParametersBuilder {
genesis_hash: TESTNET_GENESIS_HASH
.parse()
.expect("hard-coded hash parses"),
slow_start_interval: SLOW_START_INTERVAL,
disable_pow: false,
}
}
@ -237,6 +241,12 @@ impl ParametersBuilder {
self
}
/// Sets the slow start interval to be used in the [`Parameters`] being built.
pub fn with_slow_start_interval(mut self, slow_start_interval: Height) -> Self {
self.slow_start_interval = slow_start_interval;
self
}
/// Sets the `disable_pow` flag to be used in the [`Parameters`] being built.
pub fn with_disable_pow(mut self, disable_pow: bool) -> Self {
self.disable_pow = disable_pow;
@ -252,6 +262,7 @@ impl ParametersBuilder {
hrp_sapling_extended_spending_key,
hrp_sapling_extended_full_viewing_key,
hrp_sapling_payment_address,
slow_start_interval,
disable_pow,
} = self;
Parameters {
@ -261,6 +272,8 @@ impl ParametersBuilder {
hrp_sapling_extended_spending_key,
hrp_sapling_extended_full_viewing_key,
hrp_sapling_payment_address,
slow_start_interval,
slow_start_shift: Height(slow_start_interval.0 / 2),
disable_pow,
}
}
@ -290,6 +303,10 @@ pub struct Parameters {
hrp_sapling_extended_full_viewing_key: String,
/// Sapling payment address human-readable prefix for this network
hrp_sapling_payment_address: String,
/// Slow start interval for this network
slow_start_interval: Height,
/// Slow start shift for this network, always half the slow start interval
slow_start_shift: Height,
/// A flag for disabling proof-of-work checks when Zebra is validating blocks
disable_pow: bool,
}
@ -322,6 +339,7 @@ impl Parameters {
..Self::build()
.with_genesis_hash(REGTEST_GENESIS_HASH)
.with_disable_pow(true)
.with_slow_start_interval(Height::MIN)
.with_sapling_hrps(
zp_constants::regtest::HRP_SAPLING_EXTENDED_SPENDING_KEY,
zp_constants::regtest::HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY,
@ -353,6 +371,8 @@ impl Parameters {
hrp_sapling_extended_spending_key,
hrp_sapling_extended_full_viewing_key,
hrp_sapling_payment_address,
slow_start_interval,
slow_start_shift,
disable_pow,
} = Self::new_regtest(None);
@ -361,6 +381,8 @@ impl Parameters {
&& self.hrp_sapling_extended_spending_key == hrp_sapling_extended_spending_key
&& self.hrp_sapling_extended_full_viewing_key == hrp_sapling_extended_full_viewing_key
&& self.hrp_sapling_payment_address == hrp_sapling_payment_address
&& self.slow_start_interval == slow_start_interval
&& self.slow_start_shift == slow_start_shift
&& self.disable_pow == disable_pow
}
@ -394,8 +416,47 @@ impl Parameters {
&self.hrp_sapling_payment_address
}
/// Returns slow start interval for this network
pub fn slow_start_interval(&self) -> Height {
self.slow_start_interval
}
/// Returns slow start shift for this network
pub fn slow_start_shift(&self) -> Height {
self.slow_start_shift
}
/// Returns true if proof-of-work validation should be disabled for this network
pub fn disable_pow(&self) -> bool {
self.disable_pow
}
}
impl Network {
/// Returns true if proof-of-work validation should be disabled for this network
pub fn disable_pow(&self) -> bool {
if let Self::Testnet(params) = self {
params.disable_pow()
} else {
false
}
}
/// Returns slow start interval for this network
pub fn slow_start_interval(&self) -> Height {
if let Self::Testnet(params) = self {
params.slow_start_interval()
} else {
SLOW_START_INTERVAL
}
}
/// Returns slow start shift for this network
pub fn slow_start_shift(&self) -> Height {
if let Self::Testnet(params) = self {
params.slow_start_shift()
} else {
SLOW_START_SHIFT
}
}
}

View File

@ -15,7 +15,7 @@ use zebra_chain::{
},
};
use crate::{error::*, parameters::SLOW_START_INTERVAL};
use crate::error::*;
use super::subsidy;
@ -162,7 +162,7 @@ pub fn subsidy_is_valid(block: &Block, network: &Network) -> Result<(), BlockErr
let slow_start_interval = if network.disable_pow() {
Height(0)
} else {
SLOW_START_INTERVAL
network.slow_start_interval()
};
if height < slow_start_interval {

View File

@ -25,20 +25,13 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {
.activation_height(network)
.expect("blossom activation height should be available");
// TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd,
// see <https://github.com/zcash/zcash/blob/master/src/chainparams.cpp#L640>
let slow_start_shift = if network.disable_pow() {
Height(0)
} else {
SLOW_START_SHIFT
};
if height < slow_start_shift {
unreachable!(
"unsupported block height {height:?}: checkpoints should handle blocks below {slow_start_shift:?}",
if height < network.slow_start_shift() {
panic!(
"unsupported block height {height:?}: checkpoints should handle blocks below {:?}",
network.slow_start_shift()
)
} else if height < blossom_height {
let pre_blossom_height = height - slow_start_shift;
let pre_blossom_height = height - network.slow_start_shift();
let halving_shift = pre_blossom_height / PRE_BLOSSOM_HALVING_INTERVAL;
let halving_div = 1u64
@ -51,7 +44,7 @@ pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {
Some(halving_div)
} else {
let pre_blossom_height = blossom_height - slow_start_shift;
let pre_blossom_height = blossom_height - network.slow_start_shift();
let scaled_pre_blossom_height =
pre_blossom_height * HeightDiff::from(BLOSSOM_POW_TARGET_SPACING_RATIO);
@ -87,9 +80,10 @@ pub fn block_subsidy(height: Height, network: &Network) -> Result<Amount<NonNega
// TODO: Add this as a field on `testnet::Parameters` instead of checking `disable_pow()`, this is 0 for Regtest in zcashd,
// see <https://github.com/zcash/zcash/blob/master/src/chainparams.cpp#L640>
if height < SLOW_START_INTERVAL && !network.disable_pow() {
if height < network.slow_start_interval() && !network.disable_pow() {
unreachable!(
"unsupported block height {height:?}: callers should handle blocks below {SLOW_START_INTERVAL:?}",
"unsupported block height {height:?}: callers should handle blocks below {:?}",
network.slow_start_interval()
)
} else if height < blossom_height {
// this calculation is exact, because the halving divisor is 1 here
@ -145,7 +139,7 @@ mod test {
assert_eq!(
1,
halving_divisor((SLOW_START_INTERVAL + 1).unwrap(), network).unwrap()
halving_divisor((network.slow_start_interval() + 1).unwrap(), network).unwrap()
);
assert_eq!(
1,
@ -274,7 +268,7 @@ mod test {
// https://z.cash/support/faq/#what-is-slow-start-mining
assert_eq!(
Amount::try_from(1_250_000_000),
block_subsidy((SLOW_START_INTERVAL + 1).unwrap(), network)
block_subsidy((network.slow_start_interval() + 1).unwrap(), network)
);
assert_eq!(
Amount::try_from(1_250_000_000),

View File

@ -20,7 +20,7 @@ use zebra_chain::{
use zebra_script::CachedFfiTransaction;
use zebra_test::transcript::{ExpectedTranscriptError, Transcript};
use crate::{parameters::SLOW_START_SHIFT, transaction};
use crate::transaction;
use super::*;
@ -470,7 +470,7 @@ fn miner_fees_validation_for_network(network: Network) -> Result<(), Report> {
let block_iter = network.block_iter();
for (&height, block) in block_iter {
if Height(height) > SLOW_START_SHIFT {
if Height(height) > network.slow_start_shift() {
let block = Block::zcash_deserialize(&block[..]).expect("block should deserialize");
// fake the miner fee to a big amount

View File

@ -10,18 +10,6 @@ use zebra_chain::{
parameters::{Network, NetworkKind, NetworkUpgrade},
};
/// An initial period from Genesis to this Height where the block subsidy is gradually incremented. [What is slow-start mining][slow-mining]
///
/// [slow-mining]: https://z.cash/support/faq/#what-is-slow-start-mining
pub const SLOW_START_INTERVAL: Height = Height(20_000);
/// `SlowStartShift()` as described in [protocol specification §7.8][7.8]
///
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
///
/// This calculation is exact, because `SLOW_START_INTERVAL` is divisible by 2.
pub const SLOW_START_SHIFT: Height = Height(SLOW_START_INTERVAL.0 / 2);
/// The largest block subsidy, used before the first halving.
///
/// We use `25 / 2` instead of `12.5`, so that we can calculate the correct value without using floating-point.