From 86ed48c1c03afee0e45bac1500171179db57d556 Mon Sep 17 00:00:00 2001 From: ASuciuX Date: Thu, 15 Feb 2024 00:29:22 +0200 Subject: [PATCH 01/39] feat: update workflow to include optimisations 1. split big packages into `stackslib` and `stacks-node` 2. update cargo mutants to use specific version from github in order to include a timeout multiplier feature 3. add a specific run case for `stacks-signer` --- .github/workflows/pr-differences-mutants.yml | 106 +++++++++++++++---- 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/.github/workflows/pr-differences-mutants.yml b/.github/workflows/pr-differences-mutants.yml index 041db97591..a795917229 100644 --- a/.github/workflows/pr-differences-mutants.yml +++ b/.github/workflows/pr-differences-mutants.yml @@ -23,10 +23,13 @@ jobs: runs-on: ubuntu-latest outputs: - run_big_packages: ${{ steps.check_packages_and_shards.outputs.run_big_packages }} - big_packages_with_shards: ${{ steps.check_packages_and_shards.outputs.big_packages_with_shards }} + run_stackslib: ${{ steps.check_packages_and_shards.outputs.run_stackslib }} + stackslib_with_shards: ${{ steps.check_packages_and_shards.outputs.stackslib_with_shards }} + run_stacks_node: ${{ steps.check_packages_and_shards.outputs.run_stacks_node }} + stacks_node_with_shards: ${{ steps.check_packages_and_shards.outputs.stacks_node_with_shards }} run_small_packages: ${{ steps.check_packages_and_shards.outputs.run_small_packages }} small_packages_with_shards: ${{ steps.check_packages_and_shards.outputs.small_packages_with_shards }} + run_stacks_signer: ${{ steps.check_packages_and_shards.outputs.run_stacks_signer }} steps: - id: check_packages_and_shards @@ -46,7 +49,7 @@ jobs: - name: Run mutants on diffs uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package-dimension: "small" + package: "small" # Mutation testing - Execute on PR on small packages that have functions modified (run with strategy matrix shards) pr-differences-mutants-small-shards: @@ -68,15 +71,15 @@ jobs: uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: shard: ${{ matrix.shard }} - package-dimension: "small" + package: "small" - # Mutation testing - Execute on PR on big packages that have functions modified (normal run, no shards) - pr-differences-mutants-big-normal: - name: Mutation Testing - Normal, Big + # Mutation testing - Execute on PR on stackslib package (normal run, no shards) + pr-differences-mutants-stackslib-normal: + name: Mutation Testing - Normal, Stackslib needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_big_packages == 'true' && needs.check-big-packages-and-shards.outputs.big_packages_with_shards == 'false' }} + if: ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'false' }} runs-on: ubuntu-latest @@ -87,15 +90,15 @@ jobs: RUST_BACKTRACE: full uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package-dimension: "big" + package: "stackslib" - # Mutation testing - Execute on PR on big packages that have functions modified (run with strategy matrix shards) - pr-differences-mutants-big-shards: - name: Mutation Testing - Shards, Big + # Mutation testing - Execute on PR on stackslib package (run with strategy matrix shards) + pr-differences-mutants-stackslib-shards: + name: Mutation Testing - Shards, Stackslib needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_big_packages == 'true' && needs.check-big-packages-and-shards.outputs.big_packages_with_shards == 'true' }} + if: ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'true' }} runs-on: ubuntu-latest @@ -112,7 +115,67 @@ jobs: uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: shard: ${{ matrix.shard }} - package-dimension: "big" + package: "stackslib" + + # Mutation testing - Execute on PR on stacks-node package (normal run, no shards) + pr-differences-mutants-stacks-node-normal: + name: Mutation Testing - Normal, Stacks Node + + needs: check-big-packages-and-shards + + if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'false' }} + + runs-on: ubuntu-latest + + steps: + - name: Run Run mutants on diffs + env: + BITCOIND_TEST: 1 + RUST_BACKTRACE: full + uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main + with: + package: "stacks-node" + + # Mutation testing - Execute on PR on stacks-node package (run with strategy matrix shards) + pr-differences-mutants-stacks-node-shards: + name: Mutation Testing - Shards, Stacks Node + + needs: check-big-packages-and-shards + + if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'true' }} + + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + shard: [0, 1, 2, 3] + + steps: + - name: Run mutants on diffs + env: + BITCOIND_TEST: 1 + RUST_BACKTRACE: full + uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main + with: + shard: ${{ matrix.shard }} + package: "stacks-node" + + # Mutation testing - Execute on PR on stacks-signer package (normal run, no shards) + pr-differences-mutants-stacks-signer-normal: + name: Mutation Testing - Normal, Stacks Signer + + needs: check-big-packages-and-shards + + if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_signer == 'true' }} + + runs-on: ubuntu-latest + + steps: + - name: Run Run mutants on diffs + uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main + with: + package: "stacks-signer" # Output the mutants and fail the workflow if there are missed/timeout/unviable mutants output-mutants: @@ -120,20 +183,27 @@ jobs: runs-on: ubuntu-latest + if: always() needs: [ check-big-packages-and-shards, pr-differences-mutants-small-normal, pr-differences-mutants-small-shards, - pr-differences-mutants-big-normal, - pr-differences-mutants-big-shards, + pr-differences-mutants-stackslib-normal, + pr-differences-mutants-stackslib-shards, + pr-differences-mutants-stacks-node-normal, + pr-differences-mutants-stacks-node-shards, + pr-differences-mutants-stacks-signer-normal, ] steps: - name: Output Mutants uses: stacks-network/actions/stacks-core/mutation-testing/output-pr-mutants@main with: - big_packages: ${{ needs.check-big-packages-and-shards.outputs.run_big_packages }} - shards_for_big_packages: ${{ needs.check-big-packages-and-shards.outputs.big_packages_with_shards }} + stackslib_package: ${{ needs.check-big-packages-and-shards.outputs.run_stackslib }} + shards_for_stackslib_package: ${{ needs.check-big-packages-and-shards.outputs.stackslib_with_shards }} + stacks_node_package: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node }} + shards_for_stacks_node_package: ${{ needs.check-big-packages-and-shards.outputs.stacks_node_with_shards }} small_packages: ${{ needs.check-big-packages-and-shards.outputs.run_small_packages }} shards_for_small_packages: ${{ needs.check-big-packages-and-shards.outputs.small_packages_with_shards }} + stacks_signer: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_signer }} From 5444cc4f06adc424047b28989a0b44020cdad0a7 Mon Sep 17 00:00:00 2001 From: ASuciuX Date: Wed, 21 Feb 2024 17:36:14 +0200 Subject: [PATCH 02/39] feat: multi-line 'if' statements for readability --- .github/workflows/pr-differences-mutants.yml | 27 +++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-differences-mutants.yml b/.github/workflows/pr-differences-mutants.yml index a795917229..7e02c7e13d 100644 --- a/.github/workflows/pr-differences-mutants.yml +++ b/.github/workflows/pr-differences-mutants.yml @@ -41,7 +41,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'false' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && + needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'false' }} runs-on: ubuntu-latest @@ -57,7 +59,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'true' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && + needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'true' }} runs-on: ubuntu-latest @@ -79,7 +83,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'false' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && + needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'false' }} runs-on: ubuntu-latest @@ -98,7 +104,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'true' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && + needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'true' }} runs-on: ubuntu-latest @@ -123,7 +131,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'false' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && + needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'false' }} runs-on: ubuntu-latest @@ -142,7 +152,9 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'true' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && + needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'true' }} runs-on: ubuntu-latest @@ -167,7 +179,8 @@ jobs: needs: check-big-packages-and-shards - if: ${{ needs.check-big-packages-and-shards.outputs.run_stacks_signer == 'true' }} + if: | + ${{ needs.check-big-packages-and-shards.outputs.run_stacks_signer == 'true' }} runs-on: ubuntu-latest From 8a4c59dd2c7e8fa69658fd53316bd5bac298d6a9 Mon Sep 17 00:00:00 2001 From: ASuciuX Date: Thu, 22 Feb 2024 20:17:22 +0200 Subject: [PATCH 03/39] feat: format yml code --- .github/workflows/pr-differences-mutants.yml | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/pr-differences-mutants.yml b/.github/workflows/pr-differences-mutants.yml index 7e02c7e13d..0e76c1c15a 100644 --- a/.github/workflows/pr-differences-mutants.yml +++ b/.github/workflows/pr-differences-mutants.yml @@ -8,7 +8,7 @@ on: - synchronize - ready_for_review paths: - - "**.rs" + - '**.rs' concurrency: group: pr-differences-${{ github.head_ref || github.ref || github.run_id }} @@ -42,8 +42,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && - needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'false' }} + needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && + needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'false' runs-on: ubuntu-latest @@ -51,7 +51,7 @@ jobs: - name: Run mutants on diffs uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package: "small" + package: 'small' # Mutation testing - Execute on PR on small packages that have functions modified (run with strategy matrix shards) pr-differences-mutants-small-shards: @@ -60,8 +60,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && - needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'true' }} + needs.check-big-packages-and-shards.outputs.run_small_packages == 'true' && + needs.check-big-packages-and-shards.outputs.small_packages_with_shards == 'true' runs-on: ubuntu-latest @@ -75,7 +75,7 @@ jobs: uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: shard: ${{ matrix.shard }} - package: "small" + package: 'small' # Mutation testing - Execute on PR on stackslib package (normal run, no shards) pr-differences-mutants-stackslib-normal: @@ -84,8 +84,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && - needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'false' }} + needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && + needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'false' runs-on: ubuntu-latest @@ -96,7 +96,7 @@ jobs: RUST_BACKTRACE: full uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package: "stackslib" + package: 'stackslib' # Mutation testing - Execute on PR on stackslib package (run with strategy matrix shards) pr-differences-mutants-stackslib-shards: @@ -105,8 +105,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && - needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'true' }} + needs.check-big-packages-and-shards.outputs.run_stackslib == 'true' && + needs.check-big-packages-and-shards.outputs.stackslib_with_shards == 'true' runs-on: ubuntu-latest @@ -123,7 +123,7 @@ jobs: uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: shard: ${{ matrix.shard }} - package: "stackslib" + package: 'stackslib' # Mutation testing - Execute on PR on stacks-node package (normal run, no shards) pr-differences-mutants-stacks-node-normal: @@ -132,8 +132,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && - needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'false' }} + needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && + needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'false' runs-on: ubuntu-latest @@ -144,7 +144,7 @@ jobs: RUST_BACKTRACE: full uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package: "stacks-node" + package: 'stacks-node' # Mutation testing - Execute on PR on stacks-node package (run with strategy matrix shards) pr-differences-mutants-stacks-node-shards: @@ -153,8 +153,8 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && - needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'true' }} + needs.check-big-packages-and-shards.outputs.run_stacks_node == 'true' && + needs.check-big-packages-and-shards.outputs.stacks_node_with_shards == 'true' runs-on: ubuntu-latest @@ -171,7 +171,7 @@ jobs: uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: shard: ${{ matrix.shard }} - package: "stacks-node" + package: 'stacks-node' # Mutation testing - Execute on PR on stacks-signer package (normal run, no shards) pr-differences-mutants-stacks-signer-normal: @@ -180,7 +180,7 @@ jobs: needs: check-big-packages-and-shards if: | - ${{ needs.check-big-packages-and-shards.outputs.run_stacks_signer == 'true' }} + needs.check-big-packages-and-shards.outputs.run_stacks_signer == 'true' runs-on: ubuntu-latest @@ -188,7 +188,7 @@ jobs: - name: Run Run mutants on diffs uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: - package: "stacks-signer" + package: 'stacks-signer' # Output the mutants and fail the workflow if there are missed/timeout/unviable mutants output-mutants: From 50c1549a2171da19f867dfc6bc203a356de82e34 Mon Sep 17 00:00:00 2001 From: ASuciuX <151519329+ASuciuX@users.noreply.github.com> Date: Tue, 27 Feb 2024 14:04:53 +0200 Subject: [PATCH 04/39] Update .github/workflows/pr-differences-mutants.yml Co-authored-by: Jeff Bencin --- .github/workflows/pr-differences-mutants.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-differences-mutants.yml b/.github/workflows/pr-differences-mutants.yml index 0e76c1c15a..fc4a725687 100644 --- a/.github/workflows/pr-differences-mutants.yml +++ b/.github/workflows/pr-differences-mutants.yml @@ -185,7 +185,7 @@ jobs: runs-on: ubuntu-latest steps: - - name: Run Run mutants on diffs + - name: Run mutants on diffs uses: stacks-network/actions/stacks-core/mutation-testing/pr-differences@main with: package: 'stacks-signer' From e7c6592b6bd7bd73f540159a067006196ee1086e Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Wed, 27 Dec 2023 15:50:34 +0100 Subject: [PATCH 05/39] feat: add clarunit with basic usage example --- contrib/core-contract-tests/Clarinet.toml | 3 + contrib/core-contract-tests/package-lock.json | 2480 ++++++++++++++--- contrib/core-contract-tests/package.json | 3 +- .../core-contract-tests/tests/bns_test.clar | 9 + .../tests/clarunit.test.ts | 2 + 5 files changed, 2122 insertions(+), 375 deletions(-) create mode 100644 contrib/core-contract-tests/tests/bns_test.clar create mode 100644 contrib/core-contract-tests/tests/clarunit.test.ts diff --git a/contrib/core-contract-tests/Clarinet.toml b/contrib/core-contract-tests/Clarinet.toml index 7bd70e4745..f3e59d3161 100644 --- a/contrib/core-contract-tests/Clarinet.toml +++ b/contrib/core-contract-tests/Clarinet.toml @@ -27,3 +27,6 @@ path = "../../stackslib/src/chainstate/stacks/boot/signers-voting.clar" depends_on = [] clarity = 2 epoch = 2.4 + +[contracts.bns_test] +path = "./tests/bns_test.clar" diff --git a/contrib/core-contract-tests/package-lock.json b/contrib/core-contract-tests/package-lock.json index e5c3e22e18..b29bb4716d 100644 --- a/contrib/core-contract-tests/package-lock.json +++ b/contrib/core-contract-tests/package-lock.json @@ -12,12 +12,28 @@ "@hirosystems/clarinet-sdk": "^1.1.0", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", + "clarunit": "github:MarvinJanssen/clarunit#a5c042a", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", "vitest-environment-clarinet": "^1.0.0" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", + "integrity": "sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -349,15 +365,15 @@ } }, "node_modules/@hirosystems/clarinet-sdk": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@hirosystems/clarinet-sdk/-/clarinet-sdk-1.1.0.tgz", - "integrity": "sha512-O4iP+eqc2jtbCJcndC22l12ODIi8GxwUcWhWaltvnPBn+PXqCLxDqNU78C6iDCfPp/Ro2fcJy9z27KNqnu+A9g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@hirosystems/clarinet-sdk/-/clarinet-sdk-1.2.0.tgz", + "integrity": "sha512-O0Gyh3pwwOVJTbLlxHG6vSB/KXr+U/nZzd2kpubQO4Qqxjn5/vo8l8J+/fwKOxhzM4QOa42M1sCaVZSB/PkTFg==", "dependencies": { - "@hirosystems/clarinet-sdk-wasm": "^1.1.0", + "@hirosystems/clarinet-sdk-wasm": "^1.2.0", "@stacks/transactions": "^6.9.0", "kolorist": "^1.8.0", "prompts": "^2.4.2", - "vitest": "^0.34.5", + "vitest": "^1.0.4", "yargs": "^17.7.2" }, "bin": { @@ -368,465 +384,1963 @@ } }, "node_modules/@hirosystems/clarinet-sdk-wasm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@hirosystems/clarinet-sdk-wasm/-/clarinet-sdk-wasm-1.1.0.tgz", - "integrity": "sha512-hGf2Ib6qYVnhV2+idW1GuOsh1Fom4fhp+QYjxHmfGQvx9ptSb037/4YVlep+jbO4hKXHHF2uQJgKMRPwVrtN2g==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@hirosystems/clarinet-sdk-wasm/-/clarinet-sdk-wasm-1.2.0.tgz", + "integrity": "sha512-TnJ243lEgIqHSIeMdEHi1hJceFBJ5mWfjfXv86GKaoyVOS6yX1vGL2a6ZuVO9FfWPNxsiSvaQV/FndVuansAVQ==" }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/android-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" - }, - "node_modules/@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" - }, - "node_modules/@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" + "node": ">=12" } }, - "node_modules/@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", - "dependencies": { - "@stacks/common": "^6.8.1", - "cross-fetch": "^3.1.5" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/android-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@stacks/transactions": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", - "integrity": "sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==", - "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.8.1", - "@stacks/network": "^6.8.1", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/android-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/bn.js": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.4.tgz", - "integrity": "sha512-ZtBd9L8hVtoBpPMSWfbwjC4dhQtJdlPS+e1A0Rydb7vg7bDcUwiRklPx24sMYtXcmAMST/k0Wze7JLbNU/5SkA==", - "dependencies": { - "@types/node": "*" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/chai": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", - "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==" - }, - "node_modules/@types/chai-subset": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", - "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", - "dependencies": { - "@types/chai": "*" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/darwin-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/node": { - "version": "18.18.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.8.tgz", - "integrity": "sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==", - "dependencies": { - "undici-types": "~5.26.4" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", - "dependencies": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", - "dependencies": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", - "dependencies": { - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", - "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", - "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-loong64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "bin": { - "acorn": "bin/acorn" - }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-s390x": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/linux-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/sunos-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/c32check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", - "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", - "dependencies": { - "@noble/hashes": "^1.1.2", - "base-x": "^4.0.0" - }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/win32-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/win32-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@esbuild/win32-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@vitest/expect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.0.tgz", + "integrity": "sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==", "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "chai": "^4.3.10" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@vitest/runner": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.1.0.tgz", + "integrity": "sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==", "dependencies": { - "get-func-name": "^2.0.2" + "@vitest/utils": "1.1.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" }, - "engines": { - "node": "*" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "node_modules/@hirosystems/clarinet-sdk/node_modules/@vitest/snapshot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.1.0.tgz", + "integrity": "sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" }, - "engines": { - "node": ">= 8.10.0" + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/@vitest/spy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.0.tgz", + "integrity": "sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==", + "dependencies": { + "tinyspy": "^2.2.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/chokidar-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", - "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/@vitest/utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==", "dependencies": { - "chokidar": "^3.5.2", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "yargs": "^13.3.0" + "diff-sequences": "^29.6.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/esbuild": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "hasInstallScript": true, "bin": { - "chokidar": "index.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">= 8.10.0" - } - }, - "node_modules/chokidar-cli/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, "engines": { - "node": ">=6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/chokidar-cli/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@hirosystems/clarinet-sdk/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", "dependencies": { - "color-convert": "^1.9.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/chokidar-cli/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { + "node_modules/@hirosystems/clarinet-sdk/node_modules/rollup": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/tinypool": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.1.tgz", + "integrity": "sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/vite": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", + "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/vite-node": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.1.0.tgz", + "integrity": "sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@hirosystems/clarinet-sdk/node_modules/vitest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.1.0.tgz", + "integrity": "sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==", + "dependencies": { + "@vitest/expect": "1.1.0", + "@vitest/runner": "1.1.0", + "@vitest/snapshot": "1.1.0", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "acorn-walk": "^8.3.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.1", + "vite": "^5.0.0", + "vite-node": "1.1.0", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "^1.0.0", + "@vitest/ui": "^1.0.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@noble/hashes": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", + "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", + "integrity": "sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz", + "integrity": "sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz", + "integrity": "sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz", + "integrity": "sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz", + "integrity": "sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz", + "integrity": "sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz", + "integrity": "sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz", + "integrity": "sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz", + "integrity": "sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz", + "integrity": "sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz", + "integrity": "sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz", + "integrity": "sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz", + "integrity": "sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/@stacks/common": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.10.0.tgz", + "integrity": "sha512-6x5Z7AKd9/kj3+DYE9xIDIkFLHihBH614i2wqrZIjN02WxVo063hWSjIlUxlx8P4gl6olVzlOy5LzhLJD9OP0A==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, + "node_modules/@stacks/network": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.10.0.tgz", + "integrity": "sha512-mbiZ8nlsyy77ndmBdaqhHXii22IFdK4ThRcOQs9j/O00DkAr04jCM4GV5Q+VLUnZ9OBoJq7yOV7Pf6jglh+0hw==", + "dependencies": { + "@stacks/common": "^6.10.0", + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@stacks/transactions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.11.0.tgz", + "integrity": "sha512-+zIDqn9j4H/+o1ER8C9rFpig1fyrQcj2hVGNIrp+YbpPyja+cxv3fPk6kI/gePzwggzxRgUkIWhBc+mZAXuXyQ==", + "dependencies": { + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@stacks/common": "^6.10.0", + "@stacks/network": "^6.10.0", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", + "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==" + }, + "node_modules/@types/chai-subset": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", + "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/node": { + "version": "18.18.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.8.tgz", + "integrity": "sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "dependencies": { + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "dependencies": { + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "dependencies": { + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "engines": { + "node": "*" + } + }, + "node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/c32check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", + "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", + "dependencies": { + "@noble/hashes": "^1.1.2", + "base-x": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", + "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "dependencies": { + "chokidar": "^3.5.2", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "yargs": "^13.3.0" + }, + "bin": { + "chokidar": "index.js" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/chokidar-cli/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar-cli/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dependencies": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", "wrap-ansi": "^5.1.0" } }, - "node_modules/chokidar-cli/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "node_modules/chokidar-cli/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/chokidar-cli/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar-cli/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/chokidar-cli/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/chokidar-cli/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/clarunit": { + "version": "0.0.1", + "resolved": "git+ssh://git@github.com/MarvinJanssen/clarunit.git#a5c042ab8428d989c8f7653e83073b3e8c88e076", + "license": "MIT", + "dependencies": { + "@hirosystems/clarinet-sdk": "^1.2.0", + "@stacks/transactions": "^6.11.0", + "chokidar-cli": "^3.0.0", + "path": "^0.12.7", + "typescript": "^5.2.2", + "vite": "^4.4.9", + "vitest": "^1.1.0", + "vitest-environment-clarinet": "^1.0.0" + }, + "bin": { + "clarunit": "src/cli.ts" + } + }, + "node_modules/clarunit/node_modules/@esbuild/android-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", + "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/android-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", + "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/android-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", + "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", + "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/darwin-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", + "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", + "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", + "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-arm": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", + "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", + "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", + "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-loong64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", + "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", + "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", + "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/chokidar-cli/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "node_modules/clarunit/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", + "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-s390x": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", + "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/linux-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", + "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", + "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", + "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/sunos-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", + "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/win32-arm64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", + "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/win32-ia32": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", + "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@esbuild/win32-x64": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", + "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/clarunit/node_modules/@vitest/expect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.0.tgz", + "integrity": "sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==", + "dependencies": { + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/@vitest/runner": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.1.0.tgz", + "integrity": "sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==", + "dependencies": { + "@vitest/utils": "1.1.0", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/@vitest/snapshot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.1.0.tgz", + "integrity": "sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==", + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/@vitest/spy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.0.tgz", + "integrity": "sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==", + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/@vitest/utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==", + "dependencies": { + "diff-sequences": "^29.6.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/esbuild": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", + "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.10", + "@esbuild/android-arm": "0.19.10", + "@esbuild/android-arm64": "0.19.10", + "@esbuild/android-x64": "0.19.10", + "@esbuild/darwin-arm64": "0.19.10", + "@esbuild/darwin-x64": "0.19.10", + "@esbuild/freebsd-arm64": "0.19.10", + "@esbuild/freebsd-x64": "0.19.10", + "@esbuild/linux-arm": "0.19.10", + "@esbuild/linux-arm64": "0.19.10", + "@esbuild/linux-ia32": "0.19.10", + "@esbuild/linux-loong64": "0.19.10", + "@esbuild/linux-mips64el": "0.19.10", + "@esbuild/linux-ppc64": "0.19.10", + "@esbuild/linux-riscv64": "0.19.10", + "@esbuild/linux-s390x": "0.19.10", + "@esbuild/linux-x64": "0.19.10", + "@esbuild/netbsd-x64": "0.19.10", + "@esbuild/openbsd-x64": "0.19.10", + "@esbuild/sunos-x64": "0.19.10", + "@esbuild/win32-arm64": "0.19.10", + "@esbuild/win32-ia32": "0.19.10", + "@esbuild/win32-x64": "0.19.10" + } + }, + "node_modules/clarunit/node_modules/local-pkg": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", + "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "dependencies": { + "mlly": "^1.4.2", + "pkg-types": "^1.0.3" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/clarunit/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clarunit/node_modules/rollup": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", + "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.1", + "@rollup/rollup-android-arm64": "4.9.1", + "@rollup/rollup-darwin-arm64": "4.9.1", + "@rollup/rollup-darwin-x64": "4.9.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", + "@rollup/rollup-linux-arm64-gnu": "4.9.1", + "@rollup/rollup-linux-arm64-musl": "4.9.1", + "@rollup/rollup-linux-riscv64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-gnu": "4.9.1", + "@rollup/rollup-linux-x64-musl": "4.9.1", + "@rollup/rollup-win32-arm64-msvc": "4.9.1", + "@rollup/rollup-win32-ia32-msvc": "4.9.1", + "@rollup/rollup-win32-x64-msvc": "4.9.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/clarunit/node_modules/tinypool": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.1.tgz", + "integrity": "sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/clarunit/node_modules/vite-node": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.1.0.tgz", + "integrity": "sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/clarunit/node_modules/vite-node/node_modules/vite": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", + "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/chokidar-cli/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "node_modules/clarunit/node_modules/vitest": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.1.0.tgz", + "integrity": "sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==", + "dependencies": { + "@vitest/expect": "1.1.0", + "@vitest/runner": "1.1.0", + "@vitest/snapshot": "1.1.0", + "@vitest/spy": "1.1.0", + "@vitest/utils": "1.1.0", + "acorn-walk": "^8.3.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^1.3.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.1", + "vite": "^5.0.0", + "vite-node": "1.1.0", + "why-is-node-running": "^2.2.2" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">=6" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "^1.0.0", + "@vitest/ui": "^1.0.0", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/chokidar-cli/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/clarunit/node_modules/vitest/node_modules/vite": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", + "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" }, "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/chokidar-cli/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/chokidar-cli/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, "node_modules/cliui": { @@ -863,6 +2377,19 @@ "node-fetch": "^2.6.12" } }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -955,6 +2482,28 @@ "node": ">=6" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1006,6 +2555,17 @@ "node": "*" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1017,6 +2577,19 @@ "node": ">= 6" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1063,6 +2636,22 @@ "node": ">=0.12.0" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -1138,6 +2727,22 @@ "node": ">=12" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mlly": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", @@ -1155,9 +2760,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -1198,6 +2803,45 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -1245,6 +2889,15 @@ "node": ">=6" } }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -1253,6 +2906,14 @@ "node": ">=4" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", @@ -1293,9 +2954,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "funding": [ { "type": "opencollective", @@ -1311,7 +2972,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -1332,6 +2993,14 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -1393,11 +3062,41 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -1417,9 +3116,9 @@ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==" }, "node_modules/std-env": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.4.3.tgz", - "integrity": "sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==" + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, "node_modules/string-width": { "version": "4.2.3", @@ -1445,6 +3144,17 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", @@ -1523,6 +3233,14 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dependencies": { + "inherits": "2.0.3" + } + }, "node_modules/vite": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", @@ -1698,6 +3416,20 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", diff --git a/contrib/core-contract-tests/package.json b/contrib/core-contract-tests/package.json index 2f11d87369..3b28c7796f 100644 --- a/contrib/core-contract-tests/package.json +++ b/contrib/core-contract-tests/package.json @@ -12,9 +12,10 @@ "@hirosystems/clarinet-sdk": "^1.1.0", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", + "clarunit": "github:MarvinJanssen/clarunit#a5c042a", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", "vitest-environment-clarinet": "^1.0.0" } -} +} \ No newline at end of file diff --git a/contrib/core-contract-tests/tests/bns_test.clar b/contrib/core-contract-tests/tests/bns_test.clar new file mode 100644 index 0000000000..326853eabd --- /dev/null +++ b/contrib/core-contract-tests/tests/bns_test.clar @@ -0,0 +1,9 @@ +(define-public (test-can-receive-name-none) + (begin + (asserts! + (is-eq (ok true) (contract-call? .bns can-receive-name tx-sender)) + (err "Should be able to receive a name") + ) + (ok true) + ) +) diff --git a/contrib/core-contract-tests/tests/clarunit.test.ts b/contrib/core-contract-tests/tests/clarunit.test.ts new file mode 100644 index 0000000000..6601ac3b33 --- /dev/null +++ b/contrib/core-contract-tests/tests/clarunit.test.ts @@ -0,0 +1,2 @@ +import { clarunit } from "clarunit"; +clarunit(simnet); From 0e0fb30d63f46dc3bffb9b1c54c5bc041bd58ffa Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 4 Jan 2024 14:55:27 -0500 Subject: [PATCH 06/39] initial commit - local copy clarinet.toml --- contrib/core-contract-tests/Clarinet.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/core-contract-tests/Clarinet.toml b/contrib/core-contract-tests/Clarinet.toml index f3e59d3161..aa06872b8a 100644 --- a/contrib/core-contract-tests/Clarinet.toml +++ b/contrib/core-contract-tests/Clarinet.toml @@ -28,5 +28,19 @@ depends_on = [] clarity = 2 epoch = 2.4 +[contracts.pox-4] +path = "../../stackslib/src/chainstate/stacks/boot/pox-4.clar" +clarity_version = 2 +epoch = 2.4 +depends_on = ["pox-mainnet"] + +[contracts.pox-mainnet] +path = "../../stackslib/src/chainstate/stacks/boot/pox-mainnet.clar" +clarity_version = 2 +epoch = 2.4 +depends_on = [] + [contracts.bns_test] path = "./tests/bns_test.clar" +clarity_version = 2 +epoch = 2.4 From 6804bf7acf456df808231867dc6688d782c5a27e Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 4 Jan 2024 14:58:25 -0500 Subject: [PATCH 07/39] pox-4 changes - local copy --- .../src/chainstate/stacks/boot/pox-4.clar | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index d54f3b8d5f..66b4a7e3bf 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -75,6 +75,7 @@ ;; SIP18 message prefix (define-constant SIP018_MSG_PREFIX 0x534950303138) +(define-constant STACKING_THRESHOLD_100 (if is-in-mainnet u5000 u2000)) ;; Data vars that store a copy of the burnchain configuration. ;; Implemented as data-vars, so that different configurations can be @@ -237,6 +238,19 @@ bool ;; Whether the authorization can be used or not ) +;; MOCK +;; Allow to set stx-account details for any user +;; These values are used for PoX only +(define-map mock-stx-account-details principal {unlocked: uint, locked: uint, unlock-height: uint}) + +(define-read-only (get-stx-account (user principal)) + (default-to (stx-account user) (map-get? mock-stx-account-details user))) + +(define-public (mock-set-stx-account (user principal) (details {unlocked: uint, locked: uint, unlock-height: uint})) + (if (map-set mock-stx-account-details user details) + (ok true) (err u9999))) ;; define manually the error type +;; MOCK END + ;; What's the reward cycle number of the burnchain block height? ;; Will runtime-abort if height is less than the first burnchain block (this is intentional) (define-read-only (burn-height-to-reward-cycle (height uint)) @@ -613,8 +627,8 @@ (err ERR_INVALID_START_BURN_HEIGHT)) ;; must be called directly by the tx-sender or by an allowed contract-caller - (asserts! (check-caller-allowed) - (err ERR_STACKING_PERMISSION_DENIED)) + ;; (asserts! (check-caller-allowed) + ;; (err ERR_STACKING_PERMISSION_DENIED)) ;; tx-sender principal must not be stacking (asserts! (is-none (get-stacker-info tx-sender)) From 52b049bb20fd85d848467a1bcf3006712fd07649 Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 4 Jan 2024 15:29:13 -0500 Subject: [PATCH 08/39] updated existing tests --- .../tests/bns/name_register.test.ts | 8 +- .../core-contract-tests/tests/bns_test.clar | 81 +++++++++++++++++++ .../src/chainstate/stacks/boot/pox-4.clar | 31 +++---- 3 files changed, 101 insertions(+), 19 deletions(-) diff --git a/contrib/core-contract-tests/tests/bns/name_register.test.ts b/contrib/core-contract-tests/tests/bns/name_register.test.ts index 0647b0a9cc..bc6aa7efe7 100644 --- a/contrib/core-contract-tests/tests/bns/name_register.test.ts +++ b/contrib/core-contract-tests/tests/bns/name_register.test.ts @@ -366,8 +366,8 @@ describe("name revealing workflow", () => { Cl.tuple({ owner: Cl.standardPrincipal(bob), ["zonefile-hash"]: Cl.bufferFromUtf8(cases[0].zonefile), - ["lease-ending-at"]: Cl.some(Cl.uint(16)), - ["lease-started-at"]: Cl.uint(6), + ["lease-ending-at"]: Cl.some(Cl.uint(17)), + ["lease-started-at"]: Cl.uint(7), }) ); }); @@ -589,8 +589,8 @@ describe("register a name again before and after expiration", () => { Cl.tuple({ owner: Cl.standardPrincipal(charlie), ["zonefile-hash"]: Cl.bufferFromAscii("CHARLIE"), - ["lease-ending-at"]: Cl.some(Cl.uint(5029)), - ["lease-started-at"]: Cl.uint(5019), + ["lease-ending-at"]: Cl.some(Cl.uint(5030)), + ["lease-started-at"]: Cl.uint(5020), }) ); }); diff --git a/contrib/core-contract-tests/tests/bns_test.clar b/contrib/core-contract-tests/tests/bns_test.clar index 326853eabd..bfc7e16324 100644 --- a/contrib/core-contract-tests/tests/bns_test.clar +++ b/contrib/core-contract-tests/tests/bns_test.clar @@ -1,3 +1,8 @@ +(define-constant mock-pox-reward-wallet-1 { version: 0x06, hashbytes: 0x0011223344556699001122334455669900112233445566990011223344556699 }) +(define-constant mock-pox-reward-wallet-invalid { version: 0x06, hashbytes: 0x00112233445566990011223344556699001122334455669900112233445566 }) +(define-constant mock-pox-hashbytes-invalid 0x00112233445566990011223344556699001122334455669900112233445566) +(define-constant ERR_STACKING_INVALID_POX_ADDRESS 13) + (define-public (test-can-receive-name-none) (begin (asserts! @@ -7,3 +12,79 @@ (ok true) ) ) + +;; (define-public (test-mock-set-stx-account) +;; (begin +;; (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) +;; (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-get-mocked-stx-account) +;; (begin +;; (asserts! (is-eq u0 (get unlock-height (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-burn-height-to-reward-cycle) +;; (begin +;; (asserts! (is-eq u1 (contract-call? .pox-4 burn-height-to-reward-cycle u2099)) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-reward-cycle-to-burn-height) +;; (begin +;; (asserts! (is-eq u0 (contract-call? .pox-4 reward-cycle-to-burn-height u0)) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-get-stacker-info-none) +;; (begin +;; (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-invalid-pox-addr-version) +;; (let +;; ((actual (contract-call? .pox-4 check-pox-addr-version 0x07))) +;; (asserts! (not actual) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-invalid-pox-addr-hashbytes-length) +;; (let +;; ((actual (contract-call? .pox-4 check-pox-addr-hashbytes 0x00 mock-pox-hashbytes-invalid))) +;; (asserts! (not actual) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-invalid-lock-height-too-low) +;; (let +;; ((actual (contract-call? .pox-4 check-pox-lock-period u0))) +;; (asserts! (not actual) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-invalid-lock-height-too-high) +;; (let +;; ((actual (contract-call? .pox-4 check-pox-lock-period u13))) +;; (asserts! (not actual) (err u111)) +;; (ok true) +;; ) +;; ) + +;; (define-public (test-get-total-ustx-stacked) +;; (begin +;; ;; @continue +;; (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) +;; (ok true) +;; ) +;; ) \ No newline at end of file diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index 66b4a7e3bf..c135abadc3 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -86,6 +86,20 @@ (define-data-var configured bool false) (define-data-var first-pox-4-reward-cycle uint u0) +;; PoX mainnet constants +;; Min/max number of reward cycles uSTX can be locked for +(define-constant MIN_POX_REWARD_CYCLES u1) +(define-constant MAX_POX_REWARD_CYCLES u12) + +;; Default length of the PoX registration window, in burnchain blocks. +(define-constant PREPARE_CYCLE_LENGTH (if is-in-mainnet u100 u50)) + +;; Default length of the PoX reward cycle, in burnchain blocks. +(define-constant REWARD_CYCLE_LENGTH (if is-in-mainnet u2100 u1050)) + +;; Stacking thresholds +(define-constant STACKING_THRESHOLD_25 (if is-in-mainnet u20000 u8000)) + ;; This function can only be called once, when it boots up (define-public (set-burnchain-parameters (first-burn-height uint) (prepare-cycle-length uint) @@ -238,19 +252,6 @@ bool ;; Whether the authorization can be used or not ) -;; MOCK -;; Allow to set stx-account details for any user -;; These values are used for PoX only -(define-map mock-stx-account-details principal {unlocked: uint, locked: uint, unlock-height: uint}) - -(define-read-only (get-stx-account (user principal)) - (default-to (stx-account user) (map-get? mock-stx-account-details user))) - -(define-public (mock-set-stx-account (user principal) (details {unlocked: uint, locked: uint, unlock-height: uint})) - (if (map-set mock-stx-account-details user details) - (ok true) (err u9999))) ;; define manually the error type -;; MOCK END - ;; What's the reward cycle number of the burnchain block height? ;; Will runtime-abort if height is less than the first burnchain block (this is intentional) (define-read-only (burn-height-to-reward-cycle (height uint)) @@ -627,8 +628,8 @@ (err ERR_INVALID_START_BURN_HEIGHT)) ;; must be called directly by the tx-sender or by an allowed contract-caller - ;; (asserts! (check-caller-allowed) - ;; (err ERR_STACKING_PERMISSION_DENIED)) + (asserts! (check-caller-allowed) + (err ERR_STACKING_PERMISSION_DENIED)) ;; tx-sender principal must not be stacking (asserts! (is-none (get-stacker-info tx-sender)) From b3b067e989a9a9bad4075d915090a90d9905d9b0 Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 4 Jan 2024 15:39:06 -0500 Subject: [PATCH 09/39] new pox_4_tests file --- contrib/core-contract-tests/Clarinet.toml | 5 ++ .../core-contract-tests/tests/bns_test.clar | 83 +------------------ .../tests/pox_4_tests.clar | 80 ++++++++++++++++++ .../src/chainstate/stacks/boot/pox-4.clar | 13 +++ 4 files changed, 99 insertions(+), 82 deletions(-) create mode 100644 contrib/core-contract-tests/tests/pox_4_tests.clar diff --git a/contrib/core-contract-tests/Clarinet.toml b/contrib/core-contract-tests/Clarinet.toml index aa06872b8a..6925fa360b 100644 --- a/contrib/core-contract-tests/Clarinet.toml +++ b/contrib/core-contract-tests/Clarinet.toml @@ -44,3 +44,8 @@ depends_on = [] path = "./tests/bns_test.clar" clarity_version = 2 epoch = 2.4 + +[contracts.pox_4_tests] +path = "./tests/pox_4_tests.clar" +clarity_version = 2 +epoch = 2.4 diff --git a/contrib/core-contract-tests/tests/bns_test.clar b/contrib/core-contract-tests/tests/bns_test.clar index bfc7e16324..8f0d125891 100644 --- a/contrib/core-contract-tests/tests/bns_test.clar +++ b/contrib/core-contract-tests/tests/bns_test.clar @@ -1,8 +1,3 @@ -(define-constant mock-pox-reward-wallet-1 { version: 0x06, hashbytes: 0x0011223344556699001122334455669900112233445566990011223344556699 }) -(define-constant mock-pox-reward-wallet-invalid { version: 0x06, hashbytes: 0x00112233445566990011223344556699001122334455669900112233445566 }) -(define-constant mock-pox-hashbytes-invalid 0x00112233445566990011223344556699001122334455669900112233445566) -(define-constant ERR_STACKING_INVALID_POX_ADDRESS 13) - (define-public (test-can-receive-name-none) (begin (asserts! @@ -11,80 +6,4 @@ ) (ok true) ) -) - -;; (define-public (test-mock-set-stx-account) -;; (begin -;; (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) -;; (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-get-mocked-stx-account) -;; (begin -;; (asserts! (is-eq u0 (get unlock-height (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-burn-height-to-reward-cycle) -;; (begin -;; (asserts! (is-eq u1 (contract-call? .pox-4 burn-height-to-reward-cycle u2099)) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-reward-cycle-to-burn-height) -;; (begin -;; (asserts! (is-eq u0 (contract-call? .pox-4 reward-cycle-to-burn-height u0)) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-get-stacker-info-none) -;; (begin -;; (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-invalid-pox-addr-version) -;; (let -;; ((actual (contract-call? .pox-4 check-pox-addr-version 0x07))) -;; (asserts! (not actual) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-invalid-pox-addr-hashbytes-length) -;; (let -;; ((actual (contract-call? .pox-4 check-pox-addr-hashbytes 0x00 mock-pox-hashbytes-invalid))) -;; (asserts! (not actual) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-invalid-lock-height-too-low) -;; (let -;; ((actual (contract-call? .pox-4 check-pox-lock-period u0))) -;; (asserts! (not actual) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-invalid-lock-height-too-high) -;; (let -;; ((actual (contract-call? .pox-4 check-pox-lock-period u13))) -;; (asserts! (not actual) (err u111)) -;; (ok true) -;; ) -;; ) - -;; (define-public (test-get-total-ustx-stacked) -;; (begin -;; ;; @continue -;; (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) -;; (ok true) -;; ) -;; ) \ No newline at end of file +) \ No newline at end of file diff --git a/contrib/core-contract-tests/tests/pox_4_tests.clar b/contrib/core-contract-tests/tests/pox_4_tests.clar new file mode 100644 index 0000000000..035e29951a --- /dev/null +++ b/contrib/core-contract-tests/tests/pox_4_tests.clar @@ -0,0 +1,80 @@ +(define-constant mock-pox-reward-wallet-1 { version: 0x06, hashbytes: 0x0011223344556699001122334455669900112233445566990011223344556699 }) +(define-constant mock-pox-reward-wallet-invalid { version: 0x06, hashbytes: 0x00112233445566990011223344556699001122334455669900112233445566 }) +(define-constant mock-pox-hashbytes-invalid 0x00112233445566990011223344556699001122334455669900112233445566) +(define-constant ERR_STACKING_INVALID_POX_ADDRESS 13) + +(define-public (test-mock-set-stx-account) + (begin + (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) + (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) + (ok true) + ) +) + +(define-public (test-get-mocked-stx-account) + (begin + (asserts! (is-eq u0 (get unlock-height (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) + (ok true) + ) +) + +(define-public (test-burn-height-to-reward-cycle) + (begin + (asserts! (is-eq u1 (contract-call? .pox-4 burn-height-to-reward-cycle u2099)) (err u111)) + (ok true) + ) +) + +(define-public (test-reward-cycle-to-burn-height) + (begin + (asserts! (is-eq u0 (contract-call? .pox-4 reward-cycle-to-burn-height u0)) (err u111)) + (ok true) + ) +) + +(define-public (test-get-stacker-info-none) + (begin + (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err u111)) + (ok true) + ) +) + +(define-public (test-invalid-pox-addr-version) + (let + ((actual (contract-call? .pox-4 check-pox-addr-version 0x07))) + (asserts! (not actual) (err u111)) + (ok true) + ) +) + +(define-public (test-invalid-pox-addr-hashbytes-length) + (let + ((actual (contract-call? .pox-4 check-pox-addr-hashbytes 0x00 mock-pox-hashbytes-invalid))) + (asserts! (not actual) (err u111)) + (ok true) + ) +) + +(define-public (test-invalid-lock-height-too-low) + (let + ((actual (contract-call? .pox-4 check-pox-lock-period u0))) + (asserts! (not actual) (err u111)) + (ok true) + ) +) + +(define-public (test-invalid-lock-height-too-high) + (let + ((actual (contract-call? .pox-4 check-pox-lock-period u13))) + (asserts! (not actual) (err u111)) + (ok true) + ) +) + +(define-public (test-get-total-ustx-stacked) + (begin + ;; @continue + (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) + (ok true) + ) +) \ No newline at end of file diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index c135abadc3..4fc5ea74a5 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -100,6 +100,19 @@ ;; Stacking thresholds (define-constant STACKING_THRESHOLD_25 (if is-in-mainnet u20000 u8000)) +;; MOCK +;; Allow to set stx-account details for any user +;; These values are used for PoX only +(define-map mock-stx-account-details principal {unlocked: uint, locked: uint, unlock-height: uint}) + +(define-read-only (get-stx-account (user principal)) + (default-to (stx-account user) (map-get? mock-stx-account-details user))) + +(define-public (mock-set-stx-account (user principal) (details {unlocked: uint, locked: uint, unlock-height: uint})) + (if (map-set mock-stx-account-details user details) + (ok true) (err u9999))) ;; define manually the error type +;; MOCK END + ;; This function can only be called once, when it boots up (define-public (set-burnchain-parameters (first-burn-height uint) (prepare-cycle-length uint) From 960f0a00dae67efb11743a23ef3391ae79c027de Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 4 Jan 2024 20:13:41 -0500 Subject: [PATCH 10/39] clarity formatting --- .../tests/pox_4_tests.clar | 41 +++++-------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox_4_tests.clar b/contrib/core-contract-tests/tests/pox_4_tests.clar index 035e29951a..bac11afafc 100644 --- a/contrib/core-contract-tests/tests/pox_4_tests.clar +++ b/contrib/core-contract-tests/tests/pox_4_tests.clar @@ -1,80 +1,59 @@ (define-constant mock-pox-reward-wallet-1 { version: 0x06, hashbytes: 0x0011223344556699001122334455669900112233445566990011223344556699 }) (define-constant mock-pox-reward-wallet-invalid { version: 0x06, hashbytes: 0x00112233445566990011223344556699001122334455669900112233445566 }) (define-constant mock-pox-hashbytes-invalid 0x00112233445566990011223344556699001122334455669900112233445566) -(define-constant ERR_STACKING_INVALID_POX_ADDRESS 13) (define-public (test-mock-set-stx-account) (begin (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-get-mocked-stx-account) (begin (asserts! (is-eq u0 (get unlock-height (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-burn-height-to-reward-cycle) (begin (asserts! (is-eq u1 (contract-call? .pox-4 burn-height-to-reward-cycle u2099)) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-reward-cycle-to-burn-height) (begin (asserts! (is-eq u0 (contract-call? .pox-4 reward-cycle-to-burn-height u0)) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-get-stacker-info-none) (begin (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-invalid-pox-addr-version) (let ((actual (contract-call? .pox-4 check-pox-addr-version 0x07))) (asserts! (not actual) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-invalid-pox-addr-hashbytes-length) (let ((actual (contract-call? .pox-4 check-pox-addr-hashbytes 0x00 mock-pox-hashbytes-invalid))) (asserts! (not actual) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-invalid-lock-height-too-low) (let ((actual (contract-call? .pox-4 check-pox-lock-period u0))) (asserts! (not actual) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-invalid-lock-height-too-high) (let ((actual (contract-call? .pox-4 check-pox-lock-period u13))) (asserts! (not actual) (err u111)) - (ok true) - ) -) + (ok true))) (define-public (test-get-total-ustx-stacked) (begin ;; @continue (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) - (ok true) - ) -) \ No newline at end of file + (ok true))) \ No newline at end of file From 21b7c72e0675e08c3f7ebcf96f8a694b5109e93a Mon Sep 17 00:00:00 2001 From: jesus Date: Wed, 21 Feb 2024 20:48:23 -0500 Subject: [PATCH 11/39] local update --- contrib/core-contract-tests/tests/pox_4_tests.clar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/core-contract-tests/tests/pox_4_tests.clar b/contrib/core-contract-tests/tests/pox_4_tests.clar index bac11afafc..d4ecea8721 100644 --- a/contrib/core-contract-tests/tests/pox_4_tests.clar +++ b/contrib/core-contract-tests/tests/pox_4_tests.clar @@ -5,7 +5,7 @@ (define-public (test-mock-set-stx-account) (begin (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) - (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) + (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u112)) (ok true))) (define-public (test-get-mocked-stx-account) From 790ba79b84203a54c57875575f7d1072d1699c48 Mon Sep 17 00:00:00 2001 From: jesus Date: Wed, 21 Feb 2024 21:14:54 -0500 Subject: [PATCH 12/39] rebase & temp comments --- contrib/core-contract-tests/Clarinet.toml | 6 - .../tests/bns/name_register.test.ts | 172 +++++++++--------- .../src/chainstate/stacks/boot/pox-4.clar | 13 -- 3 files changed, 87 insertions(+), 104 deletions(-) diff --git a/contrib/core-contract-tests/Clarinet.toml b/contrib/core-contract-tests/Clarinet.toml index 6925fa360b..20d1f9b3ac 100644 --- a/contrib/core-contract-tests/Clarinet.toml +++ b/contrib/core-contract-tests/Clarinet.toml @@ -10,12 +10,6 @@ path = "../../stackslib/src/chainstate/stacks/boot/bns.clar" depends_on = [] epoch = 2.4 -[contracts.pox-4] -path = "../../stackslib/src/chainstate/stacks/boot/pox-4.clar" -depends_on = [] -clarity = 2 -epoch = 2.4 - [contracts.signers] path = "../../stackslib/src/chainstate/stacks/boot/signers.clar" depends_on = [] diff --git a/contrib/core-contract-tests/tests/bns/name_register.test.ts b/contrib/core-contract-tests/tests/bns/name_register.test.ts index bc6aa7efe7..afb7263199 100644 --- a/contrib/core-contract-tests/tests/bns/name_register.test.ts +++ b/contrib/core-contract-tests/tests/bns/name_register.test.ts @@ -323,54 +323,55 @@ describe("name revealing workflow", () => { expect(result).toBeErr(Cl.int(2022)); }); - it("should successfully register", () => { - const name = "bob"; - const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${cases[0].salt}`); - const sha256 = createHash("sha256").update(merged).digest(); - const ripemd160 = createHash("ripemd160").update(sha256).digest(); - simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], bob); - - const register = simnet.callPublicFn( - "bns", - "name-register", - [ - Cl.bufferFromUtf8(cases[0].namespace), - Cl.bufferFromUtf8(name), - Cl.bufferFromUtf8(cases[0].salt), - Cl.bufferFromUtf8(cases[0].zonefile), - ], - bob - ); - expect(register.result).toBeOk(Cl.bool(true)); - - const resolvePrincipal = simnet.callReadOnlyFn( - "bns", - "resolve-principal", - [Cl.standardPrincipal(bob)], - alice - ); - expect(resolvePrincipal.result).toBeOk( - Cl.tuple({ - name: Cl.bufferFromUtf8("bob"), - namespace: Cl.bufferFromUtf8("blockstack"), - }) - ); - - const nameResolve = simnet.callReadOnlyFn( - "bns", - "name-resolve", - [Cl.bufferFromUtf8(cases[0].namespace), Cl.bufferFromUtf8(name)], - alice - ); - expect(nameResolve.result).toBeOk( - Cl.tuple({ - owner: Cl.standardPrincipal(bob), - ["zonefile-hash"]: Cl.bufferFromUtf8(cases[0].zonefile), - ["lease-ending-at"]: Cl.some(Cl.uint(17)), - ["lease-started-at"]: Cl.uint(7), - }) - ); - }); + // temp disabled, focusing on importing clarunit correctly + // it("should successfully register", () => { + // const name = "bob"; + // const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${cases[0].salt}`); + // const sha256 = createHash("sha256").update(merged).digest(); + // const ripemd160 = createHash("ripemd160").update(sha256).digest(); + // simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], bob); + + // const register = simnet.callPublicFn( + // "bns", + // "name-register", + // [ + // Cl.bufferFromUtf8(cases[0].namespace), + // Cl.bufferFromUtf8(name), + // Cl.bufferFromUtf8(cases[0].salt), + // Cl.bufferFromUtf8(cases[0].zonefile), + // ], + // bob + // ); + // expect(register.result).toBeOk(Cl.bool(true)); + + // const resolvePrincipal = simnet.callReadOnlyFn( + // "bns", + // "resolve-principal", + // [Cl.standardPrincipal(bob)], + // alice + // ); + // expect(resolvePrincipal.result).toBeOk( + // Cl.tuple({ + // name: Cl.bufferFromUtf8("bob"), + // namespace: Cl.bufferFromUtf8("blockstack"), + // }) + // ); + + // const nameResolve = simnet.callReadOnlyFn( + // "bns", + // "name-resolve", + // [Cl.bufferFromUtf8(cases[0].namespace), Cl.bufferFromUtf8(name)], + // alice + // ); + // expect(nameResolve.result).toBeOk( + // Cl.tuple({ + // owner: Cl.standardPrincipal(bob), + // ["zonefile-hash"]: Cl.bufferFromUtf8(cases[0].zonefile), + // ["lease-ending-at"]: Cl.some(Cl.uint(17)), + // ["lease-started-at"]: Cl.uint(7), + // }) + // ); + // }); it("should fail registering twice", () => { const name = "bob"; @@ -557,41 +558,42 @@ describe("register a name again before and after expiration", () => { expect(register.result).toBeOk(Cl.bool(true)); }); - it("should allow someone else to register after expiration", () => { - simnet.mineEmptyBlocks(cases[0].renewalRule + 5001); - - const name = "bob"; - const salt = "2222"; - const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${salt}`); - const sha256 = createHash("sha256").update(merged).digest(); - const ripemd160 = createHash("ripemd160").update(sha256).digest(); - simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], charlie); - const register = simnet.callPublicFn( - "bns", - "name-register", - [ - Cl.bufferFromAscii(cases[0].namespace), - Cl.bufferFromAscii(name), - Cl.bufferFromAscii(salt), - Cl.bufferFromAscii("CHARLIE"), - ], - charlie - ); - expect(register.result).toBeOk(Cl.bool(true)); - - const resolve = simnet.callReadOnlyFn( - "bns", - "name-resolve", - [Cl.bufferFromAscii(cases[0].namespace), Cl.bufferFromAscii(name)], - alice - ); - expect(resolve.result).toBeOk( - Cl.tuple({ - owner: Cl.standardPrincipal(charlie), - ["zonefile-hash"]: Cl.bufferFromAscii("CHARLIE"), - ["lease-ending-at"]: Cl.some(Cl.uint(5030)), - ["lease-started-at"]: Cl.uint(5020), - }) - ); - }); + // temp disabled, focusing on importing clarunit correctly + // it("should allow someone else to register after expiration", () => { + // simnet.mineEmptyBlocks(cases[0].renewalRule + 5001); + + // const name = "bob"; + // const salt = "2222"; + // const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${salt}`); + // const sha256 = createHash("sha256").update(merged).digest(); + // const ripemd160 = createHash("ripemd160").update(sha256).digest(); + // simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], charlie); + // const register = simnet.callPublicFn( + // "bns", + // "name-register", + // [ + // Cl.bufferFromAscii(cases[0].namespace), + // Cl.bufferFromAscii(name), + // Cl.bufferFromAscii(salt), + // Cl.bufferFromAscii("CHARLIE"), + // ], + // charlie + // ); + // expect(register.result).toBeOk(Cl.bool(true)); + + // const resolve = simnet.callReadOnlyFn( + // "bns", + // "name-resolve", + // [Cl.bufferFromAscii(cases[0].namespace), Cl.bufferFromAscii(name)], + // alice + // ); + // expect(resolve.result).toBeOk( + // Cl.tuple({ + // owner: Cl.standardPrincipal(charlie), + // ["zonefile-hash"]: Cl.bufferFromAscii("CHARLIE"), + // ["lease-ending-at"]: Cl.some(Cl.uint(5030)), + // ["lease-started-at"]: Cl.uint(5020), + // }) + // ); + // }); }); diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index 4fc5ea74a5..53378fb9db 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -86,19 +86,6 @@ (define-data-var configured bool false) (define-data-var first-pox-4-reward-cycle uint u0) -;; PoX mainnet constants -;; Min/max number of reward cycles uSTX can be locked for -(define-constant MIN_POX_REWARD_CYCLES u1) -(define-constant MAX_POX_REWARD_CYCLES u12) - -;; Default length of the PoX registration window, in burnchain blocks. -(define-constant PREPARE_CYCLE_LENGTH (if is-in-mainnet u100 u50)) - -;; Default length of the PoX reward cycle, in burnchain blocks. -(define-constant REWARD_CYCLE_LENGTH (if is-in-mainnet u2100 u1050)) - -;; Stacking thresholds -(define-constant STACKING_THRESHOLD_25 (if is-in-mainnet u20000 u8000)) ;; MOCK ;; Allow to set stx-account details for any user From 8933c5bc381783b472c26cf55bf095a8d0c0d9ba Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Sun, 25 Feb 2024 22:56:06 +0100 Subject: [PATCH 13/39] Add clarunit and some basic tests --- contrib/core-contract-tests/.gitignore | 3 +- contrib/core-contract-tests/Clarinet.toml | 4 +- contrib/core-contract-tests/package-lock.json | 2798 ++++++++++++----- contrib/core-contract-tests/package.json | 5 +- .../tests/clarunit.test.ts | 2 +- .../core-contract-tests/tests/pox_4_test.clar | 123 + .../tests/pox_4_tests.clar | 59 - .../src/chainstate/stacks/boot/pox-4.clar | 15 - 8 files changed, 2075 insertions(+), 934 deletions(-) create mode 100644 contrib/core-contract-tests/tests/pox_4_test.clar delete mode 100644 contrib/core-contract-tests/tests/pox_4_tests.clar diff --git a/contrib/core-contract-tests/.gitignore b/contrib/core-contract-tests/.gitignore index 39b70c2f7f..393158bd1c 100644 --- a/contrib/core-contract-tests/.gitignore +++ b/contrib/core-contract-tests/.gitignore @@ -4,4 +4,5 @@ npm-debug.log* coverage *.info costs-reports.json -node_modules \ No newline at end of file +node_modules +history.txt diff --git a/contrib/core-contract-tests/Clarinet.toml b/contrib/core-contract-tests/Clarinet.toml index 20d1f9b3ac..605ce3989f 100644 --- a/contrib/core-contract-tests/Clarinet.toml +++ b/contrib/core-contract-tests/Clarinet.toml @@ -39,7 +39,7 @@ path = "./tests/bns_test.clar" clarity_version = 2 epoch = 2.4 -[contracts.pox_4_tests] -path = "./tests/pox_4_tests.clar" +[contracts.pox_4_test] +path = "./tests/pox_4_test.clar" clarity_version = 2 epoch = 2.4 diff --git a/contrib/core-contract-tests/package-lock.json b/contrib/core-contract-tests/package-lock.json index b29bb4716d..c7bb20afc1 100644 --- a/contrib/core-contract-tests/package-lock.json +++ b/contrib/core-contract-tests/package-lock.json @@ -10,15 +10,23 @@ "license": "ISC", "dependencies": { "@hirosystems/clarinet-sdk": "^1.1.0", + "@stacks/clarunit": "0.0.1", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", - "clarunit": "github:MarvinJanssen/clarunit#a5c042a", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", "vitest-environment-clarinet": "^1.0.0" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.19.10", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz", @@ -364,6 +372,58 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@hirosystems/clarinet-sdk": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@hirosystems/clarinet-sdk/-/clarinet-sdk-1.2.0.tgz", @@ -1023,6 +1083,36 @@ } } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -1061,6 +1151,38 @@ } ] }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz", @@ -1222,787 +1344,545 @@ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, - "node_modules/@stacks/common": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.10.0.tgz", - "integrity": "sha512-6x5Z7AKd9/kj3+DYE9xIDIkFLHihBH614i2wqrZIjN02WxVo063hWSjIlUxlx8P4gl6olVzlOy5LzhLJD9OP0A==", + "node_modules/@stacks/clarunit": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@stacks/clarunit/-/clarunit-0.0.1.tgz", + "integrity": "sha512-AKf14ycQJjyUWL6yfvXU+yMqvkCfUy2NarHbAmXx6tXfv/fyXueGkjTZTh8+0r20+XoxEvhJTnBfoAA74VLNtg==", "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" + "@hirosystems/clarinet-sdk": "^1.2.0", + "@stacks/transactions": "^6.11.0", + "chokidar-cli": "^3.0.0", + "eslint": "^8.56.0", + "path": "^0.12.7", + "typescript": "^5.2.2", + "vite": "^4.4.9", + "vitest": "^1.1.0", + "vitest-environment-clarinet": "^1.0.0" + }, + "bin": { + "clarunit": "src/cli.ts" } }, - "node_modules/@stacks/network": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.10.0.tgz", - "integrity": "sha512-mbiZ8nlsyy77ndmBdaqhHXii22IFdK4ThRcOQs9j/O00DkAr04jCM4GV5Q+VLUnZ9OBoJq7yOV7Pf6jglh+0hw==", - "dependencies": { - "@stacks/common": "^6.10.0", - "cross-fetch": "^3.1.5" + "node_modules/@stacks/clarunit/node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@stacks/transactions": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.11.0.tgz", - "integrity": "sha512-+zIDqn9j4H/+o1ER8C9rFpig1fyrQcj2hVGNIrp+YbpPyja+cxv3fPk6kI/gePzwggzxRgUkIWhBc+mZAXuXyQ==", - "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.10.0", - "@stacks/network": "^6.10.0", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" + "node_modules/@stacks/clarunit/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", - "dependencies": { - "@types/node": "*" + "node_modules/@stacks/clarunit/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/chai": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", - "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==" - }, - "node_modules/@types/chai-subset": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", - "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", - "dependencies": { - "@types/chai": "*" + "node_modules/@stacks/clarunit/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@types/node": { - "version": "18.18.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.8.tgz", - "integrity": "sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==", - "dependencies": { - "undici-types": "~5.26.4" + "node_modules/@stacks/clarunit/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", - "dependencies": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@stacks/clarunit/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", - "dependencies": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@stacks/clarunit/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", - "dependencies": { - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@stacks/clarunit/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", - "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", - "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "bin": { - "acorn": "bin/acorn" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/c32check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", - "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", - "dependencies": { - "@noble/hashes": "^1.1.2", - "base-x": "^4.0.0" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@stacks/clarunit/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dependencies": { - "get-func-name": "^2.0.2" - }, + "node_modules/@stacks/clarunit/node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", + "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", + "cpu": [ + "arm" ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/chokidar-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", - "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", - "dependencies": { - "chokidar": "^3.5.2", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "yargs": "^13.3.0" - }, - "bin": { - "chokidar": "index.js" - }, - "engines": { - "node": ">= 8.10.0" - } + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", + "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] }, - "node_modules/chokidar-cli/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar-cli/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/chokidar-cli/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/chokidar-cli/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar-cli/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/chokidar-cli/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/chokidar-cli/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/chokidar-cli/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/clarunit": { - "version": "0.0.1", - "resolved": "git+ssh://git@github.com/MarvinJanssen/clarunit.git#a5c042ab8428d989c8f7653e83073b3e8c88e076", - "license": "MIT", - "dependencies": { - "@hirosystems/clarinet-sdk": "^1.2.0", - "@stacks/transactions": "^6.11.0", - "chokidar-cli": "^3.0.0", - "path": "^0.12.7", - "typescript": "^5.2.2", - "vite": "^4.4.9", - "vitest": "^1.1.0", - "vitest-environment-clarinet": "^1.0.0" - }, - "bin": { - "clarunit": "src/cli.ts" - } - }, - "node_modules/clarunit/node_modules/@esbuild/android-arm": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.10.tgz", - "integrity": "sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", + "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", "cpu": [ - "arm" + "arm64" ], "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "darwin" + ] }, - "node_modules/clarunit/node_modules/@esbuild/android-arm64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz", - "integrity": "sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", + "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", "cpu": [ - "arm64" + "x64" ], "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "darwin" + ] }, - "node_modules/clarunit/node_modules/@esbuild/android-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.10.tgz", - "integrity": "sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", + "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", "cpu": [ - "x64" + "arm" ], "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/clarunit/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz", - "integrity": "sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", + "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", "cpu": [ "arm64" ], "optional": true, "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/clarunit/node_modules/@esbuild/darwin-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz", - "integrity": "sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", + "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", "cpu": [ - "x64" + "arm64" ], "optional": true, "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/clarunit/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz", - "integrity": "sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", + "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", "cpu": [ - "arm64" + "riscv64" ], "optional": true, "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/clarunit/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz", - "integrity": "sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", + "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", "cpu": [ "x64" ], "optional": true, "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/clarunit/node_modules/@esbuild/linux-arm": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz", - "integrity": "sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", + "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", "cpu": [ - "arm" + "x64" ], "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/clarunit/node_modules/@esbuild/linux-arm64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz", - "integrity": "sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", + "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", "cpu": [ "arm64" ], "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/clarunit/node_modules/@esbuild/linux-ia32": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz", - "integrity": "sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", + "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", "cpu": [ "ia32" ], "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/clarunit/node_modules/@esbuild/linux-loong64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz", - "integrity": "sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA==", + "node_modules/@stacks/clarunit/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", + "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", "cpu": [ - "loong64" + "x64" ], "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "win32" + ] + }, + "node_modules/@stacks/clarunit/node_modules/@vitest/expect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", + "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "dependencies": { + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz", - "integrity": "sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz", - "integrity": "sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz", - "integrity": "sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/linux-s390x": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz", - "integrity": "sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/linux-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz", - "integrity": "sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz", - "integrity": "sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz", - "integrity": "sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/sunos-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz", - "integrity": "sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/win32-arm64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz", - "integrity": "sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/win32-ia32": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz", - "integrity": "sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@esbuild/win32-x64": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz", - "integrity": "sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/clarunit/node_modules/@vitest/expect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.0.tgz", - "integrity": "sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==", - "dependencies": { - "@vitest/spy": "1.1.0", - "@vitest/utils": "1.1.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/clarunit/node_modules/@vitest/runner": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.1.0.tgz", - "integrity": "sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==", + "node_modules/@stacks/clarunit/node_modules/@vitest/runner": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", + "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", "dependencies": { - "@vitest/utils": "1.1.0", + "@vitest/utils": "1.3.1", "p-limit": "^5.0.0", "pathe": "^1.1.1" }, @@ -2010,10 +1890,10 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/@vitest/snapshot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.1.0.tgz", - "integrity": "sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==", + "node_modules/@stacks/clarunit/node_modules/@vitest/snapshot": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", + "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", "dependencies": { "magic-string": "^0.30.5", "pathe": "^1.1.1", @@ -2023,10 +1903,10 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/@vitest/spy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.0.tgz", - "integrity": "sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==", + "node_modules/@stacks/clarunit/node_modules/@vitest/spy": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", + "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", "dependencies": { "tinyspy": "^2.2.0" }, @@ -2034,12 +1914,13 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/@vitest/utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.0.tgz", - "integrity": "sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==", + "node_modules/@stacks/clarunit/node_modules/@vitest/utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", + "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", "dependencies": { "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", "loupe": "^2.3.7", "pretty-format": "^29.7.0" }, @@ -2047,10 +1928,10 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/esbuild": { - "version": "0.19.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.10.tgz", - "integrity": "sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA==", + "node_modules/@stacks/clarunit/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -2059,32 +1940,32 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.10", - "@esbuild/android-arm": "0.19.10", - "@esbuild/android-arm64": "0.19.10", - "@esbuild/android-x64": "0.19.10", - "@esbuild/darwin-arm64": "0.19.10", - "@esbuild/darwin-x64": "0.19.10", - "@esbuild/freebsd-arm64": "0.19.10", - "@esbuild/freebsd-x64": "0.19.10", - "@esbuild/linux-arm": "0.19.10", - "@esbuild/linux-arm64": "0.19.10", - "@esbuild/linux-ia32": "0.19.10", - "@esbuild/linux-loong64": "0.19.10", - "@esbuild/linux-mips64el": "0.19.10", - "@esbuild/linux-ppc64": "0.19.10", - "@esbuild/linux-riscv64": "0.19.10", - "@esbuild/linux-s390x": "0.19.10", - "@esbuild/linux-x64": "0.19.10", - "@esbuild/netbsd-x64": "0.19.10", - "@esbuild/openbsd-x64": "0.19.10", - "@esbuild/sunos-x64": "0.19.10", - "@esbuild/win32-arm64": "0.19.10", - "@esbuild/win32-ia32": "0.19.10", - "@esbuild/win32-x64": "0.19.10" - } - }, - "node_modules/clarunit/node_modules/local-pkg": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/@stacks/clarunit/node_modules/local-pkg": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", @@ -2099,7 +1980,7 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/clarunit/node_modules/p-limit": { + "node_modules/@stacks/clarunit/node_modules/p-limit": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", @@ -2113,10 +1994,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clarunit/node_modules/rollup": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.1.tgz", - "integrity": "sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==", + "node_modules/@stacks/clarunit/node_modules/rollup": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", + "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, @@ -2125,34 +2009,45 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.1", - "@rollup/rollup-android-arm64": "4.9.1", - "@rollup/rollup-darwin-arm64": "4.9.1", - "@rollup/rollup-darwin-x64": "4.9.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.1", - "@rollup/rollup-linux-arm64-gnu": "4.9.1", - "@rollup/rollup-linux-arm64-musl": "4.9.1", - "@rollup/rollup-linux-riscv64-gnu": "4.9.1", - "@rollup/rollup-linux-x64-gnu": "4.9.1", - "@rollup/rollup-linux-x64-musl": "4.9.1", - "@rollup/rollup-win32-arm64-msvc": "4.9.1", - "@rollup/rollup-win32-ia32-msvc": "4.9.1", - "@rollup/rollup-win32-x64-msvc": "4.9.1", + "@rollup/rollup-android-arm-eabi": "4.12.0", + "@rollup/rollup-android-arm64": "4.12.0", + "@rollup/rollup-darwin-arm64": "4.12.0", + "@rollup/rollup-darwin-x64": "4.12.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", + "@rollup/rollup-linux-arm64-gnu": "4.12.0", + "@rollup/rollup-linux-arm64-musl": "4.12.0", + "@rollup/rollup-linux-riscv64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-gnu": "4.12.0", + "@rollup/rollup-linux-x64-musl": "4.12.0", + "@rollup/rollup-win32-arm64-msvc": "4.12.0", + "@rollup/rollup-win32-ia32-msvc": "4.12.0", + "@rollup/rollup-win32-x64-msvc": "4.12.0", "fsevents": "~2.3.2" } }, - "node_modules/clarunit/node_modules/tinypool": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.1.tgz", - "integrity": "sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==", + "node_modules/@stacks/clarunit/node_modules/strip-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", + "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", + "dependencies": { + "js-tokens": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@stacks/clarunit/node_modules/tinypool": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", + "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", "engines": { "node": ">=14.0.0" } }, - "node_modules/clarunit/node_modules/vite-node": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.1.0.tgz", - "integrity": "sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==", + "node_modules/@stacks/clarunit/node_modules/vite-node": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", + "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", @@ -2170,13 +2065,13 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/clarunit/node_modules/vite-node/node_modules/vite": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", - "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", + "node_modules/@stacks/clarunit/node_modules/vite-node/node_modules/vite": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", + "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", "dependencies": { "esbuild": "^0.19.3", - "postcss": "^8.4.32", + "postcss": "^8.4.35", "rollup": "^4.2.0" }, "bin": { @@ -2224,18 +2119,17 @@ } } }, - "node_modules/clarunit/node_modules/vitest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.1.0.tgz", - "integrity": "sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==", + "node_modules/@stacks/clarunit/node_modules/vitest": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", + "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", "dependencies": { - "@vitest/expect": "1.1.0", - "@vitest/runner": "1.1.0", - "@vitest/snapshot": "1.1.0", - "@vitest/spy": "1.1.0", - "@vitest/utils": "1.1.0", - "acorn-walk": "^8.3.0", - "cac": "^6.7.14", + "@vitest/expect": "1.3.1", + "@vitest/runner": "1.3.1", + "@vitest/snapshot": "1.3.1", + "@vitest/spy": "1.3.1", + "@vitest/utils": "1.3.1", + "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", "execa": "^8.0.1", @@ -2244,11 +2138,11 @@ "pathe": "^1.1.1", "picocolors": "^1.0.0", "std-env": "^3.5.0", - "strip-literal": "^1.3.0", + "strip-literal": "^2.0.0", "tinybench": "^2.5.1", - "tinypool": "^0.8.1", + "tinypool": "^0.8.2", "vite": "^5.0.0", - "vite-node": "1.1.0", + "vite-node": "1.3.1", "why-is-node-running": "^2.2.2" }, "bin": { @@ -2263,8 +2157,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "^1.0.0", - "@vitest/ui": "^1.0.0", + "@vitest/browser": "1.3.1", + "@vitest/ui": "1.3.1", "happy-dom": "*", "jsdom": "*" }, @@ -2289,58 +2183,577 @@ } } }, - "node_modules/clarunit/node_modules/vitest/node_modules/vite": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", - "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", + "node_modules/@stacks/clarunit/node_modules/vitest/node_modules/vite": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", + "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/@stacks/common": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.10.0.tgz", + "integrity": "sha512-6x5Z7AKd9/kj3+DYE9xIDIkFLHihBH614i2wqrZIjN02WxVo063hWSjIlUxlx8P4gl6olVzlOy5LzhLJD9OP0A==", + "dependencies": { + "@types/bn.js": "^5.1.0", + "@types/node": "^18.0.4" + } + }, + "node_modules/@stacks/network": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.10.0.tgz", + "integrity": "sha512-mbiZ8nlsyy77ndmBdaqhHXii22IFdK4ThRcOQs9j/O00DkAr04jCM4GV5Q+VLUnZ9OBoJq7yOV7Pf6jglh+0hw==", + "dependencies": { + "@stacks/common": "^6.10.0", + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@stacks/transactions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.11.0.tgz", + "integrity": "sha512-+zIDqn9j4H/+o1ER8C9rFpig1fyrQcj2hVGNIrp+YbpPyja+cxv3fPk6kI/gePzwggzxRgUkIWhBc+mZAXuXyQ==", + "dependencies": { + "@noble/hashes": "1.1.5", + "@noble/secp256k1": "1.7.1", + "@stacks/common": "^6.10.0", + "@stacks/network": "^6.10.0", + "c32check": "^2.0.0", + "lodash.clonedeep": "^4.5.0" + } + }, + "node_modules/@types/bn.js": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.9.tgz", + "integrity": "sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==" + }, + "node_modules/@types/chai-subset": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.4.tgz", + "integrity": "sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==", + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/node": { + "version": "18.18.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.8.tgz", + "integrity": "sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "dependencies": { + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "dependencies": { + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "dependencies": { + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/c32check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", + "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", + "dependencies": { + "@noble/hashes": "^1.1.2", + "base-x": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", + "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "dependencies": { + "chokidar": "^3.5.2", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "yargs": "^13.3.0" + }, + "bin": { + "chokidar": "index.js" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/chokidar-cli/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar-cli/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/chokidar-cli/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/chokidar-cli/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar-cli/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar-cli/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/chokidar-cli/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.32", - "rollup": "^4.2.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/chokidar-cli/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, "node_modules/cliui": { @@ -2369,6 +2782,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, "node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", @@ -2411,75 +2829,331 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dependencies": { - "type-detect": "^4.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4.0" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/execa": { @@ -2504,6 +3178,40 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2526,6 +3234,29 @@ "node": ">=6" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2566,6 +3297,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -2577,6 +3327,33 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -2585,6 +3362,46 @@ "node": ">=16.17.0" } }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -2636,6 +3453,14 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -2652,11 +3477,50 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/js-tokens": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -2670,6 +3534,18 @@ "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/local-pkg": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", @@ -2703,6 +3579,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -2743,6 +3624,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mlly": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", @@ -2776,6 +3668,11 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -2828,6 +3725,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -2842,6 +3747,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", @@ -2889,6 +3810,17 @@ "node": ">=6" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path": { "version": "0.12.7", "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", @@ -2906,6 +3838,14 @@ "node": ">=4" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -2954,9 +3894,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", @@ -2980,6 +3920,14 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -3013,6 +3961,33 @@ "node": ">= 6" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -3042,6 +4017,37 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -3057,6 +4063,28 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -3155,6 +4183,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", @@ -3166,6 +4205,22 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, "node_modules/tinybench": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", @@ -3203,6 +4258,17 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -3211,6 +4277,17 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -3233,6 +4310,14 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", @@ -3496,6 +4581,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/contrib/core-contract-tests/package.json b/contrib/core-contract-tests/package.json index 3b28c7796f..644fa30e75 100644 --- a/contrib/core-contract-tests/package.json +++ b/contrib/core-contract-tests/package.json @@ -4,7 +4,8 @@ "description": "Run unit tests on this project.", "private": true, "scripts": { - "test": "vitest run -- --coverage" + "test": "vitest run -- --coverage", + "genhtml": "genhtml lcov.info --branch-coverage -o coverage/" }, "author": "", "license": "ISC", @@ -12,7 +13,7 @@ "@hirosystems/clarinet-sdk": "^1.1.0", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", - "clarunit": "github:MarvinJanssen/clarunit#a5c042a", + "@stacks/clarunit": "0.0.1", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", diff --git a/contrib/core-contract-tests/tests/clarunit.test.ts b/contrib/core-contract-tests/tests/clarunit.test.ts index 6601ac3b33..5e4fa0da43 100644 --- a/contrib/core-contract-tests/tests/clarunit.test.ts +++ b/contrib/core-contract-tests/tests/clarunit.test.ts @@ -1,2 +1,2 @@ -import { clarunit } from "clarunit"; +import { clarunit } from "@stacks/clarunit"; clarunit(simnet); diff --git a/contrib/core-contract-tests/tests/pox_4_test.clar b/contrib/core-contract-tests/tests/pox_4_test.clar new file mode 100644 index 0000000000..dedd0c5d97 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox_4_test.clar @@ -0,0 +1,123 @@ +(define-public (test-burn-height-to-reward-cycle) + (begin + (asserts! (is-eq u2 (contract-call? .pox-4 burn-height-to-reward-cycle u2100)) (err "Burn height 2100 should have been reward cycle 2")) + (ok true))) + +(define-public (test-reward-cycle-to-burn-height) + (begin + (asserts! (is-eq u10500 (contract-call? .pox-4 reward-cycle-to-burn-height u10)) (err "Cycle 10 height should have been at burn height 10500")) + (ok true))) + +(define-public (test-get-stacker-info-none) + (begin + (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err "By default, tx-sender should not have stacker info")) + (ok true))) + + +(define-private (check-pox-addr-version-iter (input (buff 1))) + (contract-call? .pox-4 check-pox-addr-version input) +) + +(define-public (test-check-pox-addr-version) + (begin + (asserts! (is-eq (map check-pox-addr-version-iter byte-list) + (list + true true true true true true true false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false + )) + (err "Only the first 6 versions should be valid") + ) + (ok true) + ) +) + +(define-private (check-pox-addr-hashbytes-iter (test-length uint) (version (buff 1))) + (contract-call? .pox-4 check-pox-addr-hashbytes version (unwrap-panic (as-max-len? (unwrap-panic (slice? byte-list u0 test-length)) u32))) +) + +(define-public (test-invalid-pox-addr-hashbytes-length) + (let ( + (test-lengths (list u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27 u28 u29 u30 u31 u32)) + (length-20-valid (list + false false false false false false false false false false false false false false false false + false false false false true false false false false false false false false false false false false + )) + (length-32-valid (list + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false true + )) + (length-all-invalid (list + false false false false false false false false false false false false false false false false + false false false false false false false false false false false false false false false false false + )) + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x00 (len test-lengths))) length-20-valid) + (err "Only length 20 should be valid for version 0x00") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x01 (len test-lengths))) length-20-valid) + (err "Only length 20 should be valid for version 0x01") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x02 (len test-lengths))) length-20-valid) + (err "Only length 20 should be valid for version 0x02") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x03 (len test-lengths))) length-20-valid) + (err "Only length 20 should be valid for version 0x03") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x04 (len test-lengths))) length-20-valid) + (err "Only length 20 should be valid for version 0x04") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x05 (len test-lengths))) length-32-valid) + (err "Only length 20 should be valid for version 0x05") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x06 (len test-lengths))) length-32-valid) + (err "Only length 20 should be valid for version 0x06") + ) + (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x07 (len test-lengths))) length-all-invalid) + (err "No length should be valid for version 0x07") + ) + (ok true) + ) +) + +(define-public (test-invalid-lock-height-too-low) + (let + ((actual (contract-call? .pox-4 check-pox-lock-period u0))) + (asserts! (not actual) (err u111)) + (ok true))) + +(define-public (test-invalid-lock-height-too-high) + (let + ((actual (contract-call? .pox-4 check-pox-lock-period u13))) + (asserts! (not actual) (err u111)) + (ok true))) + +(define-public (test-get-total-ustx-stacked) + (begin + ;; @continue + (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) + (ok true))) + + +(define-private (repeat-iter (a (buff 1)) (repeat {i: (buff 1), o: (buff 33)})) + {i: (get i repeat), o: (unwrap-panic (as-max-len? (concat (get i repeat) (get o repeat)) u33))} +) + +(define-read-only (buff-repeat (repeat (buff 1)) (times uint)) + (get o (fold repeat-iter (unwrap-panic (slice? byte-list u0 times)) {i: repeat, o: 0x})) +) + +(define-constant byte-list 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff) \ No newline at end of file diff --git a/contrib/core-contract-tests/tests/pox_4_tests.clar b/contrib/core-contract-tests/tests/pox_4_tests.clar deleted file mode 100644 index d4ecea8721..0000000000 --- a/contrib/core-contract-tests/tests/pox_4_tests.clar +++ /dev/null @@ -1,59 +0,0 @@ -(define-constant mock-pox-reward-wallet-1 { version: 0x06, hashbytes: 0x0011223344556699001122334455669900112233445566990011223344556699 }) -(define-constant mock-pox-reward-wallet-invalid { version: 0x06, hashbytes: 0x00112233445566990011223344556699001122334455669900112233445566 }) -(define-constant mock-pox-hashbytes-invalid 0x00112233445566990011223344556699001122334455669900112233445566) - -(define-public (test-mock-set-stx-account) - (begin - (unwrap! (contract-call? .pox-4 mock-set-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 {locked: u1, unlock-height: u2100, unlocked: u0}) (err u111)) - (asserts! (is-eq u1 (get locked (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u112)) - (ok true))) - -(define-public (test-get-mocked-stx-account) - (begin - (asserts! (is-eq u0 (get unlock-height (contract-call? .pox-4 get-stx-account 'ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5))) (err u111)) - (ok true))) - -(define-public (test-burn-height-to-reward-cycle) - (begin - (asserts! (is-eq u1 (contract-call? .pox-4 burn-height-to-reward-cycle u2099)) (err u111)) - (ok true))) - -(define-public (test-reward-cycle-to-burn-height) - (begin - (asserts! (is-eq u0 (contract-call? .pox-4 reward-cycle-to-burn-height u0)) (err u111)) - (ok true))) - -(define-public (test-get-stacker-info-none) - (begin - (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err u111)) - (ok true))) - -(define-public (test-invalid-pox-addr-version) - (let - ((actual (contract-call? .pox-4 check-pox-addr-version 0x07))) - (asserts! (not actual) (err u111)) - (ok true))) - -(define-public (test-invalid-pox-addr-hashbytes-length) - (let - ((actual (contract-call? .pox-4 check-pox-addr-hashbytes 0x00 mock-pox-hashbytes-invalid))) - (asserts! (not actual) (err u111)) - (ok true))) - -(define-public (test-invalid-lock-height-too-low) - (let - ((actual (contract-call? .pox-4 check-pox-lock-period u0))) - (asserts! (not actual) (err u111)) - (ok true))) - -(define-public (test-invalid-lock-height-too-high) - (let - ((actual (contract-call? .pox-4 check-pox-lock-period u13))) - (asserts! (not actual) (err u111)) - (ok true))) - -(define-public (test-get-total-ustx-stacked) - (begin - ;; @continue - (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) - (ok true))) \ No newline at end of file diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index 53378fb9db..d54f3b8d5f 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -75,7 +75,6 @@ ;; SIP18 message prefix (define-constant SIP018_MSG_PREFIX 0x534950303138) -(define-constant STACKING_THRESHOLD_100 (if is-in-mainnet u5000 u2000)) ;; Data vars that store a copy of the burnchain configuration. ;; Implemented as data-vars, so that different configurations can be @@ -86,20 +85,6 @@ (define-data-var configured bool false) (define-data-var first-pox-4-reward-cycle uint u0) - -;; MOCK -;; Allow to set stx-account details for any user -;; These values are used for PoX only -(define-map mock-stx-account-details principal {unlocked: uint, locked: uint, unlock-height: uint}) - -(define-read-only (get-stx-account (user principal)) - (default-to (stx-account user) (map-get? mock-stx-account-details user))) - -(define-public (mock-set-stx-account (user principal) (details {unlocked: uint, locked: uint, unlock-height: uint})) - (if (map-set mock-stx-account-details user details) - (ok true) (err u9999))) ;; define manually the error type -;; MOCK END - ;; This function can only be called once, when it boots up (define-public (set-burnchain-parameters (first-burn-height uint) (prepare-cycle-length uint) From 3c0e7798b25b0f7edd2d72ab51190e1d3e6b80de Mon Sep 17 00:00:00 2001 From: wileyj <2847772+wileyj@users.noreply.github.com> Date: Tue, 27 Feb 2024 11:29:41 -0800 Subject: [PATCH 14/39] Update ci trigger for merge queue --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb010862f9..552196e4ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -148,6 +148,7 @@ jobs: ) || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || + github.event_name == 'merge_group' || ( contains(' refs/heads/master From ae05a62b3e3e4044be16bcc4b5255c0a35448329 Mon Sep 17 00:00:00 2001 From: Nikos Baxevanis Date: Wed, 21 Feb 2024 14:26:57 +0100 Subject: [PATCH 15/39] Add property-based tests for signers-voting contract functions - reward-cycle-to-burn-height - burn-height-to-reward-cycle - is-in-prepare-phase This effort, initially part of https://github.com/stacks-network/stacks-core/pull/4286, is now in a separate commit and PR as it's autonomous with regards to PoX-4 property and fuzz testing. Additional property-based tests for the remaining functions of the signers-voting contract are warranted and will be addressed in separate commits/PRs. --- contrib/core-contract-tests/package-lock.json | 37 +++++ contrib/core-contract-tests/package.json | 1 + .../tests/pox-4/signers-voting.prop.test.ts | 131 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts diff --git a/contrib/core-contract-tests/package-lock.json b/contrib/core-contract-tests/package-lock.json index e5c3e22e18..d074caa541 100644 --- a/contrib/core-contract-tests/package-lock.json +++ b/contrib/core-contract-tests/package-lock.json @@ -12,6 +12,7 @@ "@hirosystems/clarinet-sdk": "^1.1.0", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", + "fast-check": "^3.15.1", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", @@ -955,6 +956,27 @@ "node": ">=6" } }, + "node_modules/fast-check": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.15.1.tgz", + "integrity": "sha512-GutOXZ+SCxGaFWfHe0Pbeq8PrkpGtPxA9/hdkI3s9YzqeMlrq5RdJ+QfYZ/S93jMX+tAyqgW0z5c9ppD+vkGUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "dependencies": { + "pure-rand": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1344,6 +1366,21 @@ "node": ">= 6" } }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", diff --git a/contrib/core-contract-tests/package.json b/contrib/core-contract-tests/package.json index 2f11d87369..078afb67df 100644 --- a/contrib/core-contract-tests/package.json +++ b/contrib/core-contract-tests/package.json @@ -12,6 +12,7 @@ "@hirosystems/clarinet-sdk": "^1.1.0", "@stacks/transactions": "^6.9.0", "chokidar-cli": "^3.0.0", + "fast-check": "^3.15.1", "typescript": "^5.2.2", "vite": "^4.4.9", "vitest": "^0.34.4", diff --git a/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts new file mode 100644 index 0000000000..b2f32efb30 --- /dev/null +++ b/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts @@ -0,0 +1,131 @@ +import fc from "fast-check"; +import { expect, it } from "vitest"; +import { Cl } from "@stacks/transactions"; + +it("should return correct reward-cycle-to-burn-height", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account: string, reward_cycle: number) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account, + ); + const first_burnchain_block_height = + // @ts-ignore + pox_4_info.value.data[ + "first-burnchain-block-height"]; + const reward_cycle_length = + // @ts-ignore + pox_4_info.value.data[ + "reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + "signers-voting", + "reward-cycle-to-burn-height", + [Cl.uint(reward_cycle)], + account, + ); + + // Assert + const expected = (reward_cycle * Number(reward_cycle_length.value)) + + Number(first_burnchain_block_height.value); + expect(actual).toBeUint(expected); + }, + ), + { numRuns: 250 }, + ); +}); + +it("should return correct burn-height-to-reward-cycle", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account: string, height: number) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account, + ); + const first_burnchain_block_height = + // @ts-ignore + pox_4_info.value.data[ + "first-burnchain-block-height"]; + const reward_cycle_length = + // @ts-ignore + pox_4_info.value.data[ + "reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + "signers-voting", + "burn-height-to-reward-cycle", + [Cl.uint(height)], + account, + ); + + // Assert + const expected = Math.floor( + (height - Number(first_burnchain_block_height.value)) / + Number(reward_cycle_length.value), + ); + expect(actual).toBeUint(expected); + }, + ), + { numRuns: 250 }, + ); +}); + +it("should return correct is-in-prepare-phase", () => { + fc.assert( + fc.property( + fc.constantFrom(...simnet.getAccounts().values()), + fc.nat(), + (account: string, height: number) => { + // Arrange + const { result: pox_4_info } = simnet.callReadOnlyFn( + "pox-4", + "get-pox-info", + [], + account, + ); + const first_burnchain_block_height = + // @ts-ignore + pox_4_info.value.data[ + "first-burnchain-block-height"]; + const prepare_cycle_length = + // @ts-ignore + pox_4_info.value.data[ + "prepare-cycle-length"]; + const reward_cycle_length = + // @ts-ignore + pox_4_info.value.data[ + "reward-cycle-length"]; + + // Act + const { result: actual } = simnet.callReadOnlyFn( + "signers-voting", + "is-in-prepare-phase", + [Cl.uint(height)], + account, + ); + + // Assert + const expected = ((height - Number(first_burnchain_block_height.value) + + Number(prepare_cycle_length.value)) % + Number(reward_cycle_length.value)) < + Number(prepare_cycle_length.value); + expect(actual).toBeBool(expected); + }, + ), + { numRuns: 250 }, + ); +}); From 6e6090eb80f5613bacceb809f0858169c129c7af Mon Sep 17 00:00:00 2001 From: Nikos Baxevanis Date: Wed, 28 Feb 2024 13:25:34 +0100 Subject: [PATCH 16/39] Bump @stacks/transactions for `isClarityType` - Bump @stacks/transactions from ^6.9.0 to ^6.12.0 for `isClarityType`. - Use `assert` and `isClarityType` for stricter TypeScript type checks. - Replace `// @ts-ignore` with precise assertions, improving tests. Thanks to Hugo Caillard for his crucial help and guidance. --- contrib/core-contract-tests/package-lock.json | 32 ++++++------- contrib/core-contract-tests/package.json | 2 +- .../tests/pox-4/signers-voting.prop.test.ts | 45 +++++++++---------- 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/contrib/core-contract-tests/package-lock.json b/contrib/core-contract-tests/package-lock.json index d074caa541..1fcb7e7f72 100644 --- a/contrib/core-contract-tests/package-lock.json +++ b/contrib/core-contract-tests/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@hirosystems/clarinet-sdk": "^1.1.0", - "@stacks/transactions": "^6.9.0", + "@stacks/transactions": "^6.12.0", "chokidar-cli": "^3.0.0", "fast-check": "^3.15.1", "typescript": "^5.2.2", @@ -417,40 +417,40 @@ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@stacks/common": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", - "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.10.0.tgz", + "integrity": "sha512-6x5Z7AKd9/kj3+DYE9xIDIkFLHihBH614i2wqrZIjN02WxVo063hWSjIlUxlx8P4gl6olVzlOy5LzhLJD9OP0A==", "dependencies": { "@types/bn.js": "^5.1.0", "@types/node": "^18.0.4" } }, "node_modules/@stacks/network": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", - "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.11.3.tgz", + "integrity": "sha512-c4ClCU/QUwuu8NbHtDKPJNa0M5YxauLN3vYaR0+S4awbhVIKFQSxirm9Q9ckV1WBh7FtD6u2S0x+tDQGAODjNg==", "dependencies": { - "@stacks/common": "^6.8.1", + "@stacks/common": "^6.10.0", "cross-fetch": "^3.1.5" } }, "node_modules/@stacks/transactions": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", - "integrity": "sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.12.0.tgz", + "integrity": "sha512-gRP3SfTaAIoTdjMvOiLrMZb/senqB8JQlT5Y4C3/CiHhiprYwTx7TbOCSa7WsNOU99H4aNfHvatmymuggXQVkA==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.8.1", - "@stacks/network": "^6.8.1", + "@stacks/common": "^6.10.0", + "@stacks/network": "^6.11.3", "c32check": "^2.0.0", "lodash.clonedeep": "^4.5.0" } }, "node_modules/@types/bn.js": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.4.tgz", - "integrity": "sha512-ZtBd9L8hVtoBpPMSWfbwjC4dhQtJdlPS+e1A0Rydb7vg7bDcUwiRklPx24sMYtXcmAMST/k0Wze7JLbNU/5SkA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", "dependencies": { "@types/node": "*" } diff --git a/contrib/core-contract-tests/package.json b/contrib/core-contract-tests/package.json index 078afb67df..561c7ab2c6 100644 --- a/contrib/core-contract-tests/package.json +++ b/contrib/core-contract-tests/package.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@hirosystems/clarinet-sdk": "^1.1.0", - "@stacks/transactions": "^6.9.0", + "@stacks/transactions": "^6.12.0", "chokidar-cli": "^3.0.0", "fast-check": "^3.15.1", "typescript": "^5.2.2", diff --git a/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts b/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts index b2f32efb30..0dc8ea2171 100644 --- a/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts +++ b/contrib/core-contract-tests/tests/pox-4/signers-voting.prop.test.ts @@ -1,6 +1,6 @@ import fc from "fast-check"; -import { expect, it } from "vitest"; -import { Cl } from "@stacks/transactions"; +import { assert, expect, it } from "vitest"; +import { Cl, ClarityType, isClarityType } from "@stacks/transactions"; it("should return correct reward-cycle-to-burn-height", () => { fc.assert( @@ -15,14 +15,12 @@ it("should return correct reward-cycle-to-burn-height", () => { [], account, ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); const first_burnchain_block_height = - // @ts-ignore - pox_4_info.value.data[ - "first-burnchain-block-height"]; + pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = - // @ts-ignore - pox_4_info.value.data[ - "reward-cycle-length"]; + pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( @@ -33,6 +31,8 @@ it("should return correct reward-cycle-to-burn-height", () => { ); // Assert + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); + assert(isClarityType(first_burnchain_block_height, ClarityType.UInt)); const expected = (reward_cycle * Number(reward_cycle_length.value)) + Number(first_burnchain_block_height.value); expect(actual).toBeUint(expected); @@ -55,14 +55,12 @@ it("should return correct burn-height-to-reward-cycle", () => { [], account, ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); const first_burnchain_block_height = - // @ts-ignore - pox_4_info.value.data[ - "first-burnchain-block-height"]; + pox_4_info.value.data["first-burnchain-block-height"]; const reward_cycle_length = - // @ts-ignore - pox_4_info.value.data[ - "reward-cycle-length"]; + pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( @@ -73,6 +71,8 @@ it("should return correct burn-height-to-reward-cycle", () => { ); // Assert + assert(isClarityType(first_burnchain_block_height, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); const expected = Math.floor( (height - Number(first_burnchain_block_height.value)) / Number(reward_cycle_length.value), @@ -97,18 +97,14 @@ it("should return correct is-in-prepare-phase", () => { [], account, ); + assert(isClarityType(pox_4_info, ClarityType.ResponseOk)); + assert(isClarityType(pox_4_info.value, ClarityType.Tuple)); const first_burnchain_block_height = - // @ts-ignore - pox_4_info.value.data[ - "first-burnchain-block-height"]; + pox_4_info.value.data["first-burnchain-block-height"]; const prepare_cycle_length = - // @ts-ignore - pox_4_info.value.data[ - "prepare-cycle-length"]; + pox_4_info.value.data["prepare-cycle-length"]; const reward_cycle_length = - // @ts-ignore - pox_4_info.value.data[ - "reward-cycle-length"]; + pox_4_info.value.data["reward-cycle-length"]; // Act const { result: actual } = simnet.callReadOnlyFn( @@ -119,6 +115,9 @@ it("should return correct is-in-prepare-phase", () => { ); // Assert + assert(isClarityType(first_burnchain_block_height, ClarityType.UInt)); + assert(isClarityType(prepare_cycle_length, ClarityType.UInt)); + assert(isClarityType(reward_cycle_length, ClarityType.UInt)); const expected = ((height - Number(first_burnchain_block_height.value) + Number(prepare_cycle_length.value)) % Number(reward_cycle_length.value)) < From 3c8d656b44890a92fb767e73ada3818dabc6db43 Mon Sep 17 00:00:00 2001 From: Jeff Bencin Date: Fri, 16 Feb 2024 21:46:07 -0500 Subject: [PATCH 17/39] chore: Remove imports already included by `std::prelude` --- clarity/src/libclarity.rs | 1 - clarity/src/vm/analysis/type_checker/v2_05/mod.rs | 1 - clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs | 2 -- .../src/vm/analysis/type_checker/v2_05/natives/sequences.rs | 2 -- clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs | 2 -- clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs | 2 -- clarity/src/vm/analysis/type_checker/v2_1/mod.rs | 1 - clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs | 2 -- .../src/vm/analysis/type_checker/v2_1/natives/sequences.rs | 2 -- clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs | 2 -- clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs | 1 - clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs | 2 -- clarity/src/vm/ast/definition_sorter/mod.rs | 2 -- clarity/src/vm/ast/parser/v1.rs | 1 - clarity/src/vm/ast/parser/v2/mod.rs | 1 - clarity/src/vm/ast/sugar_expander/mod.rs | 2 -- clarity/src/vm/callables.rs | 2 -- clarity/src/vm/contexts.rs | 1 - clarity/src/vm/contracts.rs | 2 -- clarity/src/vm/costs/mod.rs | 1 - clarity/src/vm/database/clarity_db.rs | 2 -- clarity/src/vm/database/clarity_store.rs | 1 - clarity/src/vm/database/key_value_wrapper.rs | 2 -- clarity/src/vm/database/structures.rs | 1 - clarity/src/vm/docs/contracts.rs | 1 - clarity/src/vm/functions/arithmetic.rs | 1 - clarity/src/vm/functions/assets.rs | 2 -- clarity/src/vm/functions/conversions.rs | 2 -- clarity/src/vm/functions/database.rs | 1 - clarity/src/vm/functions/principals.rs | 2 -- clarity/src/vm/functions/sequences.rs | 1 - clarity/src/vm/mod.rs | 1 - clarity/src/vm/representations.rs | 1 - clarity/src/vm/tests/conversions.rs | 4 +--- clarity/src/vm/tests/datamaps.rs | 2 -- clarity/src/vm/tests/sequences.rs | 2 -- clarity/src/vm/tests/traits.rs | 2 -- clarity/src/vm/types/mod.rs | 1 - clarity/src/vm/types/serialization.rs | 2 -- clarity/src/vm/types/signatures.rs | 1 - clarity/src/vm/variables.rs | 1 - stacks-common/src/address/c32.rs | 2 -- stacks-common/src/address/mod.rs | 1 - stacks-common/src/deps_common/bitcoin/blockdata/constants.rs | 3 --- stacks-common/src/deps_common/bitcoin/blockdata/script.rs | 1 - .../src/deps_common/bitcoin/blockdata/transaction.rs | 1 - .../src/deps_common/bitcoin/network/message_blockdata.rs | 1 - stacks-common/src/deps_common/bitcoin/util/hash.rs | 1 - stacks-common/src/types/mod.rs | 1 - stacks-common/src/util/hash.rs | 1 - stacks-common/src/util/vrf.rs | 3 +-- stacks-signer/src/config.rs | 1 - stackslib/src/blockstack_cli.rs | 1 - stackslib/src/burnchains/affirmation.rs | 1 - stackslib/src/burnchains/bitcoin/indexer.rs | 1 - stackslib/src/burnchains/burnchain.rs | 2 -- stackslib/src/burnchains/mod.rs | 2 -- stackslib/src/burnchains/tests/db.rs | 1 - stackslib/src/chainstate/burn/db/sortdb.rs | 3 +-- stackslib/src/chainstate/burn/distribution.rs | 1 - stackslib/src/chainstate/burn/mod.rs | 1 - stackslib/src/chainstate/burn/operations/mod.rs | 1 - stackslib/src/chainstate/coordinator/mod.rs | 1 - stackslib/src/chainstate/stacks/address.rs | 2 +- stackslib/src/chainstate/stacks/boot/contract_tests.rs | 1 - stackslib/src/chainstate/stacks/boot/docs.rs | 2 -- stackslib/src/chainstate/stacks/boot/mod.rs | 5 +---- stackslib/src/chainstate/stacks/boot/pox_2_tests.rs | 1 - stackslib/src/chainstate/stacks/boot/pox_3_tests.rs | 1 - stackslib/src/chainstate/stacks/boot/pox_4_tests.rs | 1 - stackslib/src/chainstate/stacks/boot/signers_voting_tests.rs | 1 - stackslib/src/chainstate/stacks/db/blocks.rs | 1 - stackslib/src/chainstate/stacks/db/transactions.rs | 1 - stackslib/src/chainstate/stacks/index/cache.rs | 2 -- stackslib/src/chainstate/stacks/index/file.rs | 2 -- stackslib/src/chainstate/stacks/index/storage.rs | 2 -- stackslib/src/chainstate/stacks/index/trie_sql.rs | 2 -- stackslib/src/chainstate/stacks/miner.rs | 1 - stackslib/src/chainstate/stacks/mod.rs | 1 - stackslib/src/chainstate/stacks/transaction.rs | 1 - stackslib/src/clarity_cli.rs | 2 -- stackslib/src/clarity_vm/clarity.rs | 1 - stackslib/src/core/mod.rs | 4 +--- stackslib/src/cost_estimates/fee_medians.rs | 2 -- stackslib/src/cost_estimates/fee_scalar.rs | 2 -- stackslib/src/cost_estimates/mod.rs | 1 - stackslib/src/cost_estimates/pessimistic.rs | 2 -- stackslib/src/main.rs | 1 - stackslib/src/monitoring/mod.rs | 1 - stackslib/src/net/api/mod.rs | 2 -- stackslib/src/net/atlas/db.rs | 1 - stackslib/src/net/atlas/mod.rs | 1 - stackslib/src/net/atlas/tests.rs | 1 - stackslib/src/net/chat.rs | 1 - stackslib/src/net/codec.rs | 1 - stackslib/src/net/connection.rs | 1 - stackslib/src/net/db.rs | 1 - stackslib/src/net/download.rs | 2 -- stackslib/src/net/http/request.rs | 1 - stackslib/src/net/inv/epoch2x.rs | 1 - stackslib/src/net/mod.rs | 2 -- stackslib/src/net/rpc.rs | 1 - stackslib/src/util_lib/boot.rs | 2 -- stackslib/src/util_lib/db.rs | 1 - stackslib/src/util_lib/strings.rs | 1 - testnet/stacks-node/src/config.rs | 1 - testnet/stacks-node/src/main.rs | 1 - testnet/stacks-node/src/nakamoto_node/miner.rs | 1 - testnet/stacks-node/src/nakamoto_node/peer.rs | 1 - testnet/stacks-node/src/neon_node.rs | 2 -- testnet/stacks-node/src/node.rs | 1 - testnet/stacks-node/src/tests/epoch_205.rs | 1 - testnet/stacks-node/src/tests/mempool.rs | 1 - testnet/stacks-node/src/tests/mod.rs | 1 - testnet/stacks-node/src/tests/neon_integrations.rs | 1 - 115 files changed, 6 insertions(+), 164 deletions(-) diff --git a/clarity/src/libclarity.rs b/clarity/src/libclarity.rs index 4540d15e8c..daae7dcfd7 100644 --- a/clarity/src/libclarity.rs +++ b/clarity/src/libclarity.rs @@ -51,7 +51,6 @@ pub use stacks_common::{ pub mod vm; pub mod boot_util { - use std::convert::TryFrom; use stacks_common::types::chainstate::StacksAddress; diff --git a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs index 7c6b587556..286e2e11fa 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/mod.rs @@ -19,7 +19,6 @@ pub mod contexts; pub mod natives; use std::collections::BTreeMap; -use std::convert::TryInto; use hashbrown::HashMap; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs index 46830a8762..b38cfd0d11 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; - use stacks_common::types::StacksEpochId; use super::{ diff --git a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs index 81d52bb23d..bed885d147 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/natives/sequences.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs index 918e099671..df9c35ed0e 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/assets.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - use stacks_common::types::StacksEpochId; use crate::vm::analysis::errors::CheckErrors; diff --git a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs index 6529b859f5..1830caf7ce 100644 --- a/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_05/tests/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - use stacks_common::types::StacksEpochId; use crate::vm::analysis::errors::CheckErrors; diff --git a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs index 44aab0b4f2..a0937e84c8 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/mod.rs @@ -18,7 +18,6 @@ pub mod contexts; pub mod natives; use std::collections::BTreeMap; -use std::convert::TryInto; use hashbrown::HashMap; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs index 1c30eb7795..9fdc8c704c 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; - use stacks_common::types::StacksEpochId; use super::{ diff --git a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs index 52ceca66b6..090b259a26 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/natives/sequences.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - use stacks_common::types::StacksEpochId; use super::{SimpleNativeFunction, TypedNativeFunction}; diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs index 8989fb295e..c870fdbab7 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/assets.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - #[cfg(test)] use rstest::rstest; #[cfg(test)] diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs index 25e0eb0548..2f023dcf4f 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/contracts.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::fs::read_to_string; use assert_json_diff::assert_json_eq; diff --git a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs index d8733cfab8..85a6b39ea9 100644 --- a/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs +++ b/clarity/src/vm/analysis/type_checker/v2_1/tests/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - #[cfg(test)] use rstest::rstest; #[cfg(test)] diff --git a/clarity/src/vm/ast/definition_sorter/mod.rs b/clarity/src/vm/ast/definition_sorter/mod.rs index a48bfd0e34..eee6625310 100644 --- a/clarity/src/vm/ast/definition_sorter/mod.rs +++ b/clarity/src/vm/ast/definition_sorter/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::iter::FromIterator; - use hashbrown::{HashMap, HashSet}; use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; diff --git a/clarity/src/vm/ast/parser/v1.rs b/clarity/src/vm/ast/parser/v1.rs index d4dbdcffc4..4cdea6e278 100644 --- a/clarity/src/vm/ast/parser/v1.rs +++ b/clarity/src/vm/ast/parser/v1.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::cmp; -use std::convert::TryInto; use lazy_static::lazy_static; use regex::{Captures, Regex}; diff --git a/clarity/src/vm/ast/parser/v2/mod.rs b/clarity/src/vm/ast/parser/v2/mod.rs index 6238af1383..addbba1c59 100644 --- a/clarity/src/vm/ast/parser/v2/mod.rs +++ b/clarity/src/vm/ast/parser/v2/mod.rs @@ -1,6 +1,5 @@ pub mod lexer; -use std::convert::TryFrom; use std::num::ParseIntError; use stacks_common::util::hash::hex_bytes; diff --git a/clarity/src/vm/ast/sugar_expander/mod.rs b/clarity/src/vm/ast/sugar_expander/mod.rs index cf070548a8..7fc6064b85 100644 --- a/clarity/src/vm/ast/sugar_expander/mod.rs +++ b/clarity/src/vm/ast/sugar_expander/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - use hashbrown::{HashMap, HashSet}; use crate::vm::ast::errors::{ParseError, ParseErrors, ParseResult}; diff --git a/clarity/src/vm/callables.rs b/clarity/src/vm/callables.rs index 597dbab358..32e7d05514 100644 --- a/clarity/src/vm/callables.rs +++ b/clarity/src/vm/callables.rs @@ -15,9 +15,7 @@ // along with this program. If not, see . use std::collections::BTreeMap; -use std::convert::TryInto; use std::fmt; -use std::iter::FromIterator; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/contexts.rs b/clarity/src/vm/contexts.rs index 104adbab13..4b2d6c46d2 100644 --- a/clarity/src/vm/contexts.rs +++ b/clarity/src/vm/contexts.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{BTreeMap, BTreeSet}; -use std::convert::TryInto; use std::fmt; use std::mem::replace; diff --git a/clarity/src/vm/contracts.rs b/clarity/src/vm/contracts.rs index 0019106ef1..1982665aee 100644 --- a/clarity/src/vm/contracts.rs +++ b/clarity/src/vm/contracts.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - use stacks_common::types::StacksEpochId; use crate::vm::ast::ContractAST; diff --git a/clarity/src/vm/costs/mod.rs b/clarity/src/vm/costs/mod.rs index 2222aa4c12..e0a664ac64 100644 --- a/clarity/src/vm/costs/mod.rs +++ b/clarity/src/vm/costs/mod.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::BTreeMap; -use std::convert::{TryFrom, TryInto}; use std::{cmp, fmt}; use hashbrown::HashMap; diff --git a/clarity/src/vm/database/clarity_db.rs b/clarity/src/vm/database/clarity_db.rs index 5ef6c458d2..4388e88e58 100644 --- a/clarity/src/vm/database/clarity_db.rs +++ b/clarity/src/vm/database/clarity_db.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - use serde_json; use stacks_common::address::AddressHashMode; use stacks_common::consts::{ diff --git a/clarity/src/vm/database/clarity_store.rs b/clarity/src/vm/database/clarity_store.rs index f3d9d2bb09..f093c5a3c8 100644 --- a/clarity/src/vm/database/clarity_store.rs +++ b/clarity/src/vm/database/clarity_store.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; use std::path::PathBuf; use rusqlite::Connection; diff --git a/clarity/src/vm/database/key_value_wrapper.rs b/clarity/src/vm/database/key_value_wrapper.rs index bc4b85a9b0..65de1adce4 100644 --- a/clarity/src/vm/database/key_value_wrapper.rs +++ b/clarity/src/vm/database/key_value_wrapper.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::clone::Clone; -use std::cmp::Eq; use std::hash::Hash; use hashbrown::HashMap; diff --git a/clarity/src/vm/database/structures.rs b/clarity/src/vm/database/structures.rs index 53c7fbd681..937eda2bdc 100644 --- a/clarity/src/vm/database/structures.rs +++ b/clarity/src/vm/database/structures.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; use std::io::Write; use serde::Deserialize; diff --git a/clarity/src/vm/docs/contracts.rs b/clarity/src/vm/docs/contracts.rs index 37d1452a1e..7426be7966 100644 --- a/clarity/src/vm/docs/contracts.rs +++ b/clarity/src/vm/docs/contracts.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::iter::FromIterator; use hashbrown::{HashMap, HashSet}; use stacks_common::consts::CHAIN_ID_TESTNET; diff --git a/clarity/src/vm/functions/arithmetic.rs b/clarity/src/vm/functions/arithmetic.rs index bd0edbf5eb..1d52ae4390 100644 --- a/clarity/src/vm/functions/arithmetic.rs +++ b/clarity/src/vm/functions/arithmetic.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::cmp; -use std::convert::TryFrom; use integer_sqrt::IntegerSquareRoot; diff --git a/clarity/src/vm/functions/assets.rs b/clarity/src/vm/functions/assets.rs index 3e926f2cc7..0d004a846a 100644 --- a/clarity/src/vm/functions/assets.rs +++ b/clarity/src/vm/functions/assets.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - use stacks_common::types::StacksEpochId; use crate::vm::costs::cost_functions::ClarityCostFunction; diff --git a/clarity/src/vm/functions/conversions.rs b/clarity/src/vm/functions/conversions.rs index b788455f9c..090f0d2107 100644 --- a/clarity/src/vm/functions/conversions.rs +++ b/clarity/src/vm/functions/conversions.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; - use stacks_common::codec::StacksMessageCodec; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/functions/database.rs b/clarity/src/vm/functions/database.rs index e52ac57b54..b047faf682 100644 --- a/clarity/src/vm/functions/database.rs +++ b/clarity/src/vm/functions/database.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::cmp; -use std::convert::{TryFrom, TryInto}; use stacks_common::types::chainstate::StacksBlockId; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/functions/principals.rs b/clarity/src/vm/functions/principals.rs index 426fa4f703..99246019da 100644 --- a/clarity/src/vm/functions/principals.rs +++ b/clarity/src/vm/functions/principals.rs @@ -1,5 +1,3 @@ -use std::convert::TryFrom; - use stacks_common::address::{ C32_ADDRESS_VERSION_MAINNET_MULTISIG, C32_ADDRESS_VERSION_MAINNET_SINGLESIG, C32_ADDRESS_VERSION_TESTNET_MULTISIG, C32_ADDRESS_VERSION_TESTNET_SINGLESIG, diff --git a/clarity/src/vm/functions/sequences.rs b/clarity/src/vm/functions/sequences.rs index 029e62484a..60445f9632 100644 --- a/clarity/src/vm/functions/sequences.rs +++ b/clarity/src/vm/functions/sequences.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::cmp; -use std::convert::{TryFrom, TryInto}; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/mod.rs b/clarity/src/vm/mod.rs index 45d71cf222..9d74fae5d7 100644 --- a/clarity/src/vm/mod.rs +++ b/clarity/src/vm/mod.rs @@ -50,7 +50,6 @@ pub mod test_util; pub mod clarity; use std::collections::BTreeMap; -use std::convert::{TryFrom, TryInto}; use serde_json; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/representations.rs b/clarity/src/vm/representations.rs index 580e9a51c2..15e674eb13 100644 --- a/clarity/src/vm/representations.rs +++ b/clarity/src/vm/representations.rs @@ -16,7 +16,6 @@ use std::borrow::Borrow; use std::cmp::Ordering; -use std::convert::TryFrom; use std::fmt; use std::io::{Read, Write}; use std::ops::Deref; diff --git a/clarity/src/vm/tests/conversions.rs b/clarity/src/vm/tests/conversions.rs index 0d5e559758..dbe45eb724 100644 --- a/clarity/src/vm/tests/conversions.rs +++ b/clarity/src/vm/tests/conversions.rs @@ -15,15 +15,13 @@ // along with this program. If not, see . pub use crate::vm::analysis::errors::{CheckError, CheckErrors}; -use crate::vm::execute_v2; use crate::vm::types::SequenceSubtype::{BufferType, StringType}; use crate::vm::types::StringSubtype::ASCII; use crate::vm::types::TypeSignature::SequenceType; use crate::vm::types::{ ASCIIData, BuffData, BufferLength, CharType, SequenceData, TypeSignature, UTF8Data, Value, }; -use crate::vm::ClarityVersion; -use std::convert::TryFrom; +use crate::vm::{execute_v2, ClarityVersion}; #[test] fn test_simple_buff_to_int_le() { diff --git a/clarity/src/vm/tests/datamaps.rs b/clarity/src/vm/tests/datamaps.rs index 87f5dbcf30..828de608e7 100644 --- a/clarity/src/vm/tests/datamaps.rs +++ b/clarity/src/vm/tests/datamaps.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{From, TryFrom}; - use crate::vm::errors::{CheckErrors, Error, ShortReturnType}; use crate::vm::types::{ ListData, SequenceData, TupleData, TupleTypeSignature, TypeSignature, Value, diff --git a/clarity/src/vm/tests/sequences.rs b/clarity/src/vm/tests/sequences.rs index 51de0e4023..e252f917ee 100644 --- a/clarity/src/vm/tests/sequences.rs +++ b/clarity/src/vm/tests/sequences.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; - use rstest::rstest; use rstest_reuse::{self, *}; use stacks_common::types::StacksEpochId; diff --git a/clarity/src/vm/tests/traits.rs b/clarity/src/vm/tests/traits.rs index 250ebc3412..97c4292b0d 100644 --- a/clarity/src/vm/tests/traits.rs +++ b/clarity/src/vm/tests/traits.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; - use stacks_common::types::StacksEpochId; use super::MemoryEnvironmentGenerator; diff --git a/clarity/src/vm/types/mod.rs b/clarity/src/vm/types/mod.rs index cc3cbeeba0..1c25e1c380 100644 --- a/clarity/src/vm/types/mod.rs +++ b/clarity/src/vm/types/mod.rs @@ -20,7 +20,6 @@ pub mod serialization; pub mod signatures; use std::collections::BTreeMap; -use std::convert::{TryFrom, TryInto}; use std::{char, cmp, fmt, str}; use regex::Regex; diff --git a/clarity/src/vm/types/serialization.rs b/clarity/src/vm/types/serialization.rs index 69a662e6b7..c7a92203b4 100644 --- a/clarity/src/vm/types/serialization.rs +++ b/clarity/src/vm/types/serialization.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::borrow::Borrow; -use std::convert::{TryFrom, TryInto}; use std::io::{Read, Write}; use std::{cmp, error, fmt, str}; diff --git a/clarity/src/vm/types/signatures.rs b/clarity/src/vm/types/signatures.rs index c6838eb3fb..29445d2499 100644 --- a/clarity/src/vm/types/signatures.rs +++ b/clarity/src/vm/types/signatures.rs @@ -16,7 +16,6 @@ use std::collections::btree_map::Entry; use std::collections::BTreeMap; -use std::convert::{TryFrom, TryInto}; use std::hash::{Hash, Hasher}; use std::{cmp, fmt}; diff --git a/clarity/src/vm/variables.rs b/clarity/src/vm/variables.rs index 66de0f3b6e..539e14c39e 100644 --- a/clarity/src/vm/variables.rs +++ b/clarity/src/vm/variables.rs @@ -13,7 +13,6 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use super::errors::InterpreterError; use crate::vm::contexts::{Environment, LocalContext}; diff --git a/stacks-common/src/address/c32.rs b/stacks-common/src/address/c32.rs index 67a0504b33..a8c26632f8 100644 --- a/stacks-common/src/address/c32.rs +++ b/stacks-common/src/address/c32.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; - use sha2::{Digest, Sha256}; use super::Error; diff --git a/stacks-common/src/address/mod.rs b/stacks-common/src/address/mod.rs index b4bcb936c9..381456f661 100644 --- a/stacks-common/src/address/mod.rs +++ b/stacks-common/src/address/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::{error, fmt}; use sha2::{Digest, Sha256}; diff --git a/stacks-common/src/deps_common/bitcoin/blockdata/constants.rs b/stacks-common/src/deps_common/bitcoin/blockdata/constants.rs index 4a9cfddef7..7d3c7d1b4f 100644 --- a/stacks-common/src/deps_common/bitcoin/blockdata/constants.rs +++ b/stacks-common/src/deps_common/bitcoin/blockdata/constants.rs @@ -19,8 +19,6 @@ //! single transaction //! -use std::default::Default; - use crate::deps_common::bitcoin::blockdata::block::{Block, BlockHeader}; use crate::deps_common::bitcoin::blockdata::transaction::{OutPoint, Transaction, TxIn, TxOut}; use crate::deps_common::bitcoin::blockdata::{opcodes, script}; @@ -139,7 +137,6 @@ pub fn genesis_block(network: Network) -> Block { #[cfg(test)] mod test { - use std::default::Default; use crate::deps_common::bitcoin::blockdata::constants::{ bitcoin_genesis_tx, genesis_block, COIN_VALUE, MAX_SEQUENCE, diff --git a/stacks-common/src/deps_common/bitcoin/blockdata/script.rs b/stacks-common/src/deps_common/bitcoin/blockdata/script.rs index f055316f25..8b08ab998a 100644 --- a/stacks-common/src/deps_common/bitcoin/blockdata/script.rs +++ b/stacks-common/src/deps_common/bitcoin/blockdata/script.rs @@ -24,7 +24,6 @@ //! This module provides the structures and functions needed to support scripts. //! -use std::default::Default; use std::mem::size_of; use std::{error, fmt}; diff --git a/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs b/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs index f92a11cd1b..1ece07c511 100644 --- a/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs +++ b/stacks-common/src/deps_common/bitcoin/blockdata/transaction.rs @@ -23,7 +23,6 @@ //! This module provides the structures and functions needed to support transactions. //! -use std::default::Default; use std::fmt; use std::io::Write; diff --git a/stacks-common/src/deps_common/bitcoin/network/message_blockdata.rs b/stacks-common/src/deps_common/bitcoin/network/message_blockdata.rs index 099acca559..419b405a17 100644 --- a/stacks-common/src/deps_common/bitcoin/network/message_blockdata.rs +++ b/stacks-common/src/deps_common/bitcoin/network/message_blockdata.rs @@ -135,7 +135,6 @@ impl ConsensusDecodable for Inventory { #[cfg(test)] mod tests { - use std::default::Default; use super::{GetBlocksMessage, GetHeadersMessage}; use crate::deps_common::bitcoin::network::serialize::{deserialize, serialize}; diff --git a/stacks-common/src/deps_common/bitcoin/util/hash.rs b/stacks-common/src/deps_common/bitcoin/util/hash.rs index 364b5f609b..3e9186bd92 100644 --- a/stacks-common/src/deps_common/bitcoin/util/hash.rs +++ b/stacks-common/src/deps_common/bitcoin/util/hash.rs @@ -17,7 +17,6 @@ use std::char::from_digit; use std::cmp::min; -use std::default::Default; use std::io::{Cursor, Write}; use std::{error, fmt, mem}; diff --git a/stacks-common/src/types/mod.rs b/stacks-common/src/types/mod.rs index 998edda48e..cf5603dba9 100644 --- a/stacks-common/src/types/mod.rs +++ b/stacks-common/src/types/mod.rs @@ -1,5 +1,4 @@ use std::cmp::Ordering; -use std::convert::TryFrom; use std::fmt; use crate::address::c32::{c32_address, c32_address_decode}; diff --git a/stacks-common/src/util/hash.rs b/stacks-common/src/util/hash.rs index 634cbf485b..a5e4341b60 100644 --- a/stacks-common/src/util/hash.rs +++ b/stacks-common/src/util/hash.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::char::from_digit; -use std::convert::TryInto; use std::fmt::Write; use std::{fmt, mem}; diff --git a/stacks-common/src/util/vrf.rs b/stacks-common/src/util/vrf.rs index 410c4a07e2..ddfdedfaa8 100644 --- a/stacks-common/src/util/vrf.rs +++ b/stacks-common/src/util/vrf.rs @@ -17,8 +17,7 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -use std::clone::Clone; -use std::cmp::{Eq, Ord, Ordering, PartialEq}; +use std::cmp::Ordering; use std::fmt::Debug; use std::hash::{Hash, Hasher}; /// This codebase is based on routines defined in the IETF draft for verifiable random functions diff --git a/stacks-signer/src/config.rs b/stacks-signer/src/config.rs index df9e2db404..bb09d3262d 100644 --- a/stacks-signer/src/config.rs +++ b/stacks-signer/src/config.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::fs; use std::net::{SocketAddr, ToSocketAddrs}; use std::path::PathBuf; diff --git a/stackslib/src/blockstack_cli.rs b/stackslib/src/blockstack_cli.rs index d708383f14..6fb9f45ed6 100644 --- a/stackslib/src/blockstack_cli.rs +++ b/stackslib/src/blockstack_cli.rs @@ -23,7 +23,6 @@ extern crate blockstack_lib; extern crate clarity; extern crate stacks_common; -use std::convert::TryFrom; use std::io::prelude::*; use std::io::Read; use std::{env, fs, io}; diff --git a/stackslib/src/burnchains/affirmation.rs b/stackslib/src/burnchains/affirmation.rs index bfe59ed274..1eb4874e42 100644 --- a/stackslib/src/burnchains/affirmation.rs +++ b/stackslib/src/burnchains/affirmation.rs @@ -232,7 +232,6 @@ /// use std::cmp; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::fmt; use std::fmt::Write; use std::sync::mpsc::SyncSender; diff --git a/stackslib/src/burnchains/bitcoin/indexer.rs b/stackslib/src/burnchains/bitcoin/indexer.rs index 2d3e981e27..51de78a53f 100644 --- a/stackslib/src/burnchains/bitcoin/indexer.rs +++ b/stackslib/src/burnchains/bitcoin/indexer.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::net::Shutdown; use std::ops::{Deref, DerefMut}; use std::path::PathBuf; diff --git a/stackslib/src/burnchains/burnchain.rs b/stackslib/src/burnchains/burnchain.rs index d5f33a5ea7..e3947bd5a8 100644 --- a/stackslib/src/burnchains/burnchain.rs +++ b/stackslib/src/burnchains/burnchain.rs @@ -15,8 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; -use std::marker::Send; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::mpsc::sync_channel; diff --git a/stackslib/src/burnchains/mod.rs b/stackslib/src/burnchains/mod.rs index 8734d605d8..c6e4204542 100644 --- a/stackslib/src/burnchains/mod.rs +++ b/stackslib/src/burnchains/mod.rs @@ -15,8 +15,6 @@ // along with this program. If not, see . use std::collections::HashMap; -use std::convert::TryFrom; -use std::default::Default; use std::marker::PhantomData; use std::{error, fmt, io}; diff --git a/stackslib/src/burnchains/tests/db.rs b/stackslib/src/burnchains/tests/db.rs index 13db19bcf7..7b2a87be4c 100644 --- a/stackslib/src/burnchains/tests/db.rs +++ b/stackslib/src/burnchains/tests/db.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::cmp; -use std::convert::TryInto; use stacks_common::address::AddressHashMode; use stacks_common::deps_common::bitcoin::blockdata::transaction::Transaction as BtcTx; diff --git a/stackslib/src/chainstate/burn/db/sortdb.rs b/stackslib/src/chainstate/burn/db/sortdb.rs index 86dffd5723..d027f6ffd9 100644 --- a/stackslib/src/chainstate/burn/db/sortdb.rs +++ b/stackslib/src/chainstate/burn/db/sortdb.rs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::cmp::{Ord, Ordering}; +use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; -use std::convert::{From, TryFrom, TryInto}; use std::io::{ErrorKind, Write}; use std::ops::{Deref, DerefMut}; use std::str::FromStr; diff --git a/stackslib/src/chainstate/burn/distribution.rs b/stackslib/src/chainstate/burn/distribution.rs index b9685a9a99..2a16897100 100644 --- a/stackslib/src/chainstate/burn/distribution.rs +++ b/stackslib/src/chainstate/burn/distribution.rs @@ -16,7 +16,6 @@ use std::cmp; use std::collections::{BTreeMap, HashMap}; -use std::convert::TryInto; use stacks_common::address::AddressHashMode; use stacks_common::util::hash::Hash160; diff --git a/stackslib/src/chainstate/burn/mod.rs b/stackslib/src/chainstate/burn/mod.rs index 8031762355..13f290d93b 100644 --- a/stackslib/src/chainstate/burn/mod.rs +++ b/stackslib/src/chainstate/burn/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; use std::fmt; use std::io::Write; diff --git a/stackslib/src/chainstate/burn/operations/mod.rs b/stackslib/src/chainstate/burn/operations/mod.rs index e7c48cb1cb..e51a20f630 100644 --- a/stackslib/src/chainstate/burn/operations/mod.rs +++ b/stackslib/src/chainstate/burn/operations/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{From, TryInto}; use std::{error, fmt, fs, io}; use clarity::vm::types::PrincipalData; diff --git a/stackslib/src/chainstate/coordinator/mod.rs b/stackslib/src/chainstate/coordinator/mod.rs index 6211c74d97..324d42f483 100644 --- a/stackslib/src/chainstate/coordinator/mod.rs +++ b/stackslib/src/chainstate/coordinator/mod.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::path::PathBuf; use std::sync::atomic::AtomicBool; use std::sync::mpsc::SyncSender; diff --git a/stackslib/src/chainstate/stacks/address.rs b/stackslib/src/chainstate/stacks/address.rs index e11730bca2..c3706a2565 100644 --- a/stackslib/src/chainstate/stacks/address.rs +++ b/stackslib/src/chainstate/stacks/address.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::cmp::{Ord, Ordering}; +use std::cmp::Ordering; use std::io::prelude::*; use std::io::{Read, Write}; use std::{fmt, io}; diff --git a/stackslib/src/chainstate/stacks/boot/contract_tests.rs b/stackslib/src/chainstate/stacks/boot/contract_tests.rs index ce12011c73..23f2c92008 100644 --- a/stackslib/src/chainstate/stacks/boot/contract_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/contract_tests.rs @@ -1,5 +1,4 @@ use std::collections::{HashMap, VecDeque}; -use std::convert::{TryFrom, TryInto}; use clarity::vm::analysis::arithmetic_checker::ArithmeticOnlyChecker; use clarity::vm::analysis::mem_type_check; diff --git a/stackslib/src/chainstate/stacks/boot/docs.rs b/stackslib/src/chainstate/stacks/boot/docs.rs index 08a203122a..62580f384a 100644 --- a/stackslib/src/chainstate/stacks/boot/docs.rs +++ b/stackslib/src/chainstate/stacks/boot/docs.rs @@ -1,5 +1,3 @@ -use std::iter::FromIterator; - use clarity::vm::docs::contracts::{produce_docs_refs, ContractSupportDocs}; use hashbrown::{HashMap, HashSet}; diff --git a/stackslib/src/chainstate/stacks/boot/mod.rs b/stackslib/src/chainstate/stacks/boot/mod.rs index 7d6d141e10..abba9be6c7 100644 --- a/stackslib/src/chainstate/stacks/boot/mod.rs +++ b/stackslib/src/chainstate/stacks/boot/mod.rs @@ -14,10 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::boxed::Box; use std::cmp; -use std::collections::{BTreeMap, HashMap}; -use std::convert::{TryFrom, TryInto}; +use std::collections::BTreeMap; use clarity::vm::analysis::CheckErrors; use clarity::vm::ast::ASTRules; @@ -1326,7 +1324,6 @@ pub mod signers_voting_tests; #[cfg(test)] pub mod test { use std::collections::{HashMap, HashSet}; - use std::convert::From; use std::fs; use clarity::boot_util::boot_code_addr; diff --git a/stackslib/src/chainstate/stacks/boot/pox_2_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_2_tests.rs index 119d4e4186..07d34a04cc 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_2_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_2_tests.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use clarity::vm::clarity::ClarityConnection; use clarity::vm::contexts::OwnedEnvironment; diff --git a/stackslib/src/chainstate/stacks/boot/pox_3_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_3_tests.rs index 65aedb1302..f0c7a9ef75 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_3_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_3_tests.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use clarity::vm::clarity::ClarityConnection; use clarity::vm::contexts::OwnedEnvironment; diff --git a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs index d9857c55d6..ebb8c5f078 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use clarity::vm::clarity::ClarityConnection; use clarity::vm::contexts::OwnedEnvironment; diff --git a/stackslib/src/chainstate/stacks/boot/signers_voting_tests.rs b/stackslib/src/chainstate/stacks/boot/signers_voting_tests.rs index cc7226e6ef..5ac7d461c2 100644 --- a/stackslib/src/chainstate/stacks/boot/signers_voting_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/signers_voting_tests.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use clarity::boot_util::boot_code_addr; use clarity::vm::clarity::ClarityConnection; diff --git a/stackslib/src/chainstate/stacks/db/blocks.rs b/stackslib/src/chainstate/stacks/db/blocks.rs index 77fc754a65..708f3a6a0d 100644 --- a/stackslib/src/chainstate/stacks/db/blocks.rs +++ b/stackslib/src/chainstate/stacks/db/blocks.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet}; -use std::convert::From; use std::io::prelude::*; use std::io::{Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/db/transactions.rs b/stackslib/src/chainstate/stacks/db/transactions.rs index b0822b817c..9297252d15 100644 --- a/stackslib/src/chainstate/stacks/db/transactions.rs +++ b/stackslib/src/chainstate/stacks/db/transactions.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet}; -use std::convert::{TryFrom, TryInto}; use std::io::prelude::*; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/index/cache.rs b/stackslib/src/chainstate/stacks/index/cache.rs index 3763f15c6b..a711603447 100644 --- a/stackslib/src/chainstate/stacks/index/cache.rs +++ b/stackslib/src/chainstate/stacks/index/cache.rs @@ -16,10 +16,8 @@ use std::char::from_digit; use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::hash::{Hash, Hasher}; use std::io::{BufWriter, Cursor, Read, Seek, SeekFrom, Write}; -use std::iter::FromIterator; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/index/file.rs b/stackslib/src/chainstate/stacks/index/file.rs index 99df760167..1477f9a7dd 100644 --- a/stackslib/src/chainstate/stacks/index/file.rs +++ b/stackslib/src/chainstate/stacks/index/file.rs @@ -16,11 +16,9 @@ use std::char::from_digit; use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::fs::OpenOptions; use std::hash::{Hash, Hasher}; use std::io::{BufWriter, Cursor, Read, Seek, SeekFrom, Write}; -use std::iter::FromIterator; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/index/storage.rs b/stackslib/src/chainstate/stacks/index/storage.rs index c39976419e..97f7ca999a 100644 --- a/stackslib/src/chainstate/stacks/index/storage.rs +++ b/stackslib/src/chainstate/stacks/index/storage.rs @@ -16,10 +16,8 @@ use std::char::from_digit; use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::hash::{Hash, Hasher}; use std::io::{BufWriter, Cursor, Read, Seek, SeekFrom, Write}; -use std::iter::FromIterator; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/index/trie_sql.rs b/stackslib/src/chainstate/stacks/index/trie_sql.rs index d538ed7e50..be1ae91c21 100644 --- a/stackslib/src/chainstate/stacks/index/trie_sql.rs +++ b/stackslib/src/chainstate/stacks/index/trie_sql.rs @@ -19,9 +19,7 @@ use std::char::from_digit; use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; use std::io::{BufWriter, Cursor, Read, Seek, SeekFrom, Write}; -use std::iter::FromIterator; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/chainstate/stacks/miner.rs b/stackslib/src/chainstate/stacks/miner.rs index b4dbcc5541..c04b03dcda 100644 --- a/stackslib/src/chainstate/stacks/miner.rs +++ b/stackslib/src/chainstate/stacks/miner.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet}; -use std::convert::From; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::thread::ThreadId; diff --git a/stackslib/src/chainstate/stacks/mod.rs b/stackslib/src/chainstate/stacks/mod.rs index bb68fb90bc..7247a28f7e 100644 --- a/stackslib/src/chainstate/stacks/mod.rs +++ b/stackslib/src/chainstate/stacks/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{From, TryFrom}; use std::io::prelude::*; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; diff --git a/stackslib/src/chainstate/stacks/transaction.rs b/stackslib/src/chainstate/stacks/transaction.rs index 0c764ec83b..4ede285e41 100644 --- a/stackslib/src/chainstate/stacks/transaction.rs +++ b/stackslib/src/chainstate/stacks/transaction.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::io; use std::io::prelude::*; use std::io::{Read, Write}; diff --git a/stackslib/src/clarity_cli.rs b/stackslib/src/clarity_cli.rs index 426b45bc8a..00a067408e 100644 --- a/stackslib/src/clarity_cli.rs +++ b/stackslib/src/clarity_cli.rs @@ -14,10 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::{TryFrom, TryInto}; use std::ffi::OsStr; use std::io::{Read, Write}; -use std::iter::Iterator; use std::path::PathBuf; use std::str::FromStr; use std::{env, fs, io, process}; diff --git a/stackslib/src/clarity_vm/clarity.rs b/stackslib/src/clarity_vm/clarity.rs index 8351412119..81a421cdef 100644 --- a/stackslib/src/clarity_vm/clarity.rs +++ b/stackslib/src/clarity_vm/clarity.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::{error, fmt, thread}; use clarity::vm::analysis::errors::{CheckError, CheckErrors}; diff --git a/stackslib/src/core/mod.rs b/stackslib/src/core/mod.rs index 2280fe6d71..45556adf7a 100644 --- a/stackslib/src/core/mod.rs +++ b/stackslib/src/core/mod.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::HashSet; -use std::convert::TryFrom; use clarity::vm::costs::ExecutionCost; use lazy_static::lazy_static; @@ -34,8 +33,7 @@ pub mod mempool; #[cfg(test)] pub mod tests; -use std::cmp::{Ord, Ordering, PartialOrd}; - +use std::cmp::Ordering; pub type StacksEpoch = GenericStacksEpoch; // fork set identifier -- to be mixed with the consensus hash (encodes the version) diff --git a/stackslib/src/cost_estimates/fee_medians.rs b/stackslib/src/cost_estimates/fee_medians.rs index f3a7282a17..88ab0e9c2a 100644 --- a/stackslib/src/cost_estimates/fee_medians.rs +++ b/stackslib/src/cost_estimates/fee_medians.rs @@ -1,7 +1,5 @@ use std::cmp; use std::cmp::Ordering; -use std::convert::TryFrom; -use std::iter::FromIterator; use std::path::Path; use clarity::vm::costs::ExecutionCost; diff --git a/stackslib/src/cost_estimates/fee_scalar.rs b/stackslib/src/cost_estimates/fee_scalar.rs index 895d47ed8f..1c0349e42b 100644 --- a/stackslib/src/cost_estimates/fee_scalar.rs +++ b/stackslib/src/cost_estimates/fee_scalar.rs @@ -1,6 +1,4 @@ use std::cmp; -use std::convert::TryFrom; -use std::iter::FromIterator; use std::path::Path; use clarity::vm::costs::ExecutionCost; diff --git a/stackslib/src/cost_estimates/mod.rs b/stackslib/src/cost_estimates/mod.rs index 1d799607c1..fc4aa5b1b2 100644 --- a/stackslib/src/cost_estimates/mod.rs +++ b/stackslib/src/cost_estimates/mod.rs @@ -2,7 +2,6 @@ use std::cmp; use std::collections::HashMap; use std::error::Error; use std::fmt::Display; -use std::iter::FromIterator; use std::ops::{Add, Div, Mul, Rem, Sub}; use std::path::Path; diff --git a/stackslib/src/cost_estimates/pessimistic.rs b/stackslib/src/cost_estimates/pessimistic.rs index 7e222f5de6..b986d54dc7 100644 --- a/stackslib/src/cost_estimates/pessimistic.rs +++ b/stackslib/src/cost_estimates/pessimistic.rs @@ -1,6 +1,4 @@ use std::cmp; -use std::convert::TryFrom; -use std::iter::FromIterator; use std::path::Path; use clarity::vm::costs::ExecutionCost; diff --git a/stackslib/src/main.rs b/stackslib/src/main.rs index 652d9bf2dc..3d9029281f 100644 --- a/stackslib/src/main.rs +++ b/stackslib/src/main.rs @@ -34,7 +34,6 @@ use tikv_jemallocator::Jemalloc; static GLOBAL: Jemalloc = Jemalloc; use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; use std::fs::{File, OpenOptions}; use std::io::prelude::*; use std::io::BufReader; diff --git a/stackslib/src/monitoring/mod.rs b/stackslib/src/monitoring/mod.rs index ff718ba30c..302ff4d0d1 100644 --- a/stackslib/src/monitoring/mod.rs +++ b/stackslib/src/monitoring/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; use std::error::Error; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/stackslib/src/net/api/mod.rs b/stackslib/src/net/api/mod.rs index 4b45c9f4e0..b6fb21fc2a 100644 --- a/stackslib/src/net/api/mod.rs +++ b/stackslib/src/net/api/mod.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::From; - use clarity::vm::costs::ExecutionCost; use stacks_common::codec::read_next; use stacks_common::types::chainstate::{BlockHeaderHash, StacksBlockId}; diff --git a/stackslib/src/net/atlas/db.rs b/stackslib/src/net/atlas/db.rs index 10f48a6114..784bff9639 100644 --- a/stackslib/src/net/atlas/db.rs +++ b/stackslib/src/net/atlas/db.rs @@ -34,7 +34,6 @@ //! use std::collections::HashSet; -use std::convert::{From, TryFrom}; use std::fs; use clarity::vm::types::QualifiedContractIdentifier; diff --git a/stackslib/src/net/atlas/mod.rs b/stackslib/src/net/atlas/mod.rs index ffeb569f95..45100d984b 100644 --- a/stackslib/src/net/atlas/mod.rs +++ b/stackslib/src/net/atlas/mod.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; use std::hash::{Hash, Hasher}; use clarity::vm::types::{QualifiedContractIdentifier, SequenceData, TupleData, Value}; diff --git a/stackslib/src/net/atlas/tests.rs b/stackslib/src/net/atlas/tests.rs index 567d49fe61..2ebcb71316 100644 --- a/stackslib/src/net/atlas/tests.rs +++ b/stackslib/src/net/atlas/tests.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{BinaryHeap, HashMap, HashSet}; -use std::convert::TryFrom; use std::{thread, time}; use clarity::vm::types::QualifiedContractIdentifier; diff --git a/stackslib/src/net/chat.rs b/stackslib/src/net/chat.rs index c547eb5af5..1b54241197 100644 --- a/stackslib/src/net/chat.rs +++ b/stackslib/src/net/chat.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::TryFrom; use std::io::{Read, Write}; use std::net::SocketAddr; use std::{cmp, mem}; diff --git a/stackslib/src/net/codec.rs b/stackslib/src/net/codec.rs index e4ba530f2e..c0496aa14c 100644 --- a/stackslib/src/net/codec.rs +++ b/stackslib/src/net/codec.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::HashSet; -use std::convert::TryFrom; use std::io::prelude::*; use std::io::Read; use std::{io, mem}; diff --git a/stackslib/src/net/connection.rs b/stackslib/src/net/connection.rs index 44559fca5c..25d3ee7489 100644 --- a/stackslib/src/net/connection.rs +++ b/stackslib/src/net/connection.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::VecDeque; -use std::convert::TryFrom; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; use std::sync::mpsc::{ diff --git a/stackslib/src/net/db.rs b/stackslib/src/net/db.rs index 46707cbdbf..1c116a6174 100644 --- a/stackslib/src/net/db.rs +++ b/stackslib/src/net/db.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::HashSet; -use std::convert::{From, TryFrom}; use std::{fmt, fs}; use clarity::vm::types::{ diff --git a/stackslib/src/net/download.rs b/stackslib/src/net/download.rs index d44efef4a1..f19d6f47d0 100644 --- a/stackslib/src/net/download.rs +++ b/stackslib/src/net/download.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::TryFrom; use std::hash::{Hash, Hasher}; use std::io::{Read, Write}; use std::net::{IpAddr, SocketAddr}; @@ -2507,7 +2506,6 @@ impl PeerNetwork { #[cfg(test)] pub mod test { use std::collections::HashMap; - use std::convert::TryFrom; use clarity::vm::clarity::ClarityConnection; use clarity::vm::costs::ExecutionCost; diff --git a/stackslib/src/net/http/request.rs b/stackslib/src/net/http/request.rs index 36df8235a0..287acb1166 100644 --- a/stackslib/src/net/http/request.rs +++ b/stackslib/src/net/http/request.rs @@ -16,7 +16,6 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::io::{Read, Write}; -use std::string::ToString; use percent_encoding::percent_decode_str; use rand::{thread_rng, Rng}; diff --git a/stackslib/src/net/inv/epoch2x.rs b/stackslib/src/net/inv/epoch2x.rs index 4e97996410..480743a369 100644 --- a/stackslib/src/net/inv/epoch2x.rs +++ b/stackslib/src/net/inv/epoch2x.rs @@ -16,7 +16,6 @@ use std::cmp; use std::collections::{BTreeMap, HashMap, HashSet}; -use std::convert::TryFrom; use std::io::{Read, Write}; use std::net::SocketAddr; diff --git a/stackslib/src/net/mod.rs b/stackslib/src/net/mod.rs index fbdc914fb7..6136a4d094 100644 --- a/stackslib/src/net/mod.rs +++ b/stackslib/src/net/mod.rs @@ -15,9 +15,7 @@ // along with this program. If not, see . use std::borrow::Borrow; -use std::cmp::PartialEq; use std::collections::{HashMap, HashSet}; -use std::convert::{From, TryFrom}; use std::hash::{Hash, Hasher}; use std::io::prelude::*; use std::io::{Read, Write}; diff --git a/stackslib/src/net/rpc.rs b/stackslib/src/net/rpc.rs index d6d75cff17..e2f93d7289 100644 --- a/stackslib/src/net/rpc.rs +++ b/stackslib/src/net/rpc.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::collections::{HashMap, HashSet, VecDeque}; -use std::convert::TryFrom; use std::io::prelude::*; use std::io::{Read, Seek, SeekFrom, Write}; use std::net::SocketAddr; diff --git a/stackslib/src/util_lib/boot.rs b/stackslib/src/util_lib/boot.rs index af3f443278..95cfca9c41 100644 --- a/stackslib/src/util_lib/boot.rs +++ b/stackslib/src/util_lib/boot.rs @@ -1,5 +1,3 @@ -use std::convert::TryFrom; - use clarity::vm::database::STXBalance; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::ContractName; diff --git a/stackslib/src/util_lib/db.rs b/stackslib/src/util_lib/db.rs index 584423ffb8..a06c23408b 100644 --- a/stackslib/src/util_lib/db.rs +++ b/stackslib/src/util_lib/db.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryInto; use std::io::Error as IOError; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; diff --git a/stackslib/src/util_lib/strings.rs b/stackslib/src/util_lib/strings.rs index 3efb1fc7d9..0486e6bf81 100644 --- a/stackslib/src/util_lib/strings.rs +++ b/stackslib/src/util_lib/strings.rs @@ -15,7 +15,6 @@ // along with this program. If not, see . use std::borrow::Borrow; -use std::convert::TryFrom; use std::io::prelude::*; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; diff --git a/testnet/stacks-node/src/config.rs b/testnet/stacks-node/src/config.rs index eb118eb553..7e2751d7a8 100644 --- a/testnet/stacks-node/src/config.rs +++ b/testnet/stacks-node/src/config.rs @@ -1,5 +1,4 @@ use std::collections::HashSet; -use std::convert::TryInto; use std::fs; use std::net::{SocketAddr, ToSocketAddrs}; use std::path::PathBuf; diff --git a/testnet/stacks-node/src/main.rs b/testnet/stacks-node/src/main.rs index 29d1fde368..95a1dda4b8 100644 --- a/testnet/stacks-node/src/main.rs +++ b/testnet/stacks-node/src/main.rs @@ -32,7 +32,6 @@ pub mod syncctl; pub mod tenure; use std::collections::HashMap; -use std::convert::TryInto; use std::{env, panic, process}; use backtrace::Backtrace; diff --git a/testnet/stacks-node/src/nakamoto_node/miner.rs b/testnet/stacks-node/src/nakamoto_node/miner.rs index 5e3c39c9e9..5186943197 100644 --- a/testnet/stacks-node/src/nakamoto_node/miner.rs +++ b/testnet/stacks-node/src/nakamoto_node/miner.rs @@ -14,7 +14,6 @@ use std::collections::HashMap; // // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::convert::TryFrom; use std::thread; use std::thread::JoinHandle; use std::time::{Duration, Instant}; diff --git a/testnet/stacks-node/src/nakamoto_node/peer.rs b/testnet/stacks-node/src/nakamoto_node/peer.rs index 2c8beb7744..eeb6789d30 100644 --- a/testnet/stacks-node/src/nakamoto_node/peer.rs +++ b/testnet/stacks-node/src/nakamoto_node/peer.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . use std::collections::VecDeque; -use std::default::Default; use std::net::SocketAddr; use std::sync::mpsc::TrySendError; use std::time::Duration; diff --git a/testnet/stacks-node/src/neon_node.rs b/testnet/stacks-node/src/neon_node.rs index a9c0393674..49064d4971 100644 --- a/testnet/stacks-node/src/neon_node.rs +++ b/testnet/stacks-node/src/neon_node.rs @@ -140,8 +140,6 @@ use std::cmp; use std::cmp::Ordering as CmpOrdering; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; -use std::convert::{TryFrom, TryInto}; -use std::default::Default; use std::io::{Read, Write}; use std::net::SocketAddr; use std::sync::mpsc::{Receiver, TrySendError}; diff --git a/testnet/stacks-node/src/node.rs b/testnet/stacks-node/src/node.rs index cdebdbc781..90c2123079 100644 --- a/testnet/stacks-node/src/node.rs +++ b/testnet/stacks-node/src/node.rs @@ -1,5 +1,4 @@ use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; use std::net::SocketAddr; use std::thread::JoinHandle; use std::{env, thread, time}; diff --git a/testnet/stacks-node/src/tests/epoch_205.rs b/testnet/stacks-node/src/tests/epoch_205.rs index 844a314bc6..0f689f00ef 100644 --- a/testnet/stacks-node/src/tests/epoch_205.rs +++ b/testnet/stacks-node/src/tests/epoch_205.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::convert::TryFrom; use std::sync::atomic::Ordering; use std::{env, thread}; diff --git a/testnet/stacks-node/src/tests/mempool.rs b/testnet/stacks-node/src/tests/mempool.rs index cc1f3d8228..8c906cd43e 100644 --- a/testnet/stacks-node/src/tests/mempool.rs +++ b/testnet/stacks-node/src/tests/mempool.rs @@ -1,4 +1,3 @@ -use std::convert::{From, TryFrom}; use std::sync::Mutex; use clarity::vm::costs::ExecutionCost; diff --git a/testnet/stacks-node/src/tests/mod.rs b/testnet/stacks-node/src/tests/mod.rs index 485dd524d2..7dbabae3ed 100644 --- a/testnet/stacks-node/src/tests/mod.rs +++ b/testnet/stacks-node/src/tests/mod.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . use std::collections::HashMap; -use std::convert::TryInto; use std::sync::atomic::AtomicU64; use std::sync::Arc; diff --git a/testnet/stacks-node/src/tests/neon_integrations.rs b/testnet/stacks-node/src/tests/neon_integrations.rs index d751035ac9..cd0c96358e 100644 --- a/testnet/stacks-node/src/tests/neon_integrations.rs +++ b/testnet/stacks-node/src/tests/neon_integrations.rs @@ -1,5 +1,4 @@ use std::collections::{HashMap, HashSet}; -use std::convert::TryFrom; use std::path::Path; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{mpsc, Arc}; From 898f59e1fd3f1aa56df34086f2fe3d769c3f962a Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Thu, 29 Feb 2024 10:05:44 +0100 Subject: [PATCH 18/39] fix: name register TS test --- .../tests/bns/name_register.test.ts | 91 +++++++++---------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/contrib/core-contract-tests/tests/bns/name_register.test.ts b/contrib/core-contract-tests/tests/bns/name_register.test.ts index afb7263199..448df6b322 100644 --- a/contrib/core-contract-tests/tests/bns/name_register.test.ts +++ b/contrib/core-contract-tests/tests/bns/name_register.test.ts @@ -323,55 +323,54 @@ describe("name revealing workflow", () => { expect(result).toBeErr(Cl.int(2022)); }); - // temp disabled, focusing on importing clarunit correctly - // it("should successfully register", () => { - // const name = "bob"; - // const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${cases[0].salt}`); - // const sha256 = createHash("sha256").update(merged).digest(); - // const ripemd160 = createHash("ripemd160").update(sha256).digest(); - // simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], bob); + it("should successfully register", () => { + const name = "bob"; + const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${cases[0].salt}`); + const sha256 = createHash("sha256").update(merged).digest(); + const ripemd160 = createHash("ripemd160").update(sha256).digest(); + simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], bob); - // const register = simnet.callPublicFn( - // "bns", - // "name-register", - // [ - // Cl.bufferFromUtf8(cases[0].namespace), - // Cl.bufferFromUtf8(name), - // Cl.bufferFromUtf8(cases[0].salt), - // Cl.bufferFromUtf8(cases[0].zonefile), - // ], - // bob - // ); - // expect(register.result).toBeOk(Cl.bool(true)); + const register = simnet.callPublicFn( + "bns", + "name-register", + [ + Cl.bufferFromUtf8(cases[0].namespace), + Cl.bufferFromUtf8(name), + Cl.bufferFromUtf8(cases[0].salt), + Cl.bufferFromUtf8(cases[0].zonefile), + ], + bob + ); + expect(register.result).toBeOk(Cl.bool(true)); - // const resolvePrincipal = simnet.callReadOnlyFn( - // "bns", - // "resolve-principal", - // [Cl.standardPrincipal(bob)], - // alice - // ); - // expect(resolvePrincipal.result).toBeOk( - // Cl.tuple({ - // name: Cl.bufferFromUtf8("bob"), - // namespace: Cl.bufferFromUtf8("blockstack"), - // }) - // ); + const resolvePrincipal = simnet.callReadOnlyFn( + "bns", + "resolve-principal", + [Cl.standardPrincipal(bob)], + alice + ); + expect(resolvePrincipal.result).toBeOk( + Cl.tuple({ + name: Cl.bufferFromUtf8("bob"), + namespace: Cl.bufferFromUtf8("blockstack"), + }) + ); - // const nameResolve = simnet.callReadOnlyFn( - // "bns", - // "name-resolve", - // [Cl.bufferFromUtf8(cases[0].namespace), Cl.bufferFromUtf8(name)], - // alice - // ); - // expect(nameResolve.result).toBeOk( - // Cl.tuple({ - // owner: Cl.standardPrincipal(bob), - // ["zonefile-hash"]: Cl.bufferFromUtf8(cases[0].zonefile), - // ["lease-ending-at"]: Cl.some(Cl.uint(17)), - // ["lease-started-at"]: Cl.uint(7), - // }) - // ); - // }); + const nameResolve = simnet.callReadOnlyFn( + "bns", + "name-resolve", + [Cl.bufferFromUtf8(cases[0].namespace), Cl.bufferFromUtf8(name)], + alice + ); + expect(nameResolve.result).toBeOk( + Cl.tuple({ + owner: Cl.standardPrincipal(bob), + ["zonefile-hash"]: Cl.bufferFromUtf8(cases[0].zonefile), + ["lease-ending-at"]: Cl.some(Cl.uint(16)), + ["lease-started-at"]: Cl.uint(6), + }) + ); + }); it("should fail registering twice", () => { const name = "bob"; From 1625de1da28a6e9b2a0f8f1d5301196c7a19cd78 Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Thu, 29 Feb 2024 10:08:01 +0100 Subject: [PATCH 19/39] fix: typo in test error message --- contrib/core-contract-tests/tests/pox_4_test.clar | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox_4_test.clar b/contrib/core-contract-tests/tests/pox_4_test.clar index dedd0c5d97..2d6f0f49fc 100644 --- a/contrib/core-contract-tests/tests/pox_4_test.clar +++ b/contrib/core-contract-tests/tests/pox_4_test.clar @@ -81,10 +81,10 @@ (err "Only length 20 should be valid for version 0x04") ) (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x05 (len test-lengths))) length-32-valid) - (err "Only length 20 should be valid for version 0x05") + (err "Only length 32 should be valid for version 0x05") ) (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x06 (len test-lengths))) length-32-valid) - (err "Only length 20 should be valid for version 0x06") + (err "Only length 32 should be valid for version 0x06") ) (asserts! (is-eq (map check-pox-addr-hashbytes-iter test-lengths (buff-repeat 0x07 (len test-lengths))) length-all-invalid) (err "No length should be valid for version 0x07") @@ -107,7 +107,6 @@ (define-public (test-get-total-ustx-stacked) (begin - ;; @continue (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) (ok true))) From 4ad742cdf378734cdedd78cdfa437ac130bb3db4 Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Thu, 29 Feb 2024 10:21:47 +0100 Subject: [PATCH 20/39] chore: clean up tests --- .../core-contract-tests/tests/pox_4_test.clar | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/contrib/core-contract-tests/tests/pox_4_test.clar b/contrib/core-contract-tests/tests/pox_4_test.clar index 2d6f0f49fc..704c42bbb2 100644 --- a/contrib/core-contract-tests/tests/pox_4_test.clar +++ b/contrib/core-contract-tests/tests/pox_4_test.clar @@ -1,17 +1,25 @@ (define-public (test-burn-height-to-reward-cycle) (begin (asserts! (is-eq u2 (contract-call? .pox-4 burn-height-to-reward-cycle u2100)) (err "Burn height 2100 should have been reward cycle 2")) - (ok true))) + (asserts! (is-eq u3 (contract-call? .pox-4 burn-height-to-reward-cycle u3150)) (err "Burn height 3150 should have been reward cycle 2")) + (ok true) + ) +) (define-public (test-reward-cycle-to-burn-height) (begin (asserts! (is-eq u10500 (contract-call? .pox-4 reward-cycle-to-burn-height u10)) (err "Cycle 10 height should have been at burn height 10500")) - (ok true))) + (asserts! (is-eq u18900 (contract-call? .pox-4 reward-cycle-to-burn-height u18)) (err "Cycle 18 height should have been at burn height 18900")) + (ok true) + ) +) (define-public (test-get-stacker-info-none) (begin (asserts! (is-none (contract-call? .pox-4 get-stacker-info tx-sender)) (err "By default, tx-sender should not have stacker info")) - (ok true))) + (ok true) + ) +) (define-private (check-pox-addr-version-iter (input (buff 1))) @@ -93,22 +101,27 @@ ) ) -(define-public (test-invalid-lock-height-too-low) - (let - ((actual (contract-call? .pox-4 check-pox-lock-period u0))) - (asserts! (not actual) (err u111)) - (ok true))) +(define-private (check-pox-lock-period-iter (period uint)) + (contract-call? .pox-4 check-pox-lock-period period) +) -(define-public (test-invalid-lock-height-too-high) - (let - ((actual (contract-call? .pox-4 check-pox-lock-period u13))) - (asserts! (not actual) (err u111)) - (ok true))) +(define-public (test-check-pox-lock-period) + (let ((actual (map check-pox-lock-period-iter (list u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13)))) + (asserts! (is-eq + actual + (list true true true true true true true true true true true true true false)) + (err {err: "Expected only lock periods 1 to 12 to be valid", actual: actual}) + ) + (ok true) + ) +) (define-public (test-get-total-ustx-stacked) (begin - (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err u111)) - (ok true))) + (asserts! (is-eq (contract-call? .pox-4 get-total-ustx-stacked u1) u0) (err "Total ustx stacked should be 0")) + (ok true) + ) +) (define-private (repeat-iter (a (buff 1)) (repeat {i: (buff 1), o: (buff 33)})) From 07ebe46eafef83cebe6c47ca9ef2c87d28a5b426 Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Thu, 29 Feb 2024 10:29:03 +0100 Subject: [PATCH 21/39] chore: forgot to switch back to false --- contrib/core-contract-tests/tests/pox_4_test.clar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/core-contract-tests/tests/pox_4_test.clar b/contrib/core-contract-tests/tests/pox_4_test.clar index 704c42bbb2..a158d9033e 100644 --- a/contrib/core-contract-tests/tests/pox_4_test.clar +++ b/contrib/core-contract-tests/tests/pox_4_test.clar @@ -109,7 +109,7 @@ (let ((actual (map check-pox-lock-period-iter (list u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13)))) (asserts! (is-eq actual - (list true true true true true true true true true true true true true false)) + (list false true true true true true true true true true true true true false)) (err {err: "Expected only lock periods 1 to 12 to be valid", actual: actual}) ) (ok true) From 4962452c06cb5f6e36819a6fd57e5a03cd1390b6 Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Thu, 29 Feb 2024 10:57:57 +0100 Subject: [PATCH 22/39] fix: attempt to fix codecov upload --- .github/workflows/stacks-core-tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stacks-core-tests.yml b/.github/workflows/stacks-core-tests.yml index 1e883d3d96..e8d82b4dcb 100644 --- a/.github/workflows/stacks-core-tests.yml +++ b/.github/workflows/stacks-core-tests.yml @@ -160,9 +160,10 @@ jobs: id: codecov uses: stacks-network/actions/codecov@main with: + fail_ci_if_error: true test-name: ${{ matrix.test-name }} upload-only: true - filename: ./lcov.info + filename: ./contrib/core-contract-tests/lcov.info # Core contract tests on Clarinet v1 # Check for false positives/negatives From 8d327754a8a9ad6e8ead8706cb6f91d2714877fa Mon Sep 17 00:00:00 2001 From: jesus Date: Mon, 26 Feb 2024 14:04:43 -0500 Subject: [PATCH 23/39] two minor checks --- stackslib/src/chainstate/stacks/boot/pox-4.clar | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index d54f3b8d5f..77c8ef2550 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -32,6 +32,7 @@ (define-constant ERR_DELEGATION_ALREADY_REVOKED 34) (define-constant ERR_INVALID_SIGNATURE_PUBKEY 35) (define-constant ERR_INVALID_SIGNATURE_RECOVER 36) +(define-constant ERR_INVALID_REWARD_CYCLE 37) ;; Valid values for burnchain address versions. ;; These first four correspond to address hash modes in Stacks 2.1, @@ -1368,6 +1369,10 @@ (asserts! (is-eq (unwrap! (principal-construct? (if is-in-mainnet STACKS_ADDR_VERSION_MAINNET STACKS_ADDR_VERSION_TESTNET) (hash160 signer-key)) (err ERR_INVALID_SIGNER_KEY)) tx-sender) (err ERR_NOT_ALLOWED)) + ;; Must be called with positive period + (asserts! (>= period u1) (err ERR_STACKING_INVALID_LOCK_PERIOD)) + ;; Must be current or future reward cycle + (asserts! (>= reward-cycle (current-pox-reward-cycle)) (err ERR_INVALID_REWARD_CYCLE)) (map-set signer-key-authorizations { pox-addr: pox-addr, period: period, reward-cycle: reward-cycle, topic: topic, signer-key: signer-key } allowed) (ok allowed))) From 11a5ce92b7c7f50d14f91033d88779294985542b Mon Sep 17 00:00:00 2001 From: jesus Date: Mon, 26 Feb 2024 16:18:04 -0500 Subject: [PATCH 24/39] updated test_set_signer_key_auth passing again, still work remaining --- .../src/chainstate/stacks/boot/pox_4_tests.rs | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs index ebb8c5f078..33567e6d42 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs @@ -2642,6 +2642,7 @@ fn test_set_signer_key_auth() { let mut signer_nonce = 0; let signer_key = &keys[1]; let signer_public_key = StacksPublicKey::from_private(signer_key); + let signer_addr = key_to_stacks_addr(&signer_key); let pox_addr = pox_addr_from(&signer_key); // Only the address associated with `signer-key` can enable auth for that key @@ -2657,21 +2658,38 @@ fn test_set_signer_key_auth() { Some(&alice_key), ); + let current_cycle = get_current_reward_cycle(&peer, &burnchain); + println!("Current cycle: {}", current_cycle); + + // Test that period is at least u1 + let invalid_auth_tx_period: StacksTransaction = make_pox_4_set_signer_key_auth( + &pox_addr, + &signer_key, + 22, + &Pox4SignatureTopic::StackStx, + 0, + false, + signer_nonce, + Some(&signer_key), + ); + + // Test that confirmed reward cycle is at least current reward cycle + // Disable auth for `signer-key` - let disable_auth_nonce = signer_nonce; + signer_nonce += 1; let disable_auth_tx: StacksTransaction = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period, false, - disable_auth_nonce, + signer_nonce, None, ); let latest_block = - peer.tenure_with_txs(&[invalid_enable_tx, disable_auth_tx], &mut coinbase_nonce); + peer.tenure_with_txs(&[invalid_enable_tx, invalid_auth_tx_period, disable_auth_tx], &mut coinbase_nonce); let alice_txs = get_last_block_sender_transactions(&observer, alice_addr); let invalid_enable_tx_result = alice_txs @@ -2682,11 +2700,18 @@ fn test_set_signer_key_auth() { let expected_error = Value::error(Value::Int(19)).unwrap(); assert_eq!(invalid_enable_tx_result, expected_error); + let signer_txs = get_last_block_sender_transactions(&observer, signer_addr); + + // // Print all signer transaction receipts + println!("signer_txs: {:?}", signer_txs); + for tx in signer_txs { + println!("txs in signer_tx? {:?}", tx.result); + } let signer_key_enabled = get_signer_key_authorization_pox_4( &mut peer, &latest_block, &pox_addr, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, @@ -2700,7 +2725,7 @@ fn test_set_signer_key_auth() { let enable_auth_tx = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period, true, @@ -2714,7 +2739,7 @@ fn test_set_signer_key_auth() { &mut peer, &latest_block, &pox_addr, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, @@ -2728,7 +2753,7 @@ fn test_set_signer_key_auth() { let disable_auth_tx = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period, false, @@ -2742,7 +2767,7 @@ fn test_set_signer_key_auth() { &mut peer, &latest_block, &pox_addr, - 1, + 22, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, From 2a63322ea619606706d63137954fad9bbe577805 Mon Sep 17 00:00:00 2001 From: jesus Date: Tue, 27 Feb 2024 07:25:43 -0500 Subject: [PATCH 25/39] completed updating test_set_signer_key_auth --- .../src/chainstate/stacks/boot/pox_4_tests.rs | 63 +++++++++++++------ 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs index 33567e6d42..0ddf9075c2 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs @@ -2645,6 +2645,8 @@ fn test_set_signer_key_auth() { let signer_addr = key_to_stacks_addr(&signer_key); let pox_addr = pox_addr_from(&signer_key); + let current_reward_cycle = get_current_reward_cycle(&peer, &burnchain); + // Only the address associated with `signer-key` can enable auth for that key let invalid_enable_nonce = alice_nonce; let invalid_enable_tx = make_pox_4_set_signer_key_auth( @@ -2658,29 +2660,39 @@ fn test_set_signer_key_auth() { Some(&alice_key), ); - let current_cycle = get_current_reward_cycle(&peer, &burnchain); - println!("Current cycle: {}", current_cycle); - // Test that period is at least u1 - let invalid_auth_tx_period: StacksTransaction = make_pox_4_set_signer_key_auth( + let signer_invalid_period_nonce = signer_nonce; + signer_nonce += 1; + let invalid_tx_period: StacksTransaction = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 22, + current_reward_cycle, &Pox4SignatureTopic::StackStx, 0, false, - signer_nonce, + signer_invalid_period_nonce, Some(&signer_key), ); + let signer_invalid_cycle_nonce = signer_nonce; + signer_nonce += 1; // Test that confirmed reward cycle is at least current reward cycle + let invalid_tx_cycle: StacksTransaction = make_pox_4_set_signer_key_auth( + &pox_addr, + &signer_key, + 1, + &Pox4SignatureTopic::StackStx, + 1, + false, + signer_invalid_cycle_nonce, + Some(&signer_key), + ); // Disable auth for `signer-key` - signer_nonce += 1; let disable_auth_tx: StacksTransaction = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 22, + current_reward_cycle, &Pox4SignatureTopic::StackStx, lock_period, false, @@ -2689,7 +2701,7 @@ fn test_set_signer_key_auth() { ); let latest_block = - peer.tenure_with_txs(&[invalid_enable_tx, invalid_auth_tx_period, disable_auth_tx], &mut coinbase_nonce); + peer.tenure_with_txs(&[invalid_enable_tx, invalid_tx_period, invalid_tx_cycle, disable_auth_tx], &mut coinbase_nonce); let alice_txs = get_last_block_sender_transactions(&observer, alice_addr); let invalid_enable_tx_result = alice_txs @@ -2702,16 +2714,29 @@ fn test_set_signer_key_auth() { let signer_txs = get_last_block_sender_transactions(&observer, signer_addr); - // // Print all signer transaction receipts - println!("signer_txs: {:?}", signer_txs); - for tx in signer_txs { - println!("txs in signer_tx? {:?}", tx.result); - } + let invalid_tx_period_result = signer_txs.clone() + .get(signer_invalid_period_nonce as usize) + .unwrap() + .result + .clone(); + + // Check for invalid lock period err + assert_eq!(invalid_tx_period_result, Value::error(Value::Int(2)).unwrap()); + + let invalid_tx_cycle_result = signer_txs.clone() + .get(signer_invalid_cycle_nonce as usize) + .unwrap() + .result + .clone(); + + // Check for invalid cycle err + assert_eq!(invalid_tx_cycle_result, Value::error(Value::Int(37)).unwrap()); + let signer_key_enabled = get_signer_key_authorization_pox_4( &mut peer, &latest_block, &pox_addr, - 22, + current_reward_cycle.clone() as u64, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, @@ -2725,7 +2750,7 @@ fn test_set_signer_key_auth() { let enable_auth_tx = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 22, + current_reward_cycle, &Pox4SignatureTopic::StackStx, lock_period, true, @@ -2739,7 +2764,7 @@ fn test_set_signer_key_auth() { &mut peer, &latest_block, &pox_addr, - 22, + current_reward_cycle.clone() as u64, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, @@ -2753,7 +2778,7 @@ fn test_set_signer_key_auth() { let disable_auth_tx = make_pox_4_set_signer_key_auth( &pox_addr, &signer_key, - 22, + current_reward_cycle, &Pox4SignatureTopic::StackStx, lock_period, false, @@ -2767,7 +2792,7 @@ fn test_set_signer_key_auth() { &mut peer, &latest_block, &pox_addr, - 22, + current_reward_cycle.clone() as u64, &Pox4SignatureTopic::StackStx, lock_period.try_into().unwrap(), &signer_public_key, From 37a681dc04c8e173d906b5e2d45efabb692ed482 Mon Sep 17 00:00:00 2001 From: jesus Date: Tue, 27 Feb 2024 07:28:35 -0500 Subject: [PATCH 26/39] formatter --- .../src/chainstate/stacks/boot/pox_4_tests.rs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs index 0ddf9075c2..4f51b81e82 100644 --- a/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs +++ b/stackslib/src/chainstate/stacks/boot/pox_4_tests.rs @@ -2678,9 +2678,9 @@ fn test_set_signer_key_auth() { signer_nonce += 1; // Test that confirmed reward cycle is at least current reward cycle let invalid_tx_cycle: StacksTransaction = make_pox_4_set_signer_key_auth( - &pox_addr, - &signer_key, - 1, + &pox_addr, + &signer_key, + 1, &Pox4SignatureTopic::StackStx, 1, false, @@ -2700,8 +2700,15 @@ fn test_set_signer_key_auth() { None, ); - let latest_block = - peer.tenure_with_txs(&[invalid_enable_tx, invalid_tx_period, invalid_tx_cycle, disable_auth_tx], &mut coinbase_nonce); + let latest_block = peer.tenure_with_txs( + &[ + invalid_enable_tx, + invalid_tx_period, + invalid_tx_cycle, + disable_auth_tx, + ], + &mut coinbase_nonce, + ); let alice_txs = get_last_block_sender_transactions(&observer, alice_addr); let invalid_enable_tx_result = alice_txs @@ -2714,23 +2721,31 @@ fn test_set_signer_key_auth() { let signer_txs = get_last_block_sender_transactions(&observer, signer_addr); - let invalid_tx_period_result = signer_txs.clone() + let invalid_tx_period_result = signer_txs + .clone() .get(signer_invalid_period_nonce as usize) .unwrap() .result .clone(); // Check for invalid lock period err - assert_eq!(invalid_tx_period_result, Value::error(Value::Int(2)).unwrap()); + assert_eq!( + invalid_tx_period_result, + Value::error(Value::Int(2)).unwrap() + ); - let invalid_tx_cycle_result = signer_txs.clone() + let invalid_tx_cycle_result = signer_txs + .clone() .get(signer_invalid_cycle_nonce as usize) .unwrap() .result .clone(); // Check for invalid cycle err - assert_eq!(invalid_tx_cycle_result, Value::error(Value::Int(37)).unwrap()); + assert_eq!( + invalid_tx_cycle_result, + Value::error(Value::Int(37)).unwrap() + ); let signer_key_enabled = get_signer_key_authorization_pox_4( &mut peer, From 5a54ae45a572403402846a762f5f869197afd546 Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 29 Feb 2024 08:18:45 -0500 Subject: [PATCH 27/39] remaining tests intact --- stackslib/src/chainstate/stacks/boot/pox-4.clar | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index 77c8ef2550..8ccf3567a2 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -117,6 +117,9 @@ ;; (6) (reward-cycle-to-burn-height (+ lock-period first-reward-cycle)) == (get unlock-height (stx-account stacker)) ;; These invariants only hold while `cur-reward-cycle < (+ lock-period first-reward-cycle)` ;; +(define-map protocols principal (list 10000 uint)) +(define-map protocol-positions {protocol: principal, position-id: uint} {status: (string-ascii 32), collateral: uint}) + (define-map stacking-state { stacker: principal } { From 8490fd9f999e3005b44644ff9ef6a3944daf52b4 Mon Sep 17 00:00:00 2001 From: jesus Date: Thu, 29 Feb 2024 10:17:55 -0500 Subject: [PATCH 28/39] removed throwaway --- stackslib/src/chainstate/stacks/boot/pox-4.clar | 3 --- 1 file changed, 3 deletions(-) diff --git a/stackslib/src/chainstate/stacks/boot/pox-4.clar b/stackslib/src/chainstate/stacks/boot/pox-4.clar index 8ccf3567a2..77c8ef2550 100644 --- a/stackslib/src/chainstate/stacks/boot/pox-4.clar +++ b/stackslib/src/chainstate/stacks/boot/pox-4.clar @@ -117,9 +117,6 @@ ;; (6) (reward-cycle-to-burn-height (+ lock-period first-reward-cycle)) == (get unlock-height (stx-account stacker)) ;; These invariants only hold while `cur-reward-cycle < (+ lock-period first-reward-cycle)` ;; -(define-map protocols principal (list 10000 uint)) -(define-map protocol-positions {protocol: principal, position-id: uint} {status: (string-ascii 32), collateral: uint}) - (define-map stacking-state { stacker: principal } { From 770ee39af0f41603a3c96152baad3d3c13d42b7e Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Thu, 29 Feb 2024 12:07:17 -0500 Subject: [PATCH 29/39] Round up thresholds using +0.9 Signed-off-by: Jacinta Ferrant --- stacks-signer/src/signer.rs | 5 +++-- testnet/stacks-node/src/nakamoto_node/miner.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index b92ed0e1de..42e57baf3e 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -156,8 +156,9 @@ impl From for Signer { .expect("FATAL: Too many registered signers to fit in a u32"); let num_keys = u32::try_from(signer_config.registered_signers.public_keys.key_ids.len()) .expect("FATAL: Too many key ids to fit in a u32"); - let threshold = num_keys * 7 / 10; - let dkg_threshold = num_keys * 9 / 10; + // Always add +0.9 to force any remainder to round up to the next integer + let threshold = (num_keys * 7 + 9) / 10; + let dkg_threshold = (num_keys * 9 + 9) / 10; let coordinator_config = CoordinatorConfig { threshold, diff --git a/testnet/stacks-node/src/nakamoto_node/miner.rs b/testnet/stacks-node/src/nakamoto_node/miner.rs index 5186943197..9ebcb7856b 100644 --- a/testnet/stacks-node/src/nakamoto_node/miner.rs +++ b/testnet/stacks-node/src/nakamoto_node/miner.rs @@ -391,7 +391,8 @@ impl BlockMinerThread { let slot_ids = slot_ids_addresses.keys().cloned().collect::>(); // If more than a threshold percentage of the signers reject the block, we should not wait any further let weights: u64 = signer_weights.values().sum(); - let rejection_threshold = weights / 10 * 7; + // Always add +0.9 to force any remainder to round up to the next integer + let rejection_threshold = (weights * 7 + 9) / 10; let mut rejections = HashSet::new(); let mut rejections_weight: u64 = 0; let now = Instant::now(); From 206eca639fd0bf101f4e4f933af1fcf68062328a Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Thu, 29 Feb 2024 12:58:22 -0500 Subject: [PATCH 30/39] Cast to f64 and use ceil instead Signed-off-by: Jacinta Ferrant --- stacks-signer/src/signer.rs | 5 ++--- testnet/stacks-node/src/nakamoto_node/miner.rs | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index 42e57baf3e..27f42dd69f 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -156,9 +156,8 @@ impl From for Signer { .expect("FATAL: Too many registered signers to fit in a u32"); let num_keys = u32::try_from(signer_config.registered_signers.public_keys.key_ids.len()) .expect("FATAL: Too many key ids to fit in a u32"); - // Always add +0.9 to force any remainder to round up to the next integer - let threshold = (num_keys * 7 + 9) / 10; - let dkg_threshold = (num_keys * 9 + 9) / 10; + let threshold = (num_keys as f64 * 7_f64 / 10_f64).ceil() as u32; + let dkg_threshold = (num_keys as f64 * 9_f64 / 10_f64).ceil() as u32; let coordinator_config = CoordinatorConfig { threshold, diff --git a/testnet/stacks-node/src/nakamoto_node/miner.rs b/testnet/stacks-node/src/nakamoto_node/miner.rs index 9ebcb7856b..ec57fc3ef7 100644 --- a/testnet/stacks-node/src/nakamoto_node/miner.rs +++ b/testnet/stacks-node/src/nakamoto_node/miner.rs @@ -391,8 +391,7 @@ impl BlockMinerThread { let slot_ids = slot_ids_addresses.keys().cloned().collect::>(); // If more than a threshold percentage of the signers reject the block, we should not wait any further let weights: u64 = signer_weights.values().sum(); - // Always add +0.9 to force any remainder to round up to the next integer - let rejection_threshold = (weights * 7 + 9) / 10; + let rejection_threshold: u64 = (weights as f64 * 7_f64 / 10_f64).ceil() as u64; let mut rejections = HashSet::new(); let mut rejections_weight: u64 = 0; let now = Instant::now(); From a9ef3ba14f4f0d6d992ada06d689dbd6a1244712 Mon Sep 17 00:00:00 2001 From: MarvinJanssen Date: Fri, 1 Mar 2024 14:08:41 +0100 Subject: [PATCH 31/39] chore: enabled disabled unit test --- .../tests/bns/name_register.test.ts | 75 +++++++++---------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/contrib/core-contract-tests/tests/bns/name_register.test.ts b/contrib/core-contract-tests/tests/bns/name_register.test.ts index 448df6b322..0647b0a9cc 100644 --- a/contrib/core-contract-tests/tests/bns/name_register.test.ts +++ b/contrib/core-contract-tests/tests/bns/name_register.test.ts @@ -557,42 +557,41 @@ describe("register a name again before and after expiration", () => { expect(register.result).toBeOk(Cl.bool(true)); }); - // temp disabled, focusing on importing clarunit correctly - // it("should allow someone else to register after expiration", () => { - // simnet.mineEmptyBlocks(cases[0].renewalRule + 5001); - - // const name = "bob"; - // const salt = "2222"; - // const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${salt}`); - // const sha256 = createHash("sha256").update(merged).digest(); - // const ripemd160 = createHash("ripemd160").update(sha256).digest(); - // simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], charlie); - // const register = simnet.callPublicFn( - // "bns", - // "name-register", - // [ - // Cl.bufferFromAscii(cases[0].namespace), - // Cl.bufferFromAscii(name), - // Cl.bufferFromAscii(salt), - // Cl.bufferFromAscii("CHARLIE"), - // ], - // charlie - // ); - // expect(register.result).toBeOk(Cl.bool(true)); - - // const resolve = simnet.callReadOnlyFn( - // "bns", - // "name-resolve", - // [Cl.bufferFromAscii(cases[0].namespace), Cl.bufferFromAscii(name)], - // alice - // ); - // expect(resolve.result).toBeOk( - // Cl.tuple({ - // owner: Cl.standardPrincipal(charlie), - // ["zonefile-hash"]: Cl.bufferFromAscii("CHARLIE"), - // ["lease-ending-at"]: Cl.some(Cl.uint(5030)), - // ["lease-started-at"]: Cl.uint(5020), - // }) - // ); - // }); + it("should allow someone else to register after expiration", () => { + simnet.mineEmptyBlocks(cases[0].renewalRule + 5001); + + const name = "bob"; + const salt = "2222"; + const merged = new TextEncoder().encode(`${name}.${cases[0].namespace}${salt}`); + const sha256 = createHash("sha256").update(merged).digest(); + const ripemd160 = createHash("ripemd160").update(sha256).digest(); + simnet.callPublicFn("bns", "name-preorder", [Cl.buffer(ripemd160), Cl.uint(2560000)], charlie); + const register = simnet.callPublicFn( + "bns", + "name-register", + [ + Cl.bufferFromAscii(cases[0].namespace), + Cl.bufferFromAscii(name), + Cl.bufferFromAscii(salt), + Cl.bufferFromAscii("CHARLIE"), + ], + charlie + ); + expect(register.result).toBeOk(Cl.bool(true)); + + const resolve = simnet.callReadOnlyFn( + "bns", + "name-resolve", + [Cl.bufferFromAscii(cases[0].namespace), Cl.bufferFromAscii(name)], + alice + ); + expect(resolve.result).toBeOk( + Cl.tuple({ + owner: Cl.standardPrincipal(charlie), + ["zonefile-hash"]: Cl.bufferFromAscii("CHARLIE"), + ["lease-ending-at"]: Cl.some(Cl.uint(5029)), + ["lease-started-at"]: Cl.uint(5019), + }) + ); + }); }); From 533bf19f7c7f1819e2641c2cea87ff1cfea9c045 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Mon, 26 Feb 2024 18:28:37 -0500 Subject: [PATCH 32/39] Filter only invalid formed transactions and enforce one per signer in stacks-signer Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/mod.rs | 9 - stacks-signer/src/runloop.rs | 8 +- stacks-signer/src/signer.rs | 728 ++++++++++++-------------------- 3 files changed, 268 insertions(+), 477 deletions(-) diff --git a/stacks-signer/src/client/mod.rs b/stacks-signer/src/client/mod.rs index 959ce56dbf..138913ee6c 100644 --- a/stacks-signer/src/client/mod.rs +++ b/stacks-signer/src/client/mod.rs @@ -207,15 +207,6 @@ pub(crate) mod tests { TcpListener::bind(config.node_host).unwrap() } - /// Create a mock server on the same port as the config and write a response to it - pub fn mock_server_from_config_and_write_response( - config: &GlobalConfig, - bytes: &[u8], - ) -> [u8; 1024] { - let mock_server = mock_server_from_config(config); - write_response(mock_server, bytes) - } - /// Write a response to the mock server and return the request bytes pub fn write_response(mock_server: TcpListener, bytes: &[u8]) -> [u8; 1024] { debug!("Writing a response..."); diff --git a/stacks-signer/src/runloop.rs b/stacks-signer/src/runloop.rs index 0b6a0c05a3..02fb494c6a 100644 --- a/stacks-signer/src/runloop.rs +++ b/stacks-signer/src/runloop.rs @@ -156,6 +156,12 @@ impl RunLoop { if signer.reward_cycle == prior_reward_cycle { // The signers have been calculated for the next reward cycle. Update the current one debug!("Signer #{}: Next reward cycle ({reward_cycle}) signer set calculated. Updating current reward cycle ({prior_reward_cycle}) signer.", signer.signer_id); + signer.next_signers = new_signer_config + .registered_signers + .signer_ids + .keys() + .copied() + .collect(); signer.next_signer_ids = new_signer_config .registered_signers .signer_ids @@ -201,7 +207,7 @@ impl RunLoop { if signer.approved_aggregate_public_key.is_none() { retry_with_exponential_backoff(|| { signer - .update_dkg(&self.stacks_client, current_reward_cycle) + .update_dkg(&self.stacks_client) .map_err(backoff::Error::transient) })?; } diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index 27f42dd69f..f2e5c92e38 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -134,10 +134,14 @@ pub struct Signer { pub signer_ids: Vec, /// The addresses of other signers mapped to their signer slot ID pub signer_slot_ids: HashMap, + /// The addresses of other signers + pub signers: Vec, /// The other signer ids for the NEXT reward cycle's signers pub next_signer_ids: Vec, /// The signer addresses mapped to slot ID for the NEXT reward cycle's signers pub next_signer_slot_ids: HashMap, + /// The addresses of the signers for the NEXT reward cycle + pub next_signers: Vec, /// The reward cycle this signer belongs to pub reward_cycle: u64, /// The tx fee in uSTX to use if the epoch is pre Nakamoto (Epoch 3.0) @@ -209,8 +213,15 @@ impl From for Signer { .copied() .collect(), signer_slot_ids: signer_config.registered_signers.signer_slot_ids, + signers: signer_config + .registered_signers + .signer_ids + .keys() + .copied() + .collect(), next_signer_ids: vec![], next_signer_slot_ids: HashMap::new(), + next_signers: vec![], reward_cycle: signer_config.reward_cycle, tx_fee_ustx: signer_config.tx_fee_ustx, coordinator_selector, @@ -353,7 +364,6 @@ impl Signer { stacks_client: &StacksClient, block_validate_response: &BlockValidateResponse, res: Sender>, - current_reward_cycle: u64, ) { let block_info = match block_validate_response { BlockValidateResponse::Ok(block_validate_ok) => { @@ -364,11 +374,7 @@ impl Signer { debug!("Signer #{}: Received a block validate response for a block we have not seen before. Ignoring...", self.signer_id); return; }; - let is_valid = self.verify_block_transactions( - stacks_client, - &block_info.block, - current_reward_cycle, - ); + let is_valid = self.verify_block_transactions(stacks_client, &block_info.block); block_info.valid = Some(is_valid); info!( "Signer #{}: Treating block validation for block {} as valid: {:?}", @@ -413,7 +419,7 @@ impl Signer { msg: Message::NonceRequest(nonce_request), sig: vec![], }; - self.handle_packets(stacks_client, res, &[packet], current_reward_cycle); + self.handle_packets(stacks_client, res, &[packet]); } else { let coordinator_id = self.coordinator_selector.get_coordinator().0; if block_info.valid.unwrap_or(false) @@ -449,7 +455,6 @@ impl Signer { stacks_client: &StacksClient, res: Sender>, messages: &[SignerMessage], - current_reward_cycle: u64, ) { let coordinator_pubkey = self.coordinator_selector.get_coordinator().1; let packets: Vec = messages @@ -462,7 +467,7 @@ impl Signer { } }) .collect(); - self.handle_packets(stacks_client, res, &packets, current_reward_cycle); + self.handle_packets(stacks_client, res, &packets); } /// Handle proposed blocks submitted by the miners to stackerdb @@ -492,7 +497,6 @@ impl Signer { stacks_client: &StacksClient, res: Sender>, packets: &[Packet], - current_reward_cycle: u64, ) { let signer_outbound_messages = self .signing_round @@ -520,7 +524,7 @@ impl Signer { if !operation_results.is_empty() { // We have finished a signing or DKG round, either successfully or due to error. // Regardless of the why, update our state to Idle as we should not expect the operation to continue. - self.process_operation_results(stacks_client, &operation_results, current_reward_cycle); + self.process_operation_results(stacks_client, &operation_results); self.send_operation_results(res, operation_results); self.finish_operation(); } else if !packets.is_empty() && self.coordinator.state != CoordinatorState::Idle { @@ -631,7 +635,6 @@ impl Signer { &mut self, stacks_client: &StacksClient, block: &NakamotoBlock, - current_reward_cycle: u64, ) -> bool { if self.approved_aggregate_public_key.is_some() { // We do not enforce a block contain any transactions except the aggregate votes when it is NOT already set @@ -639,9 +642,7 @@ impl Signer { debug!("Signer #{}: Already have an aggregate key for reward cycle {}. Skipping transaction verification...", self.signer_id, self.reward_cycle); return true; } - if let Ok(expected_transactions) = - self.get_expected_transactions(stacks_client, current_reward_cycle) - { + if let Ok(expected_transactions) = self.get_expected_transactions(stacks_client) { //It might be worth building a hashset of the blocks' txids and checking that against the expected transaction's txid. let block_tx_hashset = block.txs.iter().map(|tx| tx.txid()).collect::>(); // Ensure the block contains the transactions we expect @@ -708,144 +709,73 @@ impl Signer { } } - /// Filter out transactions from the stackerdb that are not valid - /// i.e. not valid vote-for-aggregate-public-key transactions from registered signers - fn filter_invalid_transactions( + /// Select one transaction per address by sorting based first on nonce and then txid + fn filter_one_transaction_per_address( &self, - stacks_client: &StacksClient, - current_reward_cycle: u64, - signer_slot_ids: &HashMap, - transaction: StacksTransaction, - ) -> Option { - // Filter out transactions that have already been confirmed (can happen if a signer did not update stacker db since the last block was processed) + transactions: Vec, + ) -> Vec { + let mut filtered_transactions: HashMap = HashMap::new(); + for transaction in transactions { + let origin_address = transaction.origin_address(); + let origin_nonce = transaction.get_origin_nonce(); + if let Some(entry) = filtered_transactions.get_mut(&origin_address) { + let entry_nonce = entry.get_origin_nonce(); + if entry_nonce > origin_nonce + || (entry_nonce == origin_nonce && entry.txid() > transaction.txid()) + { + *entry = transaction; + } + } else { + filtered_transactions.insert(origin_address, transaction); + } + } + filtered_transactions.into_values().collect() + } + + /// Verify that the transaction is a valid vote for the aggregate public key + /// Note: it does not verify the function arguments, only that the transaction is validly formed + fn valid_vote_transaction( + &self, + account_nonces: &HashMap, + transaction: &StacksTransaction, + ) -> bool { let origin_address = transaction.origin_address(); let origin_nonce = transaction.get_origin_nonce(); - let Some(origin_signer_id) = signer_slot_ids.get(&origin_address) else { + let Some(account_nonce) = account_nonces.get(&origin_address) else { debug!( - "Signer #{}: Unrecognized origin address ({origin_address}). Filtering ({}).", - self.signer_id, - transaction.txid() - ); - return None; - }; - let Ok(account_nonce) = retry_with_exponential_backoff(|| { - stacks_client - .get_account_nonce(&origin_address) - .map_err(backoff::Error::transient) - }) else { - warn!( - "Signer #{}: Unable to get account for transaction origin address: {origin_address}. Filtering ({}).", + "Signer #{}: Unrecognized origin address ({origin_address}).", self.signer_id, - transaction.txid() ); - return None; + return false; }; - // TODO: add a check that we don't have two conflicting transactions in the same block from the same signer. This is a potential attack vector (will result in an invalid block) - if origin_nonce < account_nonce { - debug!("Signer #{}: Received a transaction with an outdated nonce ({account_nonce} < {origin_nonce}). Filtering ({}).", self.signer_id, transaction.txid()); - return None; - } if transaction.is_mainnet() != self.mainnet { debug!( - "Signer #{}: Received a transaction with an unexpected network. Filtering ({}).", + "Signer #{}: Received a transaction for an unexpected network.", self.signer_id, - transaction.txid() ); - return None; - } - let Ok(valid) = retry_with_exponential_backoff(|| { - self.verify_payload( - stacks_client, - &transaction, - *origin_signer_id, - current_reward_cycle, - ) - .map_err(backoff::Error::transient) - }) else { - warn!( - "Signer #{}: Unable to validate transaction payload. Filtering ({}).", - self.signer_id, - transaction.txid() - ); - return None; - }; - if !valid { - debug!( - "Signer #{}: Received a transaction with an invalid payload. Filtering ({}).", - self.signer_id, - transaction.txid() - ); - return None; - } - debug!( - "Signer #{}: Expect transaction {} ({transaction:?})", - self.signer_id, - transaction.txid() - ); - Some(transaction) - } - - ///Helper function to verify the payload contents of a transaction are as expected - fn verify_payload( - &self, - stacks_client: &StacksClient, - transaction: &StacksTransaction, - origin_signer_id: u32, - current_reward_cycle: u64, - ) -> Result { - let Some((index, _point, round, reward_cycle)) = - Self::parse_vote_for_aggregate_public_key(transaction) - else { - // The transaction is not a valid vote-for-aggregate-public-key transaction - return Ok(false); - }; - if index != origin_signer_id as u64 { - // The signer is attempting to vote for another signer id than their own - return Ok(false); - } - let next_reward_cycle = current_reward_cycle.wrapping_add(1); - if reward_cycle != next_reward_cycle { - // The signer is attempting to vote for a reward cycle that is not the next reward cycle - return Ok(false); - } - - let vote = stacks_client.get_vote_for_aggregate_public_key( - round, - reward_cycle, - transaction.origin_address(), - )?; - if vote.is_some() { - // The signer has already voted for this round and reward cycle - return Ok(false); + return false; } - - let last_round = stacks_client.get_last_round(reward_cycle)?; - // TODO: should we impose a limit on the number of special cased transactions allowed for a single signer at any given time?? In theory only 1 would be required per dkg round i.e. per block - if last_round.unwrap_or(0).saturating_add(1) < round { - // Do not allow future votes. This is to prevent signers sending a bazillion votes for a future round and clogging the block space - // The signer is attempting to vote for a round that is greater than one past the last round - return Ok(false); + if origin_nonce < *account_nonce { + debug!("Signer #{}: Received a transaction with an outdated nonce ({account_nonce} < {origin_nonce}).", self.signer_id); + return false; } - Ok(true) + Self::parse_vote_for_aggregate_public_key(transaction).is_some() } - /// Get this signer's transactions from stackerdb, filtering out any invalid transactions + /// Get transactions from stackerdb for the given addresses and account nonces, filtering out any malformed transactions fn get_signer_transactions( &mut self, - stacks_client: &StacksClient, - current_reward_cycle: u64, + nonces: &HashMap, ) -> Result, ClientError> { let transactions: Vec<_> = self .stackerdb .get_current_transactions_with_retry(self.signer_id)? .into_iter() .filter_map(|tx| { - self.filter_invalid_transactions( - stacks_client, - current_reward_cycle, - &self.signer_slot_ids, - tx, - ) + if !self.valid_vote_transaction(nonces, &tx) { + return None; + } + Some(tx) }) .collect(); Ok(transactions) @@ -855,7 +785,6 @@ impl Signer { fn get_expected_transactions( &mut self, stacks_client: &StacksClient, - current_reward_cycle: u64, ) -> Result, ClientError> { if self.next_signer_ids.is_empty() { debug!( @@ -864,20 +793,22 @@ impl Signer { ); return Ok(vec![]); } + // Get all the account nonces for the next signers + let account_nonces = self.get_account_nonces(stacks_client, &self.next_signers); let transactions: Vec<_> = self .stackerdb .get_next_transactions_with_retry(&self.next_signer_ids)? .into_iter() .filter_map(|tx| { - self.filter_invalid_transactions( - stacks_client, - current_reward_cycle, - &self.next_signer_slot_ids, - tx, - ) + if !self.valid_vote_transaction(&account_nonces, &tx) { + return None; + } + Some(tx) }) .collect(); - Ok(transactions) + + // We only allow enforcement of one special cased transaction per signer address per block + Ok(self.filter_one_transaction_per_address(transactions)) } /// Determine the vote for a block and update the block info and nonce request accordingly @@ -954,7 +885,6 @@ impl Signer { &mut self, stacks_client: &StacksClient, operation_results: &[OperationResult], - current_reward_cycle: u64, ) { for operation_result in operation_results { // Signers only every trigger non-taproot signing rounds over blocks. Ignore SignTaproot results @@ -967,7 +897,7 @@ impl Signer { debug!("Signer #{}: Received a signature result for a taproot signature. Nothing to broadcast as we currently sign blocks with a FROST signature.", self.signer_id); } OperationResult::Dkg(point) => { - self.process_dkg(stacks_client, point, current_reward_cycle); + self.process_dkg(stacks_client, point); } OperationResult::SignError(e) => { warn!("Signer #{}: Received a Sign error: {e:?}", self.signer_id); @@ -982,12 +912,7 @@ impl Signer { } /// Process a dkg result by broadcasting a vote to the stacks node - fn process_dkg( - &mut self, - stacks_client: &StacksClient, - point: &Point, - current_reward_cycle: u64, - ) { + fn process_dkg(&mut self, stacks_client: &StacksClient, point: &Point) { let epoch = retry_with_exponential_backoff(|| { stacks_client .get_node_epoch() @@ -1004,19 +929,41 @@ impl Signer { None }; // Get our current nonce from the stacks node and compare it against what we have sitting in the stackerdb instance - let nonce = self.get_next_nonce(stacks_client, current_reward_cycle); + let signer_address = stacks_client.get_signer_address(); + // Retreieve ALL account nonces as we may have transactions from other signers in our stackerdb slot that we care about + let account_nonces = self.get_account_nonces(stacks_client, &self.signers); + let account_nonce = account_nonces.get(signer_address).unwrap_or(&0); + let signer_transactions = retry_with_exponential_backoff(|| { + self.get_signer_transactions(&account_nonces) + .map_err(backoff::Error::transient) + }) + .map_err(|e| { + warn!( + "Signer #{}: Unable to get signer transactions: {e:?}", + self.signer_id + ); + }) + .unwrap_or_default(); + // If we have a transaction in the stackerdb slot, we need to increment the nonce hence the +1, else should use the account nonce + let next_nonce = signer_transactions + .first() + .map(|tx| tx.get_origin_nonce().wrapping_add(1)) + .unwrap_or(*account_nonce); match stacks_client.build_vote_for_aggregate_public_key( self.stackerdb.get_signer_slot_id(), self.coordinator.current_dkg_id, *point, self.reward_cycle, tx_fee, - nonce, + next_nonce, ) { - Ok(transaction) => { - if let Err(e) = - self.broadcast_dkg_vote(stacks_client, transaction, epoch, current_reward_cycle) - { + Ok(new_transaction) => { + if let Err(e) = self.broadcast_dkg_vote( + stacks_client, + epoch, + signer_transactions, + new_transaction, + ) { warn!( "Signer #{}: Failed to broadcast DKG vote ({point:?}): {e:?}", self.signer_id @@ -1032,42 +979,47 @@ impl Signer { } } - /// Get the next available nonce, taking into consideration the nonce we have sitting in stackerdb as well as the account nonce - fn get_next_nonce(&mut self, stacks_client: &StacksClient, current_reward_cycle: u64) -> u64 { - let signer_address = stacks_client.get_signer_address(); - let mut next_nonce = stacks_client - .get_account_nonce(signer_address) - .map_err(|e| { + // Get the account nonces for the provided list of signer addresses + fn get_account_nonces( + &self, + stacks_client: &StacksClient, + signer_addresses: &[StacksAddress], + ) -> HashMap { + let mut account_nonces = HashMap::with_capacity(signer_addresses.len()); + for address in signer_addresses { + let Ok(account_nonce) = retry_with_exponential_backoff(|| { + stacks_client + .get_account_nonce(address) + .map_err(backoff::Error::transient) + }) else { warn!( - "Signer #{}: Failed to get account nonce for signer: {e:?}", + "Signer #{}: Unable to get account nonce for address: {address}.", self.signer_id ); - }) - .unwrap_or(0); - - let current_transactions = self.get_signer_transactions(stacks_client, current_reward_cycle).map_err(|e| { - warn!("Signer #{}: Failed to get old transactions: {e:?}. Defaulting to account nonce.", self.signer_id); - }).unwrap_or_default(); - - for transaction in current_transactions { - let origin_nonce = transaction.get_origin_nonce(); - let origin_address = transaction.origin_address(); - if origin_address == *signer_address && origin_nonce >= next_nonce { - next_nonce = origin_nonce.wrapping_add(1); - } + continue; + }; + account_nonces.insert(*address, account_nonce); } - next_nonce + account_nonces } /// broadcast the dkg vote transaction according to the current epoch fn broadcast_dkg_vote( &mut self, stacks_client: &StacksClient, - new_transaction: StacksTransaction, epoch: StacksEpochId, - current_reward_cycle: u64, + mut signer_transactions: Vec, + new_transaction: StacksTransaction, ) -> Result<(), ClientError> { let txid = new_transaction.txid(); + if self.approved_aggregate_public_key.is_some() { + // We do not enforce a block contain any transactions except the aggregate votes when it is NOT already set + info!( + "Signer #{}: Already has an aggregate key for reward cycle {}. Do not broadcast the transaction ({txid:?}).", + self.signer_id, self.reward_cycle + ); + return Ok(()); + } if epoch >= StacksEpochId::Epoch30 { debug!("Signer #{}: Received a DKG result while in epoch 3.0. Broadcast the transaction only to stackerDB.", self.signer_id); } else if epoch == StacksEpochId::Epoch25 { @@ -1082,23 +1034,8 @@ impl Signer { return Ok(()); } // For all Pox-4 epochs onwards, broadcast the results also to stackerDB for other signers/miners to observe - // TODO: Should we even store transactions if not in prepare phase? Should the miner just ignore all signer transactions if not in prepare phase? - let txid = new_transaction.txid(); - let new_transactions = if self.approved_aggregate_public_key.is_some() { - // We do not enforce a block contain any transactions except the aggregate votes when it is NOT already set - info!( - "Signer #{}: Already has an aggregate key for reward cycle {}. Do not broadcast the transaction ({txid:?}).", - self.signer_id, self.reward_cycle - ); - vec![] - } else { - let mut new_transactions = self.get_signer_transactions(stacks_client, current_reward_cycle).map_err(|e| { - warn!("Signer #{}: Failed to get old transactions: {e:?}. Potentially overwriting our existing stackerDB transactions", self.signer_id); - }).unwrap_or_default(); - new_transactions.push(new_transaction); - new_transactions - }; - let signer_message = SignerMessage::Transactions(new_transactions); + signer_transactions.push(new_transaction); + let signer_message = SignerMessage::Transactions(signer_transactions); self.stackerdb.send_message_with_retry(signer_message)?; info!( "Signer #{}: Broadcasted DKG vote transaction ({txid}) to stacker DB", @@ -1225,11 +1162,7 @@ impl Signer { } /// Update the DKG for the provided signer info, triggering it if required - pub fn update_dkg( - &mut self, - stacks_client: &StacksClient, - current_reward_cycle: u64, - ) -> Result<(), ClientError> { + pub fn update_dkg(&mut self, stacks_client: &StacksClient) -> Result<(), ClientError> { let reward_cycle = self.reward_cycle; self.approved_aggregate_public_key = stacks_client.get_approved_aggregate_key(reward_cycle)?; @@ -1249,30 +1182,29 @@ impl Signer { let coordinator_id = self.coordinator_selector.get_coordinator().0; if self.signer_id == coordinator_id && self.state == State::Idle { debug!( - "Signer #{}: Checking if old transactions exist", + "Signer #{}: Checking if old vote transaction exists in StackerDB...", self.signer_id ); // Have I already voted and have a pending transaction? Check stackerdb for the same round number and reward cycle vote transaction - let old_transactions = self.get_signer_transactions(stacks_client, current_reward_cycle).map_err(|e| { - warn!("Signer #{}: Failed to get old transactions: {e:?}. Potentially overwriting our existing transactions", self.signer_id); + // Only get the account nonce of THIS signer as we only care about our own votes, not other signer votes + let signer_address = stacks_client.get_signer_address(); + let account_nonces = self.get_account_nonces(stacks_client, &[signer_address.clone()]); + let old_transactions = self.get_signer_transactions(&account_nonces).map_err(|e| { + warn!("Signer #{}: Failed to get old signer transactions: {e:?}. May trigger DKG unnecessarily", self.signer_id); }).unwrap_or_default(); // Check if we have an existing vote transaction for the same round and reward cycle for transaction in old_transactions.iter() { - let origin_address = transaction.origin_address(); - if &origin_address != stacks_client.get_signer_address() { - continue; - } - let Some((_index, point, round, _reward_cycle)) = - Self::parse_vote_for_aggregate_public_key(transaction) - else { - // The transaction is not a valid vote-for-aggregate-public-key transaction - error!("BUG: Signer #{}: Received an unrecognized transaction ({}) in an already filtered list: {transaction:?}", self.signer_id, transaction.txid()); - continue; - }; + let (_index, point, round, reward_cycle) = + Self::parse_vote_for_aggregate_public_key(transaction).expect(&format!("BUG: Signer #{}: Received an invalid {VOTE_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); if Some(point) == self.coordinator.aggregate_public_key && round == self.coordinator.current_dkg_id + && reward_cycle == self.reward_cycle { - debug!("Signer #{}: Not triggering a DKG round. Already have a pending vote transaction for aggregate public key {point:?} for round {round}...", self.signer_id); + debug!("Signer #{}: Not triggering a DKG round. Already have a pending vote transaction.", self.signer_id; + "txid" => %transaction.txid(), + "point" => %point, + "round" => round + ); return Ok(()); } } @@ -1312,12 +1244,7 @@ impl Signer { "Signer #{}: Received a block proposal result from the stacks node...", self.signer_id ); - self.handle_block_validate_response( - stacks_client, - block_validate_response, - res, - current_reward_cycle, - ) + self.handle_block_validate_response(stacks_client, block_validate_response, res) } Some(SignerEvent::SignerMessages(signer_set, messages)) => { if *signer_set != self.stackerdb.get_signer_set() { @@ -1329,7 +1256,7 @@ impl Signer { self.signer_id, messages.len() ); - self.handle_signer_messages(stacks_client, res, messages, current_reward_cycle); + self.handle_signer_messages(stacks_client, res, messages); } Some(SignerEvent::ProposedBlocks(blocks)) => { if current_reward_cycle != self.reward_cycle { @@ -1388,7 +1315,6 @@ impl Signer { #[cfg(test)] mod tests { - use std::thread::spawn; use blockstack_lib::chainstate::stacks::boot::SIGNERS_VOTING_NAME; use blockstack_lib::chainstate::stacks::{ @@ -1398,113 +1324,24 @@ mod tests { use blockstack_lib::util_lib::boot::boot_code_id; use blockstack_lib::util_lib::strings::StacksString; use clarity::vm::Value; + use hashbrown::HashMap; use rand::thread_rng; use rand_core::RngCore; - use serial_test::serial; use stacks_common::consts::CHAIN_ID_TESTNET; use stacks_common::types::chainstate::StacksPrivateKey; use wsts::curve::point::Point; use wsts::curve::scalar::Scalar; - use crate::client::tests::{ - build_account_nonce_response, build_get_approved_aggregate_key_response, - build_get_last_round_response, generate_signer_config, mock_server_from_config, - mock_server_from_config_and_write_response, write_response, - }; + use crate::client::tests::generate_signer_config; use crate::client::{StacksClient, VOTE_FUNCTION_NAME}; use crate::config::GlobalConfig; use crate::signer::Signer; #[test] - fn filter_invalid_transaction_bad_origin_id() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 2, 20); - let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); - let signer_private_key = StacksPrivateKey::new(); - let invalid_tx = StacksTransaction { - version: TransactionVersion::Testnet, - chain_id: CHAIN_ID_TESTNET, - auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), - anchor_mode: TransactionAnchorMode::Any, - post_condition_mode: TransactionPostConditionMode::Allow, - post_conditions: vec![], - payload: TransactionPayload::SmartContract( - TransactionSmartContract { - name: "test-contract".into(), - code_body: StacksString::from_str("(/ 1 0)").unwrap(), - }, - None, - ), - }; - assert!(signer - .filter_invalid_transactions(&stacks_client, 0, &signer.signer_slot_ids, invalid_tx) - .is_none()); - } - - #[test] - #[serial] - fn filter_invalid_transaction_bad_nonce() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 2, 20); - let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); - let signer_private_key = config.stacks_private_key; - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; - let invalid_tx = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 0, // Old nonce - 10, - ) - .unwrap(); - - let h = spawn(move || { - signer.filter_invalid_transactions( - &stacks_client, - 0, - &signer.signer_slot_ids, - invalid_tx, - ) - }); - - let response = build_account_nonce_response(1); - let mock_server = mock_server_from_config(&config); - write_response(mock_server, response.as_bytes()); - assert!(h.join().unwrap().is_none()); - } - - #[test] - #[serial] - fn verify_valid_transaction() { - // Create a runloop of a valid signer + fn valid_vote_transaction() { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let mut signer_config = generate_signer_config(&config, 5, 20); - signer_config.reward_cycle = 1; - - // valid transaction + let signer_config = generate_signer_config(&config, 5, 20); let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); let signer_private_key = config.stacks_private_key; let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); @@ -1523,7 +1360,7 @@ mod tests { round_arg.clone(), reward_cycle_arg.clone(), ]; - let valid_transaction = StacksClient::build_signed_contract_call_transaction( + let valid_tx = StacksClient::build_signed_contract_call_transaction( &contract_addr, contract_name.clone(), VOTE_FUNCTION_NAME.into(), @@ -1535,38 +1372,15 @@ mod tests { 10, ) .unwrap(); - - let vote_response = build_get_approved_aggregate_key_response(None); - let last_round_response = build_get_last_round_response(round); - - let h = spawn(move || { - assert!(signer - .verify_payload( - &stacks_client, - &valid_transaction, - signer.signer_id, - signer.reward_cycle.saturating_sub(1) - ) - .unwrap()) - }); - - let mock_server = mock_server_from_config(&config); - write_response(mock_server, vote_response.as_bytes()); - - let mock_server = mock_server_from_config(&config); - write_response(mock_server, last_round_response.as_bytes()); - - h.join().unwrap(); + let mut account_nonces = HashMap::new(); + account_nonces.insert(valid_tx.origin_address(), 1); + assert!(signer.valid_vote_transaction(&account_nonces, &valid_tx)); } #[test] - #[serial] - fn verify_transaction_filters_malformed_contract_calls() { - // Create a runloop of a valid signer + fn valid_vote_transaction_malformed_transactions() { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let mut signer_config = generate_signer_config(&config, 5, 20); - signer_config.reward_cycle = 1; - + let signer_config = generate_signer_config(&config, 5, 20); let signer = Signer::from(signer_config.clone()); let signer_private_key = config.stacks_private_key; @@ -1641,23 +1455,6 @@ mod tests { 10, ) .unwrap(); - let invalid_signer_id_argument = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &[ - Value::UInt(signer.signer_id.wrapping_add(1) as u128), // Not the signers id - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ], - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); let invalid_function_arg_signer_index = StacksClient::build_signed_contract_call_transaction( @@ -1733,42 +1530,44 @@ mod tests { ) .unwrap(); - let stacks_client = StacksClient::from(&config); + let invalid_nonce = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + config.network.to_chain_id(), + 0, // Old nonce + 10, + ) + .unwrap(); + + let mut account_nonces = HashMap::new(); + account_nonces.insert(invalid_not_contract_call.origin_address(), 1); for tx in vec![ invalid_not_contract_call, invalid_signers_contract_addr, invalid_signers_contract_name, invalid_signers_vote_function, - invalid_signer_id_argument, invalid_function_arg_signer_index, invalid_function_arg_key, invalid_function_arg_round, invalid_function_arg_reward_cycle, + invalid_nonce, ] { - let result = signer - .verify_payload( - &stacks_client, - &tx, - signer.signer_id, - signer.reward_cycle.saturating_sub(1), - ) - .unwrap(); - assert!(!result); + assert!(!signer.valid_vote_transaction(&account_nonces, &tx)); } } #[test] - #[serial] - fn verify_transaction_filters_invalid_reward_cycle() { - // Create a runloop of a valid signer + fn filter_one_transaction_per_signer_multiple_addresses() { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let mut signer_config = generate_signer_config(&config, 5, 20); - signer_config.reward_cycle = 1; - + let signer_config = generate_signer_config(&config, 5, 20); let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); - let signer_private_key = config.stacks_private_key; + let signer_private_key_1 = config.stacks_private_key; + let signer_private_key_2 = StacksPrivateKey::new(); let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); let contract_addr = vote_contract_id.issuer.into(); let contract_name = vote_contract_id.name.clone(); @@ -1785,70 +1584,50 @@ mod tests { round_arg.clone(), reward_cycle_arg.clone(), ]; - // Invalid reward cycle (voting for the current is not allowed. only the next) - let signer = Signer::from(signer_config.clone()); - let invalid_reward_cycle = StacksClient::build_signed_contract_call_transaction( + + let valid_tx_1_address_1 = StacksClient::build_signed_contract_call_transaction( &contract_addr, contract_name.clone(), VOTE_FUNCTION_NAME.into(), &valid_function_args, - &signer_private_key, + &signer_private_key_1, TransactionVersion::Testnet, config.network.to_chain_id(), 1, 10, ) .unwrap(); - let h = spawn(move || { - assert!(!signer - .verify_payload( - &stacks_client, - &invalid_reward_cycle, - signer.signer_id, - signer.reward_cycle - ) - .unwrap()) - }); - h.join().unwrap(); - } - - #[test] - #[serial] - fn verify_transaction_filters_already_voted() { - // Create a runloop of a valid signer - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let mut signer_config = generate_signer_config(&config, 5, 20); - signer_config.reward_cycle = 1; - - let signer = Signer::from(signer_config.clone()); - - let signer_private_key = config.stacks_private_key; - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; + let valid_tx_2_address_1 = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key_1, + TransactionVersion::Testnet, + config.network.to_chain_id(), + 2, + 10, + ) + .unwrap(); + let valid_tx_3_address_1 = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key_1, + TransactionVersion::Testnet, + config.network.to_chain_id(), + 3, + 10, + ) + .unwrap(); - // Already voted - let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); - let invalid_already_voted = StacksClient::build_signed_contract_call_transaction( + let valid_tx_1_address_2 = StacksClient::build_signed_contract_call_transaction( &contract_addr, contract_name.clone(), VOTE_FUNCTION_NAME.into(), &valid_function_args, - &signer_private_key, + &signer_private_key_2, TransactionVersion::Testnet, config.network.to_chain_id(), 1, @@ -1856,30 +1635,34 @@ mod tests { ) .unwrap(); - let vote_response = build_get_approved_aggregate_key_response(Some(point)); + let valid_tx_2_address_2 = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key_2, + TransactionVersion::Testnet, + config.network.to_chain_id(), + 1, + 10, + ) + .unwrap(); - let h = spawn(move || { - assert!(!signer - .verify_payload( - &stacks_client, - &invalid_already_voted, - signer.signer_id, - signer.reward_cycle.saturating_sub(1) - ) - .unwrap()) - }); - mock_server_from_config_and_write_response(&config, vote_response.as_bytes()); - h.join().unwrap(); + let txs = signer.filter_one_transaction_per_address(vec![ + valid_tx_1_address_1.clone(), + valid_tx_3_address_1, + valid_tx_2_address_2, + valid_tx_2_address_1.clone(), + ]); + assert_eq!(txs.len(), 2); + assert!(txs.contains(&valid_tx_1_address_1)); + assert!(txs.contains(&valid_tx_1_address_2)); } #[test] - #[serial] - fn verify_transaction_filters_ivalid_round_number() { - // Create a runloop of a valid signer + fn filter_one_transaction_per_signer_duplicate_nonces() { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let mut signer_config = generate_signer_config(&config, 5, 20); - signer_config.reward_cycle = 1; - + let signer_config = generate_signer_config(&config, 5, 20); let signer = Signer::from(signer_config.clone()); let signer_private_key = config.stacks_private_key; @@ -1899,9 +1682,8 @@ mod tests { round_arg.clone(), reward_cycle_arg.clone(), ]; - let signer = Signer::from(signer_config.clone()); - let stacks_client = StacksClient::from(&config); - let invalid_round_number = StacksClient::build_signed_contract_call_transaction( + let nonce = 0; + let valid_tx_1 = StacksClient::build_signed_contract_call_transaction( &contract_addr, contract_name.clone(), VOTE_FUNCTION_NAME.into(), @@ -1909,27 +1691,39 @@ mod tests { &signer_private_key, TransactionVersion::Testnet, config.network.to_chain_id(), - 1, + nonce, + 10, + ) + .unwrap(); + let valid_tx_2 = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + config.network.to_chain_id(), + nonce, + 10, + ) + .unwrap(); + let valid_tx_3 = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + VOTE_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + config.network.to_chain_id(), + nonce, 10, ) .unwrap(); - // invalid round number - let vote_response = build_get_approved_aggregate_key_response(None); - let last_round_response = build_get_last_round_response(0); - - let h = spawn(move || { - assert!(!signer - .verify_payload( - &stacks_client, - &invalid_round_number, - signer.signer_id, - signer.reward_cycle.saturating_sub(1) - ) - .unwrap()) - }); - mock_server_from_config_and_write_response(&config, vote_response.as_bytes()); - mock_server_from_config_and_write_response(&config, last_round_response.as_bytes()); - h.join().unwrap(); + let mut txs = vec![valid_tx_2, valid_tx_1, valid_tx_3]; + let filtered_txs = signer.filter_one_transaction_per_address(txs.clone()); + txs.sort_by(|a, b| a.txid().cmp(&b.txid())); + assert_eq!(filtered_txs.len(), 1); + assert!(filtered_txs.contains(&txs.first().expect("failed to get first tx"))); } } From f6aa7e351439bfa492866faa7678cf5c932e5f18 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Tue, 27 Feb 2024 13:12:20 -0500 Subject: [PATCH 33/39] Make filtering of signer transactions global and use in miner Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/stacks_client.rs | 11 +- stacks-signer/src/signer.rs | 540 +------------ .../src/chainstate/nakamoto/signer_set.rs | 84 +- .../src/chainstate/nakamoto/tests/mod.rs | 759 +++++++++++++++++- stackslib/src/chainstate/stacks/boot/mod.rs | 3 +- stackslib/src/net/tests/mod.rs | 8 +- testnet/stacks-node/src/mockamoto.rs | 4 +- .../stacks-node/src/nakamoto_node/miner.rs | 65 +- .../src/tests/nakamoto_integrations.rs | 8 +- testnet/stacks-node/src/tests/signer.rs | 226 +++++- 10 files changed, 1101 insertions(+), 607 deletions(-) diff --git a/stacks-signer/src/client/stacks_client.rs b/stacks-signer/src/client/stacks_client.rs index caa5c7018a..5e422b3c62 100644 --- a/stacks-signer/src/client/stacks_client.rs +++ b/stacks-signer/src/client/stacks_client.rs @@ -17,7 +17,9 @@ use std::net::SocketAddr; use blockstack_lib::burnchains::Txid; use blockstack_lib::chainstate::nakamoto::NakamotoBlock; -use blockstack_lib::chainstate::stacks::boot::{RewardSet, SIGNERS_NAME, SIGNERS_VOTING_NAME}; +use blockstack_lib::chainstate::stacks::boot::{ + RewardSet, SIGNERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, +}; use blockstack_lib::chainstate::stacks::{ StacksTransaction, StacksTransactionSigner, TransactionAnchorMode, TransactionAuth, TransactionContractCall, TransactionPayload, TransactionPostConditionMode, @@ -47,9 +49,6 @@ use wsts::state_machine::PublicKeys; use crate::client::{retry_with_exponential_backoff, ClientError}; use crate::config::{GlobalConfig, RegisteredSignersInfo}; -/// The name of the function for casting a DKG result to signer vote contract -pub const VOTE_FUNCTION_NAME: &str = "vote-for-aggregate-public-key"; - /// The Stacks signer client used to communicate with the stacks node #[derive(Clone, Debug)] pub struct StacksClient { @@ -502,10 +501,10 @@ impl StacksClient { tx_fee: Option, nonce: u64, ) -> Result { - debug!("Building {VOTE_FUNCTION_NAME} transaction..."); + debug!("Building {SIGNERS_VOTING_FUNCTION_NAME} transaction..."); let contract_address = boot_code_addr(self.mainnet); let contract_name = ContractName::from(SIGNERS_VOTING_NAME); - let function_name = ClarityName::from(VOTE_FUNCTION_NAME); + let function_name = ClarityName::from(SIGNERS_VOTING_FUNCTION_NAME); let function_args = vec![ ClarityValue::UInt(signer_index as u128), ClarityValue::buff_from(point.compress().data.to_vec())?, diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index f2e5c92e38..e759f2ff70 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -17,11 +17,11 @@ use std::collections::VecDeque; use std::sync::mpsc::Sender; use std::time::Instant; +use blockstack_lib::chainstate::nakamoto::signer_set::NakamotoSigners; use blockstack_lib::chainstate::nakamoto::{NakamotoBlock, NakamotoBlockVote}; -use blockstack_lib::chainstate::stacks::boot::SIGNERS_VOTING_NAME; -use blockstack_lib::chainstate::stacks::{StacksTransaction, TransactionPayload}; +use blockstack_lib::chainstate::stacks::boot::SIGNERS_VOTING_FUNCTION_NAME; +use blockstack_lib::chainstate::stacks::StacksTransaction; use blockstack_lib::net::api::postblock_proposal::BlockValidateResponse; -use blockstack_lib::util_lib::boot::boot_code_id; use hashbrown::{HashMap, HashSet}; use libsigner::{BlockRejection, BlockResponse, RejectCode, SignerEvent, SignerMessage}; use slog::{slog_debug, slog_error, slog_info, slog_warn}; @@ -32,7 +32,7 @@ use stacks_common::util::hash::Sha512Trunc256Sum; use stacks_common::{debug, error, info, warn}; use wsts::common::{MerkleRoot, Signature}; use wsts::curve::keys::PublicKey; -use wsts::curve::point::{Compressed, Point}; +use wsts::curve::point::Point; use wsts::net::{Message, NonceRequest, Packet, SignatureShareRequest}; use wsts::state_machine::coordinator::fire::Coordinator as FireCoordinator; use wsts::state_machine::coordinator::{ @@ -42,9 +42,7 @@ use wsts::state_machine::signer::Signer as WSTSSigner; use wsts::state_machine::{OperationResult, SignError}; use wsts::v2; -use crate::client::{ - retry_with_exponential_backoff, ClientError, StackerDB, StacksClient, VOTE_FUNCTION_NAME, -}; +use crate::client::{retry_with_exponential_backoff, ClientError, StackerDB, StacksClient}; use crate::config::SignerConfig; use crate::coordinator::CoordinatorSelector; @@ -709,70 +707,17 @@ impl Signer { } } - /// Select one transaction per address by sorting based first on nonce and then txid - fn filter_one_transaction_per_address( - &self, - transactions: Vec, - ) -> Vec { - let mut filtered_transactions: HashMap = HashMap::new(); - for transaction in transactions { - let origin_address = transaction.origin_address(); - let origin_nonce = transaction.get_origin_nonce(); - if let Some(entry) = filtered_transactions.get_mut(&origin_address) { - let entry_nonce = entry.get_origin_nonce(); - if entry_nonce > origin_nonce - || (entry_nonce == origin_nonce && entry.txid() > transaction.txid()) - { - *entry = transaction; - } - } else { - filtered_transactions.insert(origin_address, transaction); - } - } - filtered_transactions.into_values().collect() - } - - /// Verify that the transaction is a valid vote for the aggregate public key - /// Note: it does not verify the function arguments, only that the transaction is validly formed - fn valid_vote_transaction( - &self, - account_nonces: &HashMap, - transaction: &StacksTransaction, - ) -> bool { - let origin_address = transaction.origin_address(); - let origin_nonce = transaction.get_origin_nonce(); - let Some(account_nonce) = account_nonces.get(&origin_address) else { - debug!( - "Signer #{}: Unrecognized origin address ({origin_address}).", - self.signer_id, - ); - return false; - }; - if transaction.is_mainnet() != self.mainnet { - debug!( - "Signer #{}: Received a transaction for an unexpected network.", - self.signer_id, - ); - return false; - } - if origin_nonce < *account_nonce { - debug!("Signer #{}: Received a transaction with an outdated nonce ({account_nonce} < {origin_nonce}).", self.signer_id); - return false; - } - Self::parse_vote_for_aggregate_public_key(transaction).is_some() - } - /// Get transactions from stackerdb for the given addresses and account nonces, filtering out any malformed transactions fn get_signer_transactions( &mut self, - nonces: &HashMap, + nonces: &std::collections::HashMap, ) -> Result, ClientError> { let transactions: Vec<_> = self .stackerdb .get_current_transactions_with_retry(self.signer_id)? .into_iter() .filter_map(|tx| { - if !self.valid_vote_transaction(nonces, &tx) { + if !NakamotoSigners::valid_vote_transaction(nonces, &tx, self.mainnet) { return None; } Some(tx) @@ -797,18 +742,16 @@ impl Signer { let account_nonces = self.get_account_nonces(stacks_client, &self.next_signers); let transactions: Vec<_> = self .stackerdb - .get_next_transactions_with_retry(&self.next_signer_ids)? - .into_iter() - .filter_map(|tx| { - if !self.valid_vote_transaction(&account_nonces, &tx) { - return None; - } - Some(tx) - }) - .collect(); - + .get_next_transactions_with_retry(&self.next_signer_ids)?; + let mut filtered_transactions = std::collections::HashMap::new(); + NakamotoSigners::update_filtered_transactions( + &mut filtered_transactions, + &account_nonces, + self.mainnet, + transactions, + ); // We only allow enforcement of one special cased transaction per signer address per block - Ok(self.filter_one_transaction_per_address(transactions)) + Ok(filtered_transactions.into_values().collect()) } /// Determine the vote for a block and update the block info and nonce request accordingly @@ -984,8 +927,8 @@ impl Signer { &self, stacks_client: &StacksClient, signer_addresses: &[StacksAddress], - ) -> HashMap { - let mut account_nonces = HashMap::with_capacity(signer_addresses.len()); + ) -> std::collections::HashMap { + let mut account_nonces = std::collections::HashMap::with_capacity(signer_addresses.len()); for address in signer_addresses { let Ok(account_nonce) = retry_with_exponential_backoff(|| { stacks_client @@ -1195,7 +1138,7 @@ impl Signer { // Check if we have an existing vote transaction for the same round and reward cycle for transaction in old_transactions.iter() { let (_index, point, round, reward_cycle) = - Self::parse_vote_for_aggregate_public_key(transaction).expect(&format!("BUG: Signer #{}: Received an invalid {VOTE_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); + NakamotoSigners::parse_vote_for_aggregate_public_key(transaction).expect(&format!("BUG: Signer #{}: Received an invalid {SIGNERS_VOTING_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); if Some(point) == self.coordinator.aggregate_public_key && round == self.coordinator.current_dkg_id && reward_cycle == self.reward_cycle @@ -1281,449 +1224,4 @@ impl Signer { } Ok(()) } - - fn parse_vote_for_aggregate_public_key( - transaction: &StacksTransaction, - ) -> Option<(u64, Point, u64, u64)> { - let TransactionPayload::ContractCall(payload) = &transaction.payload else { - // Not a contract call so not a special cased vote for aggregate public key transaction - return None; - }; - if payload.contract_identifier() - != boot_code_id(SIGNERS_VOTING_NAME, transaction.is_mainnet()) - || payload.function_name != VOTE_FUNCTION_NAME.into() - { - // This is not a special cased transaction. - return None; - } - if payload.function_args.len() != 4 { - return None; - } - let signer_index_value = payload.function_args.first()?; - let signer_index = u64::try_from(signer_index_value.clone().expect_u128().ok()?).ok()?; - let point_value = payload.function_args.get(1)?; - let point_bytes = point_value.clone().expect_buff(33).ok()?; - let compressed_data = Compressed::try_from(point_bytes.as_slice()).ok()?; - let point = Point::try_from(&compressed_data).ok()?; - let round_value = payload.function_args.get(2)?; - let round = u64::try_from(round_value.clone().expect_u128().ok()?).ok()?; - let reward_cycle = - u64::try_from(payload.function_args.get(3)?.clone().expect_u128().ok()?).ok()?; - Some((signer_index, point, round, reward_cycle)) - } -} - -#[cfg(test)] -mod tests { - - use blockstack_lib::chainstate::stacks::boot::SIGNERS_VOTING_NAME; - use blockstack_lib::chainstate::stacks::{ - StacksTransaction, TransactionAnchorMode, TransactionAuth, TransactionPayload, - TransactionPostConditionMode, TransactionSmartContract, TransactionVersion, - }; - use blockstack_lib::util_lib::boot::boot_code_id; - use blockstack_lib::util_lib::strings::StacksString; - use clarity::vm::Value; - use hashbrown::HashMap; - use rand::thread_rng; - use rand_core::RngCore; - use stacks_common::consts::CHAIN_ID_TESTNET; - use stacks_common::types::chainstate::StacksPrivateKey; - use wsts::curve::point::Point; - use wsts::curve::scalar::Scalar; - - use crate::client::tests::generate_signer_config; - use crate::client::{StacksClient, VOTE_FUNCTION_NAME}; - use crate::config::GlobalConfig; - use crate::signer::Signer; - - #[test] - fn valid_vote_transaction() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 5, 20); - let signer = Signer::from(signer_config.clone()); - - let signer_private_key = config.stacks_private_key; - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; - let valid_tx = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - let mut account_nonces = HashMap::new(); - account_nonces.insert(valid_tx.origin_address(), 1); - assert!(signer.valid_vote_transaction(&account_nonces, &valid_tx)); - } - - #[test] - fn valid_vote_transaction_malformed_transactions() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 5, 20); - let signer = Signer::from(signer_config.clone()); - - let signer_private_key = config.stacks_private_key; - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; - - let signer = Signer::from(signer_config.clone()); - // Create a invalid transaction that is not a contract call - let invalid_not_contract_call = StacksTransaction { - version: TransactionVersion::Testnet, - chain_id: CHAIN_ID_TESTNET, - auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), - anchor_mode: TransactionAnchorMode::Any, - post_condition_mode: TransactionPostConditionMode::Allow, - post_conditions: vec![], - payload: TransactionPayload::SmartContract( - TransactionSmartContract { - name: "test-contract".into(), - code_body: StacksString::from_str("(/ 1 0)").unwrap(), - }, - None, - ), - }; - let invalid_signers_contract_addr = StacksClient::build_signed_contract_call_transaction( - &config.stacks_address, // Not the signers contract address - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - let invalid_signers_contract_name = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - "bad-signers-contract-name".into(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_signers_vote_function = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - "some-other-function".into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_function_arg_signer_index = - StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &[ - point_arg.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ], - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_function_arg_key = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &[ - signer_index.clone(), - signer_index.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ], - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_function_arg_round = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &[ - signer_index.clone(), - point_arg.clone(), - point_arg.clone(), - reward_cycle_arg.clone(), - ], - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_function_arg_reward_cycle = - StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &[ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - point_arg.clone(), - ], - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let invalid_nonce = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 0, // Old nonce - 10, - ) - .unwrap(); - - let mut account_nonces = HashMap::new(); - account_nonces.insert(invalid_not_contract_call.origin_address(), 1); - for tx in vec![ - invalid_not_contract_call, - invalid_signers_contract_addr, - invalid_signers_contract_name, - invalid_signers_vote_function, - invalid_function_arg_signer_index, - invalid_function_arg_key, - invalid_function_arg_round, - invalid_function_arg_reward_cycle, - invalid_nonce, - ] { - assert!(!signer.valid_vote_transaction(&account_nonces, &tx)); - } - } - - #[test] - fn filter_one_transaction_per_signer_multiple_addresses() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 5, 20); - let signer = Signer::from(signer_config.clone()); - - let signer_private_key_1 = config.stacks_private_key; - let signer_private_key_2 = StacksPrivateKey::new(); - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; - - let valid_tx_1_address_1 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key_1, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - let valid_tx_2_address_1 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key_1, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 2, - 10, - ) - .unwrap(); - let valid_tx_3_address_1 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key_1, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 3, - 10, - ) - .unwrap(); - - let valid_tx_1_address_2 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key_2, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let valid_tx_2_address_2 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key_2, - TransactionVersion::Testnet, - config.network.to_chain_id(), - 1, - 10, - ) - .unwrap(); - - let txs = signer.filter_one_transaction_per_address(vec![ - valid_tx_1_address_1.clone(), - valid_tx_3_address_1, - valid_tx_2_address_2, - valid_tx_2_address_1.clone(), - ]); - assert_eq!(txs.len(), 2); - assert!(txs.contains(&valid_tx_1_address_1)); - assert!(txs.contains(&valid_tx_1_address_2)); - } - - #[test] - fn filter_one_transaction_per_signer_duplicate_nonces() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); - let signer_config = generate_signer_config(&config, 5, 20); - let signer = Signer::from(signer_config.clone()); - - let signer_private_key = config.stacks_private_key; - let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, signer.mainnet); - let contract_addr = vote_contract_id.issuer.into(); - let contract_name = vote_contract_id.name.clone(); - let signer_index = Value::UInt(signer.signer_id as u128); - let point = Point::from(Scalar::random(&mut thread_rng())); - let point_arg = - Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); - let round = thread_rng().next_u64(); - let round_arg = Value::UInt(round as u128); - let reward_cycle_arg = Value::UInt(signer.reward_cycle as u128); - let valid_function_args = vec![ - signer_index.clone(), - point_arg.clone(), - round_arg.clone(), - reward_cycle_arg.clone(), - ]; - let nonce = 0; - let valid_tx_1 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - nonce, - 10, - ) - .unwrap(); - let valid_tx_2 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - nonce, - 10, - ) - .unwrap(); - let valid_tx_3 = StacksClient::build_signed_contract_call_transaction( - &contract_addr, - contract_name.clone(), - VOTE_FUNCTION_NAME.into(), - &valid_function_args, - &signer_private_key, - TransactionVersion::Testnet, - config.network.to_chain_id(), - nonce, - 10, - ) - .unwrap(); - - let mut txs = vec![valid_tx_2, valid_tx_1, valid_tx_3]; - let filtered_txs = signer.filter_one_transaction_per_address(txs.clone()); - txs.sort_by(|a, b| a.txid().cmp(&b.txid())); - assert_eq!(filtered_txs.len(), 1); - assert!(filtered_txs.contains(&txs.first().expect("failed to get first tx"))); - } } diff --git a/stackslib/src/chainstate/nakamoto/signer_set.rs b/stackslib/src/chainstate/nakamoto/signer_set.rs index c0d6b23717..a39d6bebc2 100644 --- a/stackslib/src/chainstate/nakamoto/signer_set.rs +++ b/stackslib/src/chainstate/nakamoto/signer_set.rs @@ -46,7 +46,7 @@ use stacks_common::util::hash::{to_hex, Hash160, MerkleHashFunc, MerkleTree, Sha use stacks_common::util::retry::BoundReader; use stacks_common::util::secp256k1::MessageSignature; use stacks_common::util::vrf::{VRFProof, VRFPublicKey, VRF}; -use wsts::curve::point::Point; +use wsts::curve::point::{Compressed, Point}; use crate::burnchains::{Burnchain, PoxConstants, Txid}; use crate::chainstate::burn::db::sortdb::{ @@ -63,7 +63,7 @@ use crate::chainstate::stacks::address::PoxAddress; use crate::chainstate::stacks::boot::{ PoxVersions, RawRewardSetEntry, RewardSet, BOOT_TEST_POX_4_AGG_KEY_CONTRACT, BOOT_TEST_POX_4_AGG_KEY_FNAME, POX_4_NAME, SIGNERS_MAX_LIST_SIZE, SIGNERS_NAME, SIGNERS_PK_LEN, - SIGNERS_UPDATE_STATE, + SIGNERS_UPDATE_STATE, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, }; use crate::chainstate::stacks::db::{ ChainstateTx, ClarityTx, DBConfig as ChainstateConfig, MinerPaymentSchedule, @@ -487,4 +487,84 @@ impl NakamotoSigners { } Ok(signers) } + + /// Verify that the transaction is a valid vote for the aggregate public key + /// Note: it does not verify the function arguments, only that the transaction is validly formed + /// and has a valid nonce from an expected address + pub fn valid_vote_transaction( + account_nonces: &HashMap, + transaction: &StacksTransaction, + is_mainnet: bool, + ) -> bool { + let origin_address = transaction.origin_address(); + let origin_nonce = transaction.get_origin_nonce(); + let Some(account_nonce) = account_nonces.get(&origin_address) else { + debug!("valid_vote_transaction: Unrecognized origin address ({origin_address}).",); + return false; + }; + if transaction.is_mainnet() != is_mainnet { + debug!("valid_vote_transaction: Received a transaction for an unexpected network.",); + return false; + } + if origin_nonce < *account_nonce { + debug!("valid_vote_transaction: Received a transaction with an outdated nonce ({account_nonce} < {origin_nonce})."); + return false; + } + Self::parse_vote_for_aggregate_public_key(transaction).is_some() + } + + pub fn parse_vote_for_aggregate_public_key( + transaction: &StacksTransaction, + ) -> Option<(u64, Point, u64, u64)> { + let TransactionPayload::ContractCall(payload) = &transaction.payload else { + // Not a contract call so not a special cased vote for aggregate public key transaction + return None; + }; + if payload.contract_identifier() + != boot_code_id(SIGNERS_VOTING_NAME, transaction.is_mainnet()) + || payload.function_name != SIGNERS_VOTING_FUNCTION_NAME.into() + { + // This is not a special cased transaction. + return None; + } + if payload.function_args.len() != 4 { + return None; + } + let signer_index_value = payload.function_args.first()?; + let signer_index = u64::try_from(signer_index_value.clone().expect_u128().ok()?).ok()?; + let point_value = payload.function_args.get(1)?; + let point_bytes = point_value.clone().expect_buff(33).ok()?; + let compressed_data = Compressed::try_from(point_bytes.as_slice()).ok()?; + let point = Point::try_from(&compressed_data).ok()?; + let round_value = payload.function_args.get(2)?; + let round = u64::try_from(round_value.clone().expect_u128().ok()?).ok()?; + let reward_cycle = + u64::try_from(payload.function_args.get(3)?.clone().expect_u128().ok()?).ok()?; + Some((signer_index, point, round, reward_cycle)) + } + + /// Update the map of filtered valid transactions, selecting one per address based first on lowest nonce, then txid + pub fn update_filtered_transactions( + filtered_transactions: &mut HashMap, + account_nonces: &HashMap, + mainnet: bool, + transactions: Vec, + ) { + for transaction in transactions { + if NakamotoSigners::valid_vote_transaction(&account_nonces, &transaction, mainnet) { + let origin_address = transaction.origin_address(); + let origin_nonce = transaction.get_origin_nonce(); + if let Some(entry) = filtered_transactions.get_mut(&origin_address) { + let entry_nonce = entry.get_origin_nonce(); + if entry_nonce > origin_nonce + || (entry_nonce == origin_nonce && entry.txid() > transaction.txid()) + { + *entry = transaction; + } + } else { + filtered_transactions.insert(origin_address, transaction); + } + } + } + } } diff --git a/stackslib/src/chainstate/nakamoto/tests/mod.rs b/stackslib/src/chainstate/nakamoto/tests/mod.rs index 284a0af64d..c27505b516 100644 --- a/stackslib/src/chainstate/nakamoto/tests/mod.rs +++ b/stackslib/src/chainstate/nakamoto/tests/mod.rs @@ -15,17 +15,22 @@ // along with this program. If not, see . use std::borrow::BorrowMut; +use std::collections::HashMap; use std::fs; use clarity::types::chainstate::{PoxId, SortitionId, StacksBlockId}; use clarity::vm::clarity::ClarityConnection; use clarity::vm::costs::ExecutionCost; use clarity::vm::types::StacksAddressExtensions; +use clarity::vm::Value; +use rand::{thread_rng, RngCore}; use rusqlite::Connection; use stacks_common::address::AddressHashMode; use stacks_common::bitvec::BitVec; use stacks_common::codec::StacksMessageCodec; -use stacks_common::consts::{FIRST_BURNCHAIN_CONSENSUS_HASH, FIRST_STACKS_BLOCK_HASH}; +use stacks_common::consts::{ + CHAIN_ID_MAINNET, CHAIN_ID_TESTNET, FIRST_BURNCHAIN_CONSENSUS_HASH, FIRST_STACKS_BLOCK_HASH, +}; use stacks_common::types::chainstate::{ BlockHeaderHash, BurnchainHeaderHash, ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey, StacksWorkScore, TrieHash, VRFSeed, @@ -37,6 +42,8 @@ use stacks_common::util::secp256k1::{MessageSignature, Secp256k1PublicKey}; use stacks_common::util::vrf::{VRFPrivateKey, VRFProof, VRFPublicKey, VRF}; use stdext::prelude::Integer; use stx_genesis::GenesisData; +use wsts::curve::point::Point; +use wsts::curve::scalar::Scalar; use crate::burnchains::{BurnchainSigner, PoxConstants, Txid}; use crate::chainstate::burn::db::sortdb::tests::make_fork_run; @@ -52,13 +59,16 @@ use crate::chainstate::coordinator::tests::{ }; use crate::chainstate::nakamoto::coordinator::tests::boot_nakamoto; use crate::chainstate::nakamoto::miner::NakamotoBlockBuilder; +use crate::chainstate::nakamoto::signer_set::NakamotoSigners; use crate::chainstate::nakamoto::tenure::NakamotoTenure; use crate::chainstate::nakamoto::test_signers::TestSigners; use crate::chainstate::nakamoto::tests::node::TestStacker; use crate::chainstate::nakamoto::{ NakamotoBlock, NakamotoBlockHeader, NakamotoChainState, SortitionHandle, FIRST_STACKS_BLOCK_ID, }; -use crate::chainstate::stacks::boot::MINERS_NAME; +use crate::chainstate::stacks::boot::{ + MINERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, +}; use crate::chainstate::stacks::db::{ ChainStateBootData, ChainstateAccountBalance, ChainstateAccountLockup, ChainstateBNSName, ChainstateBNSNamespace, StacksAccount, StacksBlockHeaderTypes, StacksChainState, @@ -67,13 +77,15 @@ use crate::chainstate::stacks::db::{ use crate::chainstate::stacks::{ CoinbasePayload, StacksBlock, StacksBlockHeader, StacksTransaction, StacksTransactionSigner, TenureChangeCause, TenureChangePayload, ThresholdSignature, TokenTransferMemo, - TransactionAnchorMode, TransactionAuth, TransactionPayload, TransactionVersion, + TransactionAnchorMode, TransactionAuth, TransactionContractCall, TransactionPayload, + TransactionPostConditionMode, TransactionSmartContract, TransactionVersion, }; use crate::core; use crate::core::{StacksEpochExtension, STACKS_EPOCH_3_0_MARKER}; use crate::net::codec::test::check_codec_and_corruption; use crate::util_lib::boot::boot_code_id; use crate::util_lib::db::Error as db_error; +use crate::util_lib::strings::StacksString; /// Get an address's account pub fn get_account( @@ -2068,3 +2080,744 @@ fn test_make_miners_stackerdb_config() { assert_eq!(miner_hashbytes[8].1, miner_hash160s[8]); assert_eq!(miner_hashbytes[9].1, miner_hash160s[8]); } + +#[test] +fn parse_vote_for_aggregate_public_key_valid() { + let signer_private_key = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u64(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let valid_function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + let valid_tx = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr, + contract_name, + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args, + }), + }; + let (res_signer_index, res_point, res_round, res_reward_cycle) = + NakamotoSigners::parse_vote_for_aggregate_public_key(&valid_tx).unwrap(); + assert_eq!(res_signer_index, signer_index); + assert_eq!(res_point, point); + assert_eq!(res_round, round); + assert_eq!(res_reward_cycle, reward_cycle); +} + +#[test] +fn parse_vote_for_aggregate_public_key_invalid() { + let signer_private_key = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr: StacksAddress = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u32(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let valid_function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + + let mut invalid_contract_address = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: StacksAddress::p2pkh( + false, + &StacksPublicKey::from_private(&signer_private_key), + ), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_contract_address.set_origin_nonce(1); + + let mut invalid_contract_name = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: "bad-signers-contract-name".into(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_contract_name.set_origin_nonce(1); + + let mut invalid_signers_vote_function = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: "some-other-function".into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_signers_vote_function.set_origin_nonce(1); + + let mut invalid_function_arg_signer_index = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + point_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_signer_index.set_origin_nonce(1); + + let mut invalid_function_arg_key = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + signer_index_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_key.set_origin_nonce(1); + + let mut invalid_function_arg_round = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + point_arg.clone(), + point_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_round.set_origin_nonce(1); + + let mut invalid_function_arg_reward_cycle = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + point_arg.clone(), + ], + }), + }; + invalid_function_arg_reward_cycle.set_origin_nonce(1); + + let mut account_nonces = std::collections::HashMap::new(); + account_nonces.insert(invalid_contract_name.origin_address(), 1); + for (i, tx) in vec![ + invalid_contract_address, + invalid_contract_name, + invalid_signers_vote_function, + invalid_function_arg_signer_index, + invalid_function_arg_key, + invalid_function_arg_round, + invalid_function_arg_reward_cycle, + ] + .iter() + .enumerate() + { + assert!( + NakamotoSigners::parse_vote_for_aggregate_public_key(&tx).is_none(), + "{}", + format!("parsed the {i}th transaction: {tx:?}") + ); + } +} + +#[test] +fn valid_vote_transaction() { + let signer_private_key = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u32(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let valid_function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + let mut valid_tx = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr, + contract_name: contract_name, + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args, + }), + }; + valid_tx.set_origin_nonce(1); + let mut account_nonces = std::collections::HashMap::new(); + account_nonces.insert(valid_tx.origin_address(), 1); + assert!(NakamotoSigners::valid_vote_transaction( + &account_nonces, + &valid_tx, + mainnet + )); +} + +#[test] +fn valid_vote_transaction_malformed_transactions() { + let signer_private_key = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr: StacksAddress = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u32(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let valid_function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + // Create a invalid transaction that is not a contract call + let mut invalid_not_contract_call = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::SmartContract( + TransactionSmartContract { + name: "test-contract".into(), + code_body: StacksString::from_str("(/ 1 0)").unwrap(), + }, + None, + ), + }; + invalid_not_contract_call.set_origin_nonce(1); + + let mut invalid_contract_address = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: StacksAddress::p2pkh( + mainnet, + &StacksPublicKey::from_private(&signer_private_key), + ), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_contract_address.set_origin_nonce(1); + + let mut invalid_contract_name = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: "bad-signers-contract-name".into(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_contract_name.set_origin_nonce(1); + + let mut invalid_network = StacksTransaction { + version: TransactionVersion::Mainnet, + chain_id: CHAIN_ID_MAINNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_network.set_origin_nonce(1); + + let mut invalid_signers_vote_function = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: "some-other-function".into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_signers_vote_function.set_origin_nonce(1); + + let mut invalid_function_arg_signer_index = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + point_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_signer_index.set_origin_nonce(1); + + let mut invalid_function_arg_key = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + signer_index_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_key.set_origin_nonce(1); + + let mut invalid_function_arg_round = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + point_arg.clone(), + point_arg.clone(), + reward_cycle_arg.clone(), + ], + }), + }; + invalid_function_arg_round.set_origin_nonce(1); + + let mut invalid_function_arg_reward_cycle = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + point_arg.clone(), + ], + }), + }; + invalid_function_arg_reward_cycle.set_origin_nonce(1); + + let mut invalid_nonce = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: valid_function_args.clone(), + }), + }; + invalid_nonce.set_origin_nonce(0); // old nonce + + let mut account_nonces = std::collections::HashMap::new(); + account_nonces.insert(invalid_not_contract_call.origin_address(), 1); + for tx in vec![ + invalid_not_contract_call, + invalid_contract_address, + invalid_contract_name, + invalid_signers_vote_function, + invalid_function_arg_signer_index, + invalid_function_arg_key, + invalid_function_arg_round, + invalid_function_arg_reward_cycle, + invalid_nonce, + invalid_network, + ] { + assert!(!NakamotoSigners::valid_vote_transaction( + &account_nonces, + &tx, + mainnet + )); + } +} + +#[test] +fn filter_one_transaction_per_signer_multiple_addresses() { + let signer_private_key_1 = StacksPrivateKey::new(); + let signer_private_key_2 = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr: StacksAddress = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u32(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + + let mut valid_tx_1_address_1 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key_1).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_1_address_1.set_origin_nonce(1); + + let mut valid_tx_2_address_1 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key_1).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_2_address_1.set_origin_nonce(2); + + let mut valid_tx_3_address_1 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key_1).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_3_address_1.set_origin_nonce(3); + + let mut valid_tx_1_address_2 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key_2).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_1_address_2.set_origin_nonce(1); + + let mut valid_tx_2_address_2 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key_2).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr, + contract_name, + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args, + }), + }; + valid_tx_2_address_2.set_origin_nonce(2); + let mut filtered_transactions = HashMap::new(); + let mut account_nonces = std::collections::HashMap::new(); + account_nonces.insert(valid_tx_1_address_1.origin_address(), 1); + account_nonces.insert(valid_tx_1_address_2.origin_address(), 1); + NakamotoSigners::update_filtered_transactions( + &mut filtered_transactions, + &account_nonces, + false, + vec![ + valid_tx_1_address_1.clone(), + valid_tx_3_address_1, + valid_tx_1_address_2.clone(), + valid_tx_2_address_2, + valid_tx_2_address_1, + ], + ); + let txs: Vec<_> = filtered_transactions.into_values().collect(); + assert_eq!(txs.len(), 2); + assert!(txs.contains(&valid_tx_1_address_1)); + assert!(txs.contains(&valid_tx_1_address_2)); +} + +#[test] +fn filter_one_transaction_per_signer_duplicate_nonces() { + let signer_private_key = StacksPrivateKey::new(); + let mainnet = false; + let chainid = CHAIN_ID_TESTNET; + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, mainnet); + let contract_addr: StacksAddress = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u32(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle = thread_rng().next_u64(); + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + + let function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + + let mut valid_tx_1 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_1.set_origin_nonce(0); + + let mut valid_tx_2 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr.clone(), + contract_name: contract_name.clone(), + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args: function_args.clone(), + }), + }; + valid_tx_2.set_origin_nonce(0); + + let mut valid_tx_3 = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::ContractCall(TransactionContractCall { + address: contract_addr, + contract_name, + function_name: SIGNERS_VOTING_FUNCTION_NAME.into(), + function_args, + }), + }; + valid_tx_3.set_origin_nonce(0); + + let mut account_nonces = std::collections::HashMap::new(); + account_nonces.insert(valid_tx_1.origin_address(), 0); + let mut txs = vec![valid_tx_2, valid_tx_1, valid_tx_3]; + let mut filtered_transactions = HashMap::new(); + NakamotoSigners::update_filtered_transactions( + &mut filtered_transactions, + &account_nonces, + false, + txs.clone(), + ); + let filtered_txs: Vec<_> = filtered_transactions.into_values().collect(); + txs.sort_by(|a, b| a.txid().cmp(&b.txid())); + assert_eq!(filtered_txs.len(), 1); + assert!(filtered_txs.contains(&txs.first().expect("failed to get first tx"))); +} diff --git a/stackslib/src/chainstate/stacks/boot/mod.rs b/stackslib/src/chainstate/stacks/boot/mod.rs index abba9be6c7..834d83ed20 100644 --- a/stackslib/src/chainstate/stacks/boot/mod.rs +++ b/stackslib/src/chainstate/stacks/boot/mod.rs @@ -78,6 +78,7 @@ pub const POX_3_NAME: &'static str = "pox-3"; pub const POX_4_NAME: &'static str = "pox-4"; pub const SIGNERS_NAME: &'static str = "signers"; pub const SIGNERS_VOTING_NAME: &'static str = "signers-voting"; +pub const SIGNERS_VOTING_FUNCTION_NAME: &str = "vote-for-aggregate-public-key"; /// This is the name of a variable in the `.signers` contract which tracks the most recently updated /// reward cycle number. pub const SIGNERS_UPDATE_STATE: &'static str = "last-set-cycle"; @@ -1933,7 +1934,7 @@ pub mod test { let payload = TransactionPayload::new_contract_call( boot_code_test_addr(), SIGNERS_VOTING_NAME, - "vote-for-aggregate-public-key", + SIGNERS_VOTING_FUNCTION_NAME, vec![ Value::UInt(signer_index), aggregate_public_key, diff --git a/stackslib/src/net/tests/mod.rs b/stackslib/src/net/tests/mod.rs index acff183d92..9111f10fc0 100644 --- a/stackslib/src/net/tests/mod.rs +++ b/stackslib/src/net/tests/mod.rs @@ -46,7 +46,9 @@ use crate::chainstate::stacks::address::PoxAddress; use crate::chainstate::stacks::boot::test::{ key_to_stacks_addr, make_pox_4_lockup, make_signer_key_signature, with_sortdb, }; -use crate::chainstate::stacks::boot::MINERS_NAME; +use crate::chainstate::stacks::boot::{ + MINERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, +}; use crate::chainstate::stacks::db::{MinerPaymentTxFees, StacksAccount, StacksChainState}; use crate::chainstate::stacks::events::TransactionOrigin; use crate::chainstate::stacks::{ @@ -185,9 +187,9 @@ impl NakamotoBootPlan { function_name, .. }) => { - if contract_name.as_str() == "signers-voting" + if contract_name.as_str() == SIGNERS_VOTING_NAME && address.is_burn() - && function_name.as_str() == "vote-for-aggregate-public-key" + && function_name.as_str() == SIGNERS_VOTING_FUNCTION_NAME { false } else { diff --git a/testnet/stacks-node/src/mockamoto.rs b/testnet/stacks-node/src/mockamoto.rs index 2629f4f9b2..011300bc88 100644 --- a/testnet/stacks-node/src/mockamoto.rs +++ b/testnet/stacks-node/src/mockamoto.rs @@ -49,7 +49,7 @@ use stacks::chainstate::nakamoto::{ NakamotoBlock, NakamotoBlockHeader, NakamotoChainState, SetupBlockResult, }; use stacks::chainstate::stacks::address::PoxAddress; -use stacks::chainstate::stacks::boot::SIGNERS_VOTING_NAME; +use stacks::chainstate::stacks::boot::{SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME}; use stacks::chainstate::stacks::db::{ChainStateBootData, ClarityTx, StacksChainState}; use stacks::chainstate::stacks::miner::{ BlockBuilder, BlockBuilderSettings, BlockLimitFunction, MinerStatus, TransactionResult, @@ -934,7 +934,7 @@ impl MockamotoNode { let vote_payload = TransactionPayload::new_contract_call( boot_code_addr(false), SIGNERS_VOTING_NAME, - "vote-for-aggregate-public-key", + SIGNERS_VOTING_FUNCTION_NAME, vec![ ClarityValue::UInt(0), aggregate_public_key_val, diff --git a/testnet/stacks-node/src/nakamoto_node/miner.rs b/testnet/stacks-node/src/nakamoto_node/miner.rs index ec57fc3ef7..9c886b4343 100644 --- a/testnet/stacks-node/src/nakamoto_node/miner.rs +++ b/testnet/stacks-node/src/nakamoto_node/miner.rs @@ -331,48 +331,43 @@ impl BlockMinerThread { }) .collect(); - // There may be more than signer messages, but odds are there is only one transacton per signer - let mut transactions_to_include = Vec::with_capacity(signer_messages.len()); + if signer_messages.is_empty() { + return Ok(vec![]); + } + + // Get all nonces for the signers from clarity DB to use to validate transactions + let account_nonces = chainstate + .with_read_only_clarity_tx(&sortdb.index_conn(), &self.parent_tenure_id, |clarity_tx| { + clarity_tx.with_clarity_db_readonly(|clarity_db| { + addresses + .iter() + .map(|address| { + ( + address.clone(), + clarity_db + .get_account_nonce(&address.clone().into()) + .unwrap_or(0), + ) + }) + .collect::>() + }) + }) + .unwrap_or_default(); + let mut filtered_transactions: HashMap = HashMap::new(); for (_slot, signer_message) in signer_messages { match signer_message { SignerMessage::Transactions(transactions) => { - for transaction in transactions { - let address = transaction.origin_address(); - let nonce = transaction.get_origin_nonce(); - if !addresses.contains(&address) { - test_debug!("Miner: ignoring transaction ({:?}) with nonce {nonce} from address {address}", transaction.txid()); - continue; - } - - let cur_nonce = chainstate - .with_read_only_clarity_tx( - &sortdb.index_conn(), - &self.parent_tenure_id, - |clarity_tx| { - clarity_tx.with_clarity_db_readonly(|clarity_db| { - clarity_db.get_account_nonce(&address.into()).unwrap_or(0) - }) - }, - ) - .unwrap_or(0); - - if cur_nonce > nonce { - test_debug!("Miner: ignoring transaction ({:?}) with nonce {nonce} from address {address}", transaction.txid()); - continue; - } - debug!("Miner: including signer transaction."; - "nonce" => {nonce}, - "origin_address" => %address, - "txid" => %transaction.txid() - ); - // TODO : filter out transactions that are not valid votes. Do not include transactions with invalid/duplicate nonces for the same address. - transactions_to_include.push(transaction); - } + NakamotoSigners::update_filtered_transactions( + &mut filtered_transactions, + &account_nonces, + self.config.is_mainnet(), + transactions, + ) } _ => {} // Any other message is ignored } } - Ok(transactions_to_include) + Ok(filtered_transactions.into_values().collect()) } fn wait_for_signer_signature( diff --git a/testnet/stacks-node/src/tests/nakamoto_integrations.rs b/testnet/stacks-node/src/tests/nakamoto_integrations.rs index e97aefd42a..3b46ce24ac 100644 --- a/testnet/stacks-node/src/tests/nakamoto_integrations.rs +++ b/testnet/stacks-node/src/tests/nakamoto_integrations.rs @@ -30,7 +30,9 @@ use stacks::chainstate::nakamoto::miner::NakamotoBlockBuilder; use stacks::chainstate::nakamoto::test_signers::TestSigners; use stacks::chainstate::nakamoto::{NakamotoBlock, NakamotoChainState}; use stacks::chainstate::stacks::address::PoxAddress; -use stacks::chainstate::stacks::boot::{MINERS_NAME, SIGNERS_VOTING_NAME}; +use stacks::chainstate::stacks::boot::{ + MINERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, +}; use stacks::chainstate::stacks::db::StacksChainState; use stacks::chainstate::stacks::miner::{BlockBuilder, BlockLimitFunction, TransactionResult}; use stacks::chainstate::stacks::{StacksTransaction, ThresholdSignature, TransactionPayload}; @@ -455,7 +457,7 @@ pub fn boot_to_epoch_3( 300, &StacksAddress::burn_address(false), SIGNERS_VOTING_NAME, - "vote-for-aggregate-public-key", + SIGNERS_VOTING_FUNCTION_NAME, &[ clarity::vm::Value::UInt(i as u128), aggregate_public_key.clone(), @@ -564,7 +566,7 @@ fn signer_vote_if_needed( 300, &StacksAddress::burn_address(false), SIGNERS_VOTING_NAME, - "vote-for-aggregate-public-key", + SIGNERS_VOTING_FUNCTION_NAME, &[ clarity::vm::Value::UInt(i as u128), aggregate_public_key.clone(), diff --git a/testnet/stacks-node/src/tests/signer.rs b/testnet/stacks-node/src/tests/signer.rs index d903f58c43..3fd265d798 100644 --- a/testnet/stacks-node/src/tests/signer.rs +++ b/testnet/stacks-node/src/tests/signer.rs @@ -7,23 +7,35 @@ use std::time::{Duration, Instant}; use std::{env, thread}; use clarity::boot_util::boot_code_id; +use clarity::vm::Value; use libsigner::{ BlockResponse, RejectCode, RunningSigner, Signer, SignerEventReceiver, SignerMessage, BLOCK_MSG_ID, }; +use rand::thread_rng; +use rand_core::RngCore; use stacks::burnchains::Txid; use stacks::chainstate::coordinator::comm::CoordinatorChannels; use stacks::chainstate::nakamoto::signer_set::NakamotoSigners; use stacks::chainstate::nakamoto::{NakamotoBlock, NakamotoBlockHeader, NakamotoBlockVote}; -use stacks::chainstate::stacks::boot::SIGNERS_NAME; +use stacks::chainstate::stacks::boot::{ + SIGNERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, +}; use stacks::chainstate::stacks::miner::TransactionEvent; -use stacks::chainstate::stacks::{StacksPrivateKey, StacksTransaction, ThresholdSignature}; +use stacks::chainstate::stacks::{ + StacksPrivateKey, StacksTransaction, ThresholdSignature, TransactionAnchorMode, + TransactionAuth, TransactionPayload, TransactionPostConditionMode, TransactionSmartContract, + TransactionVersion, +}; use stacks::core::StacksEpoch; use stacks::net::api::postblock_proposal::BlockValidateResponse; +use stacks::util_lib::strings::StacksString; use stacks_common::bitvec::BitVec; use stacks_common::codec::{read_next, StacksMessageCodec}; -use stacks_common::consts::SIGNER_SLOTS_PER_USER; -use stacks_common::types::chainstate::{ConsensusHash, StacksBlockId, TrieHash}; +use stacks_common::consts::{CHAIN_ID_TESTNET, SIGNER_SLOTS_PER_USER}; +use stacks_common::types::chainstate::{ + ConsensusHash, StacksAddress, StacksBlockId, StacksPublicKey, TrieHash, +}; use stacks_common::types::StacksEpochId; use stacks_common::util::hash::{MerkleTree, Sha512Trunc256Sum}; use stacks_common::util::secp256k1::MessageSignature; @@ -545,38 +557,190 @@ impl SignerTest { .unwrap(); // Get the signer indices let reward_cycle = self.get_current_reward_cycle(); - let valid_signer_index = self.get_signer_index(reward_cycle); - let round = self - .stacks_client - .get_last_round(reward_cycle) - .expect("FATAL: failed to get round") - .unwrap_or(0) - .saturating_add(1); - let point = Point::from(Scalar::random(&mut rand::thread_rng())); - let invalid_nonce_tx = self - .stacks_client - .build_vote_for_aggregate_public_key( - valid_signer_index, - round, - point, - reward_cycle, + + let signer_private_key = self.signer_stacks_private_keys[0]; + + let vote_contract_id = boot_code_id(SIGNERS_VOTING_NAME, false); + let contract_addr = vote_contract_id.issuer.into(); + let contract_name = vote_contract_id.name.clone(); + + let signer_index = thread_rng().next_u64(); + let signer_index_arg = Value::UInt(signer_index as u128); + + let point = Point::from(Scalar::random(&mut thread_rng())); + let point_arg = + Value::buff_from(point.compress().data.to_vec()).expect("Failed to create buff"); + + let round = thread_rng().next_u64(); + let round_arg = Value::UInt(round as u128); + + let reward_cycle_arg = Value::UInt(reward_cycle as u128); + let valid_function_args = vec![ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ]; + + // Create a invalid transaction that is not a contract call + let invalid_not_contract_call = StacksTransaction { + version: TransactionVersion::Testnet, + chain_id: CHAIN_ID_TESTNET, + auth: TransactionAuth::from_p2pkh(&signer_private_key).unwrap(), + anchor_mode: TransactionAnchorMode::Any, + post_condition_mode: TransactionPostConditionMode::Allow, + post_conditions: vec![], + payload: TransactionPayload::SmartContract( + TransactionSmartContract { + name: "test-contract".into(), + code_body: StacksString::from_str("(/ 1 0)").unwrap(), + }, None, - 0, // Old nonce + ), + }; + let invalid_contract_address = StacksClient::build_signed_contract_call_transaction( + &StacksAddress::p2pkh(false, &StacksPublicKey::from_private(&signer_private_key)), + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_contract_name = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + "bad-signers-contract-name".into(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_signers_vote_function = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + "some-other-function".into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_function_arg_signer_index = + StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &[ + point_arg.clone(), + point_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, ) - .expect("FATAL: failed to build vote for aggregate public key"); + .unwrap(); + + let invalid_function_arg_key = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &[ + signer_index_arg.clone(), + signer_index_arg.clone(), + round_arg.clone(), + reward_cycle_arg.clone(), + ], + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_function_arg_round = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &[ + signer_index_arg.clone(), + point_arg.clone(), + point_arg.clone(), + reward_cycle_arg.clone(), + ], + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_function_arg_reward_cycle = + StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &[ + signer_index_arg.clone(), + point_arg.clone(), + round_arg.clone(), + point_arg.clone(), + ], + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 1, + 10, + ) + .unwrap(); + + let invalid_nonce = StacksClient::build_signed_contract_call_transaction( + &contract_addr, + contract_name.clone(), + SIGNERS_VOTING_FUNCTION_NAME.into(), + &valid_function_args, + &signer_private_key, + TransactionVersion::Testnet, + CHAIN_ID_TESTNET, + 0, // Old nonce + 10, + ) + .unwrap(); + let invalid_stacks_client = StacksClient::new(StacksPrivateKey::new(), host, false); let invalid_signer_tx = invalid_stacks_client - .build_vote_for_aggregate_public_key( - valid_signer_index, - round, - point, - reward_cycle, - None, - 0, - ) + .build_vote_for_aggregate_public_key(0, round, point, reward_cycle, None, 0) .expect("FATAL: failed to build vote for aggregate public key"); - // TODO: add invalid contract calls (one with non 'vote-for-aggregate-public-key' function call and one with invalid function args) - vec![invalid_nonce_tx, invalid_signer_tx] + + vec![ + invalid_nonce, + invalid_not_contract_call, + invalid_contract_name, + invalid_contract_address, + invalid_signers_vote_function, + invalid_function_arg_key, + invalid_function_arg_reward_cycle, + invalid_function_arg_round, + invalid_function_arg_signer_index, + invalid_signer_tx, + ] } fn shutdown(self) { From ce308f33c6df9d620a3d64c36eed8241b0281f04 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Wed, 28 Feb 2024 09:03:34 -0500 Subject: [PATCH 34/39] CRC: rename point vars to dkg_public_key for clarity Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/stacks_client.rs | 8 ++++---- stacks-signer/src/signer.rs | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stacks-signer/src/client/stacks_client.rs b/stacks-signer/src/client/stacks_client.rs index 5e422b3c62..471cec068f 100644 --- a/stacks-signer/src/client/stacks_client.rs +++ b/stacks-signer/src/client/stacks_client.rs @@ -483,12 +483,12 @@ impl StacksClient { "Failed to convert aggregate public key to compressed data: {e}" )) })?; - let point = Point::try_from(&compressed_data).map_err(|e| { + let dkg_public_key = Point::try_from(&compressed_data).map_err(|e| { ClientError::MalformedClarityValue(format!( "Failed to convert aggregate public key to a point: {e}" )) })?; - Ok(Some(point)) + Ok(Some(dkg_public_key)) } /// Helper function to create a stacks transaction for a modifying contract call @@ -496,7 +496,7 @@ impl StacksClient { &self, signer_index: u32, round: u64, - point: Point, + dkg_public_key: Point, reward_cycle: u64, tx_fee: Option, nonce: u64, @@ -507,7 +507,7 @@ impl StacksClient { let function_name = ClarityName::from(SIGNERS_VOTING_FUNCTION_NAME); let function_args = vec![ ClarityValue::UInt(signer_index as u128), - ClarityValue::buff_from(point.compress().data.to_vec())?, + ClarityValue::buff_from(dkg_public_key.compress().data.to_vec())?, ClarityValue::UInt(round as u128), ClarityValue::UInt(reward_cycle as u128), ]; diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index e759f2ff70..e67d203700 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -839,8 +839,8 @@ impl Signer { OperationResult::SignTaproot(_) => { debug!("Signer #{}: Received a signature result for a taproot signature. Nothing to broadcast as we currently sign blocks with a FROST signature.", self.signer_id); } - OperationResult::Dkg(point) => { - self.process_dkg(stacks_client, point); + OperationResult::Dkg(dkg_public_key) => { + self.process_dkg(stacks_client, dkg_public_key); } OperationResult::SignError(e) => { warn!("Signer #{}: Received a Sign error: {e:?}", self.signer_id); @@ -855,7 +855,7 @@ impl Signer { } /// Process a dkg result by broadcasting a vote to the stacks node - fn process_dkg(&mut self, stacks_client: &StacksClient, point: &Point) { + fn process_dkg(&mut self, stacks_client: &StacksClient, dkg_public_key: &Point) { let epoch = retry_with_exponential_backoff(|| { stacks_client .get_node_epoch() @@ -895,7 +895,7 @@ impl Signer { match stacks_client.build_vote_for_aggregate_public_key( self.stackerdb.get_signer_slot_id(), self.coordinator.current_dkg_id, - *point, + *dkg_public_key, self.reward_cycle, tx_fee, next_nonce, @@ -908,14 +908,14 @@ impl Signer { new_transaction, ) { warn!( - "Signer #{}: Failed to broadcast DKG vote ({point:?}): {e:?}", + "Signer #{}: Failed to broadcast DKG public key vote ({dkg_public_key:?}): {e:?}", self.signer_id ); } } Err(e) => { warn!( - "Signer #{}: Failed to build DKG vote ({point:?}) transaction: {e:?}.", + "Signer #{}: Failed to build DKG public key vote ({dkg_public_key:?}) transaction: {e:?}.", self.signer_id ); } @@ -1137,15 +1137,15 @@ impl Signer { }).unwrap_or_default(); // Check if we have an existing vote transaction for the same round and reward cycle for transaction in old_transactions.iter() { - let (_index, point, round, reward_cycle) = + let (_index, dkg_public_key, round, reward_cycle) = NakamotoSigners::parse_vote_for_aggregate_public_key(transaction).expect(&format!("BUG: Signer #{}: Received an invalid {SIGNERS_VOTING_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); - if Some(point) == self.coordinator.aggregate_public_key + if Some(dkg_public_key) == self.coordinator.aggregate_public_key && round == self.coordinator.current_dkg_id && reward_cycle == self.reward_cycle { debug!("Signer #{}: Not triggering a DKG round. Already have a pending vote transaction.", self.signer_id; "txid" => %transaction.txid(), - "point" => %point, + "dkg_public_key" => %dkg_public_key, "round" => round ); return Ok(()); From c533146b7d4d1dd38ac381fc54fcd18a3bd3a6bd Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Fri, 1 Mar 2024 08:15:05 -0500 Subject: [PATCH 35/39] CRC: pull parsed aggregate key vote results into a struct Signed-off-by: Jacinta Ferrant --- stacks-signer/src/signer.rs | 14 ++++++------- .../src/chainstate/nakamoto/signer_set.rs | 20 +++++++++++++++---- .../src/chainstate/nakamoto/tests/mod.rs | 11 +++++----- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index e67d203700..fd80138aa1 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -1131,22 +1131,22 @@ impl Signer { // Have I already voted and have a pending transaction? Check stackerdb for the same round number and reward cycle vote transaction // Only get the account nonce of THIS signer as we only care about our own votes, not other signer votes let signer_address = stacks_client.get_signer_address(); - let account_nonces = self.get_account_nonces(stacks_client, &[signer_address.clone()]); + let account_nonces = self.get_account_nonces(stacks_client, &[*signer_address]); let old_transactions = self.get_signer_transactions(&account_nonces).map_err(|e| { warn!("Signer #{}: Failed to get old signer transactions: {e:?}. May trigger DKG unnecessarily", self.signer_id); }).unwrap_or_default(); // Check if we have an existing vote transaction for the same round and reward cycle for transaction in old_transactions.iter() { - let (_index, dkg_public_key, round, reward_cycle) = - NakamotoSigners::parse_vote_for_aggregate_public_key(transaction).expect(&format!("BUG: Signer #{}: Received an invalid {SIGNERS_VOTING_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); - if Some(dkg_public_key) == self.coordinator.aggregate_public_key - && round == self.coordinator.current_dkg_id + let params = + NakamotoSigners::parse_vote_for_aggregate_public_key(transaction).unwrap_or_else(|| panic!("BUG: Signer #{}: Received an invalid {SIGNERS_VOTING_FUNCTION_NAME} transaction in an already filtered list: {transaction:?}", self.signer_id)); + if Some(params.aggregate_key) == self.coordinator.aggregate_public_key + && params.voting_round == self.coordinator.current_dkg_id && reward_cycle == self.reward_cycle { debug!("Signer #{}: Not triggering a DKG round. Already have a pending vote transaction.", self.signer_id; "txid" => %transaction.txid(), - "dkg_public_key" => %dkg_public_key, - "round" => round + "aggregate_key" => %params.aggregate_key, + "voting_round" => params.voting_round ); return Ok(()); } diff --git a/stackslib/src/chainstate/nakamoto/signer_set.rs b/stackslib/src/chainstate/nakamoto/signer_set.rs index a39d6bebc2..5049286908 100644 --- a/stackslib/src/chainstate/nakamoto/signer_set.rs +++ b/stackslib/src/chainstate/nakamoto/signer_set.rs @@ -99,6 +99,13 @@ pub struct SignerCalculation { pub events: Vec, } +pub struct AggregateKeyVoteParams { + pub signer_index: u64, + pub aggregate_key: Point, + pub voting_round: u64, + pub reward_cycle: u64, +} + impl RawRewardSetEntry { pub fn from_pox_4_tuple(is_mainnet: bool, tuple: TupleData) -> Result { let mut tuple_data = tuple.data_map; @@ -515,7 +522,7 @@ impl NakamotoSigners { pub fn parse_vote_for_aggregate_public_key( transaction: &StacksTransaction, - ) -> Option<(u64, Point, u64, u64)> { + ) -> Option { let TransactionPayload::ContractCall(payload) = &transaction.payload else { // Not a contract call so not a special cased vote for aggregate public key transaction return None; @@ -535,12 +542,17 @@ impl NakamotoSigners { let point_value = payload.function_args.get(1)?; let point_bytes = point_value.clone().expect_buff(33).ok()?; let compressed_data = Compressed::try_from(point_bytes.as_slice()).ok()?; - let point = Point::try_from(&compressed_data).ok()?; + let aggregate_key = Point::try_from(&compressed_data).ok()?; let round_value = payload.function_args.get(2)?; - let round = u64::try_from(round_value.clone().expect_u128().ok()?).ok()?; + let voting_round = u64::try_from(round_value.clone().expect_u128().ok()?).ok()?; let reward_cycle = u64::try_from(payload.function_args.get(3)?.clone().expect_u128().ok()?).ok()?; - Some((signer_index, point, round, reward_cycle)) + Some(AggregateKeyVoteParams { + signer_index, + aggregate_key, + voting_round, + reward_cycle, + }) } /// Update the map of filtered valid transactions, selecting one per address based first on lowest nonce, then txid diff --git a/stackslib/src/chainstate/nakamoto/tests/mod.rs b/stackslib/src/chainstate/nakamoto/tests/mod.rs index c27505b516..28d620b814 100644 --- a/stackslib/src/chainstate/nakamoto/tests/mod.rs +++ b/stackslib/src/chainstate/nakamoto/tests/mod.rs @@ -2122,12 +2122,11 @@ fn parse_vote_for_aggregate_public_key_valid() { function_args: valid_function_args, }), }; - let (res_signer_index, res_point, res_round, res_reward_cycle) = - NakamotoSigners::parse_vote_for_aggregate_public_key(&valid_tx).unwrap(); - assert_eq!(res_signer_index, signer_index); - assert_eq!(res_point, point); - assert_eq!(res_round, round); - assert_eq!(res_reward_cycle, reward_cycle); + let params = NakamotoSigners::parse_vote_for_aggregate_public_key(&valid_tx).unwrap(); + assert_eq!(params.signer_index, signer_index); + assert_eq!(params.aggregate_key, point); + assert_eq!(params.voting_round, round); + assert_eq!(params.reward_cycle, reward_cycle); } #[test] From fd54d9d81bf2639e8ba943f731411a76dfb21610 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Wed, 28 Feb 2024 19:05:14 -0500 Subject: [PATCH 36/39] Fix signer id use in stackerdb Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/mod.rs | 15 +- stacks-signer/src/client/stackerdb.rs | 6 +- stacks-signer/src/client/stacks_client.rs | 125 ++------------- stacks-signer/src/config.rs | 32 ++-- stacks-signer/src/coordinator.rs | 4 +- stacks-signer/src/runloop.rs | 178 ++++++++++++++++++---- stacks-signer/src/signer.rs | 58 +++---- 7 files changed, 215 insertions(+), 203 deletions(-) diff --git a/stacks-signer/src/client/mod.rs b/stacks-signer/src/client/mod.rs index 138913ee6c..424564a9fb 100644 --- a/stacks-signer/src/client/mod.rs +++ b/stacks-signer/src/client/mod.rs @@ -99,9 +99,6 @@ pub enum ClientError { /// No reward set exists for the given reward cycle #[error("No reward set exists for reward cycle {0}")] NoRewardSet(u64), - /// Reward set contained corrupted data - #[error("{0}")] - CorruptedRewardSet(String), /// Stacks node does not support a feature we need #[error("Stacks node does not support a required feature: {0}")] UnsupportedStacksFeature(String), @@ -156,7 +153,7 @@ pub(crate) mod tests { use wsts::state_machine::PublicKeys; use super::*; - use crate::config::{GlobalConfig, RegisteredSignersInfo, SignerConfig}; + use crate::config::{GlobalConfig, ParsedSignerEntries, SignerConfig}; pub struct MockServerClient { pub server: TcpListener, @@ -425,7 +422,7 @@ pub(crate) mod tests { let mut start_key_id = 1u32; let mut end_key_id = start_key_id; let mut signer_public_keys = HashMap::new(); - let mut signer_slot_ids = HashMap::new(); + let mut signer_slot_ids = vec![]; let ecdsa_private_key = config.ecdsa_private_key; let ecdsa_public_key = ecdsa::PublicKey::new(&ecdsa_private_key).expect("Failed to create ecdsa public key"); @@ -459,7 +456,7 @@ pub(crate) mod tests { &StacksPublicKey::from_slice(ecdsa_public_key.to_bytes().as_slice()) .expect("Failed to create stacks public key"), ); - signer_slot_ids.insert(address, signer_id); // Note in a real world situation, these would not always match + signer_slot_ids.push(signer_id); // Note in a real world situation, these would not always match signer_ids.insert(address, signer_id); continue; @@ -486,7 +483,7 @@ pub(crate) mod tests { &StacksPublicKey::from_slice(public_key.to_bytes().as_slice()) .expect("Failed to create stacks public key"), ); - signer_slot_ids.insert(address, signer_id); // Note in a real world situation, these would not always match + signer_slot_ids.push(signer_id); // Note in a real world situation, these would not always match signer_ids.insert(address, signer_id); start_key_id = end_key_id; } @@ -495,14 +492,14 @@ pub(crate) mod tests { signer_id: 0, signer_slot_id: 0, key_ids: signer_key_ids.get(&0).cloned().unwrap_or_default(), - registered_signers: RegisteredSignersInfo { - signer_slot_ids, + signer_entries: ParsedSignerEntries { public_keys, coordinator_key_ids, signer_key_ids, signer_ids, signer_public_keys, }, + signer_slot_ids, ecdsa_private_key: config.ecdsa_private_key, stacks_private_key: config.stacks_private_key, node_host: config.node_host, diff --git a/stacks-signer/src/client/stackerdb.rs b/stacks-signer/src/client/stackerdb.rs index affd43ab2a..13fb77af78 100644 --- a/stacks-signer/src/client/stackerdb.rs +++ b/stacks-signer/src/client/stackerdb.rs @@ -225,19 +225,17 @@ impl StackerDB { Ok(transactions) } - /// Get the latest signer transactions from signer ids for the current reward cycle + /// Get this signer's latest transactions from stackerdb pub fn get_current_transactions_with_retry( &mut self, - signer_id: u32, ) -> Result, ClientError> { - debug!("Signer #{signer_id}: Getting latest transactions from stacker db",); let Some(transactions_session) = self .signers_message_stackerdb_sessions .get_mut(&TRANSACTIONS_MSG_ID) else { return Err(ClientError::NotConnected); }; - Self::get_transactions(transactions_session, &[signer_id]) + Self::get_transactions(transactions_session, &[self.signer_slot_id]) } /// Get the latest signer transactions from signer ids for the next reward cycle diff --git a/stacks-signer/src/client/stacks_client.rs b/stacks-signer/src/client/stacks_client.rs index 471cec068f..da67e6f448 100644 --- a/stacks-signer/src/client/stacks_client.rs +++ b/stacks-signer/src/client/stacks_client.rs @@ -18,7 +18,7 @@ use std::net::SocketAddr; use blockstack_lib::burnchains::Txid; use blockstack_lib::chainstate::nakamoto::NakamotoBlock; use blockstack_lib::chainstate::stacks::boot::{ - RewardSet, SIGNERS_NAME, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, + NakamotoSignerEntry, SIGNERS_VOTING_FUNCTION_NAME, SIGNERS_VOTING_NAME, }; use blockstack_lib::chainstate::stacks::{ StacksTransaction, StacksTransactionSigner, TransactionAnchorMode, TransactionAuth, @@ -34,20 +34,17 @@ use blockstack_lib::net::api::postblock_proposal::NakamotoBlockProposal; use blockstack_lib::util_lib::boot::{boot_code_addr, boot_code_id}; use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; use clarity::vm::{ClarityName, ContractName, Value as ClarityValue}; -use hashbrown::{HashMap, HashSet}; use serde_json::json; -use slog::{slog_debug, slog_warn}; +use slog::slog_debug; use stacks_common::codec::StacksMessageCodec; use stacks_common::consts::{CHAIN_ID_MAINNET, CHAIN_ID_TESTNET}; +use stacks_common::debug; use stacks_common::types::chainstate::{StacksAddress, StacksPrivateKey, StacksPublicKey}; use stacks_common::types::StacksEpochId; -use stacks_common::{debug, warn}; -use wsts::curve::ecdsa; use wsts::curve::point::{Compressed, Point}; -use wsts::state_machine::PublicKeys; use crate::client::{retry_with_exponential_backoff, ClientError}; -use crate::config::{GlobalConfig, RegisteredSignersInfo}; +use crate::config::GlobalConfig; /// The Stacks signer client used to communicate with the stacks node #[derive(Clone, Debug)] @@ -296,8 +293,11 @@ impl StacksClient { Ok(round) } - /// Get the reward set from the stacks node for the given reward cycle - pub fn get_reward_set(&self, reward_cycle: u64) -> Result { + /// Get the reward set signers from the stacks node for the given reward cycle + pub fn get_reward_set_signers( + &self, + reward_cycle: u64, + ) -> Result>, ClientError> { debug!("Getting reward set for reward cycle {reward_cycle}..."); let send_request = || { self.stacks_node_client @@ -310,104 +310,7 @@ impl StacksClient { return Err(ClientError::RequestFailure(response.status())); } let stackers_response = response.json::()?; - Ok(stackers_response.stacker_set) - } - - /// Get the registered signers for a specific reward cycle - /// Returns None if no signers are registered or its not Nakamoto cycle - pub fn get_registered_signers_info( - &self, - reward_cycle: u64, - ) -> Result, ClientError> { - debug!("Getting registered signers for reward cycle {reward_cycle}..."); - let reward_set = self.get_reward_set(reward_cycle)?; - let Some(reward_set_signers) = reward_set.signers else { - warn!("No reward set signers found for reward cycle {reward_cycle}."); - return Ok(None); - }; - if reward_set_signers.is_empty() { - warn!("No registered signers found for reward cycle {reward_cycle}."); - return Ok(None); - } - // signer uses a Vec for its key_ids, but coordinator uses a HashSet for each signer since it needs to do lots of lookups - let mut weight_end = 1; - let mut coordinator_key_ids = HashMap::with_capacity(4000); - let mut signer_key_ids = HashMap::with_capacity(reward_set_signers.len()); - let mut signer_ids = HashMap::with_capacity(reward_set_signers.len()); - let mut public_keys = PublicKeys { - signers: HashMap::with_capacity(reward_set_signers.len()), - key_ids: HashMap::with_capacity(4000), - }; - let mut signer_public_keys = HashMap::with_capacity(reward_set_signers.len()); - for (i, entry) in reward_set_signers.iter().enumerate() { - let signer_id = u32::try_from(i).expect("FATAL: number of signers exceeds u32::MAX"); - let ecdsa_public_key = ecdsa::PublicKey::try_from(entry.signing_key.as_slice()).map_err(|e| { - ClientError::CorruptedRewardSet(format!( - "Reward cycle {reward_cycle} failed to convert signing key to ecdsa::PublicKey: {e}" - )) - })?; - let signer_public_key = Point::try_from(&Compressed::from(ecdsa_public_key.to_bytes())) - .map_err(|e| { - ClientError::CorruptedRewardSet(format!( - "Reward cycle {reward_cycle} failed to convert signing key to Point: {e}" - )) - })?; - let stacks_public_key = StacksPublicKey::from_slice(entry.signing_key.as_slice()).map_err(|e| { - ClientError::CorruptedRewardSet(format!( - "Reward cycle {reward_cycle} failed to convert signing key to StacksPublicKey: {e}" - )) - })?; - - let stacks_address = StacksAddress::p2pkh(self.mainnet, &stacks_public_key); - - signer_ids.insert(stacks_address, signer_id); - signer_public_keys.insert(signer_id, signer_public_key); - let weight_start = weight_end; - weight_end = weight_start + entry.weight; - for key_id in weight_start..weight_end { - public_keys.key_ids.insert(key_id, ecdsa_public_key); - public_keys.signers.insert(signer_id, ecdsa_public_key); - coordinator_key_ids - .entry(signer_id) - .or_insert(HashSet::with_capacity(entry.weight as usize)) - .insert(key_id); - signer_key_ids - .entry(signer_id) - .or_insert(Vec::with_capacity(entry.weight as usize)) - .push(key_id); - } - } - - let signer_set = - u32::try_from(reward_cycle % 2).expect("FATAL: reward_cycle % 2 exceeds u32::MAX"); - let signer_stackerdb_contract_id = boot_code_id(SIGNERS_NAME, self.mainnet); - // Get the signer writers from the stacker-db to find the signer slot id - let signer_slots_weights = self - .get_stackerdb_signer_slots(&signer_stackerdb_contract_id, signer_set) - .unwrap(); - let mut signer_slot_ids = HashMap::with_capacity(signer_slots_weights.len()); - for (index, (address, _)) in signer_slots_weights.into_iter().enumerate() { - signer_slot_ids.insert( - address, - u32::try_from(index).expect("FATAL: number of signers exceeds u32::MAX"), - ); - } - - for address in signer_ids.keys() { - if !signer_slot_ids.contains_key(address) { - debug!("Signer {address} does not have a slot id in the stackerdb"); - return Ok(None); - } - } - - Ok(Some(RegisteredSignersInfo { - public_keys, - signer_key_ids, - signer_ids, - signer_slot_ids, - signer_public_keys, - coordinator_key_ids, - })) + Ok(stackers_response.stacker_set.signers) } /// Retreive the current pox data from the stacks node @@ -687,7 +590,9 @@ mod tests { use blockstack_lib::chainstate::nakamoto::NakamotoBlockHeader; use blockstack_lib::chainstate::stacks::address::PoxAddress; - use blockstack_lib::chainstate::stacks::boot::{NakamotoSignerEntry, PoxStartCycleInfo}; + use blockstack_lib::chainstate::stacks::boot::{ + NakamotoSignerEntry, PoxStartCycleInfo, RewardSet, + }; use blockstack_lib::chainstate::stacks::ThresholdSignature; use rand::thread_rng; use rand_core::RngCore; @@ -1232,9 +1137,9 @@ mod tests { let stackers_response_json = serde_json::to_string(&stackers_response) .expect("Failed to serialize get stacker response"); let response = format!("HTTP/1.1 200 OK\n\n{stackers_response_json}"); - let h = spawn(move || mock.client.get_reward_set(0)); + let h = spawn(move || mock.client.get_reward_set_signers(0)); write_response(mock.server, response.as_bytes()); - assert_eq!(h.join().unwrap().unwrap(), stacker_set); + assert_eq!(h.join().unwrap().unwrap(), stacker_set.signers); } #[test] diff --git a/stacks-signer/src/config.rs b/stacks-signer/src/config.rs index bb09d3262d..6eefa8cf5b 100644 --- a/stacks-signer/src/config.rs +++ b/stacks-signer/src/config.rs @@ -110,22 +110,20 @@ impl Network { } } -/// The registered signer information for a specific reward cycle +/// Parsed Reward Set #[derive(Debug, Clone)] -pub struct RegisteredSignersInfo { - /// The signer to key ids mapping for the coordinator - pub coordinator_key_ids: HashMap>, - /// The signer to key ids mapping for the signers - pub signer_key_ids: HashMap>, - /// The signer ids to wsts pubilc keys mapping - pub signer_public_keys: HashMap, - /// The signer addresses mapped to their signer ids +pub struct ParsedSignerEntries { + /// The signer addresses mapped to signer id pub signer_ids: HashMap, - /// The signer slot id for a signer address registered in stackerdb - /// This corresponds to their unique index when voting in a reward cycle - pub signer_slot_ids: HashMap, - /// The public keys for the reward cycle + /// The signer ids mapped to public key and key ids mapped to public keys pub public_keys: PublicKeys, + /// The signer ids mapped to key ids + pub signer_key_ids: HashMap>, + /// The signer ids mapped to wsts public keys + pub signer_public_keys: HashMap, + /// The signer ids mapped to a hash set of key ids + /// The wsts coordinator uses a hash set for each signer since it needs to do lots of lookups + pub coordinator_key_ids: HashMap>, } /// The Configuration info needed for an individual signer per reward cycle @@ -133,14 +131,16 @@ pub struct RegisteredSignersInfo { pub struct SignerConfig { /// The reward cycle of the configuration pub reward_cycle: u64, - /// The signer ID assigned to this signer + /// The signer ID assigned to this signer to be used in DKG and Sign rounds pub signer_id: u32, - /// The index into the signers list of this signer's key (may be different from signer_id) + /// The signer stackerdb slot id (may be different from signer_id) pub signer_slot_id: u32, /// This signer's key ids pub key_ids: Vec, /// The registered signers for this reward cycle - pub registered_signers: RegisteredSignersInfo, + pub signer_entries: ParsedSignerEntries, + /// The signer slot ids of all signers registered for this reward cycle + pub signer_slot_ids: Vec, /// The Scalar representation of the private key for signer communication pub ecdsa_private_key: Scalar, /// The private key for this signer diff --git a/stacks-signer/src/coordinator.rs b/stacks-signer/src/coordinator.rs index 2c23fd0b32..234d1ade84 100644 --- a/stacks-signer/src/coordinator.rs +++ b/stacks-signer/src/coordinator.rs @@ -174,7 +174,7 @@ mod tests { let number_of_tests = 5; let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); let public_keys = generate_signer_config(&config, 10, 4000) - .registered_signers + .signer_entries .public_keys; let mut results = Vec::new(); @@ -197,7 +197,7 @@ mod tests { ) -> Vec> { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); let public_keys = generate_signer_config(&config, 10, 4000) - .registered_signers + .signer_entries .public_keys; let mut results = Vec::new(); let same_hash = generate_random_consensus_hash(); diff --git a/stacks-signer/src/runloop.rs b/stacks-signer/src/runloop.rs index 02fb494c6a..649dec7385 100644 --- a/stacks-signer/src/runloop.rs +++ b/stacks-signer/src/runloop.rs @@ -18,16 +18,20 @@ use std::sync::mpsc::Sender; use std::time::Duration; use blockstack_lib::chainstate::burn::ConsensusHashExtensions; -use hashbrown::HashMap; +use blockstack_lib::chainstate::stacks::boot::{NakamotoSignerEntry, SIGNERS_NAME}; +use blockstack_lib::util_lib::boot::boot_code_id; +use hashbrown::{HashMap, HashSet}; use libsigner::{SignerEvent, SignerRunLoop}; use slog::{slog_debug, slog_error, slog_info, slog_warn}; -use stacks_common::types::chainstate::ConsensusHash; +use stacks_common::types::chainstate::{ConsensusHash, StacksAddress, StacksPublicKey}; use stacks_common::{debug, error, info, warn}; +use wsts::curve::ecdsa; +use wsts::curve::point::{Compressed, Point}; use wsts::state_machine::coordinator::State as CoordinatorState; -use wsts::state_machine::OperationResult; +use wsts::state_machine::{OperationResult, PublicKeys}; use crate::client::{retry_with_exponential_backoff, ClientError, StacksClient}; -use crate::config::{GlobalConfig, SignerConfig}; +use crate::config::{GlobalConfig, ParsedSignerEntries, SignerConfig}; use crate::signer::{Command as SignerCommand, Signer, State as SignerState}; /// Which operation to perform @@ -78,27 +82,116 @@ impl From for RunLoop { } impl RunLoop { + /// Parse Nakamoto signer entries into relevant signer information + pub fn parse_nakamoto_signer_entries( + signers: &[NakamotoSignerEntry], + is_mainnet: bool, + ) -> ParsedSignerEntries { + let mut weight_end = 1; + let mut coordinator_key_ids = HashMap::with_capacity(4000); + let mut signer_key_ids = HashMap::with_capacity(signers.len()); + let mut signer_ids = HashMap::with_capacity(signers.len()); + let mut public_keys = PublicKeys { + signers: HashMap::with_capacity(signers.len()), + key_ids: HashMap::with_capacity(4000), + }; + let mut signer_public_keys = HashMap::with_capacity(signers.len()); + for (i, entry) in signers.iter().enumerate() { + // TODO: track these signer ids as non participating if any of the conversions fail + let signer_id = u32::try_from(i).expect("FATAL: number of signers exceeds u32::MAX"); + let ecdsa_public_key = ecdsa::PublicKey::try_from(entry.signing_key.as_slice()) + .expect("FATAL: corrupted signing key"); + let signer_public_key = Point::try_from(&Compressed::from(ecdsa_public_key.to_bytes())) + .expect("FATAL: corrupted signing key"); + let stacks_public_key = StacksPublicKey::from_slice(entry.signing_key.as_slice()) + .expect("FATAL: Corrupted signing key"); + + let stacks_address = StacksAddress::p2pkh(is_mainnet, &stacks_public_key); + signer_ids.insert(stacks_address, signer_id); + signer_public_keys.insert(signer_id, signer_public_key); + let weight_start = weight_end; + weight_end = weight_start + entry.weight; + for key_id in weight_start..weight_end { + public_keys.key_ids.insert(key_id, ecdsa_public_key); + public_keys.signers.insert(signer_id, ecdsa_public_key); + coordinator_key_ids + .entry(signer_id) + .or_insert(HashSet::with_capacity(entry.weight as usize)) + .insert(key_id); + signer_key_ids + .entry(signer_id) + .or_insert(Vec::with_capacity(entry.weight as usize)) + .push(key_id); + } + } + ParsedSignerEntries { + signer_ids, + public_keys, + signer_key_ids, + signer_public_keys, + coordinator_key_ids, + } + } + + /// Get the registered signers for a specific reward cycle + /// Returns None if no signers are registered or its not Nakamoto cycle + pub fn get_parsed_reward_set( + &self, + reward_cycle: u64, + ) -> Result, ClientError> { + debug!("Getting registered signers for reward cycle {reward_cycle}..."); + let Some(signers) = self.stacks_client.get_reward_set_signers(reward_cycle)? else { + warn!("No reward set signers found for reward cycle {reward_cycle}."); + return Ok(None); + }; + if signers.is_empty() { + warn!("No registered signers found for reward cycle {reward_cycle}."); + return Ok(None); + } + Ok(Some(Self::parse_nakamoto_signer_entries( + &signers, + self.config.network.is_mainnet(), + ))) + } + + /// Get the stackerdb signer slots for a specific reward cycle + pub fn get_parsed_signer_slots( + &self, + stacks_client: &StacksClient, + reward_cycle: u64, + ) -> Result, ClientError> { + let signer_set = + u32::try_from(reward_cycle % 2).expect("FATAL: reward_cycle % 2 exceeds u32::MAX"); + let signer_stackerdb_contract_id = + boot_code_id(SIGNERS_NAME, self.config.network.is_mainnet()); + // Get the signer writers from the stacker-db to find the signer slot id + let stackerdb_signer_slots = + stacks_client.get_stackerdb_signer_slots(&signer_stackerdb_contract_id, signer_set)?; + let mut signer_slot_ids = HashMap::with_capacity(stackerdb_signer_slots.len()); + for (index, (address, _)) in stackerdb_signer_slots.into_iter().enumerate() { + signer_slot_ids.insert( + address, + u32::try_from(index).expect("FATAL: number of signers exceeds u32::MAX"), + ); + } + Ok(signer_slot_ids) + } /// Get a signer configuration for a specific reward cycle from the stacks node fn get_signer_config(&mut self, reward_cycle: u64) -> Option { // We can only register for a reward cycle if a reward set exists. - let registered_signers = self - .stacks_client - .get_registered_signers_info(reward_cycle).map_err(|e| { - error!( - "Failed to retrieve registered signers info for reward cycle {reward_cycle}: {e}" - ); - e - }).ok()??; - + let signer_entries = self.get_parsed_reward_set(reward_cycle).ok()??; + let signer_slot_ids = self + .get_parsed_signer_slots(&self.stacks_client, reward_cycle) + .ok()?; let current_addr = self.stacks_client.get_signer_address(); - let Some(signer_slot_id) = registered_signers.signer_slot_ids.get(current_addr) else { + let Some(signer_slot_id) = signer_slot_ids.get(current_addr) else { warn!( "Signer {current_addr} was not found in stacker db. Must not be registered for this reward cycle {reward_cycle}." ); return None; }; - let Some(signer_id) = registered_signers.signer_ids.get(current_addr) else { + let Some(signer_id) = signer_entries.signer_ids.get(current_addr) else { warn!( "Signer {current_addr} was found in stacker db but not the reward set for reward cycle {reward_cycle}." ); @@ -107,7 +200,7 @@ impl RunLoop { info!( "Signer #{signer_id} ({current_addr}) is registered for reward cycle {reward_cycle}." ); - let key_ids = registered_signers + let key_ids = signer_entries .signer_key_ids .get(signer_id) .cloned() @@ -117,7 +210,8 @@ impl RunLoop { signer_id: *signer_id, signer_slot_id: *signer_slot_id, key_ids, - registered_signers, + signer_entries, + signer_slot_ids: signer_slot_ids.into_values().collect(), ecdsa_private_key: self.config.ecdsa_private_key, stacks_private_key: self.config.stacks_private_key, node_host: self.config.node_host, @@ -156,20 +250,13 @@ impl RunLoop { if signer.reward_cycle == prior_reward_cycle { // The signers have been calculated for the next reward cycle. Update the current one debug!("Signer #{}: Next reward cycle ({reward_cycle}) signer set calculated. Updating current reward cycle ({prior_reward_cycle}) signer.", signer.signer_id); - signer.next_signers = new_signer_config - .registered_signers + signer.next_signer_addresses = new_signer_config + .signer_entries .signer_ids .keys() .copied() .collect(); - signer.next_signer_ids = new_signer_config - .registered_signers - .signer_ids - .values() - .copied() - .collect(); - signer.next_signer_slot_ids = - new_signer_config.registered_signers.signer_slot_ids.clone(); + signer.next_signer_slot_ids = new_signer_config.signer_slot_ids.clone(); } } self.stacks_signers @@ -301,3 +388,40 @@ impl SignerRunLoop, RunLoopCommand> for RunLoop { None } } +#[cfg(test)] +mod tests { + use blockstack_lib::chainstate::stacks::boot::NakamotoSignerEntry; + use stacks_common::types::chainstate::{StacksPrivateKey, StacksPublicKey}; + + use super::RunLoop; + + #[test] + fn parse_nakamoto_signer_entries_test() { + let nmb_signers = 10; + let weight = 10; + let mut signer_entries = Vec::with_capacity(nmb_signers); + for _ in 0..nmb_signers { + let key = StacksPublicKey::from_private(&StacksPrivateKey::new()).to_bytes_compressed(); + let mut signing_key = [0u8; 33]; + signing_key.copy_from_slice(&key); + signer_entries.push(NakamotoSignerEntry { + signing_key, + stacked_amt: 0, + weight, + }); + } + + let parsed_entries = RunLoop::parse_nakamoto_signer_entries(&signer_entries, false); + assert_eq!(parsed_entries.signer_ids.len(), nmb_signers); + let mut signer_ids = parsed_entries + .signer_ids + .into_values() + .into_iter() + .collect::>(); + signer_ids.sort(); + assert_eq!( + signer_ids, + (0..nmb_signers as u32).into_iter().collect::>() + ); + } +} diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index fd80138aa1..29960874c2 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -128,18 +128,14 @@ pub struct Signer { pub mainnet: bool, /// The signer id pub signer_id: u32, - /// The other signer ids for this signer's reward cycle - pub signer_ids: Vec, - /// The addresses of other signers mapped to their signer slot ID - pub signer_slot_ids: HashMap, + /// The signer slot ids for the signers in the reward cycle + pub signer_slot_ids: Vec, /// The addresses of other signers - pub signers: Vec, - /// The other signer ids for the NEXT reward cycle's signers - pub next_signer_ids: Vec, - /// The signer addresses mapped to slot ID for the NEXT reward cycle's signers - pub next_signer_slot_ids: HashMap, + pub signer_addresses: Vec, + /// The signer slot ids for the signers in the NEXT reward cycle + pub next_signer_slot_ids: Vec, /// The addresses of the signers for the NEXT reward cycle - pub next_signers: Vec, + pub next_signer_addresses: Vec, /// The reward cycle this signer belongs to pub reward_cycle: u64, /// The tx fee in uSTX to use if the epoch is pre Nakamoto (Epoch 3.0) @@ -154,9 +150,9 @@ impl From for Signer { fn from(signer_config: SignerConfig) -> Self { let stackerdb = StackerDB::from(&signer_config); - let num_signers = u32::try_from(signer_config.registered_signers.public_keys.signers.len()) + let num_signers = u32::try_from(signer_config.signer_entries.public_keys.signers.len()) .expect("FATAL: Too many registered signers to fit in a u32"); - let num_keys = u32::try_from(signer_config.registered_signers.public_keys.key_ids.len()) + let num_keys = u32::try_from(signer_config.signer_entries.public_keys.key_ids.len()) .expect("FATAL: Too many key ids to fit in a u32"); let threshold = (num_keys as f64 * 7_f64 / 10_f64).ceil() as u32; let dkg_threshold = (num_keys as f64 * 9_f64 / 10_f64).ceil() as u32; @@ -172,8 +168,8 @@ impl From for Signer { dkg_end_timeout: signer_config.dkg_end_timeout, nonce_timeout: signer_config.nonce_timeout, sign_timeout: signer_config.sign_timeout, - signer_key_ids: signer_config.registered_signers.coordinator_key_ids, - signer_public_keys: signer_config.registered_signers.signer_public_keys, + signer_key_ids: signer_config.signer_entries.coordinator_key_ids, + signer_public_keys: signer_config.signer_entries.signer_public_keys, }; let coordinator = FireCoordinator::new(coordinator_config); @@ -184,10 +180,10 @@ impl From for Signer { signer_config.signer_id, signer_config.key_ids, signer_config.ecdsa_private_key, - signer_config.registered_signers.public_keys.clone(), + signer_config.signer_entries.public_keys.clone(), ); let coordinator_selector = - CoordinatorSelector::from(signer_config.registered_signers.public_keys); + CoordinatorSelector::from(signer_config.signer_entries.public_keys); debug!( "Signer #{}: initial coordinator is signer {}", @@ -204,22 +200,14 @@ impl From for Signer { stackerdb, mainnet: signer_config.mainnet, signer_id: signer_config.signer_id, - signer_ids: signer_config - .registered_signers + signer_addresses: signer_config + .signer_entries .signer_ids - .values() - .copied() + .into_keys() .collect(), - signer_slot_ids: signer_config.registered_signers.signer_slot_ids, - signers: signer_config - .registered_signers - .signer_ids - .keys() - .copied() - .collect(), - next_signer_ids: vec![], - next_signer_slot_ids: HashMap::new(), - next_signers: vec![], + signer_slot_ids: signer_config.signer_slot_ids.clone(), + next_signer_slot_ids: vec![], + next_signer_addresses: vec![], reward_cycle: signer_config.reward_cycle, tx_fee_ustx: signer_config.tx_fee_ustx, coordinator_selector, @@ -714,7 +702,7 @@ impl Signer { ) -> Result, ClientError> { let transactions: Vec<_> = self .stackerdb - .get_current_transactions_with_retry(self.signer_id)? + .get_current_transactions_with_retry()? .into_iter() .filter_map(|tx| { if !NakamotoSigners::valid_vote_transaction(nonces, &tx, self.mainnet) { @@ -731,7 +719,7 @@ impl Signer { &mut self, stacks_client: &StacksClient, ) -> Result, ClientError> { - if self.next_signer_ids.is_empty() { + if self.next_signer_slot_ids.is_empty() { debug!( "Signer #{}: No next signers. Skipping transaction retrieval.", self.signer_id @@ -739,10 +727,10 @@ impl Signer { return Ok(vec![]); } // Get all the account nonces for the next signers - let account_nonces = self.get_account_nonces(stacks_client, &self.next_signers); + let account_nonces = self.get_account_nonces(stacks_client, &self.next_signer_addresses); let transactions: Vec<_> = self .stackerdb - .get_next_transactions_with_retry(&self.next_signer_ids)?; + .get_next_transactions_with_retry(&self.next_signer_slot_ids)?; let mut filtered_transactions = std::collections::HashMap::new(); NakamotoSigners::update_filtered_transactions( &mut filtered_transactions, @@ -874,7 +862,7 @@ impl Signer { // Get our current nonce from the stacks node and compare it against what we have sitting in the stackerdb instance let signer_address = stacks_client.get_signer_address(); // Retreieve ALL account nonces as we may have transactions from other signers in our stackerdb slot that we care about - let account_nonces = self.get_account_nonces(stacks_client, &self.signers); + let account_nonces = self.get_account_nonces(stacks_client, &self.signer_addresses); let account_nonce = account_nonces.get(signer_address).unwrap_or(&0); let signer_transactions = retry_with_exponential_backoff(|| { self.get_signer_transactions(&account_nonces) From 73fd5e0309b5f62135a71c2dd6f3dea8ba406977 Mon Sep 17 00:00:00 2001 From: Jacinta Ferrant Date: Thu, 29 Feb 2024 10:45:19 -0500 Subject: [PATCH 37/39] Wrap signer slot ID in a struct to prevent conflation with signer ID Signed-off-by: Jacinta Ferrant --- stacks-signer/src/client/mod.rs | 7 ++++--- stacks-signer/src/client/stackerdb.rs | 21 +++++++++++---------- stacks-signer/src/config.rs | 6 ++++-- stacks-signer/src/runloop.rs | 16 +++++++--------- stacks-signer/src/signer.rs | 16 +++++++++++++--- testnet/stacks-node/src/tests/signer.rs | 8 +++++--- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/stacks-signer/src/client/mod.rs b/stacks-signer/src/client/mod.rs index 424564a9fb..63dc0e9a1f 100644 --- a/stacks-signer/src/client/mod.rs +++ b/stacks-signer/src/client/mod.rs @@ -154,6 +154,7 @@ pub(crate) mod tests { use super::*; use crate::config::{GlobalConfig, ParsedSignerEntries, SignerConfig}; + use crate::signer::SignerSlotID; pub struct MockServerClient { pub server: TcpListener, @@ -456,7 +457,7 @@ pub(crate) mod tests { &StacksPublicKey::from_slice(ecdsa_public_key.to_bytes().as_slice()) .expect("Failed to create stacks public key"), ); - signer_slot_ids.push(signer_id); // Note in a real world situation, these would not always match + signer_slot_ids.push(SignerSlotID(signer_id)); signer_ids.insert(address, signer_id); continue; @@ -483,14 +484,14 @@ pub(crate) mod tests { &StacksPublicKey::from_slice(public_key.to_bytes().as_slice()) .expect("Failed to create stacks public key"), ); - signer_slot_ids.push(signer_id); // Note in a real world situation, these would not always match + signer_slot_ids.push(SignerSlotID(signer_id)); signer_ids.insert(address, signer_id); start_key_id = end_key_id; } SignerConfig { reward_cycle, signer_id: 0, - signer_slot_id: 0, + signer_slot_id: SignerSlotID(rand::thread_rng().gen_range(0..num_signers)), // Give a random signer slot id between 0 and num_signers key_ids: signer_key_ids.get(&0).cloned().unwrap_or_default(), signer_entries: ParsedSignerEntries { public_keys, diff --git a/stacks-signer/src/client/stackerdb.rs b/stacks-signer/src/client/stackerdb.rs index 13fb77af78..77f4d679d9 100644 --- a/stacks-signer/src/client/stackerdb.rs +++ b/stacks-signer/src/client/stackerdb.rs @@ -33,6 +33,7 @@ use stacks_common::{debug, warn}; use super::ClientError; use crate::client::retry_with_exponential_backoff; use crate::config::SignerConfig; +use crate::signer::SignerSlotID; /// The StackerDB client for communicating with the .signers contract pub struct StackerDB { @@ -42,9 +43,9 @@ pub struct StackerDB { /// The private key used in all stacks node communications stacks_private_key: StacksPrivateKey, /// A map of a message ID to last chunk version for each session - slot_versions: HashMap>, + slot_versions: HashMap>, /// The signer slot ID -- the index into the signer list for this signer daemon's signing key. - signer_slot_id: u32, + signer_slot_id: SignerSlotID, /// The reward cycle of the connecting signer reward_cycle: u64, /// The stacker-db transaction msg session for the NEXT reward cycle @@ -69,7 +70,7 @@ impl StackerDB { stacks_private_key: StacksPrivateKey, is_mainnet: bool, reward_cycle: u64, - signer_slot_id: u32, + signer_slot_id: SignerSlotID, ) -> Self { let mut signers_message_stackerdb_sessions = HashMap::new(); let stackerdb_issuer = boot_code_addr(is_mainnet); @@ -134,7 +135,7 @@ impl StackerDB { 1 }; - let mut chunk = StackerDBChunkData::new(slot_id, slot_version, message_bytes.clone()); + let mut chunk = StackerDBChunkData::new(slot_id.0, slot_version, message_bytes.clone()); chunk.sign(&self.stacks_private_key)?; let Some(session) = self.signers_message_stackerdb_sessions.get_mut(&msg_id) else { @@ -184,11 +185,11 @@ impl StackerDB { /// Get the transactions from stackerdb for the signers fn get_transactions( transactions_session: &mut StackerDBSession, - signer_ids: &[u32], + signer_ids: &[SignerSlotID], ) -> Result, ClientError> { let send_request = || { transactions_session - .get_latest_chunks(signer_ids) + .get_latest_chunks(&signer_ids.iter().map(|id| id.0).collect::>()) .map_err(backoff::Error::transient) }; let chunk_ack = retry_with_exponential_backoff(send_request)?; @@ -241,7 +242,7 @@ impl StackerDB { /// Get the latest signer transactions from signer ids for the next reward cycle pub fn get_next_transactions_with_retry( &mut self, - signer_ids: &[u32], + signer_ids: &[SignerSlotID], ) -> Result, ClientError> { debug!("Getting latest chunks from stackerdb for the following signers: {signer_ids:?}",); Self::get_transactions(&mut self.next_transaction_session, signer_ids) @@ -253,7 +254,7 @@ impl StackerDB { } /// Retrieve the signer slot ID - pub fn get_signer_slot_id(&mut self) -> u32 { + pub fn get_signer_slot_id(&mut self) -> SignerSlotID { self.signer_slot_id } } @@ -300,8 +301,8 @@ mod tests { let signer_message = SignerMessage::Transactions(vec![tx.clone()]); let message = signer_message.serialize_to_vec(); - let signer_ids = vec![0, 1]; - let h = spawn(move || stackerdb.get_next_transactions_with_retry(&signer_ids)); + let signer_slot_ids = vec![SignerSlotID(0), SignerSlotID(1)]; + let h = spawn(move || stackerdb.get_next_transactions_with_retry(&signer_slot_ids)); let mut response_bytes = b"HTTP/1.1 200 OK\n\n".to_vec(); response_bytes.extend(message); let mock_server = mock_server_from_config(&config); diff --git a/stacks-signer/src/config.rs b/stacks-signer/src/config.rs index 6eefa8cf5b..d8c7b4a8e9 100644 --- a/stacks-signer/src/config.rs +++ b/stacks-signer/src/config.rs @@ -32,6 +32,8 @@ use wsts::curve::point::Point; use wsts::curve::scalar::Scalar; use wsts::state_machine::PublicKeys; +use crate::signer::SignerSlotID; + const EVENT_TIMEOUT_MS: u64 = 5000; // Default transaction fee in microstacks (if unspecificed in the config file) // TODO: Use the fee estimation endpoint to get the default fee. @@ -134,13 +136,13 @@ pub struct SignerConfig { /// The signer ID assigned to this signer to be used in DKG and Sign rounds pub signer_id: u32, /// The signer stackerdb slot id (may be different from signer_id) - pub signer_slot_id: u32, + pub signer_slot_id: SignerSlotID, /// This signer's key ids pub key_ids: Vec, /// The registered signers for this reward cycle pub signer_entries: ParsedSignerEntries, /// The signer slot ids of all signers registered for this reward cycle - pub signer_slot_ids: Vec, + pub signer_slot_ids: Vec, /// The Scalar representation of the private key for signer communication pub ecdsa_private_key: Scalar, /// The private key for this signer diff --git a/stacks-signer/src/runloop.rs b/stacks-signer/src/runloop.rs index 649dec7385..c0ec846acd 100644 --- a/stacks-signer/src/runloop.rs +++ b/stacks-signer/src/runloop.rs @@ -32,7 +32,7 @@ use wsts::state_machine::{OperationResult, PublicKeys}; use crate::client::{retry_with_exponential_backoff, ClientError, StacksClient}; use crate::config::{GlobalConfig, ParsedSignerEntries, SignerConfig}; -use crate::signer::{Command as SignerCommand, Signer, State as SignerState}; +use crate::signer::{Command as SignerCommand, Signer, SignerSlotID, State as SignerState}; /// Which operation to perform #[derive(PartialEq, Clone, Debug)] @@ -159,7 +159,7 @@ impl RunLoop { &self, stacks_client: &StacksClient, reward_cycle: u64, - ) -> Result, ClientError> { + ) -> Result, ClientError> { let signer_set = u32::try_from(reward_cycle % 2).expect("FATAL: reward_cycle % 2 exceeds u32::MAX"); let signer_stackerdb_contract_id = @@ -171,7 +171,9 @@ impl RunLoop { for (index, (address, _)) in stackerdb_signer_slots.into_iter().enumerate() { signer_slot_ids.insert( address, - u32::try_from(index).expect("FATAL: number of signers exceeds u32::MAX"), + SignerSlotID( + u32::try_from(index).expect("FATAL: number of signers exceeds u32::MAX"), + ), ); } Ok(signer_slot_ids) @@ -413,15 +415,11 @@ mod tests { let parsed_entries = RunLoop::parse_nakamoto_signer_entries(&signer_entries, false); assert_eq!(parsed_entries.signer_ids.len(), nmb_signers); - let mut signer_ids = parsed_entries - .signer_ids - .into_values() - .into_iter() - .collect::>(); + let mut signer_ids = parsed_entries.signer_ids.into_values().collect::>(); signer_ids.sort(); assert_eq!( signer_ids, - (0..nmb_signers as u32).into_iter().collect::>() + (0..nmb_signers).map(|id| id as u32).collect::>() ); } } diff --git a/stacks-signer/src/signer.rs b/stacks-signer/src/signer.rs index 29960874c2..59962e5ae5 100644 --- a/stacks-signer/src/signer.rs +++ b/stacks-signer/src/signer.rs @@ -46,6 +46,16 @@ use crate::client::{retry_with_exponential_backoff, ClientError, StackerDB, Stac use crate::config::SignerConfig; use crate::coordinator::CoordinatorSelector; +/// The signer StackerDB slot ID, purposefully wrapped to prevent conflation with SignerID +#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)] +pub struct SignerSlotID(pub u32); + +impl std::fmt::Display for SignerSlotID { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + /// Additional Info about a proposed block pub struct BlockInfo { /// The block we are considering @@ -129,11 +139,11 @@ pub struct Signer { /// The signer id pub signer_id: u32, /// The signer slot ids for the signers in the reward cycle - pub signer_slot_ids: Vec, + pub signer_slot_ids: Vec, /// The addresses of other signers pub signer_addresses: Vec, /// The signer slot ids for the signers in the NEXT reward cycle - pub next_signer_slot_ids: Vec, + pub next_signer_slot_ids: Vec, /// The addresses of the signers for the NEXT reward cycle pub next_signer_addresses: Vec, /// The reward cycle this signer belongs to @@ -881,7 +891,7 @@ impl Signer { .map(|tx| tx.get_origin_nonce().wrapping_add(1)) .unwrap_or(*account_nonce); match stacks_client.build_vote_for_aggregate_public_key( - self.stackerdb.get_signer_slot_id(), + self.stackerdb.get_signer_slot_id().0, self.coordinator.current_dkg_id, *dkg_public_key, self.reward_cycle, diff --git a/testnet/stacks-node/src/tests/signer.rs b/testnet/stacks-node/src/tests/signer.rs index 3fd265d798..c0c2e72e2b 100644 --- a/testnet/stacks-node/src/tests/signer.rs +++ b/testnet/stacks-node/src/tests/signer.rs @@ -42,7 +42,7 @@ use stacks_common::util::secp256k1::MessageSignature; use stacks_signer::client::{StackerDB, StacksClient}; use stacks_signer::config::{build_signer_config_tomls, GlobalConfig as SignerConfig, Network}; use stacks_signer::runloop::RunLoopCommand; -use stacks_signer::signer::Command as SignerCommand; +use stacks_signer::signer::{Command as SignerCommand, SignerSlotID}; use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; use wsts::common::Signature; @@ -531,7 +531,7 @@ impl SignerTest { .unwrap() } - fn get_signer_index(&self, reward_cycle: u64) -> u32 { + fn get_signer_index(&self, reward_cycle: u64) -> SignerSlotID { let valid_signer_set = u32::try_from(reward_cycle % 2).expect("FATAL: reward_cycle % 2 exceeds u32::MAX"); let signer_stackerdb_contract_id = boot_code_id(SIGNERS_NAME, false); @@ -541,7 +541,9 @@ impl SignerTest { .expect("FATAL: failed to get signer slots from stackerdb") .iter() .position(|(address, _)| address == self.stacks_client.get_signer_address()) - .map(|pos| u32::try_from(pos).expect("FATAL: number of signers exceeds u32::MAX")) + .map(|pos| { + SignerSlotID(u32::try_from(pos).expect("FATAL: number of signers exceeds u32::MAX")) + }) .expect("FATAL: signer not registered") } From aa0f6d7e4ba422b126bd4239589f9b7e6b9f0db8 Mon Sep 17 00:00:00 2001 From: Jeff Bencin Date: Tue, 27 Feb 2024 11:49:38 -0500 Subject: [PATCH 38/39] chore: Remove unnecessary `sha2-asm` dependency --- Cargo.lock | 12 +----------- clarity/Cargo.toml | 3 --- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aedba0ffaa..d4cf3e3c08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -730,7 +730,6 @@ dependencies = [ "serde_derive", "serde_json", "serde_stacker", - "sha2-asm 0.5.5", "slog", "stacks-common", "time 0.2.27", @@ -3298,16 +3297,7 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", - "sha2-asm 0.6.3", -] - -[[package]] -name = "sha2-asm" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c2f225be6502f2134e6bbb35bb5e2957e41ffa0495ed08bce2e2b4ca885da4" -dependencies = [ - "cc", + "sha2-asm", ] [[package]] diff --git a/clarity/Cargo.toml b/clarity/Cargo.toml index c0b82a7fd1..4d51cf3e4e 100644 --- a/clarity/Cargo.toml +++ b/clarity/Cargo.toml @@ -56,6 +56,3 @@ developer-mode = [] slog_json = ["stacks_common/slog_json"] testing = [] -[target.'cfg(all(target_arch = "x86_64", not(target_env = "msvc")))'.dependencies] -sha2-asm = "0.5.3" - From ac03fc769a5f428d92898f7204e2c1ef1d97cce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Blankfors?= Date: Mon, 4 Mar 2024 11:38:58 +0100 Subject: [PATCH 39/39] fix: Port binding conflict in client::stackerdb::tests --- Cargo.lock | 78 ---------------------- stacks-signer/Cargo.toml | 1 - stacks-signer/src/client/stackerdb.rs | 5 +- stacks-signer/src/client/stacks_client.rs | 3 - stacks-signer/src/tests/conf/signer-0.toml | 1 - stacks-signer/src/tests/conf/signer-1.toml | 3 +- stacks-signer/src/tests/conf/signer-2.toml | 5 -- stacks-signer/src/tests/conf/signer-3.toml | 5 -- 8 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 stacks-signer/src/tests/conf/signer-2.toml delete mode 100644 stacks-signer/src/tests/conf/signer-3.toml diff --git a/Cargo.lock b/Cargo.lock index d4cf3e3c08..c831a5fbaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,19 +988,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.3", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "data-encoding" version = "2.5.0" @@ -1989,16 +1976,6 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.20" @@ -2278,29 +2255,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3067,12 +3021,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "sct" version = "0.7.1" @@ -3224,31 +3172,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serial_test" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ad9342b3aaca7cb43c45c097dd008d4907070394bd0751a0aa8817e5a018d" -dependencies = [ - "dashmap", - "futures", - "lazy_static", - "log", - "parking_lot", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "sha1" version = "0.6.1" @@ -3536,7 +3459,6 @@ dependencies = [ "serde_derive", "serde_json", "serde_stacker", - "serial_test", "slog", "slog-json", "slog-term", diff --git a/stacks-signer/Cargo.toml b/stacks-signer/Cargo.toml index 8944c10342..99b02761c2 100644 --- a/stacks-signer/Cargo.toml +++ b/stacks-signer/Cargo.toml @@ -44,7 +44,6 @@ wsts = { workspace = true } rand = { workspace = true } [dev-dependencies] -serial_test = "3.0.0" clarity = { path = "../clarity", features = ["testing"] } [dependencies.serde_json] diff --git a/stacks-signer/src/client/stackerdb.rs b/stacks-signer/src/client/stackerdb.rs index 77f4d679d9..1e9e2e30f6 100644 --- a/stacks-signer/src/client/stackerdb.rs +++ b/stacks-signer/src/client/stackerdb.rs @@ -269,14 +269,12 @@ mod tests { TransactionSmartContract, TransactionVersion, }; use blockstack_lib::util_lib::strings::StacksString; - use serial_test::serial; use super::*; use crate::client::tests::{generate_signer_config, mock_server_from_config, write_response}; use crate::config::GlobalConfig; #[test] - #[serial] fn get_signer_transactions_with_retry_should_succeed() { let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); let signer_config = generate_signer_config(&config, 5, 20); @@ -320,9 +318,8 @@ mod tests { } #[test] - #[serial] fn send_signer_message_with_retry_should_succeed() { - let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap(); + let config = GlobalConfig::load_from_file("./src/tests/conf/signer-1.toml").unwrap(); let signer_config = generate_signer_config(&config, 5, 20); let mut stackerdb = StackerDB::from(&signer_config); diff --git a/stacks-signer/src/client/stacks_client.rs b/stacks-signer/src/client/stacks_client.rs index da67e6f448..054e4fb374 100644 --- a/stacks-signer/src/client/stacks_client.rs +++ b/stacks-signer/src/client/stacks_client.rs @@ -596,7 +596,6 @@ mod tests { use blockstack_lib::chainstate::stacks::ThresholdSignature; use rand::thread_rng; use rand_core::RngCore; - use serial_test::serial; use stacks_common::bitvec::BitVec; use stacks_common::consts::{CHAIN_ID_TESTNET, SIGNER_SLOTS_PER_USER}; use stacks_common::types::chainstate::{ConsensusHash, StacksBlockId, TrieHash}; @@ -837,7 +836,6 @@ mod tests { #[ignore] #[test] - #[serial] fn build_vote_for_aggregate_public_key_should_succeed() { let mock = MockServerClient::new(); let point = Point::from(Scalar::random(&mut rand::thread_rng())); @@ -861,7 +859,6 @@ mod tests { #[ignore] #[test] - #[serial] fn broadcast_vote_for_aggregate_public_key_should_succeed() { let mock = MockServerClient::new(); let point = Point::from(Scalar::random(&mut rand::thread_rng())); diff --git a/stacks-signer/src/tests/conf/signer-0.toml b/stacks-signer/src/tests/conf/signer-0.toml index 42083c30a7..2c30d82326 100644 --- a/stacks-signer/src/tests/conf/signer-0.toml +++ b/stacks-signer/src/tests/conf/signer-0.toml @@ -1,4 +1,3 @@ - stacks_private_key = "6a1fc1a3183018c6d79a4e11e154d2bdad2d89ac8bc1b0a021de8b4d28774fbb01" node_host = "127.0.0.1:20443" endpoint = "localhost:30000" diff --git a/stacks-signer/src/tests/conf/signer-1.toml b/stacks-signer/src/tests/conf/signer-1.toml index 38897ae48c..99facfc1d2 100644 --- a/stacks-signer/src/tests/conf/signer-1.toml +++ b/stacks-signer/src/tests/conf/signer-1.toml @@ -1,5 +1,4 @@ - stacks_private_key = "126e916e77359ccf521e168feea1fcb9626c59dc375cae00c7464303381c7dff01" -node_host = "127.0.0.1:20443" +node_host = "127.0.0.1:20444" endpoint = "localhost:30001" network = "testnet" diff --git a/stacks-signer/src/tests/conf/signer-2.toml b/stacks-signer/src/tests/conf/signer-2.toml deleted file mode 100644 index 9235b2e076..0000000000 --- a/stacks-signer/src/tests/conf/signer-2.toml +++ /dev/null @@ -1,5 +0,0 @@ - -stacks_private_key = "b169d0d1408f66d16beb321857f525f9014dfc289f1aeedbcf96e78afeb8eb4001" -node_host = "127.0.0.1:20443" -endpoint = "localhost:30002" -network = "testnet" diff --git a/stacks-signer/src/tests/conf/signer-3.toml b/stacks-signer/src/tests/conf/signer-3.toml deleted file mode 100644 index b96eef0098..0000000000 --- a/stacks-signer/src/tests/conf/signer-3.toml +++ /dev/null @@ -1,5 +0,0 @@ - -stacks_private_key = "63cef3cd8880969b7f2450ca13b9ca57fd3cd3f7ee57ec6ed7654a84d39181e401" -node_host = "127.0.0.1:20443" -endpoint = "localhost:30003" -network = "testnet"