diff --git a/CHANGELOG.md b/CHANGELOG.md index f85ed6526b..d19470075d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,15 +11,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE ### Changed -## [3.1.0.0.1] - -### Added - -- A miner will now generate a tenure-extend when at least 70% of the signers have confirmed that they are willing to allow one, via the new timestamp included in block responses. This allows the miner to refresh its budget in between Bitcoin blocks. ([#5476](https://github.com/stacks-network/stacks-core/discussions/5476)) - -### Changed - -## [3.1.0.0.0] +## [3.1.0.0.2] ### Added @@ -28,6 +20,8 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE - `/v2/clarity/marf/:marf_key_hash` - `/v2/clarity/metadata/:principal/:contract_name/:clarity_metadata_key` - When a proposed block is validated by a node, the block can be validated even when the block version is different than the node's default ([#5539](https://github.com/stacks-network/stacks-core/pull/5539)) +- A miner will now generate a tenure-extend when at least 70% of the signers have confirmed that they are willing to allow one, via the new timestamp included in block responses. This allows the miner to refresh its budget in between Bitcoin blocks. ([#5476](https://github.com/stacks-network/stacks-core/discussions/5476)) +- Set the epoch to 3.1 in the Clarity DB upon activation. ### Changed diff --git a/stacks-signer/CHANGELOG.md b/stacks-signer/CHANGELOG.md index 2f1187de51..fd38fe9775 100644 --- a/stacks-signer/CHANGELOG.md +++ b/stacks-signer/CHANGELOG.md @@ -11,15 +11,18 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE ## Changed -## [3.1.0.0.1.0] +## [3.1.0.0.2.0] -### Added +## Added + +- **SIP-029 consensus rules, activating in epoch 3.1 at block 875,000** (see [SIP-029](https://github.com/will-corcoran/sips/blob/feat/sip-029-halving-alignment/sips/sip-029/sip-029-halving-alignment.md) for details) ### Changed - Added tenure extend timestamp to signer block responses - Added tenure_idle_timeout_secs configuration option for determining when a time-based tenure extend will be accepted + ## [3.1.0.0.0.0] ### Added diff --git a/stackslib/src/chainstate/nakamoto/mod.rs b/stackslib/src/chainstate/nakamoto/mod.rs index 35f6e5d1e1..adf9dddc0e 100644 --- a/stackslib/src/chainstate/nakamoto/mod.rs +++ b/stackslib/src/chainstate/nakamoto/mod.rs @@ -3937,7 +3937,11 @@ impl NakamotoChainState { // is this stacks block the first of a new epoch? let (applied_epoch_transition, mut tx_receipts) = - StacksChainState::process_epoch_transition(&mut clarity_tx, burn_header_height)?; + StacksChainState::process_epoch_transition( + &mut clarity_tx, + sortition_dbconn.as_burn_state_db(), + burn_header_height, + )?; debug!( "Setup block: Processed epoch transition"; diff --git a/stackslib/src/chainstate/stacks/db/blocks.rs b/stackslib/src/chainstate/stacks/db/blocks.rs index 233a9d5978..5f6b236973 100644 --- a/stackslib/src/chainstate/stacks/db/blocks.rs +++ b/stackslib/src/chainstate/stacks/db/blocks.rs @@ -4044,6 +4044,7 @@ impl StacksChainState { /// Return (applied?, receipts) pub fn process_epoch_transition( clarity_tx: &mut ClarityTx, + burn_dbconn: &dyn BurnStateDB, chain_tip_burn_header_height: u32, ) -> Result<(bool, Vec), Error> { // is this stacks block the first of a new epoch? @@ -4104,14 +4105,29 @@ impl StacksChainState { current_epoch = StacksEpochId::Epoch30; } StacksEpochId::Epoch30 => { - // no special initialization is needed, since only the coinbase emission - // schedule is changing. + receipts.append(&mut clarity_tx.block.initialize_epoch_3_1()?); current_epoch = StacksEpochId::Epoch31; } StacksEpochId::Epoch31 => { panic!("No defined transition from Epoch31 forward") } } + + if current_epoch > StacksEpochId::Epoch2_05 { + // clarity tx should now have the current epoch + assert_eq!( + clarity_tx.block.get_epoch(), + current_epoch, + "FATAL: clarity_tx does not have the current epoch" + ); + + // clarity DB should now have the current epoch + assert_eq!( + clarity_tx.block.get_clarity_db_epoch_version(burn_dbconn)?, + current_epoch, + "FATAL: clarity DB does not report the current epoch" + ); + } } } @@ -5198,7 +5214,11 @@ impl StacksChainState { // is this stacks block the first of a new epoch? let (applied_epoch_transition, mut tx_receipts) = - StacksChainState::process_epoch_transition(&mut clarity_tx, burn_tip_height)?; + StacksChainState::process_epoch_transition( + &mut clarity_tx, + burn_dbconn, + burn_tip_height, + )?; debug!( "Setup block: Processed epoch transition at {}/{}", diff --git a/stackslib/src/clarity_vm/clarity.rs b/stackslib/src/clarity_vm/clarity.rs index a5497cea24..ee8795cadd 100644 --- a/stackslib/src/clarity_vm/clarity.rs +++ b/stackslib/src/clarity_vm/clarity.rs @@ -226,6 +226,21 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { None => None, } } + + /// Load the epoch ID from the clarity DB. + /// Used to sanity-check epoch transitions. + pub fn get_clarity_db_epoch_version( + &mut self, + burn_state_db: &dyn BurnStateDB, + ) -> Result { + let mut db = self.datastore.as_clarity_db(self.header_db, burn_state_db); + // NOTE: the begin/roll_back shouldn't be necessary with how this gets used in practice, + // but is put here defensively. + db.begin(); + let result = db.get_clarity_epoch_version(); + db.roll_back()?; + Ok(result?) + } } impl ClarityInstance { @@ -1524,6 +1539,32 @@ impl<'a, 'b> ClarityBlockConnection<'a, 'b> { }) } + pub fn initialize_epoch_3_1(&mut self) -> Result, Error> { + // use the `using!` statement to ensure that the old cost_tracker is placed + // back in all branches after initialization + using!(self.cost_track, "cost tracker", |old_cost_tracker| { + // epoch initialization is *free*. + // NOTE: this also means that cost functions won't be evaluated. + self.cost_track.replace(LimitedCostTracker::new_free()); + self.epoch = StacksEpochId::Epoch31; + self.as_transaction(|tx_conn| { + // bump the epoch in the Clarity DB + tx_conn + .with_clarity_db(|db| { + db.set_clarity_epoch_version(StacksEpochId::Epoch31)?; + Ok(()) + }) + .unwrap(); + + // require 3.1 rules henceforth in this connection as well + tx_conn.epoch = StacksEpochId::Epoch31; + }); + + debug!("Epoch 3.1 initialized"); + (old_cost_tracker, Ok(vec![])) + }) + } + pub fn start_transaction_processing<'c>(&'c mut self) -> ClarityTransactionConnection<'c, 'a> { let store = &mut self.datastore; let cost_track = &mut self.cost_track; diff --git a/stackslib/src/core/mod.rs b/stackslib/src/core/mod.rs index ba4dbf14d2..0f43c40756 100644 --- a/stackslib/src/core/mod.rs +++ b/stackslib/src/core/mod.rs @@ -496,7 +496,10 @@ pub static STACKS_EPOCH_3_0_MARKER: u8 = 0x0b; /// Stacks 3.1 epoch marker. All block-commits in 3.1 must have a memo bitfield with this value /// *or greater*. -pub static STACKS_EPOCH_3_1_MARKER: u8 = 0x0c; +/// NOTE: it has to be 0x0d because a prior release of 3.1 with 0x0c before activation had a +/// consensus bug. This forces miners with this buggy release off the network if they are still +/// running it prior to 3.1 activation. +pub static STACKS_EPOCH_3_1_MARKER: u8 = 0x0d; #[test] fn test_ord_for_stacks_epoch() {