Skip to content

Commit ad4a4e2

Browse files
Merge pull request #6707 from Jiloc/feat/add-clarity-versions-to-contract-consensus-tests
feat: add `exclude_clarity_versions` to contract consensus tests
2 parents f251c33 + 7549019 commit ad4a4e2

4 files changed

+34
-66
lines changed

stackslib/src/chainstate/tests/consensus.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,7 @@ impl ContractConsensusTest<'_> {
10211021
/// * `contract_code` - Clarity source code of the contract
10221022
/// * `function_name` - Contract function to test
10231023
/// * `function_args` - Arguments passed to `function_name` on every call
1024+
/// * `exclude_clarity_versions` - List of Clarity versions to exclude from testing. For each epoch to test, at least a clarity version must available.
10241025
/// * `setup_contracts` - Contracts that must be deployed before epoch-specific logic runs
10251026
///
10261027
/// # Panics
@@ -1037,12 +1038,22 @@ impl ContractConsensusTest<'_> {
10371038
contract_code: &str,
10381039
function_name: &str,
10391040
function_args: &[ClarityValue],
1041+
exclude_clarity_versions: &[ClarityVersion],
10401042
setup_contracts: &[SetupContract],
10411043
) -> Self {
10421044
assert!(
10431045
!deploy_epochs.is_empty(),
10441046
"At least one deploy epoch is required"
10451047
);
1048+
for epoch in deploy_epochs {
1049+
let supported_versions = clarity_versions_for_epoch(*epoch);
1050+
assert!(
1051+
supported_versions
1052+
.iter()
1053+
.any(|version| !exclude_clarity_versions.contains(version)),
1054+
"Epoch {epoch} does not have any Clarity versions available after applying exclusions",
1055+
);
1056+
}
10461057
let min_deploy_epoch = deploy_epochs.iter().min().unwrap();
10471058
assert!(
10481059
call_epochs.iter().all(|e| e >= min_deploy_epoch),
@@ -1054,6 +1065,7 @@ impl ContractConsensusTest<'_> {
10541065
.all(|c| c.deploy_epoch.is_none() || c.deploy_epoch.unwrap() >= *min_deploy_epoch),
10551066
"All setup contracts must have a deploy epoch >= the minimum deploy epoch"
10561067
);
1068+
10571069
// Build epoch_blocks map based on deploy and call epochs
10581070
let mut num_blocks_per_epoch: HashMap<StacksEpochId, u64> = HashMap::new();
10591071
let mut contract_deploys_per_epoch: HashMap<StacksEpochId, Vec<(String, ClarityVersion)>> =
@@ -1103,7 +1115,12 @@ impl ContractConsensusTest<'_> {
11031115
}
11041116

11051117
if deploy_epochs.contains(epoch) {
1106-
let clarity_versions = clarity_versions_for_epoch(*epoch);
1118+
let clarity_versions_per_epoch = clarity_versions_for_epoch(*epoch);
1119+
// Exclude the clarity versions that are in the exclude_clarity_versions list.
1120+
let clarity_versions = clarity_versions_per_epoch
1121+
.iter()
1122+
.filter(|v| !exclude_clarity_versions.contains(v));
1123+
11071124
let epoch_name = format!("Epoch{}", epoch.to_string().replace('.', "_"));
11081125

11091126
// Each deployment is a seperate TestBlock
@@ -1568,6 +1585,7 @@ impl TestTxFactory {
15681585
/// * `function_args` — Function arguments, provided as a slice of [`ClarityValue`].
15691586
/// * `deploy_epochs` — *(optional)* Epochs in which to deploy the contract. Defaults to all epochs ≥ 2.0.
15701587
/// * `call_epochs` — *(optional)* Epochs in which to call the function. Defaults to [`EPOCHS_TO_TEST`].
1588+
/// * `clarity_versions` — *(optional)* Clarity versions to test. For each epoch to test, at least one of the clarity versions must be supported. Defaults to all Clarity versions.
15711589
/// * `setup_contracts` — *(optional)* Slice of [`SetupContract`] values to deploy once before the main contract logic.
15721590
///
15731591
/// # Example
@@ -1597,6 +1615,7 @@ macro_rules! contract_call_consensus_test {
15971615
function_args: $function_args:expr,
15981616
$(deploy_epochs: $deploy_epochs:expr,)?
15991617
$(call_epochs: $call_epochs:expr,)?
1618+
$(exclude_clarity_versions: $exclude_clarity_versions:expr,)?
16001619
$(setup_contracts: $setup_contracts:expr,)?
16011620
) => {
16021621
{
@@ -1609,6 +1628,8 @@ macro_rules! contract_call_consensus_test {
16091628
$(let call_epochs = $call_epochs;)?
16101629
let setup_contracts: &[$crate::chainstate::tests::consensus::SetupContract] = &[];
16111630
$(let setup_contracts = $setup_contracts;)?
1631+
let exclude_clarity_versions: &[clarity::vm::ClarityVersion] = &[];
1632+
$(let exclude_clarity_versions = $exclude_clarity_versions;)?
16121633
let contract_test = $crate::chainstate::tests::consensus::ContractConsensusTest::new(
16131634
function_name!(),
16141635
vec![],
@@ -1618,6 +1639,7 @@ macro_rules! contract_call_consensus_test {
16181639
$contract_code,
16191640
$function_name,
16201641
$function_args,
1642+
exclude_clarity_versions,
16211643
setup_contracts,
16221644
);
16231645
let result = contract_test.run();
@@ -1645,6 +1667,7 @@ pub(crate) use contract_call_consensus_test;
16451667
/// * `contract_name` — Name of the contract being tested.
16461668
/// * `contract_code` — The Clarity source code of the contract.
16471669
/// * `deploy_epochs` — *(optional)* Epochs in which to deploy the contract. Defaults to [`EPOCHS_TO_TEST`].
1670+
/// * `clarity_versions` — *(optional)* Clarity versions to test. For each epoch to test, at least one of the clarity versions must be supported. Defaults to all Clarity versions.
16481671
/// * `setup_contracts` — *(optional)* Slice of [`SetupContract`] values to deploy before the main contract.
16491672
///
16501673
/// # Example
@@ -1664,6 +1687,7 @@ macro_rules! contract_deploy_consensus_test {
16641687
contract_name: $contract_name:expr,
16651688
contract_code: $contract_code:expr,
16661689
$(deploy_epochs: $deploy_epochs:expr,)?
1690+
$(exclude_clarity_versions: $exclude_clarity_versions:expr,)?
16671691
$(setup_contracts: $setup_contracts:expr,)?
16681692
) => {
16691693
{
@@ -1676,6 +1700,7 @@ macro_rules! contract_deploy_consensus_test {
16761700
function_args: &[], // No function calls, just deploys
16771701
deploy_epochs: deploy_epochs,
16781702
call_epochs: &[], // No function calls, just deploys
1703+
$(exclude_clarity_versions: $exclude_clarity_versions,)?
16791704
$(setup_contracts: $setup_contracts,)?
16801705
);
16811706
}

stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__static_analysis_tests__static_check_error_could_not_determine_serialization_type.snap

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,6 @@ expression: result
66
Success(ExpectedBlockOutput(
77
marf_hash: "b3b9782ccbe1bf3a66f1c34fe50c83c418fd9d6265761b0a82ffe9950dc8e30f",
88
evaluated_epoch: Epoch33,
9-
transactions: [
10-
ExpectedTransactionOutput(
11-
tx: "SmartContract(name: serialization-type-Epoch3_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))",
12-
vm_error: "Some(:0:0: use of unresolved function \'to-consensus-buff?\') [NON-CONSENSUS BREAKING]",
13-
return_type: Response(ResponseData(
14-
committed: false,
15-
data: Optional(OptionalData(
16-
data: None,
17-
)),
18-
)),
19-
cost: ExecutionCost(
20-
write_length: 0,
21-
write_count: 0,
22-
read_length: 0,
23-
read_count: 0,
24-
runtime: 7374,
25-
),
26-
),
27-
],
28-
total_block_cost: ExecutionCost(
29-
write_length: 0,
30-
write_count: 0,
31-
read_length: 0,
32-
read_count: 0,
33-
runtime: 7374,
34-
),
35-
)),
36-
Success(ExpectedBlockOutput(
37-
marf_hash: "32e8a7c15c537c7cbffb74e28705816f8c607bd37d5b2fe9db78f24c697d506f",
38-
evaluated_epoch: Epoch33,
399
transactions: [
4010
ExpectedTransactionOutput(
4111
tx: "SmartContract(name: serialization-type-Epoch3_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))",
@@ -64,7 +34,7 @@ expression: result
6434
),
6535
)),
6636
Success(ExpectedBlockOutput(
67-
marf_hash: "a9b3550d29aff9a7a271ee1cb981e4bb3e1948d49026511cc8183fbe2aaeb8af",
37+
marf_hash: "000052458b68bb6d4184aee0daf39736b0799c96514237aa8377e7c10f00fd61",
6838
evaluated_epoch: Epoch33,
6939
transactions: [
7040
ExpectedTransactionOutput(
@@ -94,7 +64,7 @@ expression: result
9464
),
9565
)),
9666
Success(ExpectedBlockOutput(
97-
marf_hash: "a390adec582f30b5d9b8cb0dec54acb082db7823cd7d55a11992fda3f5f96479",
67+
marf_hash: "322b1c89f517b9a55c2487d6f900057dadab0c93034bd5120be87fd7dc7fe86f",
9868
evaluated_epoch: Epoch33,
9969
transactions: [
10070
ExpectedTransactionOutput(

stackslib/src/chainstate/tests/snapshots/blockstack_lib__chainstate__tests__static_analysis_tests__static_check_error_unknown_type_name.snap

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,6 @@ expression: result
66
Success(ExpectedBlockOutput(
77
marf_hash: "8d004a3557c0396f4fc38d9ce6bf700be2d07f6afab03f03ff4e97ab98fe0f01",
88
evaluated_epoch: Epoch33,
9-
transactions: [
10-
ExpectedTransactionOutput(
11-
tx: "SmartContract(name: unknown-type-name-Epoch3_3-Clarity1, code_body: [..], clarity_version: Some(Clarity1))",
12-
vm_error: "Some(:0:0: use of unresolved function \'from-consensus-buff?\') [NON-CONSENSUS BREAKING]",
13-
return_type: Response(ResponseData(
14-
committed: false,
15-
data: Optional(OptionalData(
16-
data: None,
17-
)),
18-
)),
19-
cost: ExecutionCost(
20-
write_length: 0,
21-
write_count: 0,
22-
read_length: 0,
23-
read_count: 0,
24-
runtime: 2394,
25-
),
26-
),
27-
],
28-
total_block_cost: ExecutionCost(
29-
write_length: 0,
30-
write_count: 0,
31-
read_length: 0,
32-
read_count: 0,
33-
runtime: 2394,
34-
),
35-
)),
36-
Success(ExpectedBlockOutput(
37-
marf_hash: "eb4d4eb367b43b2b4bc7d93341c6bca0a24204c2a0a30706a8a18b5dcaf146e3",
38-
evaluated_epoch: Epoch33,
399
transactions: [
4010
ExpectedTransactionOutput(
4111
tx: "SmartContract(name: unknown-type-name-Epoch3_3-Clarity2, code_body: [..], clarity_version: Some(Clarity2))",
@@ -64,7 +34,7 @@ expression: result
6434
),
6535
)),
6636
Success(ExpectedBlockOutput(
67-
marf_hash: "e34776337382364c9cad419d37cd265c7c9c62c36e404641a942ee13f6566562",
37+
marf_hash: "cbe12e1fc1ac7d7c8e51a5017f252d5194eae8f9954bda1db5ff63919ecaea6b",
6838
evaluated_epoch: Epoch33,
6939
transactions: [
7040
ExpectedTransactionOutput(
@@ -94,7 +64,7 @@ expression: result
9464
),
9565
)),
9666
Success(ExpectedBlockOutput(
97-
marf_hash: "33484e3c68f4d42586a392be72eaf557996936ebd7cd002151817474bd409aee",
67+
marf_hash: "461b19fae1c2c4c055386fe3500aca96406c7b4438828249ec0a1d89939348a5",
9868
evaluated_epoch: Epoch33,
9969
transactions: [
10070
ExpectedTransactionOutput(

stackslib/src/chainstate/tests/static_analysis_tests.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#[allow(unused_imports)]
1919
use clarity::vm::analysis::CheckErrorKind;
2020
use clarity::vm::types::MAX_TYPE_DEPTH;
21+
use clarity::vm::ClarityVersion;
2122

2223
use crate::chainstate::tests::consensus::{contract_deploy_consensus_test, SetupContract};
2324
use crate::core::BLOCK_LIMIT_MAINNET_21;
@@ -206,7 +207,7 @@ fn static_check_error_expected_optional_type() {
206207
);
207208
}
208209

209-
/// StaticCheckErrorKind: [`StaticCheckErrorKind::BadTraitImplementation`]
210+
/// CheckErrorKind: [`CheckErrorKind::BadTraitImplementation`]
210211
/// Caused by: trying to implement a trait with a bad implementation.
211212
/// Outcome: block accepted.
212213
#[test]
@@ -357,6 +358,7 @@ fn static_check_error_unknown_type_name() {
357358
contract_code: "
358359
(define-public (trigger)
359360
(ok (from-consensus-buff? foo 0x00)))",
361+
exclude_clarity_versions: &[ClarityVersion::Clarity1],
360362
);
361363
}
362364

@@ -430,6 +432,7 @@ fn static_check_error_could_not_determine_serialization_type() {
430432
(define-trait trait-b ((pong () (response bool bool))))
431433
(define-public (trigger (first <trait-a>) (second <trait-b>))
432434
(ok (to-consensus-buff? (list first second))))",
435+
exclude_clarity_versions: &[ClarityVersion::Clarity1],
433436
);
434437
}
435438

0 commit comments

Comments
 (0)