Skip to content
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to the versioning scheme outlined in the [README.md](README.md).

## [3.3.0.0.1]

- Add indexes to `nakamoto_block_headers` to fix a performance regression. Node may take a few minutes to restart during the upgrade while the new indexes are created.

## [3.3.0.0.0]

### Added
Expand Down
8 changes: 8 additions & 0 deletions stackslib/src/chainstate/nakamoto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,14 @@ pub static NAKAMOTO_CHAINSTATE_SCHEMA_6: &[&str] = &[
"CREATE INDEX IF NOT EXISTS nakamoto_block_headers_by_ch_bv ON nakamoto_block_headers(consensus_hash, burn_view);"
];

pub static NAKAMOTO_CHAINSTATE_SCHEMA_7: &[&str] = &[
// schema change is JUST a new index, but the index is on a table
// created by a migration, so don't add the index to the CHAINSTATE_INDEXES
r#"UPDATE db_config SET version = "12";"#,
"CREATE INDEX IF NOT EXISTS naka_block_headers_by_burn_hash ON nakamoto_block_headers(burn_header_hash);",
"CREATE INDEX IF NOT EXISTS naka_block_headers_by_burn_ht ON nakamoto_block_headers(burn_header_height);"
];

#[cfg(test)]
mod fault_injection {
static PROCESS_BLOCK_STALL: std::sync::Mutex<bool> = std::sync::Mutex::new(false);
Expand Down
17 changes: 13 additions & 4 deletions stackslib/src/chainstate/stacks/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use crate::chainstate::nakamoto::{
HeaderTypeNames, NakamotoBlockHeader, NakamotoChainState, NakamotoStagingBlocksConn,
NAKAMOTO_CHAINSTATE_SCHEMA_1, NAKAMOTO_CHAINSTATE_SCHEMA_2, NAKAMOTO_CHAINSTATE_SCHEMA_3,
NAKAMOTO_CHAINSTATE_SCHEMA_4, NAKAMOTO_CHAINSTATE_SCHEMA_5, NAKAMOTO_CHAINSTATE_SCHEMA_6,
NAKAMOTO_CHAINSTATE_SCHEMA_7,
};
use crate::chainstate::stacks::address::StacksAddressExtensions;
use crate::chainstate::stacks::boot::*;
Expand Down Expand Up @@ -282,8 +283,8 @@ impl DBConfig {
});
match epoch_id {
StacksEpochId::Epoch10 => true,
StacksEpochId::Epoch20 => (1..=11).contains(&version_u32),
StacksEpochId::Epoch2_05 => (2..=11).contains(&version_u32),
StacksEpochId::Epoch20 => (1..=12).contains(&version_u32),
StacksEpochId::Epoch2_05 => (2..=12).contains(&version_u32),
StacksEpochId::Epoch21
| StacksEpochId::Epoch22
| StacksEpochId::Epoch23
Expand All @@ -292,7 +293,7 @@ impl DBConfig {
| StacksEpochId::Epoch30
| StacksEpochId::Epoch31
| StacksEpochId::Epoch32
| StacksEpochId::Epoch33 => (3..=11).contains(&version_u32),
| StacksEpochId::Epoch33 => (3..=12).contains(&version_u32),
}
}
}
Expand Down Expand Up @@ -651,7 +652,7 @@ impl<'a> DerefMut for ChainstateTx<'a> {
}
}

pub const CHAINSTATE_VERSION: &str = "11";
pub const CHAINSTATE_VERSION: &str = "12";

const CHAINSTATE_INITIAL_SCHEMA: &[&str] = &[
"PRAGMA foreign_keys = ON;",
Expand Down Expand Up @@ -1144,6 +1145,14 @@ impl StacksChainState {
tx.execute_batch(cmd)?;
}
}
"11" => {
info!(
"Migrating chainstate schema from version 11 to 12: add index for nakamoto_block_headers"
);
for cmd in NAKAMOTO_CHAINSTATE_SCHEMA_7.iter() {
tx.execute_batch(cmd)?;
}
}
_ => {
error!(
"Invalid chain state database: expected version = {}, got {}",
Expand Down
19 changes: 11 additions & 8 deletions stackslib/src/chainstate/stacks/db/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1560,13 +1560,14 @@ impl StacksChainState {

// what version of Clarity did the transaction caller want? And, is it valid now?
let clarity_version = StacksChainState::get_tx_clarity_version(clarity_block, tx)?;
if clarity_version == ClarityVersion::Clarity2 {
// requires 2.1 and higher
if clarity_block.get_epoch() < StacksEpochId::Epoch21 {
let msg = format!("Invalid transaction {}: asks for Clarity2, but not in Stacks epoch 2.1 or later", tx.txid());
info!("{}", &msg);
return Err(Error::InvalidStacksTransaction(msg, false));
}
if clarity_version > ClarityVersion::default_for_epoch(epoch) {
let msg = format!(
"Invalid transaction {}: asks for {clarity_version}, but current epoch {epoch} only supports up to {}",
tx.txid(),
ClarityVersion::default_for_epoch(epoch)
);
info!("{msg}");
return Err(Error::InvalidStacksTransaction(msg, false));
}

let mut transaction = clarity_block.connection().start_transaction_processing();
Expand Down Expand Up @@ -8668,7 +8669,9 @@ pub mod test {
if let Err(Error::InvalidStacksTransaction(msg, ..)) =
StacksChainState::process_transaction(&mut conn, &smart_contract_v2, false, None)
{
assert!(msg.find("not in Stacks epoch 2.1 or later").is_some());
assert!(msg
.find("asks for Clarity 2, but current epoch 2.05 only supports up to Clarity 1")
.is_some());
} else {
panic!("FATAL: did not recieve the appropriate error in processing a clarity2 tx in pre-2.1 epoch");
}
Expand Down
4 changes: 2 additions & 2 deletions versions.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Update these values when a new release is created.
# `stacks-common/build.rs` will automatically update `versions.rs` with these values.
stacks_node_version = "3.3.0.0.0"
stacks_signer_version = "3.3.0.0.0.0"
stacks_node_version = "3.3.0.0.1"
stacks_signer_version = "3.3.0.0.1.0"
Loading