Skip to content

Commit 4eaeabe

Browse files
authored
Merge pull request #5089 from stacks-network/feat/clarity-wasm-develop-merge
Merging latest develop
2 parents c241855 + f97df0d commit 4eaeabe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+4877
-1759
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ jobs:
7272
- tests::neon_integrations::confirm_unparsed_ongoing_ops
7373
- tests::neon_integrations::min_txs
7474
- tests::neon_integrations::vote_for_aggregate_key_burn_op_test
75+
- tests::neon_integrations::mock_miner_replay
7576
- tests::epoch_25::microblocks_disabled
7677
- tests::should_succeed_handling_malformed_and_valid_txs
7778
- tests::nakamoto_integrations::simple_neon_integration
@@ -95,6 +96,8 @@ jobs:
9596
- tests::signer::v0::mock_sign_epoch_25
9697
- tests::signer::v0::signer_set_rollover
9798
- tests::signer::v0::miner_forking
99+
- tests::signer::v0::reloads_signer_set_in
100+
- tests::signer::v0::signers_broadcast_signed_blocks
98101
- tests::nakamoto_integrations::stack_stx_burn_op_integration_test
99102
- tests::nakamoto_integrations::check_block_heights
100103
- tests::nakamoto_integrations::clarity_burn_state

.github/workflows/stacks-core-tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ jobs:
187187
if: always()
188188
needs:
189189
- full-genesis
190-
- unit-tests
191190
- open-api-validation
192191
- core-contracts-clarinet-test
193192
steps:

clarity/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,5 @@ developer-mode = ["stacks-common/developer-mode"]
6565
slog_json = ["stacks-common/slog_json"]
6666
testing = ["canonical", "rstest", "rstest_reuse"]
6767
devtools = []
68-
69-
[target.'cfg(all(target_arch = "x86_64", not(target_env = "msvc")))'.dependencies]
70-
sha2-asm = "0.5.3"
68+
rollback_value_check = []
69+
disable-costs = []

clarity/src/vm/ast/definition_sorter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl DefinitionSorter {
173173
return Ok(());
174174
}
175175
DefineFunctions::Map => {
176-
// Args: [name, key, value]: with key value being potentialy tuples
176+
// Args: [name, key, value]: with key value being potentially tuples
177177
if function_args.len() == 3 {
178178
self.probe_for_dependencies(
179179
function_args[1],

clarity/src/vm/database/key_value_wrapper.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@ use crate::vm::types::{
3131
};
3232
use crate::vm::{StacksEpoch, Value};
3333

34-
#[cfg(rollback_value_check)]
34+
#[cfg(feature = "rollback_value_check")]
3535
type RollbackValueCheck = String;
36-
#[cfg(not(rollback_value_check))]
36+
#[cfg(not(feature = "rollback_value_check"))]
3737
type RollbackValueCheck = ();
3838

39-
#[cfg(not(rollback_value_check))]
39+
#[cfg(not(feature = "rollback_value_check"))]
4040
fn rollback_value_check(_value: &str, _check: &RollbackValueCheck) {}
4141

42-
#[cfg(not(rollback_value_check))]
42+
#[cfg(not(feature = "rollback_value_check"))]
4343
fn rollback_edits_push<T>(edits: &mut Vec<(T, RollbackValueCheck)>, key: T, _value: &str) {
4444
edits.push((key, ()));
4545
}
4646
// this function is used to check the lookup map when committing at the "bottom" of the
4747
// wrapper -- i.e., when committing to the underlying store. for the _unchecked_ implementation
4848
// this is used to get the edit _value_ out of the lookupmap, for used in the subsequent `put_all`
4949
// command.
50-
#[cfg(not(rollback_value_check))]
50+
#[cfg(not(feature = "rollback_value_check"))]
5151
fn rollback_check_pre_bottom_commit<T>(
5252
edits: Vec<(T, RollbackValueCheck)>,
5353
lookup_map: &mut HashMap<T, Vec<String>>,
@@ -71,11 +71,11 @@ where
7171
output
7272
}
7373

74-
#[cfg(rollback_value_check)]
74+
#[cfg(feature = "rollback_value_check")]
7575
fn rollback_value_check(value: &String, check: &RollbackValueCheck) {
7676
assert_eq!(value, check)
7777
}
78-
#[cfg(rollback_value_check)]
78+
#[cfg(feature = "rollback_value_check")]
7979
fn rollback_edits_push<T>(edits: &mut Vec<(T, RollbackValueCheck)>, key: T, value: &String)
8080
where
8181
T: Eq + Hash + Clone,
@@ -84,7 +84,7 @@ where
8484
}
8585
// this function is used to check the lookup map when committing at the "bottom" of the
8686
// wrapper -- i.e., when committing to the underlying store.
87-
#[cfg(rollback_value_check)]
87+
#[cfg(feature = "rollback_value_check")]
8888
fn rollback_check_pre_bottom_commit<T>(
8989
edits: Vec<(T, RollbackValueCheck)>,
9090
lookup_map: &mut HashMap<T, Vec<String>>,

clarity/src/vm/types/signatures.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,9 @@ impl TypeSignature {
17011701
clarity_version: ClarityVersion,
17021702
) -> Result<BTreeMap<ClarityName, FunctionSignature>> {
17031703
let mut trait_signature: BTreeMap<ClarityName, FunctionSignature> = BTreeMap::new();
1704-
let functions_types = type_args[0]
1704+
let functions_types = type_args
1705+
.get(0)
1706+
.ok_or_else(|| CheckErrors::InvalidTypeDescription)?
17051707
.match_list()
17061708
.ok_or(CheckErrors::DefineTraitBadSignature)?;
17071709

contrib/boot-contracts-unit-tests/tests/misc.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ describe("test `get-total-ustx-stacked`", () => {
575575
expect(response.result).toBeUint(amount * 3n);
576576
});
577577

578-
it("expires stacking after the stacking duration has finsihed", () => {
578+
it("expires stacking after the stacking duration has finished", () => {
579579
const amount = getStackingMinimum() * 2n;
580580

581581
stackers.forEach((stacker, i) => {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# Install cargo-mutants
6+
cargo install --version 24.7.1 cargo-mutants --locked
7+
8+
# Create diff file between current branch and develop branch
9+
git diff origin/develop...HEAD > git.diff
10+
11+
# Remove git diff files about removed/renamed files
12+
awk '
13+
/^diff --git/ {
14+
diff_line = $0
15+
getline
16+
if ($0 !~ /^(deleted file mode|similarity index)/) {
17+
print diff_line
18+
print
19+
}
20+
}
21+
!/^(diff --git|deleted file mode|similarity index|rename from|rename to)/ {print}
22+
' git.diff > processed.diff
23+
24+
# Extract mutants based on the processed diff
25+
cargo mutants --in-diff processed.diff --list > all_mutants.txt
26+
27+
# Create a directory for organizing mutants
28+
mkdir -p mutants_by_package
29+
30+
# Organize mutants into files based on their main folder
31+
while IFS= read -r line; do
32+
package=$(echo "$line" | cut -d'/' -f1)
33+
34+
case $package in
35+
"stackslib")
36+
echo "$line" >> "mutants_by_package/stackslib.txt"
37+
;;
38+
"testnet")
39+
echo "$line" >> "mutants_by_package/stacks-node.txt"
40+
;;
41+
"stacks-signer")
42+
echo "$line" >> "mutants_by_package/stacks-signer.txt"
43+
;;
44+
*)
45+
echo "$line" >> "mutants_by_package/small-packages.txt"
46+
;;
47+
esac
48+
done < all_mutants.txt
49+
50+
# Function to run mutants for a package
51+
run_mutants() {
52+
local package=$1
53+
local threshold=$2
54+
local output_dir=$3
55+
local mutant_file="mutants_by_package/${package}.txt"
56+
57+
if [ ! -f "$mutant_file" ]; then
58+
echo "No mutants found for $package"
59+
return 0
60+
fi
61+
62+
local regex_pattern=$(sed 's/[][()\.^$*+?{}|]/\\&/g' "$mutant_file" | paste -sd'|' -)
63+
local mutant_count=$(cargo mutants -F "$regex_pattern" -E ": replace .{1,2} with .{1,2} in " --list | wc -l)
64+
65+
if [ "$mutant_count" -gt "$threshold" ]; then
66+
echo "Running mutants for $package ($mutant_count mutants)"
67+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
68+
cargo mutants --timeout-multiplier 1.5 --no-shuffle -vV \
69+
-F "$regex_pattern" \
70+
-E ": replace .{1,2} with .{1,2} in " \
71+
--output "$output_dir" \
72+
--test-tool=nextest \
73+
--package "$package" \
74+
-- --all-targets --test-threads 1 || true
75+
76+
echo $? > "${output_dir}/exit_code.txt"
77+
else
78+
echo "Skipping $package, only $mutant_count mutants (threshold: $threshold)"
79+
fi
80+
81+
return 0
82+
}
83+
84+
# Run mutants for each wanted package
85+
run_mutants "stacks-signer" 500 "./stacks-signer_mutants" || true
86+
run_mutants "stacks-node" 540 "./stacks-node_mutants" || true
87+
run_mutants "stackslib" 72 "./stackslib_mutants" || true

docs/mutation-testing.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Mutation Testing
2+
3+
This document describes how to run mutation testing locally to mimic the outcome of a PR, without the CI limitation it provides by timing out after 6 hours.
4+
[Here is the script](../contrib/tools/local-mutation-testing.sh) to run the tests locally by running the mutants created by the changes between `HEAD` and develop.
5+
It does automatically all the steps explained below.
6+
7+
From the root level of the stacks-core repository run
8+
```sh
9+
./contrib/tools/local-mutation-testing.sh
10+
```
11+
12+
## Prerequirements
13+
14+
Install the cargo mutants library
15+
```sh
16+
cargo install --version 24.7.1 cargo-mutants --locked
17+
```
18+
19+
20+
## Steps
21+
1. Be on source branch you would use for the PR.
22+
2. Create diff file comparing this branch with the `develop` branch
23+
```sh
24+
git diff origin/develop..HEAD > git.diff
25+
```
26+
3. Clean up the diff file and create auxiliary files
27+
```sh
28+
awk '
29+
/^diff --git/ {
30+
diff_line = $0
31+
getline
32+
if ($0 !~ /^(deleted file mode|similarity index)/) {
33+
print diff_line
34+
print
35+
}
36+
}
37+
!/^(diff --git|deleted file mode|similarity index|rename from|rename to)/ {print}
38+
' git.diff > processed.diff
39+
40+
# Extract mutants based on the processed diff
41+
cargo mutants --in-diff processed.diff --list > all_mutants.txt
42+
43+
# Create a directory for organizing mutants
44+
mkdir -p mutants_by_package
45+
46+
# Organize mutants into files based on their main folder
47+
while IFS= read -r line; do
48+
package=$(echo "$line" | cut -d'/' -f1)
49+
50+
case $package in
51+
"stackslib")
52+
echo "$line" >> "mutants_by_package/stackslib.txt"
53+
;;
54+
"testnet")
55+
echo "$line" >> "mutants_by_package/stacks-node.txt"
56+
;;
57+
"stacks-signer")
58+
echo "$line" >> "mutants_by_package/stacks-signer.txt"
59+
;;
60+
*)
61+
echo "$line" >> "mutants_by_package/small-packages.txt"
62+
;;
63+
esac
64+
done < all_mutants.txt
65+
```
66+
4. Based on the package required to run the mutants for
67+
a. Stackslib package
68+
```sh
69+
regex_pattern=$(sed 's/[][()\.^$*+?{}|]/\\&/g' "mutants_by_package/stackslib.txt" | paste -sd'|' -)
70+
71+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
72+
cargo mutants --timeout-multiplier 1.5 --no-shuffle -vV \
73+
-F "$regex_pattern" \
74+
-E ": replace .{1,2} with .{1,2} in " \
75+
--output "./stackslib_mutants" \
76+
--test-tool=nextest \
77+
-- --all-targets --test-threads 1
78+
```
79+
b. Stacks-node (testnet) package
80+
```sh
81+
regex_pattern=$(sed 's/[][()\.^$*+?{}|]/\\&/g' "mutants_by_package/testnet.txt" | paste -sd'|' -)
82+
83+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
84+
cargo mutants --timeout-multiplier 1.5 --no-shuffle -vV \
85+
-F "$regex_pattern" \
86+
-E ": replace .{1,2} with .{1,2} in " \
87+
--output "./testnet_mutants" \
88+
--test-tool=nextest \
89+
-- --all-targets --test-threads 1
90+
```
91+
c. Stacks-signer
92+
```sh
93+
regex_pattern=$(sed 's/[][()\.^$*+?{}|]/\\&/g' "mutants_by_package/stacks-signer.txt" | paste -sd'|' -)
94+
95+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
96+
cargo mutants --timeout-multiplier 1.5 --no-shuffle -vV \
97+
-F "$regex_pattern" \
98+
-E ": replace .{1,2} with .{1,2} in " \
99+
--output "./stacks-signer_mutants" \
100+
--test-tool=nextest \
101+
-- --all-targets --test-threads 1
102+
```
103+
d. All other packages combined
104+
```sh
105+
regex_pattern=$(sed 's/[][()\.^$*+?{}|]/\\&/g' "mutants_by_package/small-packages.txt" | paste -sd'|' -)
106+
107+
cargo mutants --timeout-multiplier 1.5 --no-shuffle -vV \
108+
-F "$regex_pattern" \
109+
-E ": replace .{1,2} with .{1,2} in " \
110+
--output "./small-packages_mutants" \
111+
--test-tool=nextest \
112+
-- --all-targets --test-threads 1
113+
```
114+
115+
## How to run one specific mutant to test it
116+
117+
Example of output which had a missing mutant
118+
```sh
119+
MISSED stacks-signer/src/runloop.rs:424:9: replace <impl SignerRunLoop for RunLoop<Signer, T>>::run_one_pass -> Option<Vec<SignerResult>> with None in 3.0s build + 9.3s test
120+
```
121+
122+
Example of fix for it
123+
```sh
124+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
125+
cargo mutants -vV \
126+
-F "replace process_stackerdb_event" \
127+
-E ": replace <impl SignerRunLoop for RunLoop<Signer, T>>::run_one_pass -> Option<Vec<SignerResult>> with None in " \
128+
--test-tool=nextest \
129+
-- \
130+
--run-ignored all \
131+
--fail-fast \
132+
--test-threads 1
133+
```
134+
135+
General command to run
136+
```sh
137+
RUST_BACKTRACE=1 BITCOIND_TEST=1 \
138+
cargo mutants -vV \
139+
-F "replace process_stackerdb_event" \
140+
-E ": replace [modify this] with [modify this] in " \
141+
--test-tool=nextest \
142+
-- \
143+
--run-ignored all \
144+
--fail-fast \
145+
--test-threads 1
146+
```

docs/rpc-endpoints.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ Determine whether a given trait is implemented within the specified contract (ei
427427

428428
See OpenAPI [spec](./rpc/openapi.yaml) for details.
429429

430-
### POST /v2/block_proposal
430+
### POST /v3/block_proposal
431431

432432
Used by miner to validate a proposed Stacks block using JSON encoding.
433433

0 commit comments

Comments
 (0)