Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion for "feat(regtest): Add regtest halving interval and port test" #8894

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 81 additions & 22 deletions zebra-consensus/src/block/subsidy/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,71 @@
///
/// Returns `None` if the divisor would overflow a `u64`.
pub fn halving_divisor(height: Height, network: &Network) -> Option<u64> {
// Some far-future shifts can be more than 63 bits
1u64.checked_shl(num_halvings(height, network))
}

/// The halving index for a block height and network.
///
/// `Halving(height)`, as described in [protocol specification §7.8][7.8]
///
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
pub fn num_halvings(height: Height, network: &Network) -> u32 {
let slow_start_shift = network.slow_start_shift();
let blossom_height = Blossom
.activation_height(network)
.expect("blossom activation height should be available");

if height < blossom_height {
let pre_blossom_height = height - network.slow_start_shift();
let halving_shift = pre_blossom_height / network.pre_blossom_halving_interval();

let halving_div = 1u64
.checked_shl(
halving_shift
.try_into()
.expect("already checked for negatives"),
)
.expect("pre-blossom heights produce small shifts");

Some(halving_div)
let halving_index = if height < slow_start_shift {
0
} else if height < blossom_height {
let pre_blossom_height = height - slow_start_shift;
pre_blossom_height / network.pre_blossom_halving_interval()
} else {
let pre_blossom_height = blossom_height - network.slow_start_shift();
let pre_blossom_height = blossom_height - slow_start_shift;
let scaled_pre_blossom_height =
pre_blossom_height * HeightDiff::from(BLOSSOM_POW_TARGET_SPACING_RATIO);

let post_blossom_height = height - blossom_height;

let halving_shift = (scaled_pre_blossom_height + post_blossom_height)
/ network.post_blossom_halving_interval();
(scaled_pre_blossom_height + post_blossom_height) / network.post_blossom_halving_interval()
};

// Some far-future shifts can be more than 63 bits
1u64.checked_shl(
halving_shift
.try_into()
.expect("already checked for negatives"),
)
halving_index
.try_into()
.expect("already checked for negatives")
}

/// The first block height of the halving at the provided halving index for a network.
///
/// See `Halving(height)`, as described in [protocol specification §7.8][7.8]
///
/// [7.8]: https://zips.z.cash/protocol/protocol.pdf#subsidies
pub fn height_for_halving_index(halving_index: u32, network: &Network) -> Option<Height> {

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Build and Deploy Zebra Internal Docs

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Check Cargo.lock is up to date

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Install zebrad from lockfile without cache on ubuntu-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test stable on ubuntu-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test beta on ubuntu-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test stable on macos-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test stable on macos-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test stable on windows-latest

function `height_for_halving_index` is never used

Check warning on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Test beta on windows-latest

function `height_for_halving_index` is never used

Check failure on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Build zebrad crate

function `height_for_halving_index` is never used

Check failure on line 66 in zebra-consensus/src/block/subsidy/general.rs

View workflow job for this annotation

GitHub Actions / Clippy (stable) Results

function `height_for_halving_index` is never used

error: function `height_for_halving_index` is never used --> zebra-consensus/src/block/subsidy/general.rs:66:8 | 66 | pub fn height_for_halving_index(halving_index: u32, network: &Network) -> Option<Height> { | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D dead-code` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(dead_code)]`
if halving_index == 0 {
return Some(Height(0));
}

let slow_start_shift = i64::from(network.slow_start_shift().0);
let blossom_height = i64::from(
Blossom
.activation_height(network)
.expect("blossom activation height should be available")
.0,
);
let pre_blossom_halving_interval = network.pre_blossom_halving_interval();
let halving_index = i64::from(halving_index);

let unscaled_height = halving_index * pre_blossom_halving_interval;
let pre_blossom_height = unscaled_height.min(blossom_height) + slow_start_shift;
let post_blossom_height = 0.max(unscaled_height - blossom_height)
* i64::from(BLOSSOM_POW_TARGET_SPACING_RATIO)
+ slow_start_shift;

let height = pre_blossom_height + post_blossom_height;

let height = u32::try_from(height).ok()?;
height.try_into().ok()
}

/// `BlockSubsidy(height)` as described in [protocol specification §7.8][7.8]
Expand Down Expand Up @@ -503,4 +534,32 @@

Ok(())
}

#[test]
fn check_height_for_num_halvings() {
for network in Network::iter() {
for halving_index in 1..1000 {
let Some(height_for_halving) = height_for_halving_index(halving_index, &network)
else {
panic!("could not find height for halving {halving_index}");
};

let prev_height = height_for_halving
.previous()
.expect("there should be a previous height");

assert_eq!(
halving_index,
num_halvings(height_for_halving, &network),
"num_halvings should match the halving index"
);

assert_eq!(
halving_index - 1,
num_halvings(prev_height, &network),
"num_halvings for the prev height should be 1 less than the halving index"
);
}
}
}
}
Loading