Skip to content

Commit

Permalink
fix(block): Adjust block parameters to match 42.000.000 limit
Browse files Browse the repository at this point in the history
Fix parameters to ensure that the asymptotic limit is exactly
42,000,000. Also ensure that halving time is closer to intended value of
three years.

Co-authored-by: Alan Szepieniec <[email protected]>
  • Loading branch information
Sword-Smith and aszepieniec committed Dec 19, 2024
1 parent 7f41efe commit a4a8f7f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 7 deletions.
61 changes: 58 additions & 3 deletions src/models/blockchain/block/block_height.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ use crate::prelude::twenty_first;
)]
pub struct BlockHeight(BFieldElement);

// Assuming a block time of 10 minutes, and a halving every three years,
// the number of blocks per halving cycle is 157680.
pub const BLOCKS_PER_GENERATION: u64 = 157680;
// Assuming a block time of 588 seconds, and a halving every three years,
// the number of blocks per halving cycle is 160815.
pub const BLOCKS_PER_GENERATION: u64 = 160815;

impl BlockHeight {
pub fn get_generation(&self) -> u64 {
Expand Down Expand Up @@ -126,14 +126,69 @@ impl Display for BlockHeight {

#[cfg(test)]
mod test {
use num_traits::CheckedAdd;
use num_traits::CheckedSub;
use tracing_test::traced_test;

use super::*;
use crate::models::blockchain::block::Block;
use crate::models::blockchain::block::TARGET_BLOCK_INTERVAL;
use crate::models::blockchain::type_scripts::neptune_coins::NeptuneCoins;
use crate::models::proof_abstractions::timestamp::Timestamp;

#[traced_test]
#[tokio::test]
async fn genesis_test() {
assert!(BlockHeight::genesis().is_genesis());
assert!(!BlockHeight::genesis().next().is_genesis());
}

#[test]
fn block_interval_times_generation_count_is_three_years() {
let calculated_halving_time = TARGET_BLOCK_INTERVAL * (BLOCKS_PER_GENERATION as usize);
let calculated_halving_time = calculated_halving_time.to_millis();
let three_years = Timestamp::years(3);
let three_years = three_years.to_millis();
assert!(
(calculated_halving_time as f64) * 1.01 > three_years as f64
&& (calculated_halving_time as f64) * 0.99 < three_years as f64,
"target halving time must be within 1 % of 3 years. Got:\n\
three years = {three_years}ms\n calculated_halving_time = {calculated_halving_time}ms"
);
}

#[test]
fn asymptotic_limit_is_42_million() {
let generation_0_subsidy = Block::block_subsidy(BlockHeight::genesis().next());

// Genesis block does not contain block subsidy so it must be subtracted
// from total number.
let mineable_amount = generation_0_subsidy
.scalar_mul(BLOCKS_PER_GENERATION as u32)
.scalar_mul(2)
.checked_sub(&generation_0_subsidy)
.unwrap();

let designated_premine = NeptuneCoins::new(831488);
let asymptotic_limit = mineable_amount.checked_add(&designated_premine).unwrap();

let expected_limit = NeptuneCoins::new(42_000_000);
assert_eq!(expected_limit, asymptotic_limit);

// Premine is less than promise of 1.98 %
let relative_premine = designated_premine.to_nau_f64() / expected_limit.to_nau_f64();
println!("relative_premine: {relative_premine}");
println!("absolute premine: {designated_premine} coins");
assert!(relative_premine < 0.0198, "Premine may not exceed promise");

// Designated premine is less than or equal to allocation
let actual_premine = Block::premine_distribution()
.iter()
.map(|(_receiving_address, amount)| *amount)
.sum::<NeptuneCoins>();
assert!(
actual_premine <= designated_premine,
"Distributed premine may not exceed designated value"
);
}
}
13 changes: 9 additions & 4 deletions src/models/blockchain/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use tracing::warn;
use twenty_first::math::b_field_element::BFieldElement;
use twenty_first::math::bfield_codec::BFieldCodec;
use twenty_first::math::digest::Digest;

use validity::appendix_witness::AppendixWitness;
use validity::block_primitive_witness::BlockPrimitiveWitness;
use validity::block_program::BlockProgram;
Expand Down Expand Up @@ -383,6 +382,8 @@ impl Block {
*self = block;
}

/// The number of coins that can be printed into existence with the mining
/// a block with this height.
pub fn block_subsidy(block_height: BlockHeight) -> NeptuneCoins {
let mut reward: NeptuneCoins = NeptuneCoins::new(128);
let generation = block_height.get_generation();
Expand Down Expand Up @@ -1188,16 +1189,20 @@ mod block_tests {

#[test]
fn test_premine_size() {
// 831600 = 42000000 * 0.0198
// 831488 = 42000000 * 0.019797333333333333
// where 42000000 is the asymptotical limit of the token supply
// and 1.98% is the relative size of the premine
let premine_max_size = NeptuneCoins::new(831600);
// and 1.9797333...% is the relative size of the premine
let premine_max_size = NeptuneCoins::new(831488);
let total_premine = Block::premine_distribution()
.iter()
.map(|(_receiving_address, amount)| *amount)
.sum::<NeptuneCoins>();

assert!(total_premine <= premine_max_size);
assert!(
premine_max_size.to_nau_f64() / 42_000_000f64 < 0.0198f64,
"Premine must be less than or equal to promised"
)
}

mod block_is_valid {
Expand Down

0 comments on commit a4a8f7f

Please sign in to comment.