From 1e337472a9b9f43033de75713c19bc9888a8d2a0 Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Mon, 29 Apr 2024 10:02:33 -0400 Subject: [PATCH] chore: docs for BurnSamplePoint --- stackslib/src/chainstate/burn/distribution.rs | 88 ++++++++++++++++--- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/stackslib/src/chainstate/burn/distribution.rs b/stackslib/src/chainstate/burn/distribution.rs index 2a1689710..9f0b5ec1b 100644 --- a/stackslib/src/chainstate/burn/distribution.rs +++ b/stackslib/src/chainstate/burn/distribution.rs @@ -31,15 +31,22 @@ use crate::chainstate::burn::operations::{ BlockstackOperationType, LeaderBlockCommitOp, LeaderKeyRegisterOp, }; use crate::chainstate::stacks::StacksPublicKey; -use crate::core::MINING_COMMITMENT_WINDOW; use crate::monitoring; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct BurnSamplePoint { + /// min(median_burn, most_recent_burn) pub burns: u128, + /// median burn over the UTXO chain pub median_burn: u128, + /// how many times did this miner mine in the window (i.e. how long is the UTXO chain for this + /// candidate in this window). + pub frequency: u8, + /// distribution range start in a [0, 2**256) interval pub range_start: Uint256, + /// distribution range end in a [0, 2**256) interval pub range_end: Uint256, + /// block-commit from the miner candidate pub candidate: LeaderBlockCommitOp, } @@ -94,11 +101,25 @@ impl LinkedCommitIdentifier { } impl BurnSamplePoint { + pub fn zero(candidate: LeaderBlockCommitOp) -> Self { + Self { + burns: 0, + median_burn: 0, + frequency: 0, + range_start: Uint256::zero(), + range_end: Uint256::zero(), + candidate, + } + } + fn sanity_check_window( + miner_commitment_window: u8, block_commits: &Vec>, missed_commits: &Vec>, ) { - assert!(block_commits.len() <= (MINING_COMMITMENT_WINDOW as usize)); + assert!( + block_commits.len() <= usize::try_from(miner_commitment_window).expect("infallible") + ); assert_eq!(missed_commits.len() + 1, block_commits.len()); let mut block_height_at_index = None; for (index, commits) in block_commits.iter().enumerate() { @@ -151,6 +172,7 @@ impl BurnSamplePoint { /// `OP_RETURN` payload. The length of this vector must be equal to the length of the /// `block_commits` vector. `burn_blocks[i]` is `true` if the `ith` block-commit must be PoB. pub fn make_min_median_distribution( + mining_commitment_window: u8, mut block_commits: Vec>, mut missed_commits: Vec>, burn_blocks: Vec, @@ -158,7 +180,11 @@ impl BurnSamplePoint { // sanity check let window_size = block_commits.len() as u8; assert!(window_size > 0); - BurnSamplePoint::sanity_check_window(&block_commits, &missed_commits); + BurnSamplePoint::sanity_check_window( + mining_commitment_window, + &block_commits, + &missed_commits, + ); assert_eq!(burn_blocks.len(), block_commits.len()); // first, let's link all of the current block commits to the priors @@ -283,9 +309,20 @@ impl BurnSamplePoint { "median_burn" => %median_burn, "all_burns" => %format!("{:?}", all_burns)); + let frequency = linked_commits.iter().fold(0u8, |count, commit_opt| { + if commit_opt.is_some() { + count + .checked_add(1) + .expect("infallable -- commit window exceeds u8::MAX") + } else { + count + } + }); + BurnSamplePoint { burns, median_burn, + frequency, range_start: Uint256::zero(), // To be filled in range_end: Uint256::zero(), // To be filled in candidate, @@ -324,14 +361,6 @@ impl BurnSamplePoint { } } - #[cfg(test)] - pub fn make_distribution( - all_block_candidates: Vec, - _consumed_leader_keys: Vec, - ) -> Vec { - Self::make_min_median_distribution(vec![all_block_candidates], vec![], vec![true]) - } - /// Calculate the ranges between 0 and 2**256 - 1 over which each point in the burn sample /// applies, so we can later select which block to use. fn make_sortition_ranges(burn_sample: &mut Vec) -> () { @@ -423,6 +452,21 @@ mod tests { use crate::chainstate::stacks::StacksPublicKey; use crate::core::MINING_COMMITMENT_WINDOW; + impl BurnSamplePoint { + pub fn make_distribution( + mining_commitment_window: u8, + all_block_candidates: Vec, + _consumed_leader_keys: Vec, + ) -> Vec { + Self::make_min_median_distribution( + mining_commitment_window, + vec![all_block_candidates], + vec![], + vec![true], + ) + } + } + struct BurnDistFixture { consumed_leader_keys: Vec, block_commits: Vec, @@ -531,6 +575,7 @@ mod tests { ]; let mut result = BurnSamplePoint::make_min_median_distribution( + MINING_COMMITMENT_WINDOW, commits.clone(), vec![vec![]; (MINING_COMMITMENT_WINDOW - 1) as usize], vec![false, false, false, true, true, true], @@ -564,6 +609,7 @@ mod tests { // miner 2 => min = 1, median = 3, last_burn = 3 let mut result = BurnSamplePoint::make_min_median_distribution( + MINING_COMMITMENT_WINDOW, commits.clone(), vec![vec![]; (MINING_COMMITMENT_WINDOW - 1) as usize], vec![false, false, false, true, true, true], @@ -624,6 +670,7 @@ mod tests { ]; let mut result = BurnSamplePoint::make_min_median_distribution( + MINING_COMMITMENT_WINDOW, commits.clone(), vec![vec![]; (MINING_COMMITMENT_WINDOW - 1) as usize], vec![false, false, false, false, false, false], @@ -677,6 +724,7 @@ mod tests { ]; let mut result = BurnSamplePoint::make_min_median_distribution( + MINING_COMMITMENT_WINDOW, commits.clone(), vec![vec![]; (MINING_COMMITMENT_WINDOW - 1) as usize], vec![false, false, false, false, false, false], @@ -733,6 +781,7 @@ mod tests { ]; let mut result = BurnSamplePoint::make_min_median_distribution( + MINING_COMMITMENT_WINDOW, commits.clone(), missed_commits.clone(), vec![false, false, false, false, false, false], @@ -998,6 +1047,7 @@ mod tests { median_burn: block_commit_1.burn_fee.into(), range_start: Uint256::zero(), range_end: Uint256::max(), + frequency: 10, candidate: block_commit_1.clone(), }], }, @@ -1016,12 +1066,14 @@ mod tests { 0xffffffffffffffff, 0x7fffffffffffffff, ]), + frequency: 10, candidate: block_commit_1.clone(), }, BurnSamplePoint { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1041,6 +1093,7 @@ mod tests { burns: block_commit_1.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0xffffffffffffffff, @@ -1054,6 +1107,7 @@ mod tests { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1073,6 +1127,7 @@ mod tests { burns: block_commit_1.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0xffffffffffffffff, @@ -1086,6 +1141,7 @@ mod tests { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1105,6 +1161,7 @@ mod tests { burns: block_commit_1.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0xffffffffffffffff, @@ -1118,6 +1175,7 @@ mod tests { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1137,6 +1195,7 @@ mod tests { burns: block_commit_1.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0xffffffffffffffff, @@ -1150,6 +1209,7 @@ mod tests { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1169,6 +1229,7 @@ mod tests { burns: block_commit_1.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0xffffffffffffffff, @@ -1182,6 +1243,7 @@ mod tests { burns: block_commit_2.burn_fee.into(), median_burn: ((block_commit_1.burn_fee + block_commit_2.burn_fee) / 2) .into(), + frequency: 10, range_start: Uint256([ 0xffffffffffffffff, 0xffffffffffffffff, @@ -1208,6 +1270,7 @@ mod tests { BurnSamplePoint { burns: block_commit_1.burn_fee.into(), median_burn: block_commit_2.burn_fee.into(), + frequency: 10, range_start: Uint256::zero(), range_end: Uint256([ 0x3ed94d3cb0a84709, @@ -1220,6 +1283,7 @@ mod tests { BurnSamplePoint { burns: block_commit_2.burn_fee.into(), median_burn: block_commit_2.burn_fee.into(), + frequency: 10, range_start: Uint256([ 0x3ed94d3cb0a84709, 0x0963dded799a7c1a, @@ -1237,6 +1301,7 @@ mod tests { BurnSamplePoint { burns: (block_commit_3.burn_fee).into(), median_burn: block_commit_3.burn_fee.into(), + frequency: 10, range_start: Uint256([ 0x7db29a7961508e12, 0x12c7bbdaf334f834, @@ -1254,6 +1319,7 @@ mod tests { let f = &fixtures[i]; eprintln!("Fixture #{}", i); let dist = BurnSamplePoint::make_distribution( + MINING_COMMITMENT_WINDOW, f.block_commits.iter().cloned().collect(), f.consumed_leader_keys.iter().cloned().collect(), );