diff --git a/changelog.d/coinbase-intervals.changed b/changelog.d/coinbase-intervals.changed new file mode 100644 index 00000000000..c7cf533eea1 --- /dev/null +++ b/changelog.d/coinbase-intervals.changed @@ -0,0 +1 @@ +Updated coinbase intervals for Epoch 4.0 diff --git a/stacks-common/src/types/mod.rs b/stacks-common/src/types/mod.rs index 3b9e076df26..8e9032218f1 100644 --- a/stacks-common/src/types/mod.rs +++ b/stacks-common/src/types/mod.rs @@ -183,21 +183,29 @@ pub struct CoinbaseInterval { pub effective_start_height: u64, } -// From SIP-029: +/// Burnchain height of the Stacks genesis block (mainnet). +pub const BITCOIN_MAINNET_GENESIS_BURN_HEIGHT: u64 = 666_050; + +/// Burnchain height at which the Stacks 4.0 epoch activates (mainnet). +pub const BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT: u64 = 1_012_860; + +/// Burnchain height of the Stacks genesis block (testnet). +pub const BITCOIN_TESTNET_GENESIS_BURN_HEIGHT: u64 = 2_000_000; + +/// Burnchain height at which the Stacks 4.0 epoch activates (testnet). +pub const BITCOIN_TESTNET_STACKS_40_BURN_HEIGHT: u64 = 40_000_000; + +// Mainnet coinbase intervals, as defined in SIP-029 + SIP-045 // -// | Coinbase Interval | Bitcoin Height | Offset Height | Approx. Supply | STX Reward | Annual Inflation | -// |--------------------|----------------|---------------------|------------------|------------|------------------| -// | Current | - | - | 1,552,452,847 | 1000 | - | -// | 1st | 945,000 | 278,950 | 1,627,352,847 | 500 (50%) | 3.23% | -// | 2nd | 1,050,000 | 383,950 | 1,679,852,847 | 250 (50%) | 1.57% | -// | 3rd | 1,260,000 | 593,950 | 1,732,352,847 | 125 (50%) | 0.76% | -// | 4th | 1,470,000 | 803,950 | 1,758,602,847 | 62.5 (50%) | 0.37% | -// | - | 2,197,560 | 1,531,510 | 1,804,075,347 | 62.5 (0%) | 0.18% | +// | Coinbase Interval | Bitcoin Height | Offset Height | Approx. Supply | STX Reward | Annual Inflation | +// |--------------------|---------------------------------------|---------------------|------------------|------------|------------------| +// | Current | - | - | 1,552,452,847 | 1000 | - | +// | 1st (SIP-029) | 945,000 | 278,950 | 1,627,352,847 | 500 (50%) | 3.23% | +// | 2nd (SIP-045) | BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT | - | TBD | 1000 | Variable | // // The above is for mainnet, which has a burnchain year of 52596 blocks and starts at burnchain height 666050. -/// Mainnet coinbase intervals, as of SIP-029 -pub static COINBASE_INTERVALS_MAINNET: LazyLock<[CoinbaseInterval; 5]> = LazyLock::new(|| { +pub static COINBASE_INTERVALS_MAINNET: LazyLock<[CoinbaseInterval; 3]> = LazyLock::new(|| { let emissions_schedule = [ CoinbaseInterval { coinbase: 1_000 * u128::from(MICROSTACKS_PER_STACKS), @@ -208,24 +216,16 @@ pub static COINBASE_INTERVALS_MAINNET: LazyLock<[CoinbaseInterval; 5]> = LazyLoc effective_start_height: 278_950, }, CoinbaseInterval { - coinbase: 250 * u128::from(MICROSTACKS_PER_STACKS), - effective_start_height: 383_950, - }, - CoinbaseInterval { - coinbase: 125 * u128::from(MICROSTACKS_PER_STACKS), - effective_start_height: 593_950, - }, - CoinbaseInterval { - coinbase: (625 * u128::from(MICROSTACKS_PER_STACKS)) / 10, - effective_start_height: 803_950, + coinbase: 1_000 * u128::from(MICROSTACKS_PER_STACKS), + effective_start_height: BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT + - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT, }, ]; assert!(CoinbaseInterval::check_order(&emissions_schedule)); emissions_schedule }); -/// Testnet coinbase intervals, as of SIP-029 -pub static COINBASE_INTERVALS_TESTNET: LazyLock<[CoinbaseInterval; 5]> = LazyLock::new(|| { +pub static COINBASE_INTERVALS_TESTNET: LazyLock<[CoinbaseInterval; 6]> = LazyLock::new(|| { let emissions_schedule = [ CoinbaseInterval { coinbase: 1_000 * u128::from(MICROSTACKS_PER_STACKS), @@ -247,6 +247,11 @@ pub static COINBASE_INTERVALS_TESTNET: LazyLock<[CoinbaseInterval; 5]> = LazyLoc coinbase: (625 * u128::from(MICROSTACKS_PER_STACKS)) / 10, effective_start_height: 77_777 * 21, }, + CoinbaseInterval { + coinbase: 1_000 * u128::from(MICROSTACKS_PER_STACKS), + effective_start_height: BITCOIN_TESTNET_STACKS_40_BURN_HEIGHT + - BITCOIN_TESTNET_GENESIS_BURN_HEIGHT, + }, ]; assert!(CoinbaseInterval::check_order(&emissions_schedule)); emissions_schedule diff --git a/stacks-common/src/types/tests.rs b/stacks-common/src/types/tests.rs index f5b8274f577..2ff7b0a7cc7 100644 --- a/stacks-common/src/types/tests.rs +++ b/stacks-common/src/types/tests.rs @@ -17,8 +17,10 @@ use std::str::FromStr; use super::{ - set_test_coinbase_schedule, CoinbaseInterval, StacksEpochId, COINBASE_INTERVALS_MAINNET, - COINBASE_INTERVALS_TESTNET, + set_test_coinbase_schedule, CoinbaseInterval, StacksEpochId, + BITCOIN_MAINNET_GENESIS_BURN_HEIGHT, BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT, + BITCOIN_TESTNET_GENESIS_BURN_HEIGHT, BITCOIN_TESTNET_STACKS_40_BURN_HEIGHT, + COINBASE_INTERVALS_MAINNET, COINBASE_INTERVALS_TESTNET, }; #[test] @@ -41,14 +43,13 @@ fn test_stacks_epoch_id_display_fromstr_tryfrom_roundtrip() { #[test] fn test_mainnet_coinbase_emissions() { - assert_eq!(COINBASE_INTERVALS_MAINNET.len(), 5); + assert_eq!(COINBASE_INTERVALS_MAINNET.len(), 3); assert_eq!(COINBASE_INTERVALS_MAINNET[0].coinbase, 1_000_000_000); assert_eq!(COINBASE_INTERVALS_MAINNET[1].coinbase, 500_000_000); - assert_eq!(COINBASE_INTERVALS_MAINNET[2].coinbase, 250_000_000); - assert_eq!(COINBASE_INTERVALS_MAINNET[3].coinbase, 125_000_000); - assert_eq!(COINBASE_INTERVALS_MAINNET[4].coinbase, 62_500_000); + assert_eq!(COINBASE_INTERVALS_MAINNET[2].coinbase, 1_000_000_000); + + // heights from SIP-029 and SIP-045 - // heights from SIP-029 assert_eq!( COINBASE_INTERVALS_MAINNET[0].effective_start_height, 666_050 - 666_050 @@ -59,15 +60,37 @@ fn test_mainnet_coinbase_emissions() { ); assert_eq!( COINBASE_INTERVALS_MAINNET[2].effective_start_height, - 1_050_000 - 666_050 + BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT + ); +} + +#[test] +fn test_testnet_coinbase_emissions() { + assert_eq!(COINBASE_INTERVALS_TESTNET.len(), 6); + assert_eq!(COINBASE_INTERVALS_TESTNET[0].coinbase, 1_000_000_000); + assert_eq!(COINBASE_INTERVALS_TESTNET[1].coinbase, 500_000_000); + assert_eq!(COINBASE_INTERVALS_TESTNET[2].coinbase, 250_000_000); + assert_eq!(COINBASE_INTERVALS_TESTNET[3].coinbase, 125_000_000); + assert_eq!(COINBASE_INTERVALS_TESTNET[4].coinbase, 62_500_000); + assert_eq!(COINBASE_INTERVALS_TESTNET[5].coinbase, 1_000_000_000); + + assert_eq!(COINBASE_INTERVALS_TESTNET[0].effective_start_height, 0); + assert_eq!(COINBASE_INTERVALS_TESTNET[1].effective_start_height, 77_777); + assert_eq!( + COINBASE_INTERVALS_TESTNET[2].effective_start_height, + 77_777 * 7 + ); + assert_eq!( + COINBASE_INTERVALS_TESTNET[3].effective_start_height, + 77_777 * 14 ); assert_eq!( - COINBASE_INTERVALS_MAINNET[3].effective_start_height, - 1_260_000 - 666_050 + COINBASE_INTERVALS_TESTNET[4].effective_start_height, + 77_777 * 21 ); assert_eq!( - COINBASE_INTERVALS_MAINNET[4].effective_start_height, - 1_470_000 - 666_050 + COINBASE_INTERVALS_TESTNET[5].effective_start_height, + BITCOIN_TESTNET_STACKS_40_BURN_HEIGHT - BITCOIN_TESTNET_GENESIS_BURN_HEIGHT ); } @@ -93,21 +116,21 @@ fn test_get_coinbase_at_effective_height() { assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 944_999 - 666050 + 944_999 - 666_050 ), 1_000_000_000 ); assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 945_000 - 666050 + 945_000 - 666_050 ), 500_000_000 ); assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 945_001 - 666050 + 945_001 - 666_050 ), 500_000_000 ); @@ -115,89 +138,30 @@ fn test_get_coinbase_at_effective_height() { assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 1_049_999 - 666050 + BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT - 1 ), 500_000_000 ); assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 1_050_000 - 666050 + BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT ), - 250_000_000 - ); - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_050_001 - 666050 - ), - 250_000_000 - ); - - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_259_999 - 666050 - ), - 250_000_000 - ); - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_260_000 - 666050 - ), - 125_000_000 - ); - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_260_001 - 666050 - ), - 125_000_000 - ); - - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_469_999 - 666050 - ), - 125_000_000 - ); - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_470_000 - 666050 - ), - 62_500_000 - ); - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 1_470_001 - 666050 - ), - 62_500_000 - ); - - assert_eq!( - CoinbaseInterval::get_coinbase_at_effective_height( - &*COINBASE_INTERVALS_MAINNET, - 2_197_559 - 666050 - ), - 62_500_000 + 1_000_000_000 ); assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 2_197_560 - 666050 + BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT + 1 ), - 62_500_000 + 1_000_000_000 ); assert_eq!( CoinbaseInterval::get_coinbase_at_effective_height( &*COINBASE_INTERVALS_MAINNET, - 2_197_561 - 666050 + 2_000_000 - BITCOIN_MAINNET_GENESIS_BURN_HEIGHT ), - 62_500_000 + 1_000_000_000 ); } @@ -212,17 +176,22 @@ fn test_epoch_coinbase_reward() { assert_eq!(epoch.coinbase_reward(true, 666050, 945_000), 500_000_000); assert_eq!(epoch.coinbase_reward(true, 666050, 945_001), 500_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_049_999), 500_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_050_000), 250_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_050_001), 250_000_000); - - assert_eq!(epoch.coinbase_reward(true, 666050, 1_259_999), 250_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_260_000), 125_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_260_001), 125_000_000); - - assert_eq!(epoch.coinbase_reward(true, 666050, 1_469_999), 125_000_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_470_000), 62_500_000); - assert_eq!(epoch.coinbase_reward(true, 666050, 1_470_001), 62_500_000); + assert_eq!( + epoch.coinbase_reward(true, 666050, BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT - 1), + 500_000_000 + ); + assert_eq!( + epoch.coinbase_reward(true, 666050, BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT), + 1_000_000_000 + ); + assert_eq!( + epoch.coinbase_reward(true, 666050, BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT + 1), + 1_000_000_000 + ); + assert_eq!( + epoch.coinbase_reward(true, 666050, 2_000_000), + 1_000_000_000 + ); } // old coinbase schedule diff --git a/stackslib/src/core/mod.rs b/stackslib/src/core/mod.rs index d03c515200e..d7f8e1ff10d 100644 --- a/stackslib/src/core/mod.rs +++ b/stackslib/src/core/mod.rs @@ -142,7 +142,7 @@ pub const BITCOIN_MAINNET_STACKS_33_BURN_HEIGHT: u64 = 923_222; /// This is Epoch-3.4, activation timing proposed in SIP-039 pub const BITCOIN_MAINNET_STACKS_34_BURN_HEIGHT: u64 = 943_333; /// This is Epoch-4.0, activation timing TBD. Placeholder until scheduled. -pub const BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT: u64 = 4_000_000; +pub use stacks_common::types::BITCOIN_MAINNET_STACKS_40_BURN_HEIGHT; /// Bitcoin mainline testnet3 activation heights. /// TODO: No longer used since testnet3 is dead, so remove.