Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/bitcoin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ jobs:
- tests::epoch_21::test_v1_unlock_height_with_current_stackers
- tests::epoch_21::test_v1_unlock_height_with_delay_and_current_stackers
- tests::epoch_21::trait_invocation_cross_epoch
- tests::epoch_22::pox_2_stack_increase_epoch22_fix
- tests::neon_integrations::bad_microblock_pubkey
steps:
- uses: actions/checkout@v2
Expand Down
4 changes: 3 additions & 1 deletion clarity/src/vm/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ pub fn run_analysis(
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => {
TypeChecker2_05::run_pass(&epoch, &mut contract_analysis, db)
}
StacksEpochId::Epoch21 => TypeChecker2_1::run_pass(&epoch, &mut contract_analysis, db),
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => {
TypeChecker2_1::run_pass(&epoch, &mut contract_analysis, db)
}
StacksEpochId::Epoch10 => unreachable!("Epoch 1.0 is not a valid epoch for analysis"),
}?;
TraitChecker::run_pass(&epoch, &mut contract_analysis, db)?;
Expand Down
6 changes: 4 additions & 2 deletions clarity/src/vm/analysis/type_checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ impl FunctionType {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => {
self.check_args_2_05(accounting, args)
}
StacksEpochId::Epoch21 => self.check_args_2_1(accounting, args, clarity_version),
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => {
self.check_args_2_1(accounting, args, clarity_version)
}
StacksEpochId::Epoch10 => unreachable!("Epoch10 is not supported"),
}
}
Expand All @@ -66,7 +68,7 @@ impl FunctionType {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => {
self.check_args_by_allowing_trait_cast_2_05(db, func_args)
}
StacksEpochId::Epoch21 => {
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => {
self.check_args_by_allowing_trait_cast_2_1(db, clarity_version, func_args)
}
StacksEpochId::Epoch10 => unreachable!("Epoch10 is not supported"),
Expand Down
2 changes: 1 addition & 1 deletion clarity/src/vm/costs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ impl LimitedCostTracker {
}
StacksEpochId::Epoch20 => COSTS_1_NAME.to_string(),
StacksEpochId::Epoch2_05 => COSTS_2_NAME.to_string(),
StacksEpochId::Epoch21 => COSTS_3_NAME.to_string(),
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => COSTS_3_NAME.to_string(),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions clarity/src/vm/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ macro_rules! switch_on_global_epoch {
StacksEpochId::Epoch2_05 => $Epoch205Version(args, env, context),
// Note: We reuse 2.05 for 2.1.
StacksEpochId::Epoch21 => $Epoch205Version(args, env, context),
// Note: We reuse 2.05 for 2.2.
StacksEpochId::Epoch22 => $Epoch205Version(args, env, context),
}
}
};
Expand Down
4 changes: 2 additions & 2 deletions clarity/src/vm/types/signatures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ impl TypeSignature {
pub fn admits_type(&self, epoch: &StacksEpochId, other: &TypeSignature) -> Result<bool> {
match epoch {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => self.admits_type_v2_0(&other),
StacksEpochId::Epoch21 => self.admits_type_v2_1(other),
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => self.admits_type_v2_1(other),
StacksEpochId::Epoch10 => unreachable!("epoch 1.0 not supported"),
}
}
Expand Down Expand Up @@ -1045,7 +1045,7 @@ impl TypeSignature {
) -> Result<TypeSignature> {
match epoch {
StacksEpochId::Epoch20 | StacksEpochId::Epoch2_05 => Self::least_supertype_v2_0(a, b),
StacksEpochId::Epoch21 => Self::least_supertype_v2_1(a, b),
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => Self::least_supertype_v2_1(a, b),
StacksEpochId::Epoch10 => unreachable!("Clarity 1.0 is not supported"),
}
}
Expand Down
1 change: 1 addition & 0 deletions clarity/src/vm/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ impl ClarityVersion {
StacksEpochId::Epoch20 => ClarityVersion::Clarity1,
StacksEpochId::Epoch2_05 => ClarityVersion::Clarity1,
StacksEpochId::Epoch21 => ClarityVersion::Clarity2,
StacksEpochId::Epoch22 => ClarityVersion::Clarity2,
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/burnchains/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,16 @@ impl PoxConstants {
first_block_height + reward_cycle * (self.reward_cycle_length as u64) + 1
}

pub fn static_reward_cycle_to_block_height(
reward_cycle_length: u64,
first_block_height: u64,
reward_cycle: u64,
) -> u64 {
// NOTE: the `+ 1` is because the height of the first block of a reward cycle is mod 1, not
// mod 0.
first_block_height + reward_cycle * reward_cycle_length + 1
}

pub fn block_height_to_reward_cycle(
&self,
first_block_height: u64,
Expand Down
80 changes: 73 additions & 7 deletions src/chainstate/burn/db/sortdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ impl FromRow<StacksEpoch> for StacksEpoch {
}
}

pub const SORTITION_DB_VERSION: &'static str = "4";
pub const SORTITION_DB_VERSION: &'static str = "5";

const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
r#"
Expand Down Expand Up @@ -702,6 +702,9 @@ const SORTITION_DB_SCHEMA_4: &'static [&'static str] = &[
);"#,
];

const SORTITION_DB_SCHEMA_5: &'static [&'static str] = &[r#"
DELETE FROM epochs;"#];

// update this to add new indexes
const LAST_SORTITION_DB_INDEX: &'static str = "index_delegate_stx_burn_header_hash";

Expand Down Expand Up @@ -2120,7 +2123,7 @@ impl<'a> SortitionHandleConn<'a> {
prepare_end_bhh: &BurnchainHeaderHash,
pox_consts: &PoxConstants,
) -> Result<Option<(ConsensusHash, BlockHeaderHash, Txid)>, CoordinatorError> {
let rc = match self.get_heights_for_prepare_phase_end_block(
let (rc, prepare_phase_end_height) = match self.get_heights_for_prepare_phase_end_block(
prepare_end_bhh,
pox_consts,
true,
Expand All @@ -2132,7 +2135,7 @@ impl<'a> SortitionHandleConn<'a> {
block_height.into(),
)
.ok_or(CoordinatorError::NotPrepareEndBlock)?;
rc
(rc, block_height)
}
None => {
// there can't be an anchor block
Expand Down Expand Up @@ -2187,6 +2190,27 @@ impl<'a> SortitionHandleConn<'a> {
let anchor_sn = SortitionDB::get_block_snapshot(self, &anchor_sort_id)?
.ok_or(BurnchainError::MissingParentBlock)?;

// if we're in epoch 2.2, then this anchor block must also have been in epoch 2.2
let prepare_phase_end_epoch =
SortitionDB::get_stacks_epoch(self.conn(), prepare_phase_end_height.into())?
.ok_or(BurnchainError::UnsupportedBurnchain)?
.epoch_id;
let anchor_epoch = SortitionDB::get_stacks_epoch(self.conn(), anchor_sn.block_height)?
.ok_or(BurnchainError::UnsupportedBurnchain)?
.epoch_id;
if prepare_phase_end_epoch == StacksEpochId::Epoch22 {
if anchor_epoch != StacksEpochId::Epoch22 {
// No anchor block is selected if the highest possible anchor isn't 2.2
warn!(
"PoX anchor block selection would have selected block, but this block was a 2.1 block";
"would_be_anchor_stacks_block_hash" => %anchor_block_op.block_header_hash,
"would_be_anchor_consensus_hash" => %anchor_sn.consensus_hash,
"would_be_anchor_burn_height" => %anchor_sn.block_height,
);
return Ok(None);
}
}

// the sortition does not even need to have picked this anchor block; all that matters is
// that miners confirmed it. If the winning block hash doesn't even correspond to a Stacks
// block, then the honest miners in the network will affirm that it's absent.
Expand Down Expand Up @@ -2813,7 +2837,9 @@ impl SortitionDB {
}

/// Get the schema version of a sortition DB, given the path to it.
/// Returns the version string, if it exists
/// Returns the version string, if it exists.
///
/// Does **not** migrate the database (like `open()` or `connect()` would)
pub fn get_db_version_from_path(path: &str) -> Result<Option<String>, db_error> {
if fs::metadata(path).is_err() {
return Err(db_error::NoDBError);
Expand Down Expand Up @@ -2843,10 +2869,17 @@ impl SortitionDB {
match epoch {
StacksEpochId::Epoch10 => true,
StacksEpochId::Epoch20 => {
version == "1" || version == "2" || version == "3" || version == "4"
version == "1"
|| version == "2"
|| version == "3"
|| version == "4"
|| version == "5"
}
StacksEpochId::Epoch2_05 => {
version == "2" || version == "3" || version == "4" || version == "5"
}
StacksEpochId::Epoch2_05 => version == "2" || version == "3" || version == "4",
StacksEpochId::Epoch21 => version == "3" || version == "4",
StacksEpochId::Epoch21 => version == "3" || version == "4" || version == "5",
StacksEpochId::Epoch22 => version == "3" || version == "4" || version == "5",
}
}

Expand Down Expand Up @@ -2915,6 +2948,28 @@ impl SortitionDB {
Ok(())
}

fn apply_schema_5(
tx: &DBTx,
epochs: &[StacksEpoch],
first_burn_ht: u64,
pox_consts: &PoxConstants,
) -> Result<(), db_error> {
for sql_exec in SORTITION_DB_SCHEMA_5 {
tx.execute_batch(sql_exec)?;
}

StacksEpoch::validate_epochs_with_pox_consts(epochs, first_burn_ht, pox_consts);

SortitionDB::validate_and_insert_epochs(&tx, epochs)?;

tx.execute(
"INSERT OR REPLACE INTO db_config (version) VALUES (?1)",
&["5"],
)?;

Ok(())
}

fn check_schema_version_or_error(&mut self) -> Result<(), db_error> {
match SortitionDB::get_schema_version(self.conn()) {
Ok(Some(version)) => {
Expand Down Expand Up @@ -2953,6 +3008,17 @@ impl SortitionDB {
let tx = self.tx_begin()?;
SortitionDB::apply_schema_4(&tx.deref())?;
tx.commit()?;
} else if version == "4" {
let first_burn_height = self.first_block_height;
let pox_consts = self.pox_constants.clone();
let tx = self.tx_begin()?;
SortitionDB::apply_schema_5(
&tx.deref(),
epochs,
first_burn_height,
&pox_consts,
)?;
tx.commit()?;
} else if version == expected_version {
return Ok(());
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/chainstate/burn/operations/leader_block_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use crate::chainstate::stacks::address::PoxAddress;
use crate::chainstate::stacks::index::storage::TrieFileStorage;
use crate::chainstate::stacks::{StacksPrivateKey, StacksPublicKey};
use crate::codec::{write_next, Error as codec_error, StacksMessageCodec};
use crate::core::STACKS_EPOCH_2_2_MARKER;
use crate::core::{StacksEpoch, StacksEpochId};
use crate::core::{STACKS_EPOCH_2_05_MARKER, STACKS_EPOCH_2_1_MARKER};
use crate::net::Error as net_error;
Expand Down Expand Up @@ -753,6 +754,7 @@ impl LeaderBlockCommitOp {
}
StacksEpochId::Epoch2_05 => self.check_epoch_commit_marker(STACKS_EPOCH_2_05_MARKER),
StacksEpochId::Epoch21 => self.check_epoch_commit_marker(STACKS_EPOCH_2_1_MARKER),
StacksEpochId::Epoch22 => self.check_epoch_commit_marker(STACKS_EPOCH_2_2_MARKER),
}
}

Expand All @@ -767,7 +769,7 @@ impl LeaderBlockCommitOp {
) -> Result<SortitionId, op_error> {
let tx_tip = tx.context.chain_tip.clone();
let intended_sortition = match epoch_id {
StacksEpochId::Epoch21 => {
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => {
// correct behavior -- uses *sortition height* to find the intended sortition ID
let sortition_height = self
.block_height
Expand Down
2 changes: 1 addition & 1 deletion src/chainstate/coordinator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2987,7 +2987,7 @@ impl<
return Ok(Some(pox_anchor));
}
}
StacksEpochId::Epoch21 => {
StacksEpochId::Epoch21 | StacksEpochId::Epoch22 => {
// 2.1 behavior: the anchor block must also be the
// heaviest-confirmed anchor block by BTC weight, and the highest
// such anchor block if there are multiple contenders.
Expand Down
Loading