├── .cargo └── config ├── .dockerignore ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── testnet-bug.md ├── PULL_REQUEST_TEMPLATE.md ├── actions │ ├── bitcoin-int-tests │ │ ├── Dockerfile.code-cov │ │ ├── Dockerfile.generic.stacks-node │ │ ├── Dockerfile.integrations │ │ ├── Dockerfile.rustfmt │ │ └── Dockerfile.stacks-node │ ├── docsgen │ │ └── Dockerfile.docsgen │ └── open-api │ │ └── Dockerfile.open-api-validate ├── stale.yml └── workflows │ ├── ci.yml │ ├── docker-platforms.yml │ └── project-automation.yml ├── .gitignore ├── .gitmodules ├── .releaserc ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTORS.md ├── Cargo.lock ├── Cargo.toml ├── DEPLOYING.md ├── Dockerfile ├── Justfile ├── LICENSE ├── LOCAL_TESTING.md ├── PROJECT.md ├── README.md ├── benches ├── block_limits.rs ├── c32_bench.rs ├── large_contract_bench.rs └── marf_bench.rs ├── build-scripts ├── Dockerfile.linux-arm64 ├── Dockerfile.linux-armv7 ├── Dockerfile.linux-musl-x64 ├── Dockerfile.linux-x64 ├── Dockerfile.macos-arm64 ├── Dockerfile.macos-x64 ├── Dockerfile.windows-x64 └── build-dist.sh ├── build.rs ├── circle.yml ├── codecov.yml ├── contrib ├── conf │ ├── stacks-l1-mocknet-2.1.toml │ ├── stacks-l1-mocknet-double.toml │ ├── stacks-l1-mocknet-local.toml │ ├── stacks-l1-mocknet.toml │ ├── stacks-l1-testnet.toml │ ├── subnet-l2-follower.toml │ └── subnet-l2.toml ├── helm │ └── stacks-blockchain │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── README.md │ │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── configmap.yaml │ │ ├── deployment.yaml │ │ ├── metrics.yaml │ │ ├── role.yaml │ │ ├── rolebinding.yaml │ │ ├── service.yaml │ │ ├── serviceaccount.yaml │ │ └── tests │ │ │ └── test-connection.yaml │ │ └── values.yaml ├── init │ ├── README.md │ ├── org.stacks.stacks-blockchain.plist │ ├── stacks.init │ └── stacks.service ├── scripts │ ├── broadcast_tx.js │ ├── nft-use-case │ │ ├── deposit_nft.js │ │ ├── deposit_stx.js │ │ ├── mint_nft.js │ │ ├── package.json │ │ ├── publish_tx.js │ │ ├── register_nft.js │ │ ├── transfer_nft.js │ │ ├── verify.js │ │ ├── withdraw_nft_l1.js │ │ └── withdraw_nft_l2.js │ └── publish_tx.js └── tools │ ├── chain-upload.sh │ └── mempool-pusher.sh ├── core-contracts ├── Clarinet.toml ├── README.md ├── contracts │ ├── config │ │ ├── common.yaml │ │ ├── devnet.yaml │ │ ├── mainnet.yaml │ │ ├── mocknet.yaml │ │ └── testnet.yaml │ ├── process_template.sh │ └── templates │ │ ├── helper │ │ ├── simple-ft-l2-no-deposit.clar │ │ ├── simple-ft-l2.clar │ │ ├── simple-ft.clar │ │ ├── simple-nft-l2-no-deposit.clar │ │ ├── simple-nft-l2.clar │ │ ├── simple-nft-no-mint.clar │ │ ├── simple-nft.clar │ │ ├── sip-traits.clar │ │ ├── subnet-traits.clar │ │ └── test-helpers.clar │ │ ├── multi-miner.clar.mustache │ │ └── subnet.clar.mustache ├── import_map.json ├── settings │ └── Devnet.toml └── tests │ └── subnets │ ├── multiminer_test.ts │ └── subnet_test.ts ├── deployment └── Dockerfile.circleci ├── docs ├── event-dispatcher.md ├── feature-guides │ ├── subnet-participants.md │ └── trust-models.md ├── getting-started.md ├── images │ ├── deposit-stx.png │ ├── subnet-devnet.png │ ├── subnet-miners.png │ ├── subnets-architecture.png │ └── subnets-deployment-confirmed.png ├── miner-resource-recommendation.md ├── overview.md ├── rpc-endpoints.md └── rpc │ ├── api │ ├── contract │ │ ├── post-call-read-only-fn-fail.example.json │ │ ├── post-call-read-only-fn-success.example.json │ │ └── post-call-read-only-fn.schema.json │ ├── core-node │ │ ├── get-account-data.example.json │ │ ├── get-account-data.schema.json │ │ ├── get-contract-data-map-entry.example.json │ │ ├── get-contract-data-map-entry.schema.json │ │ ├── get-contract-interface.example.json │ │ ├── get-contract-interface.schema.json │ │ ├── get-contract-source.example.json │ │ ├── get-contract-source.schema.json │ │ ├── get-fee-transfer.example.json │ │ ├── get-fee-transfer.schema.json │ │ ├── get-ft-withdrawal.example.json │ │ ├── get-ft-withdrawal.schema.json │ │ ├── get-info.example.json │ │ ├── get-info.schema.json │ │ ├── get-nft-withdrawal.example.json │ │ ├── get-nft-withdrawal.schema.json │ │ ├── get-pox.example.json │ │ ├── get-pox.schema.json │ │ ├── get-stx-withdrawal.example.json │ │ ├── get-stx-withdrawal.schema.json │ │ ├── post-block-proposal.error.schema.json │ │ ├── post-block-proposal.example.json │ │ ├── post-block-proposal.okay.example.json │ │ ├── post-block-proposal.okay.schema.json │ │ ├── post-block-proposal.schema.json │ │ ├── post-fee-transaction-response.example.json │ │ ├── post-fee-transaction-response.schema.json │ │ ├── post-fee-transaction.example.json │ │ └── post-fee-transaction.schema.json │ ├── trait │ │ ├── get-is-trait-implemented.example.json │ │ └── get-is-trait-implemented.schema.json │ └── transaction │ │ ├── post-core-node-transactions-error.example.json │ │ └── post-core-node-transactions-error.schema.json │ ├── entities │ └── contracts │ │ └── read-only-function-args.schema.json │ └── openapi.yaml ├── migration-verification ├── .dockerignore ├── Dockerfile ├── README.md └── test │ ├── index.ts │ ├── package-lock.json │ ├── package.json │ └── tsconfig.json ├── net-test ├── README.md ├── bin │ ├── faucet.sh │ ├── start.sh │ └── txload.sh ├── etc │ ├── bitcoin-neon-controller.toml.in │ ├── bitcoin.conf.in │ ├── stacks-follower.toml.in │ ├── stacks-master.toml.in │ └── stacks-miner.toml.in ├── mnt │ └── cleanup.sh └── tests │ ├── config.sh │ ├── run.sh │ ├── test_2_nat_miners.sh │ ├── test_2_nat_miners_1_follower.sh │ ├── test_2_nat_miners_microblocks.sh │ └── testlib.sh ├── release_notes ├── README.md ├── changelog-0.14.1.md ├── changelog-0.14.2.md ├── changelog-0.14.3.md ├── changelog-0.14.4.md ├── changelog-0.14.5.md ├── changelog-0.14.md ├── changelog-0.16.0.md ├── changelog-0.17.md ├── changelog-0.18.6 ├── changelog-0.18.md ├── changelog-19.md ├── changelog-20.md └── wishlist-0.15.md ├── rust-toolchain ├── sample-contracts ├── names.clar ├── tokens-ft-mint.clar ├── tokens-ft.clar ├── tokens-mint.clar └── tokens.clar ├── sip ├── README.md ├── sip-000-stacks-improvement-proposal-process.md ├── sip-001-burn-election.md ├── sip-002-smart-contract-language.md ├── sip-003-peer-network.md ├── sip-004-materialized-view.md ├── sip-005-blocks-and-transactions.md ├── sip-006-runtime-cost-assessment.md ├── sip-007-stacking-consensus.md └── sip-008-analysis-cost-assessment.md ├── soar-db ├── Cargo.toml └── src │ ├── lib.rs │ ├── memory.rs │ └── tests.rs ├── src ├── blockstack_cli.rs ├── burnchains │ ├── burnchain.rs │ ├── db.rs │ ├── events.rs │ ├── indexer.rs │ ├── mod.rs │ ├── test.rs │ └── test_events_sample.jsons ├── chainstate │ ├── burn │ │ ├── db │ │ │ ├── mod.rs │ │ │ ├── processing.rs │ │ │ ├── sortdb.rs │ │ │ └── tests.rs │ │ ├── mod.rs │ │ ├── operations │ │ │ ├── deposit_ft.rs │ │ │ ├── deposit_nft.rs │ │ │ ├── deposit_stx.rs │ │ │ ├── leader_block_commit.rs │ │ │ ├── mod.rs │ │ │ ├── register_asset.rs │ │ │ ├── withdraw_ft.rs │ │ │ ├── withdraw_nft.rs │ │ │ └── withdraw_stx.rs │ │ └── sortition.rs │ ├── coordinator │ │ ├── comm.rs │ │ ├── mod.rs │ │ └── tests.rs │ ├── mod.rs │ └── stacks │ │ ├── address.rs │ │ ├── auth.rs │ │ ├── bench.rs │ │ ├── block.rs │ │ ├── boot │ │ ├── contract_tests.rs │ │ ├── cost-voting.clar │ │ ├── costs-2-testnet.clar │ │ ├── costs-2.clar │ │ ├── costs-3.clar │ │ ├── costs.clar │ │ ├── docs.rs │ │ ├── mod.rs │ │ └── subnet.clar │ │ ├── db │ │ ├── accounts.rs │ │ ├── blocks.rs │ │ ├── contracts.rs │ │ ├── headers.rs │ │ ├── mod.rs │ │ ├── transactions.rs │ │ └── unconfirmed.rs │ │ ├── events.rs │ │ ├── index │ │ ├── bits.rs │ │ ├── cache.rs │ │ ├── file.rs │ │ ├── marf.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ ├── profile.rs │ │ ├── proofs.rs │ │ ├── storage.rs │ │ ├── test │ │ │ ├── cache.rs │ │ │ ├── file.rs │ │ │ ├── marf.rs │ │ │ ├── mod.rs │ │ │ ├── node.rs │ │ │ ├── proofs.rs │ │ │ ├── storage.rs │ │ │ └── trie.rs │ │ ├── trie.rs │ │ └── trie_sql.rs │ │ ├── miner.rs │ │ ├── mod.rs │ │ └── transaction.rs ├── clarity_cli.rs ├── clarity_cli_main.rs ├── clarity_vm │ ├── clarity.rs │ ├── database │ │ ├── marf.rs │ │ └── mod.rs │ ├── mod.rs │ ├── special.rs │ ├── tests │ │ ├── analysis_costs.rs │ │ ├── ast.rs │ │ ├── costs.rs │ │ ├── epoch_switch.rs │ │ ├── forking.rs │ │ ├── large_contract.rs │ │ ├── mod.rs │ │ └── simple_tests.rs │ └── withdrawal.rs ├── core │ ├── mempool.rs │ ├── mod.rs │ └── tests │ │ └── mod.rs ├── cost_estimates │ ├── fee_medians.rs │ ├── fee_rate_fuzzer.rs │ ├── fee_scalar.rs │ ├── metrics.rs │ ├── mod.rs │ ├── pessimistic.rs │ └── tests │ │ ├── common.rs │ │ ├── cost_estimators.rs │ │ ├── fee_medians.rs │ │ ├── fee_rate_fuzzer.rs │ │ ├── fee_scalar.rs │ │ ├── metrics.rs │ │ └── mod.rs ├── deps │ ├── README.md │ ├── ctrlc │ │ ├── error.rs │ │ ├── mod.rs │ │ ├── platform │ │ │ ├── mod.rs │ │ │ ├── unix │ │ │ │ └── mod.rs │ │ │ └── windows │ │ │ │ └── mod.rs │ │ └── tests.rs │ ├── httparse │ │ └── mod.rs │ ├── httparse_tests │ │ └── mod.rs │ └── mod.rs ├── lib.rs ├── main.rs ├── monitoring │ ├── mod.rs │ └── prometheus.rs ├── net │ ├── asn.rs │ ├── atlas │ │ ├── db.rs │ │ ├── download.rs │ │ ├── mod.rs │ │ └── tests.rs │ ├── chat.rs │ ├── codec.rs │ ├── connection.rs │ ├── db.rs │ ├── dns.rs │ ├── download.rs │ ├── http.rs │ ├── inv.rs │ ├── mod.rs │ ├── neighbors.rs │ ├── p2p.rs │ ├── poll.rs │ ├── prune.rs │ ├── relay.rs │ ├── rpc.rs │ └── server.rs ├── types │ └── chainstate.rs └── util_lib │ ├── bloom.rs │ ├── boot.rs │ ├── db.rs │ ├── mod.rs │ └── strings.rs ├── stx-genesis ├── Cargo.toml ├── build.rs ├── chainstate-test.txt ├── chainstate-test.txt.sha256 ├── chainstate.txt ├── chainstate.txt.sha256 ├── name_zonefiles-test.txt ├── name_zonefiles-test.txt.sha256 ├── name_zonefiles.txt ├── name_zonefiles.txt.sha256 └── src │ └── lib.rs └── testnet ├── puppet-chain ├── .dockerignore ├── Cargo.toml ├── Dockerfile ├── README.md ├── config.toml.default ├── local-leader.toml.default └── src │ └── main.rs └── stacks-node ├── Cargo.toml ├── Stacks.toml ├── conf ├── local-follower-conf.toml ├── local-leader-conf.toml ├── mainnet-follower-conf.toml ├── mainnet-miner-conf.toml ├── mocknet-follower-conf.toml ├── mocknet-miner-conf.toml ├── prometheus.yml ├── regtest-follower-conf.toml ├── testnet-follower-conf.toml └── testnet-miner-conf.toml └── src ├── burnchains ├── commitment.rs ├── db_indexer.rs ├── l1_events.rs ├── mock_events.rs ├── mod.rs └── tests │ ├── commitment.rs │ ├── db_indexer.rs │ └── mod.rs ├── config.rs ├── event_dispatcher.rs ├── genesis_data.rs ├── keychain.rs ├── main.rs ├── monitoring ├── mod.rs └── prometheus.rs ├── neon_node.rs ├── node.rs ├── operations.rs ├── run_loop ├── l1_observer.rs ├── mod.rs └── neon.rs ├── syncctl.rs └── tests ├── forking.rs ├── integrations.rs ├── l1_multiparty.rs ├── l1_observer_test.rs ├── l2_withdrawal.rs ├── mempool.rs ├── mod.rs └── neon_integrations.rs /.cargo/config: -------------------------------------------------------------------------------- 1 | [alias] 2 | stacks-node = "run --package stacks-node --" 3 | puppet-chain = "run --package puppet-chain --" 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile* 2 | target 3 | integration_tests/blockstack-consensus-data/ 4 | integration_tests/test-out/ 5 | api/data 6 | .git 7 | .venv 8 | .dockerignore 9 | testnet/index.html 10 | testnet.log 11 | testnet-logs* 12 | legacy 13 | build-scripts 14 | dist -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | legacy/* linguist-vendored -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps To Reproduce** 14 | Please provide detailed instructions (e.g. command line invocation with parameters) to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Environment (please complete the following information):** 20 | - OS: [e.g. Ubuntu / Debian] 21 | - Rust version 22 | - Version of the appropriate binary / software package 23 | 24 | **Additional context** 25 | Please include any relevant stack traces, error messages and logs. 26 | 27 | If you are encountering an issue with a smart contract, please include the smart contract code 28 | that demonstrates the issue. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/testnet-bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Testnet Bug 3 | about: Use this template to submit Stacks 2.0 testnet bugs 4 | title: "[TESTNET BUG]" 5 | labels: bug, testnet 6 | assignees: 'timstackblock' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | ## Steps To Reproduce 15 | 16 | Please provide detailed instructions (e.g. command line invocation with parameters) to reproduce the behavior. 17 | 18 | ## Expected behavior 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | ## Environment 23 | 24 | - OS: [e.g. Ubuntu / Debian] 25 | - Rust version 26 | - Output of `stacks-node version` 27 | 28 | ## Additional context 29 | 30 | Please include any relevant stack traces, error messages and logs. 31 | 32 | If you are encountering an issue with a smart contract, please include the smart contract code 33 | that demonstrates the issue. 34 | 35 | ---- 36 | 37 | If you think this is eligible for a [bug bounty](https://testnet.blockstack.org/bounties), please check the relevant boxes below: 38 | 39 | ### Critical, Launch Blocking Bugs 40 | **Consensus critical bugs** 41 | - [ ] Can cause a chain split 42 | - [ ] Can cause an invalid transaction to get mined 43 | - [ ] Can cause an invalid block to get accepted 44 | - [ ] Can cause a node to stall 45 | 46 | **State corruption** 47 | - [ ] Can modify a smart contract’s data maps and data vars without a `contract-call? 48 | 49 | **Stolen funds** 50 | - [ ] Any address losing STX without a corresponding transfer 51 | - [ ] Modify token balances and NFT ownership in other contracts without a `contract-call?` 52 | 53 | **Take control and/or bring network to a halt** 54 | - [ ] Take control and/or bring network to a halt 55 | 56 | ### Major, Launch Blocking Bugs 57 | **Major bugs** 58 | - [ ] Performance or correctness bugs that don’t rise to P0 level 59 | - [ ] Stress test or DoS attacks that slow things down enough 60 | - [ ] Resource exhaustion 61 | - [ ] Expected functionality doesn’t work in obvious ways (important to be super specific with this wording) 62 | 63 | 64 | ### Minor, Non-launch blocking bugs 65 | **Minor bugs** 66 | - [ ] Bugs in non-critical software (CLI, UI, etc) that doesn’t impact critical functionality 67 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Description 10 | 11 | ### Applicable issues 12 | - fixes # 13 | 14 | ### Additional info (benefits, drawbacks, caveats) 15 | 16 | ### Checklist 17 | - [ ] Test coverage for new or modified code paths 18 | - [ ] Changelog is updated 19 | - [ ] Required documentation changes (e.g., `docs/rpc/openapi.yaml` and `rpc-endpoints.md` for v2 endpoints, `event-dispatcher.md` for new events) 20 | - [ ] New clarity functions have corresponding PR in `clarity-benchmarking` repo 21 | - [ ] New integration test(s) added to `bitcoin-tests.yml` 22 | -------------------------------------------------------------------------------- /.github/actions/bitcoin-int-tests/Dockerfile.code-cov: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye AS test 2 | 3 | WORKDIR /build 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y ruby-mustache && \ 7 | rustup component add llvm-tools-preview && \ 8 | cargo install \ 9 | grcov \ 10 | just 11 | 12 | ENV RUSTFLAGS="-Cinstrument-coverage" \ 13 | LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw" 14 | 15 | COPY . . 16 | 17 | RUN just process-templates && \ 18 | cargo build --workspace && \ 19 | cargo test --workspace 20 | 21 | # Generate coverage report and upload it to codecov 22 | RUN grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info 23 | 24 | FROM scratch AS export-stage 25 | COPY --from=test /build/lcov.info / 26 | -------------------------------------------------------------------------------- /.github/actions/bitcoin-int-tests/Dockerfile.generic.stacks-node: -------------------------------------------------------------------------------- 1 | FROM blockstack/stacks-blockchain:2.4.0.0.0 as stacks-node 2 | 3 | FROM rust:bullseye AS test 4 | 5 | WORKDIR /build 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y ruby-mustache && \ 9 | rustup component add llvm-tools-preview && \ 10 | cargo install \ 11 | grcov \ 12 | just 13 | 14 | ENV RUSTFLAGS="-Cinstrument-coverage" \ 15 | LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw" \ 16 | STACKS_NODE_TEST="1" 17 | 18 | COPY --from=stacks-node /bin/stacks-node /bin/ 19 | 20 | COPY . . 21 | 22 | RUN just process-templates && \ 23 | cargo build --workspace && \ 24 | cargo test --workspace --bin=subnet-node --no-run 25 | 26 | -------------------------------------------------------------------------------- /.github/actions/bitcoin-int-tests/Dockerfile.integrations: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye AS test 2 | 3 | WORKDIR /build 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y ruby-mustache && \ 7 | rustup component add llvm-tools-preview && \ 8 | cargo install \ 9 | grcov \ 10 | just 11 | 12 | ENV RUSTFLAGS="-Cinstrument-coverage" \ 13 | LLVM_PROFILE_FILE="stacks-blockchain-%p-%m.profraw" 14 | 15 | COPY . . 16 | 17 | RUN just process-templates && \ 18 | cargo build --workspace && \ 19 | cargo test --workspace --bin=subnet-node -- --ignored --test-threads 1 20 | 21 | # Generate coverage report and upload it to codecov 22 | RUN grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info 23 | 24 | FROM scratch AS export-stage 25 | COPY --from=test /build/lcov.info / 26 | -------------------------------------------------------------------------------- /.github/actions/bitcoin-int-tests/Dockerfile.rustfmt: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye 2 | 3 | WORKDIR /src 4 | 5 | COPY ./rust-toolchain . 6 | COPY ./Cargo.toml . 7 | 8 | RUN rustup component add rustfmt 9 | 10 | COPY . . 11 | 12 | RUN cargo fmt --all -- --check 13 | -------------------------------------------------------------------------------- /.github/actions/bitcoin-int-tests/Dockerfile.stacks-node: -------------------------------------------------------------------------------- 1 | FROM subnet-node:integrations AS test 2 | 3 | ARG test_name 4 | ENV STACKS_NODE_TEST="1" 5 | 6 | RUN cargo test --workspace --bin=subnet-node -- --test-threads 1 "$test_name" 7 | 8 | # Generate coverage report and upload it to codecov 9 | RUN grcov . --binary-path ./target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info 10 | 11 | FROM scratch AS export-stage 12 | COPY --from=test /build/lcov.info / 13 | -------------------------------------------------------------------------------- /.github/actions/docsgen/Dockerfile.docsgen: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | WORKDIR /src 4 | 5 | COPY . . 6 | 7 | RUN apt-get update && apt-get install -y git jq 8 | 9 | RUN cargo build 10 | 11 | RUN mkdir /out 12 | 13 | RUN /src/target/debug/stacks-inspect docgen | jq . > /out/clarity-reference.json 14 | RUN /src/target/debug/stacks-inspect docgen_boot | jq . > /out/boot-contracts-reference.json 15 | 16 | FROM scratch AS export-stage 17 | COPY --from=build /out/clarity-reference.json / 18 | COPY --from=build /out/boot-contracts-reference.json / 19 | -------------------------------------------------------------------------------- /.github/actions/open-api/Dockerfile.open-api-validate: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine as build 2 | 3 | WORKDIR /src 4 | 5 | COPY . . 6 | 7 | RUN npx redoc-cli@0.10.3 bundle -o /build/open-api-docs.html ./docs/rpc/openapi.yaml 8 | 9 | FROM scratch AS export-stage 10 | COPY --from=build /build/open-api-docs.html / 11 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 365 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 30 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | - stacks-2.1 10 | - consensus-critical 11 | - clarity 12 | # Label to use when marking an issue as stale 13 | staleLabel: stale 14 | # Comment to post when marking an issue as stale. Set to `false` to disable 15 | markComment: > 16 | This issue has been automatically marked as stale because it has not had 17 | recent activity. It will be closed if no further activity occurs. Thank you 18 | for your contributions. 19 | # Comment to post when closing a stale issue. Set to `false` to disable 20 | closeComment: > 21 | This issue has been automatically closed. Please reopen if needed. 22 | -------------------------------------------------------------------------------- /.github/workflows/docker-platforms.yml: -------------------------------------------------------------------------------- 1 | name: Build/Release Additional Docker Platform Images 2 | 3 | # Only run when: 4 | # - the workflow is automatically triggered during a release with the relevant tag 5 | # - the workflow is started from the UI with a tag 6 | on: 7 | workflow_call: 8 | inputs: 9 | tag: 10 | required: true 11 | type: string 12 | secrets: 13 | DOCKERHUB_USERNAME: 14 | required: true 15 | DOCKERHUB_PASSWORD: 16 | required: true 17 | 18 | env: 19 | BUILD_PLATFORMS: linux/arm64 20 | 21 | jobs: 22 | # Build docker image, tag it with the branch and docker image tag passed in, and publish 23 | build-publish: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v2 27 | 28 | - name: Set Vars 29 | run: | 30 | echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV 31 | echo "GITHUB_REF_SHORT=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV 32 | 33 | - name: Set up QEMU 34 | uses: docker/setup-qemu-action@v1 35 | 36 | - name: Docker meta 37 | id: meta 38 | uses: docker/metadata-action@v3 39 | with: 40 | images: | 41 | blockstack/${{ github.event.repository.name }} 42 | tags: | 43 | type=ref,event=branch 44 | ${{ inputs.tag }} 45 | 46 | - name: Set up Docker Buildx 47 | uses: docker/setup-buildx-action@v1 48 | 49 | - name: Login to DockerHub 50 | uses: docker/login-action@v1 51 | with: 52 | username: ${{ secrets.DOCKERHUB_USERNAME }} 53 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 54 | 55 | - name: Build/Tag/Push Image 56 | uses: docker/build-push-action@v2 57 | with: 58 | platforms: ${{ env.BUILD_PLATFORMS }} 59 | tags: ${{ steps.meta.outputs.tags }} 60 | labels: ${{ steps.meta.outputs.labels }} 61 | build-args: | 62 | SUBNET_NODE_VERSION=${{ inputs.tag || env.GITHUB_SHA_SHORT }} 63 | GIT_BRANCH=${{ env.GITHUB_REF_SHORT }} 64 | GIT_COMMIT=${{ env.GITHUB_SHA_SHORT }} 65 | push: true -------------------------------------------------------------------------------- /.github/workflows/project-automation.yml: -------------------------------------------------------------------------------- 1 | name: Add issues to the subnets project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | project-url: https://github.com/orgs/hirosystems/projects/24 16 | github-token: ${{ secrets.GH_TOKEN }} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | var 14 | sdist 15 | develop-eggs 16 | .installed.cfg 17 | __pycache__ 18 | 19 | # Installer logs 20 | pip-log.txt 21 | 22 | # Unit test / coverage reports 23 | .coverage 24 | .tox 25 | nosetests.xml 26 | 27 | # Translations 28 | *.mo 29 | 30 | # Mr Developer 31 | .mr.developer.cfg 32 | .project 33 | .pydevproject 34 | 35 | ignore 36 | secrets* 37 | 38 | *.pickle 39 | *.pid 40 | 41 | # vim 42 | *.swp 43 | 44 | #Docker 45 | Docker/blockstore.ini 46 | 47 | #Docs 48 | api/templates/index.html 49 | api/data 50 | 51 | # testnets 52 | testnet-logs/ 53 | testnet.log 54 | testnet/index.html 55 | 56 | # virtualenvs 57 | .venv 58 | 59 | # will have compiled files and executables 60 | /target/ 61 | /testnet/helium/target/ 62 | 63 | # These are backup files generated by rustfmt 64 | **/*.rs.bk 65 | 66 | node_modules 67 | tarpaulin-report.html 68 | osxcross 69 | osxcross*.tar.xz 70 | .DS_Store 71 | testnet/stacks-node/target 72 | 73 | net-test/etc/*.toml 74 | net-test/etc/*.conf 75 | net-test/mnt/bitcoin-* 76 | net-test/mnt/chainstate-* 77 | net-test/mnt/*.log 78 | net-test/mnt/archive/* 79 | *.log 80 | 81 | # Code Coverage files 82 | *.profraw 83 | *.profdata 84 | lcov.info 85 | coverage.lcov 86 | core-contracts/.cache 87 | 88 | # Generated files from templates 89 | core-contracts/contracts/output 90 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/.gitmodules -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | plugins: 2 | - - "@semantic-release/commit-analyzer" 3 | - preset: conventionalcommits 4 | - - "@semantic-release/release-notes-generator" 5 | - preset: conventionalcommits 6 | - "@semantic-release/github" 7 | - "@semantic-release/changelog" 8 | - "@semantic-release/git" 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "rust-lang.rust-analyzer", 4 | "vadimcn.vscode-lldb", 5 | "serayuzgur.crates", 6 | "editorconfig.editorconfig", 7 | ] 8 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enablePaths": [ 3 | "./core-contracts/tests/subnets" 4 | ], 5 | "deno.lint": true, 6 | "lldb.adapterType": "native", 7 | "lldb.launch.sourceLanguages": ["rust"] 8 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.5 2 | 3 | # Build image 4 | FROM rust:bullseye as build 5 | 6 | ARG SUBNET_NODE_VERSION="No Version Info" 7 | ARG GIT_BRANCH='No Branch Info' 8 | ARG GIT_COMMIT='No Commit Info' 9 | 10 | WORKDIR /src 11 | 12 | RUN apt-get update && \ 13 | apt-get install -y ruby-mustache && \ 14 | rustup component add llvm-tools-preview && \ 15 | cargo install just 16 | 17 | # Do after package install so we don't invalidate the cache 18 | COPY --link . . 19 | 20 | RUN --mount=type=cache,target=/usr/local/cargo/registry \ 21 | --mount=type=cache,target=/src/target,sharing=private \ 22 | mkdir -p /out /contracts && \ 23 | just process-templates && \ 24 | cd testnet/stacks-node && \ 25 | cargo build --features monitoring_prom,slog_json --release && \ 26 | cp /src/target/release/subnet-node /out 27 | 28 | # Run image 29 | FROM debian:bullseye-backports 30 | 31 | COPY --from=build /out/ /bin/ 32 | 33 | CMD ["subnet-node", "start"] 34 | -------------------------------------------------------------------------------- /benches/c32_bench.rs: -------------------------------------------------------------------------------- 1 | extern crate blockstack_lib; 2 | extern crate criterion; 3 | extern crate rand; 4 | 5 | use blockstack_lib::address::c32::{c32_address, c32_address_decode}; 6 | use blockstack_lib::address::c32_old::c32_address_decode as c32_address_decode_old; 7 | use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; 8 | use rand::Rng; 9 | 10 | fn bench_c32_decoding(c: &mut Criterion) { 11 | let mut group = c.benchmark_group("C32 Decoding"); 12 | 13 | let mut addrs: Vec = vec![]; 14 | for _ in 0..5 { 15 | // random version 16 | let random_version: u8 = rand::thread_rng().gen_range(0, 31); 17 | // random 20 bytes 18 | let random_bytes = rand::thread_rng().gen::<[u8; 20]>(); 19 | let addr = c32_address(random_version, &random_bytes).unwrap(); 20 | addrs.push(addr); 21 | } 22 | 23 | for addr in addrs.iter() { 24 | group.bench_with_input(BenchmarkId::new("Legacy", addr), addr, |b, i| { 25 | b.iter(|| c32_address_decode_old(i)) 26 | }); 27 | group.bench_with_input(BenchmarkId::new("Updated", addr), addr, |b, i| { 28 | b.iter(|| c32_address_decode(i)) 29 | }); 30 | } 31 | group.finish(); 32 | } 33 | 34 | criterion_group!(benches, bench_c32_decoding); 35 | criterion_main!(benches); 36 | -------------------------------------------------------------------------------- /build-scripts/Dockerfile.linux-arm64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add aarch64-unknown-linux-gnu 12 | 13 | RUN apt-get update && apt-get install -y git gcc-aarch64-linux-gnu 14 | 15 | RUN CC=aarch64-linux-gnu-gcc \ 16 | CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \ 17 | CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ 18 | cargo build --release --workspace --target aarch64-unknown-linux-gnu 19 | 20 | RUN mkdir /out && cp -R /src/target/aarch64-unknown-linux-gnu/release/. /out 21 | 22 | FROM scratch AS export-stage 23 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / -------------------------------------------------------------------------------- /build-scripts/Dockerfile.linux-armv7: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add armv7-unknown-linux-gnueabihf 12 | 13 | RUN apt-get update && apt-get install -y git gcc-arm-linux-gnueabihf 14 | 15 | RUN CC=arm-linux-gnueabihf-gcc \ 16 | CC_armv7_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ 17 | CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ 18 | cargo build --release --workspace --target armv7-unknown-linux-gnueabihf 19 | 20 | RUN mkdir /out && cp -R /src/target/armv7-unknown-linux-gnueabihf/release/. /out 21 | 22 | FROM scratch AS export-stage 23 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / -------------------------------------------------------------------------------- /build-scripts/Dockerfile.linux-musl-x64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add x86_64-unknown-linux-musl 12 | 13 | RUN apt-get update && apt-get install -y git musl-tools 14 | 15 | RUN CC=musl-gcc \ 16 | CC_x86_64_unknown_linux_musl=musl-gcc \ 17 | CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc \ 18 | cargo build --release --workspace --target x86_64-unknown-linux-musl 19 | 20 | RUN mkdir /out && cp -R /src/target/x86_64-unknown-linux-musl/release/. /out 21 | 22 | FROM scratch AS export-stage 23 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / -------------------------------------------------------------------------------- /build-scripts/Dockerfile.linux-x64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN apt-get update && apt-get install -y git 12 | 13 | RUN rustup target add x86_64-unknown-linux-gnu 14 | 15 | RUN cargo build --release --workspace --target x86_64-unknown-linux-gnu 16 | 17 | RUN mkdir /out && cp -R /src/target/x86_64-unknown-linux-gnu/release/. /out 18 | 19 | FROM scratch AS export-stage 20 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / -------------------------------------------------------------------------------- /build-scripts/Dockerfile.macos-arm64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add aarch64-apple-darwin 12 | 13 | RUN apt-get update && apt-get install -y clang zstd 14 | 15 | RUN wget -nc -O /tmp/osxcross.tar.zst "https://github.com/hirosystems/docker-osxcross-rust/releases/download/MacOSX12.0.sdk/osxcross-d904031_MacOSX12.0.sdk.tar.zst" 16 | RUN mkdir /opt/osxcross && tar -xaf /tmp/osxcross.tar.zst -C /opt/osxcross 17 | 18 | RUN . /opt/osxcross/env-macos-aarch64 && \ 19 | cargo build --target aarch64-apple-darwin --release --workspace 20 | 21 | RUN mkdir /out && cp -R /src/target/aarch64-apple-darwin/release/. /out 22 | 23 | FROM scratch AS export-stage 24 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / 25 | -------------------------------------------------------------------------------- /build-scripts/Dockerfile.macos-x64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add x86_64-apple-darwin 12 | 13 | RUN apt-get update && apt-get install -y clang zstd 14 | 15 | RUN wget -nc -O /tmp/osxcross.tar.zst "https://github.com/hirosystems/docker-osxcross-rust/releases/download/MacOSX12.0.sdk/osxcross-d904031_MacOSX12.0.sdk.tar.zst" 16 | RUN mkdir /opt/osxcross && tar -xaf /tmp/osxcross.tar.zst -C /opt/osxcross 17 | 18 | RUN . /opt/osxcross/env-macos-x86_64 && \ 19 | cargo build --target x86_64-apple-darwin --release --workspace 20 | 21 | RUN mkdir /out && cp -R /src/target/x86_64-apple-darwin/release/. /out 22 | 23 | FROM scratch AS export-stage 24 | COPY --from=build /out/stacks-inspect /out/blockstack-cli /out/clarity-cli /out/stacks-node / -------------------------------------------------------------------------------- /build-scripts/Dockerfile.windows-x64: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as build 2 | 3 | ARG SUBNET_NODE_VERSION="No Version Info" 4 | ARG GIT_BRANCH='No Branch Info' 5 | ARG GIT_COMMIT='No Commit Info' 6 | 7 | WORKDIR /src 8 | 9 | COPY . . 10 | 11 | RUN rustup target add x86_64-pc-windows-gnu 12 | 13 | RUN apt-get update && apt-get install -y git gcc-mingw-w64-x86-64 14 | 15 | RUN CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc \ 16 | CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc \ 17 | cargo build --release --workspace --target x86_64-pc-windows-gnu 18 | 19 | RUN mkdir /out && cp -R /src/target/x86_64-pc-windows-gnu/release/. /out 20 | 21 | FROM scratch AS export-stage 22 | COPY --from=build /out/stacks-inspect.exe /out/blockstack-cli.exe /out/clarity-cli.exe /out/stacks-node.exe / -------------------------------------------------------------------------------- /build-scripts/build-dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | script_path="$(dirname "$0")" 6 | src_dir="$(dirname "$script_path")" 7 | cd "$src_dir" 8 | 9 | build_platform () { 10 | echo "Building $1" 11 | rm -rf dist/$1 12 | DOCKER_BUILDKIT=1 docker build --progress=plain -o dist/$1 -f ./build-scripts/Dockerfile.$1 . 13 | } 14 | 15 | case $DIST_TARGET_FILTER in 16 | (*[![:blank:]]*) 17 | case $DIST_TARGET_FILTER in 18 | linux-x64) build_platform linux-x64 ;; 19 | linux-musl-x64) build_platform linux-musl-x64 ;; 20 | linux-armv7) build_platform linux-armv7 ;; 21 | linux-arm64) build_platform linux-arm64 ;; 22 | windows-x64) build_platform windows-x64 ;; 23 | macos-x64) build_platform macos-x64 ;; 24 | macos-arm64) build_platform macos-arm64 ;; 25 | *) 26 | echo "Invalid dist target filter '$DIST_TARGET_FILTER'" 27 | exit 1 28 | ;; 29 | esac 30 | ;; 31 | (*) 32 | echo "Building distrubtions for all targets." 33 | build_platform linux-x64 34 | build_platform linux-musl-x64 35 | build_platform linux-armv7 36 | build_platform linux-arm64 37 | build_platform windows-x64 38 | build_platform macos-x64 39 | build_platform macos-arm64 40 | ;; 41 | esac 42 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | fn current_git_hash() -> Option { 4 | if option_env!("GIT_COMMIT") == None { 5 | let commit = Command::new("git") 6 | .arg("log") 7 | .arg("-1") 8 | .arg("--pretty=format:%h") // Abbreviated commit hash 9 | .current_dir(env!("CARGO_MANIFEST_DIR")) 10 | .output(); 11 | 12 | if let Ok(commit) = commit { 13 | if let Ok(commit) = String::from_utf8(commit.stdout) { 14 | return Some(commit); 15 | } 16 | } 17 | } else { 18 | return option_env!("GIT_COMMIT").map(String::from); 19 | } 20 | 21 | None 22 | } 23 | 24 | fn current_git_branch() -> Option { 25 | if option_env!("GIT_BRANCH") == None { 26 | let commit = Command::new("git") 27 | .arg("rev-parse") 28 | .arg("--abbrev-ref") 29 | .arg("HEAD") 30 | .output(); 31 | if let Ok(commit) = commit { 32 | if let Ok(commit) = String::from_utf8(commit.stdout) { 33 | return Some(commit); 34 | } 35 | } 36 | } else { 37 | return option_env!("GIT_BRANCH").map(String::from); 38 | } 39 | 40 | None 41 | } 42 | 43 | fn is_working_tree_clean() -> bool { 44 | let status = Command::new("git") 45 | .arg("diff") 46 | .arg("--quiet") 47 | .arg("--exit-code") 48 | .current_dir(env!("CARGO_MANIFEST_DIR")) 49 | .status(); 50 | 51 | if let Ok(status) = status { 52 | status.code() == Some(0) 53 | } else { 54 | true 55 | } 56 | } 57 | 58 | fn main() { 59 | if let Some(git) = current_git_hash() { 60 | println!("cargo:rustc-env=GIT_COMMIT={}", git); 61 | } 62 | if let Some(git) = current_git_branch() { 63 | println!("cargo:rustc-env=GIT_BRANCH={}", git); 64 | } 65 | if !is_working_tree_clean() { 66 | println!("cargo:rustc-env=GIT_TREE_CLEAN=+"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | patch: off 4 | 5 | github_checks: 6 | annotations: false 7 | -------------------------------------------------------------------------------- /contrib/conf/stacks-l1-mocknet-2.1.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "127.0.0.1:20443" 4 | p2p_bind = "127.0.0.1:20444" 5 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 7 | miner = true 8 | wait_time_for_microblocks = 5000 9 | use_test_genesis_chainstate = true 10 | 11 | [burnchain] 12 | chain = "bitcoin" 13 | mode = "mocknet" 14 | 15 | [[burnchain.epochs]] 16 | epoch_name = "1.0" 17 | start_height = 0 18 | 19 | [[burnchain.epochs]] 20 | epoch_name = "2.0" 21 | start_height = 0 22 | 23 | [[burnchain.epochs]] 24 | epoch_name = "2.05" 25 | start_height = 1 26 | 27 | [[burnchain.epochs]] 28 | epoch_name = "2.1" 29 | start_height = 2 30 | 31 | [[ustx_balance]] 32 | # secret key = aaf57b4730f713cf942bc63f0801c4a62abe5a6ac8e3da10389f9ca3420b0dc701 33 | address = "ST18F1AHKW194BWQ3CEFDPWVRARA79RBGFEWSDQR8" 34 | amount = 100000000000000 35 | 36 | [[ustx_balance]] 37 | # secret key = 0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101 38 | # this is also a miner present in the sample subnet contract 39 | address = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP" 40 | amount = 100000000000000 41 | 42 | [[ustx_balance]] 43 | # secret key = 374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001 44 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 45 | amount = 100000000000000 46 | 47 | [[ustx_balance]] 48 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 49 | amount = 100000000000000 50 | 51 | [[events_observer]] 52 | endpoint = "localhost:50303" 53 | retry_count = 255 54 | events_keys = ["*"] 55 | -------------------------------------------------------------------------------- /contrib/conf/stacks-l1-mocknet-double.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "127.0.0.1:20443" 4 | p2p_bind = "127.0.0.1:20444" 5 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 7 | miner = true 8 | wait_time_for_microblocks = 5000 9 | use_test_genesis_chainstate = true 10 | 11 | [burnchain] 12 | chain = "bitcoin" 13 | mode = "mocknet" 14 | 15 | 16 | [[burnchain.epochs]] 17 | epoch_name = "1.0" 18 | start_height = 0 19 | 20 | [[burnchain.epochs]] 21 | epoch_name = "2.0" 22 | start_height = 0 23 | 24 | [[burnchain.epochs]] 25 | epoch_name = "2.05" 26 | start_height = 1 27 | 28 | [[burnchain.epochs]] 29 | epoch_name = "2.1" 30 | start_height = 2 31 | 32 | [[ustx_balance]] 33 | # secret key = aaf57b4730f713cf942bc63f0801c4a62abe5a6ac8e3da10389f9ca3420b0dc701 34 | address = "ST18F1AHKW194BWQ3CEFDPWVRARA79RBGFEWSDQR8" 35 | amount = 100000000000000 36 | 37 | [[ustx_balance]] 38 | # secret key = 0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101 39 | # this is also a miner present in the sample subnet contract 40 | address = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP" 41 | amount = 100000000000000 42 | 43 | [[ustx_balance]] 44 | # secret key = 374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001 45 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 46 | amount = 100000000000000 47 | 48 | [[ustx_balance]] 49 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 50 | amount = 100000000000000 51 | 52 | [[events_observer]] 53 | endpoint = "localhost:50303" 54 | retry_count = 255 55 | events_keys = ["*"] 56 | 57 | [[events_observer]] 58 | endpoint = "localhost:52303" 59 | retry_count = 255 60 | events_keys = ["*"] 61 | -------------------------------------------------------------------------------- /contrib/conf/stacks-l1-mocknet-local.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "127.0.0.1:20443" 4 | p2p_bind = "127.0.0.1:20444" 5 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 7 | miner = true 8 | use_test_genesis_chainstate = true 9 | 10 | [burnchain] 11 | commit_anchor_block_within = 10_000 12 | chain = "bitcoin" 13 | mode = "mocknet" 14 | 15 | [[ustx_balance]] 16 | # secret key = aaf57b4730f713cf942bc63f0801c4a62abe5a6ac8e3da10389f9ca3420b0dc701 17 | address = "ST18F1AHKW194BWQ3CEFDPWVRARA79RBGFEWSDQR8" 18 | amount = 100000000000000 19 | 20 | [[ustx_balance]] 21 | # secret key = 0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101 22 | # this is also a miner present in the sample subnet contract 23 | address = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP" 24 | amount = 100000000000000 25 | 26 | [[ustx_balance]] 27 | # secret key = 374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001 28 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 29 | amount = 100000000000000 30 | 31 | [[ustx_balance]] 32 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 33 | amount = 100000000000000 34 | 35 | [[events_observer]] 36 | endpoint = "localhost:49303" 37 | retry_count = 255 38 | events_keys = ["*"] 39 | -------------------------------------------------------------------------------- /contrib/conf/stacks-l1-mocknet.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "127.0.0.1:20443" 4 | p2p_bind = "127.0.0.1:20444" 5 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 7 | miner = true 8 | wait_time_for_microblocks = 5000 9 | use_test_genesis_chainstate = true 10 | 11 | [burnchain] 12 | chain = "bitcoin" 13 | mode = "mocknet" 14 | 15 | [[burnchain.epochs]] 16 | epoch_name = "1.0" 17 | start_height = 0 18 | 19 | [[burnchain.epochs]] 20 | epoch_name = "2.0" 21 | start_height = 0 22 | 23 | [[burnchain.epochs]] 24 | epoch_name = "2.05" 25 | start_height = 1 26 | 27 | [[burnchain.epochs]] 28 | epoch_name = "2.1" 29 | start_height = 4 30 | 31 | [[ustx_balance]] 32 | # secret key = aaf57b4730f713cf942bc63f0801c4a62abe5a6ac8e3da10389f9ca3420b0dc701 33 | address = "ST18F1AHKW194BWQ3CEFDPWVRARA79RBGFEWSDQR8" 34 | amount = 100000000000000 35 | 36 | [[ustx_balance]] 37 | # secret key = 0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101 38 | # this is also a miner present in the sample subnet contract 39 | address = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP" 40 | amount = 100000000000000 41 | 42 | [[ustx_balance]] 43 | # secret key = 374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001 44 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 45 | amount = 100000000000000 46 | 47 | [[ustx_balance]] 48 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 49 | amount = 100000000000000 50 | 51 | [[events_observer]] 52 | endpoint = "localhost:50303" 53 | retry_count = 255 54 | events_keys = ["*"] 55 | -------------------------------------------------------------------------------- /contrib/conf/stacks-l1-testnet.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | working_dir = "/tmp/stacks-testnet" 3 | rpc_bind = "127.0.0.1:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | bootstrap_node = "047435c194e9b01b3d7f7a2802d6684a3af68d05bbf4ec8f17021980d777691f1d51651f7f1d566532c804da506c117bbf79ad62eea81213ba58f8808b4d9504ad@testnet.stacks.co:20444" 6 | 7 | [burnchain] 8 | chain = "bitcoin" 9 | mode = "xenon" 10 | peer_host = "bitcoind.testnet.stacks.co" 11 | username = "blockstack" 12 | password = "blockstacksystem" 13 | rpc_port = 18332 14 | peer_port = 18333 15 | 16 | # Used for sending events to a local stacks-blockchain-api service 17 | [[events_observer]] 18 | endpoint = "localhost:50303" 19 | retry_count = 255 20 | events_keys = ["*"] 21 | 22 | [[ustx_balance]] 23 | address = "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2" 24 | amount = 10000000000000000 25 | 26 | [[ustx_balance]] 27 | address = "ST319CF5WV77KYR1H3GT0GZ7B8Q4AQPY42ETP1VPF" 28 | amount = 10000000000000000 29 | 30 | [[ustx_balance]] 31 | address = "ST221Z6TDTC5E0BYR2V624Q2ST6R0Q71T78WTAX6H" 32 | amount = 10000000000000000 33 | 34 | [[ustx_balance]] 35 | address = "ST2TFVBMRPS5SSNP98DQKQ5JNB2B6NZM91C4K3P7B" 36 | amount = 10000000000000000 37 | -------------------------------------------------------------------------------- /contrib/conf/subnet-l2-follower.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | working_dir = "/tmp/subnet-l1-follower" 3 | rpc_bind = "127.0.0.1:15443" 4 | p2p_bind = "127.0.0.1:15444" 5 | data_url = "https://127.0.0.1:15443" 6 | p2p_address = "127.0.0.1:15444" 7 | seed = "4040404040404040404040404040404040404040404040404040404040404040" 8 | local_peer_seed = "3030303030303030303030303030303030303030303030303030303030303030" 9 | miner = false 10 | wait_time_for_microblocks = 1_000 11 | wait_before_first_anchored_block = 2_000 12 | mining_key = "0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101" 13 | # This is the peer key from subnet-l2.toml 14 | bootstrap_node = "03187db77a59f1c5f3cfd2296f87ebd7e829226b0f628d9efe4b9f221414e3b967@localhost:19444" 15 | 16 | [burnchain] 17 | chain = "stacks_layer_1" 18 | mode = "subnet" 19 | rpc_ssl = false 20 | rpc_port = 20443 21 | peer_host = "127.0.0.1" 22 | first_burn_header_height = 1 23 | contract_identifier = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP.subnet" 24 | observer_port = 47303 25 | -------------------------------------------------------------------------------- /contrib/conf/subnet-l2.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | working_dir = "/tmp/subnet-l1" 3 | rpc_bind = "127.0.0.1:19443" 4 | p2p_bind = "127.0.0.1:19444" 5 | seed = "1010101010101010101010101010101010101010101010101010101010101010" 6 | local_peer_seed = "2020202020202020202020202020202020202020202020202020202020202020" 7 | miner = true 8 | wait_time_for_microblocks = 1_000 9 | wait_before_first_anchored_block = 2_000 10 | data_url = "https://127.0.0.1:19443" 11 | p2p_address = "127.0.0.1:19444" 12 | mining_key = "0916e2eb04b5702e0e946081829cee67d3bb76e1792af506646843db9252ff4101" 13 | 14 | [burnchain] 15 | chain = "stacks_layer_1" 16 | mode = "subnet" 17 | rpc_ssl = false 18 | rpc_port = 20443 19 | peer_host = "127.0.0.1" 20 | first_burn_header_height = 1 21 | contract_identifier = "ST2GE6HSXT81X9X3ATQ14WPT49X915R8X7FVERMBP.subnet" 22 | observer_port = 49303 23 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: stacks-blockchain 3 | description: A Helm chart for the Stacks Blockchain 4 | type: application 5 | version: 1.0.0 6 | appVersion: v23.0.0.10 7 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the stacks-blockchain node URL by running these commands: 2 | {{- if contains "NodePort" .Values.service.type }} 3 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "stacks-blockchain.fullname" . }}) 4 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 5 | echo http://$NODE_IP:$NODE_PORT/v2/info 6 | {{- else if contains "LoadBalancer" .Values.service.type }} 7 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 8 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "stacks-blockchain.fullname" . }}' 9 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "stacks-blockchain.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 10 | echo http://$SERVICE_IP:{{ .Values.service.rpcPort | default .Values.node.rpcPort }}/v2/info 11 | {{- else if contains "ClusterIP" .Values.service.type }} 12 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "stacks-blockchain.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 13 | echo "Visit http://127.0.0.1:{{ .Values.node.rpcPort | default 20443 }}/v2/info to use your application" 14 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME {{ .Values.node.rpcPort | default 20443 }}:{{ .Values.node.rpcPort | default 20443 }} {{ .Values.node.p2pPort | default 20444 }}:{{ .Values.node.p2pPort |default 20444 }} 15 | {{- end }} 16 | 17 | 2. Test a connection to the stacks-blockchain node by running the following command: 18 | NOTE: The stacks-blockchain node may take up to 5 minutes to enter a communicable state once its pod enters the "Running" phase. 19 | helm test --namespace {{ .Release.Namespace }} {{ include "stacks-blockchain.fullname" . }} 20 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "stacks-blockchain.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 7 | {{- end }} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "stacks-blockchain.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "stacks-blockchain.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 32 | {{- end }} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "stacks-blockchain.labels" -}} 38 | helm.sh/chart: {{ include "stacks-blockchain.chart" . }} 39 | {{ include "stacks-blockchain.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end }} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "stacks-blockchain.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "stacks-blockchain.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end }} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "stacks-blockchain.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create }} 59 | {{- default (include "stacks-blockchain.fullname" .) .Values.serviceAccount.name }} 60 | {{- else }} 61 | {{- default "default" .Values.serviceAccount.name }} 62 | {{- end }} 63 | {{- end }} 64 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "stacks-blockchain.fullname" . }} 6 | labels: {{- include "stacks-blockchain.labels" . | nindent 4 }} 7 | {{- if .Values.config.annotations }} 8 | annotations: {{ toYaml .Values.config.annotations | nindent 4 }} 9 | {{- end }} 10 | data: 11 | {{- if .Values.config.raw }} 12 | config.toml: {{- toYaml .Values.config.raw | indent 2 }} 13 | {{- else }} 14 | {{- if and (empty .Values.config.node.seed) (.Values.config.node.miner) }} 15 | {{- fail "Please enter a private key under config.node.seed" }} 16 | {{- end }} 17 | config.toml: | 18 | [node] 19 | {{- range $key, $val := .Values.config.node }} 20 | {{- if regexMatch "^(?i)(true|false)$" ($val | toString) }} 21 | {{- $key | nindent 4 }} = {{ $val }} 22 | {{- else }} 23 | {{- $key | nindent 4 }} = {{ $val | quote }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | [burnchain] 28 | {{- range $key, $val := .Values.config.burnchain }} 29 | {{- if regexMatch "^[0-9]+$" ($val | toString) }} 30 | {{- $key | nindent 4 }} = {{ $val }} 31 | {{- else }} 32 | {{- $key | nindent 4 }} = {{ $val | quote }} 33 | {{- end }} 34 | {{- end }} 35 | {{ range $key, $val := .Values.config.ustx_balance }} 36 | [[ustx_balance]] 37 | {{- range $inner_key, $inner_val := $val }} 38 | {{- if regexMatch "^[0-9]+$" ($inner_val | toString) }} 39 | {{- $inner_key | nindent 4 }} = {{ $inner_val }} 40 | {{- else }} 41 | {{- $inner_key | nindent 4 }} = {{ $inner_val | quote }} 42 | {{- end }} 43 | {{- end }} 44 | {{- end }} 45 | {{- end }} 46 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/metrics.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.enabled -}} 2 | --- 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | name: {{ include "stacks-blockchain.fullname" . }} 7 | labels: 8 | {{- include "stacks-blockchain.labels" . | nindent 4 }} 9 | spec: 10 | endpoints: 11 | - interval: {{ .Values.metrics.interval | default "30s" }} 12 | port: metrics 13 | path: / 14 | jobLabel: {{ include "stacks-blockchain.fullname" . }} 15 | namespaceSelector: 16 | matchNames: 17 | - {{ .Release.Namespace }} 18 | selector: 19 | matchLabels: 20 | {{- include "stacks-blockchain.selectorLabels" . | nindent 6 }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/role.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.rbac.create .Values.rbac.rules -}} 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: Role 5 | metadata: 6 | name: {{ include "stacks-blockchain.fullname" . }} 7 | labels: {{- include "stacks-blockchain.labels" . | nindent 4 }} 8 | rules: 9 | {{- .Values.rbac.rules | toYaml | nindent 2}} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.rbac.create .Values.rbac.rules -}} 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: RoleBinding 5 | metadata: 6 | name: {{ include "stacks-blockchain.fullname" . }} 7 | labels: {{- include "stacks-blockchain.labels" . | nindent 4 }} 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: {{ include "stacks-blockchain.fullname" . }} 12 | subjects: 13 | - kind: ServiceAccount 14 | name: {{ include "stacks-blockchain.serviceAccountName" . }} 15 | namespace: {{ .Release.Namespace }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "stacks-blockchain.fullname" . }} 6 | labels: {{- include "stacks-blockchain.labels" . | nindent 4 }} 7 | {{- if .Values.service.annotations }} 8 | annotations: {{ toYaml .Values.service.annotations | nindent 4 }} 9 | {{- end }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | {{- if and (.Values.service.externalTrafficPolicy) (not (eq .Values.service.type "ClusterIP")) }} 13 | externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }} 14 | {{- end }} 15 | ports: 16 | - port: {{ .Values.service.rpcPort | default .Values.node.rpcPort }} 17 | targetPort: rpc 18 | protocol: TCP 19 | name: rpc 20 | - port: {{ .Values.service.p2pPort | default .Values.node.p2pPort }} 21 | targetPort: p2p 22 | protocol: TCP 23 | name: p2p 24 | {{- if .Values.metrics.enabled }} 25 | - port: {{ .Values.metrics.port | default 9153 }} 26 | targetPort: metrics 27 | protocol: TCP 28 | name: metrics 29 | {{- end }} 30 | selector: {{- include "stacks-blockchain.selectorLabels" . | nindent 4 }} 31 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | --- 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: {{ include "stacks-blockchain.serviceAccountName" . }} 7 | labels: {{- include "stacks-blockchain.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | {{- end }} 12 | -------------------------------------------------------------------------------- /contrib/helm/stacks-blockchain/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: "{{ include "stacks-blockchain.fullname" . }}-test-connection" 6 | labels: 7 | {{- include "stacks-blockchain.labels" . | nindent 4 }} 8 | annotations: 9 | "helm.sh/hook": test 10 | spec: 11 | containers: 12 | - name: wget 13 | image: busybox 14 | command: 15 | - wget 16 | args: 17 | - '{{ include "stacks-blockchain.fullname" . }}:{{ .Values.service.rpcPort | default .Values.node.rpcPort }}/v2/info' 18 | - -qO 19 | - '-' 20 | restartPolicy: Never 21 | -------------------------------------------------------------------------------- /contrib/init/README.md: -------------------------------------------------------------------------------- 1 | Sample configuration files for: 2 | 3 | ``` 4 | systemd: stacks.service 5 | SysVinit: stacks.init 6 | MacOS: org.stacks.stacks-blockchain.plist 7 | ``` 8 | 9 | have been made available to assist packagers in creating node packages here. 10 | 11 | See [docs/init.md](../../docs/init.md) for more information. 12 | -------------------------------------------------------------------------------- /contrib/init/org.stacks.stacks-blockchain.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | org.stacks.stacks-blockchain 7 | ProgramArguments 8 | 9 | /usr/local/bin/stacks-node 10 | start 11 | --config=/etc/stacks-blockchain/Config.toml 12 | 13 | 14 | ProcessType 15 | Standard 16 | 17 | StandardErrorPath 18 | /tmp/stacks-blockchain.log 19 | 20 | StandardOutPath 21 | /tmp/stacks-blockchain.log 22 | 23 | RunAtLoad 24 | 25 | 26 | ExitTimeOut 27 | 60 28 | 29 | KeepAlive 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /contrib/init/stacks.service: -------------------------------------------------------------------------------- 1 | # # Modeled after https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service 2 | 3 | [Unit] 4 | Description=Stacks Blockchain 5 | # https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/ 6 | After=network-online.target 7 | Wants=network-online.target 8 | 9 | ConditionFileIsExecutable=/usr/local/bin/stacks-node 10 | ConditionPathExists=/etc/stacks-blockchain/Config.toml 11 | ConditionPathIsDirectory=/stacks-blockchain 12 | 13 | [Service] 14 | #ExecStart=/bin/sh -c "/usr/local/bin/stacks-node start --config=/etc/stacks-blockchain/Config.toml >> /stacks-blockchain/output.log 2>&1" 15 | ExecStart=/bin/sh -c "/usr/local/bin/stacks-node start --config=/etc/stacks-blockchain/Config.toml" 16 | ExecStartPost=/bin/sh -c "umask 022; sleep 2 && pgrep -f \"/usr/local/bin/stacks-node start --config=/etc/stacks-blockchain/Config.toml\" > /run/stacks-blockchain/stacks-blockchain.pid" 17 | ExecStopPost=/bin/sh -c "if [ -f \"/run/stacks-blockchain/stacks-blockchain.pid\" ]; then rm -f /run/stacks-blockchain/stacks-blockchain.pid; fi" 18 | 19 | # Make sure the config directory is readable by the service user 20 | PermissionsStartOnly=true 21 | #ExecStartPre=/bin/chgrp stacks /etc/stacks-blockchain/ 22 | 23 | # Process management 24 | #################### 25 | Type=simple 26 | PIDFile=/run/stacks-blockchain/stacks-blockchain.pid 27 | Restart=no 28 | TimeoutStopSec=600 29 | KillSignal=SIGTERM 30 | 31 | # Directory creation and permissions 32 | #################################### 33 | # Run as stacks:stacks 34 | User=stacks 35 | Group=stacks 36 | 37 | # /run/stacks-blockchain 38 | RuntimeDirectory=stacks-blockchain 39 | RuntimeDirectoryMode=0710 40 | 41 | # Hardening measures 42 | #################### 43 | 44 | # Provide a private /tmp and /var/tmp. 45 | PrivateTmp=true 46 | 47 | # Mount /usr, /boot/ and /etc read-only for the process. 48 | ProtectSystem=full 49 | 50 | # Deny access to /home, /root and /run/user 51 | ProtectHome=true 52 | 53 | # Disallow the process and all of its children to gain 54 | # new privileges through execve(). 55 | NoNewPrivileges=true 56 | 57 | # Use a new /dev namespace only populated with API pseudo devices 58 | # such as /dev/null, /dev/zero and /dev/random. 59 | PrivateDevices=true 60 | 61 | [Install] 62 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /contrib/scripts/broadcast_tx.js: -------------------------------------------------------------------------------- 1 | const network = require("@stacks/network"); 2 | const transactions = require("@stacks/transactions"); 3 | const fs = require("fs"); 4 | 5 | async function main() { 6 | const txFilename = process.argv[2]; 7 | const endpoint = process.argv[3]; 8 | const myNet = new network.StacksTestnet(); 9 | if (endpoint) { 10 | myNet.coreApiUrl = endpoint; 11 | } 12 | const txHex = fs.readFileSync(txFilename, { encoding: "utf-8" }); 13 | const transaction = transactions.deserializeTransaction( 14 | Buffer.from(txHex, "hex") 15 | ); 16 | const txid = await transactions.broadcastTransaction(transaction, myNet); 17 | 18 | console.log(txid); 19 | } 20 | 21 | main(); 22 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/deposit_nft.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | standardPrincipalCV, 5 | uintCV, 6 | contractPrincipalCV, 7 | PostConditionMode, 8 | broadcastTransaction, 9 | } from "@stacks/transactions"; 10 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 11 | 12 | async function main() { 13 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 14 | const senderKey = process.env.USER_KEY; 15 | const addr = process.env.USER_ADDR; 16 | const nonce = parseInt(process.argv[2]); 17 | 18 | const txOptions = { 19 | contractAddress: "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM", 20 | contractName: "subnet", 21 | functionName: "deposit-nft-asset", 22 | functionArgs: [ 23 | contractPrincipalCV(addr, "simple-nft-l1"), // contract ID of nft contract on L1 24 | uintCV(5), // ID 25 | standardPrincipalCV(addr), // sender 26 | ], 27 | senderKey, 28 | validateWithAbi: false, 29 | network, 30 | anchorMode: AnchorMode.Any, 31 | fee: 10000, 32 | postConditionMode: PostConditionMode.Allow, 33 | nonce, 34 | }; 35 | 36 | const transaction = await makeContractCall(txOptions); 37 | 38 | const txid = await broadcastTransaction(transaction, network); 39 | 40 | console.log(txid); 41 | } 42 | 43 | main(); 44 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/deposit_stx.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | standardPrincipalCV, 5 | uintCV, 6 | PostConditionMode, 7 | } from "@stacks/transactions"; 8 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 9 | 10 | async function main() { 11 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 12 | const senderKey = process.env.USER_KEY; 13 | const addr = process.env.USER_ADDR; 14 | const nonce = parseInt(process.argv[2]); 15 | 16 | const txOptions = { 17 | contractAddress: "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM", 18 | contractName: "subnet-alpha", 19 | functionName: "deposit-stx", 20 | functionArgs: [ 21 | uintCV(500_000_000_000), // ID 22 | standardPrincipalCV(addr), // sender 23 | ], 24 | senderKey, 25 | validateWithAbi: false, 26 | network, 27 | anchorMode: AnchorMode.Any, 28 | fee: 10000, 29 | postConditionMode: PostConditionMode.Allow, 30 | nonce, 31 | }; 32 | 33 | const transaction = await makeContractCall(txOptions); 34 | 35 | console.log(transaction.serialize().toString("hex")); 36 | } 37 | 38 | main(); 39 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/mint_nft.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | standardPrincipalCV, 5 | uintCV, 6 | broadcastTransaction, 7 | } from "@stacks/transactions"; 8 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 9 | 10 | async function main() { 11 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 12 | const senderKey = process.env.USER_KEY; 13 | const addr = process.env.USER_ADDR; 14 | const nonce = parseInt(process.argv[2]); 15 | 16 | const txOptions = { 17 | contractAddress: addr, 18 | contractName: "simple-nft-l1", 19 | functionName: "gift-nft", 20 | functionArgs: [standardPrincipalCV(addr), uintCV(5)], 21 | senderKey, 22 | validateWithAbi: false, 23 | network, 24 | anchorMode: AnchorMode.Any, 25 | fee: 10000, 26 | nonce, 27 | }; 28 | 29 | const transaction = await makeContractCall(txOptions); 30 | 31 | const txid = await broadcastTransaction(transaction, network); 32 | 33 | console.log(txid); 34 | } 35 | 36 | main(); 37 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "@stacks/network": "^4.3.2", 5 | "@stacks/transactions": "^4.3.3" 6 | }, 7 | "name": "use-case-module", 8 | "version": "1.0.0", 9 | "author": "Hiro PBC", 10 | "license": "ISC", 11 | "description": "Package for running NFT use case" 12 | } 13 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/publish_tx.js: -------------------------------------------------------------------------------- 1 | import { 2 | AnchorMode, 3 | makeContractDeploy, 4 | broadcastTransaction, 5 | } from "@stacks/transactions"; 6 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 7 | import { readFileSync } from "fs"; 8 | 9 | async function main() { 10 | const contractName = process.argv[2]; 11 | const contractFilename = process.argv[3]; 12 | const networkLayer = parseInt(process.argv[4]); 13 | const nonce = parseInt(process.argv[5]); 14 | const senderKey = process.env.USER_KEY; 15 | const networkUrl = 16 | networkLayer == 2 ? process.env.SUBNET_URL : HIRO_MOCKNET_DEFAULT; 17 | 18 | const codeBody = readFileSync(contractFilename, { encoding: "utf-8" }); 19 | 20 | const transaction = await makeContractDeploy({ 21 | codeBody, 22 | contractName, 23 | senderKey, 24 | network: new StacksTestnet({ url: networkUrl }), 25 | anchorMode: AnchorMode.Any, 26 | fee: 10000, 27 | nonce, 28 | }); 29 | 30 | const txid = await broadcastTransaction( 31 | transaction, 32 | new StacksTestnet({ url: networkUrl }) 33 | ); 34 | 35 | console.log(txid); 36 | } 37 | 38 | main(); 39 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/register_nft.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | contractPrincipalCV, 5 | broadcastTransaction, 6 | getNonce, 7 | } from "@stacks/transactions"; 8 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 9 | 10 | async function main() { 11 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 12 | const senderKey = process.env.AUTH_SUBNET_MINER_KEY; 13 | const userAddr = process.env.USER_ADDR; 14 | const nonce = 15 | (await getNonce(process.env.AUTH_SUBNET_MINER_ADDR, network)) + 1n; 16 | 17 | const txOptions = { 18 | contractAddress: "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM", 19 | contractName: "subnet", 20 | functionName: "register-new-nft-contract", 21 | functionArgs: [ 22 | contractPrincipalCV(userAddr, "simple-nft-l1"), 23 | contractPrincipalCV(userAddr, "simple-nft-l2"), 24 | ], 25 | senderKey, 26 | validateWithAbi: false, 27 | network, 28 | anchorMode: AnchorMode.Any, 29 | fee: 10000, 30 | nonce, 31 | }; 32 | 33 | const transaction = await makeContractCall(txOptions); 34 | 35 | const txid = await broadcastTransaction(transaction, network); 36 | 37 | console.log(txid); 38 | } 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/transfer_nft.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | standardPrincipalCV, 5 | uintCV, 6 | PostConditionMode, 7 | broadcastTransaction, 8 | } from "@stacks/transactions"; 9 | import { StacksTestnet } from "@stacks/network"; 10 | 11 | async function main() { 12 | const network = new StacksTestnet({ url: process.env.SUBNET_URL }); 13 | const senderKey = process.env.USER_KEY; 14 | const addr = process.env.USER_ADDR; 15 | const alt_addr = process.env.ALT_USER_ADDR; 16 | const nonce = parseInt(process.argv[2]); 17 | 18 | const txOptions = { 19 | contractAddress: addr, 20 | contractName: "simple-nft-l2", 21 | functionName: "transfer", 22 | functionArgs: [ 23 | uintCV(5), // ID 24 | standardPrincipalCV(addr), // sender 25 | standardPrincipalCV(alt_addr), // recipient 26 | ], 27 | senderKey, 28 | validateWithAbi: false, 29 | network, 30 | anchorMode: AnchorMode.Any, 31 | fee: 10000, 32 | nonce, 33 | postConditionMode: PostConditionMode.Allow, 34 | }; 35 | 36 | const transaction = await makeContractCall(txOptions); 37 | 38 | const txid = await broadcastTransaction(transaction, network); 39 | 40 | console.log(txid); 41 | } 42 | 43 | main(); 44 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/verify.js: -------------------------------------------------------------------------------- 1 | import { uintCV, callReadOnlyFunction, cvToString } from "@stacks/transactions"; 2 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 3 | 4 | async function main() { 5 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 6 | const senderAddress = process.env.ALT_USER_ADDR; 7 | const addr = process.env.USER_ADDR; 8 | 9 | const txOptions = { 10 | contractAddress: addr, 11 | contractName: "simple-nft-l1", 12 | functionName: "get-owner", 13 | functionArgs: [uintCV(5)], 14 | network, 15 | senderAddress, 16 | }; 17 | 18 | const result = await callReadOnlyFunction(txOptions); 19 | 20 | console.log(cvToString(result.value)); 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/withdraw_nft_l1.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | deserializeCV, 4 | AnchorMode, 5 | standardPrincipalCV, 6 | uintCV, 7 | someCV, 8 | PostConditionMode, 9 | contractPrincipalCV, 10 | broadcastTransaction, 11 | } from "@stacks/transactions"; 12 | import { StacksTestnet, HIRO_MOCKNET_DEFAULT } from "@stacks/network"; 13 | 14 | // NOTE: The arguments to the `withdraw-nft-asset` function change with Stacks 2.1 15 | async function main() { 16 | const network = new StacksTestnet({ url: HIRO_MOCKNET_DEFAULT }); 17 | const subnetUrl = process.env.SUBNET_URL; 18 | const senderKey = process.env.ALT_USER_KEY; 19 | const addr = process.env.ALT_USER_ADDR; 20 | const contractAddr = process.env.USER_ADDR; 21 | const withdrawalBlockHeight = process.argv[2]; 22 | const nonce = parseInt(process.argv[3]); 23 | const withdrawalId = 0; 24 | 25 | let json_merkle_entry = await fetch( 26 | `${subnetUrl}/v2/withdrawal/nft/${withdrawalBlockHeight}/${addr}/${withdrawalId}/${contractAddr}/simple-nft-l2/5` 27 | ).then((x) => x.json()); 28 | console.log(JSON.stringify(json_merkle_entry)); 29 | let cv_merkle_entry = { 30 | withdrawal_leaf_hash: deserializeCV(json_merkle_entry.withdrawal_leaf_hash), 31 | withdrawal_root: deserializeCV(json_merkle_entry.withdrawal_root), 32 | sibling_hashes: deserializeCV(json_merkle_entry.sibling_hashes), 33 | }; 34 | 35 | const txOptions = { 36 | senderKey, 37 | network, 38 | anchorMode: AnchorMode.Any, 39 | contractAddress: "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM", 40 | contractName: "subnet", 41 | functionName: "withdraw-nft-asset", 42 | functionArgs: [ 43 | contractPrincipalCV(contractAddr, "simple-nft-l1"), // nft-contract 44 | uintCV(5), // ID 45 | standardPrincipalCV(addr), // recipient 46 | uintCV(withdrawalId), // withdrawal ID 47 | uintCV(withdrawalBlockHeight), // withdrawal block height 48 | someCV(contractPrincipalCV(contractAddr, "simple-nft-l1")), // nft-mint-contract 49 | cv_merkle_entry.withdrawal_root, // withdrawal root 50 | cv_merkle_entry.withdrawal_leaf_hash, // withdrawal leaf hash 51 | cv_merkle_entry.sibling_hashes, 52 | ], // sibling hashes 53 | fee: 10000, 54 | postConditionMode: PostConditionMode.Allow, 55 | nonce, 56 | }; 57 | 58 | const transaction = await makeContractCall(txOptions); 59 | 60 | const txid = await broadcastTransaction(transaction, network); 61 | 62 | console.log(txid); 63 | } 64 | 65 | main(); 66 | -------------------------------------------------------------------------------- /contrib/scripts/nft-use-case/withdraw_nft_l2.js: -------------------------------------------------------------------------------- 1 | import { 2 | makeContractCall, 3 | AnchorMode, 4 | standardPrincipalCV, 5 | contractPrincipalCV, 6 | uintCV, 7 | broadcastTransaction, 8 | PostConditionMode, 9 | } from "@stacks/transactions"; 10 | import { StacksTestnet } from "@stacks/network"; 11 | 12 | async function main() { 13 | const network = new StacksTestnet({ url: process.env.SUBNET_URL }); 14 | const senderKey = process.env.ALT_USER_KEY; 15 | const contractAddr = process.env.USER_ADDR; 16 | const addr = process.env.ALT_USER_ADDR; 17 | const nonce = parseInt(process.argv[2]); 18 | 19 | const txOptions = { 20 | contractAddress: "ST000000000000000000002AMW42H", 21 | contractName: "subnet", 22 | functionName: "nft-withdraw?", 23 | functionArgs: [ 24 | contractPrincipalCV(contractAddr, "simple-nft-l2"), 25 | uintCV(5), // ID 26 | standardPrincipalCV(addr), // recipient 27 | ], 28 | senderKey, 29 | validateWithAbi: false, 30 | network, 31 | anchorMode: AnchorMode.Any, 32 | fee: 10000, 33 | nonce, 34 | postConditionMode: PostConditionMode.Allow, 35 | }; 36 | 37 | const transaction = await makeContractCall(txOptions); 38 | 39 | const txid = await broadcastTransaction(transaction, network); 40 | 41 | console.log(txid); 42 | } 43 | 44 | main(); 45 | -------------------------------------------------------------------------------- /contrib/scripts/publish_tx.js: -------------------------------------------------------------------------------- 1 | const network = require("@stacks/network"); 2 | const transactions = require("@stacks/transactions"); 3 | const fs = require("fs"); 4 | 5 | async function main() { 6 | const senderKey = process.env.CONTRACT_PUBLISH_KEY; 7 | const contractName = process.argv[2]; 8 | const contractFilename = process.argv[3]; 9 | const nonce = parseInt(process.argv[4]); 10 | 11 | const codeBody = fs.readFileSync(contractFilename, { encoding: "utf-8" }); 12 | 13 | const transaction = await transactions.makeContractDeploy({ 14 | codeBody, 15 | contractName, 16 | senderKey, 17 | network: new network.StacksTestnet(), 18 | anchorMode: transactions.AnchorMode.Any, 19 | nonce, 20 | }); 21 | 22 | console.log(transaction.serialize().toString("hex")); 23 | } 24 | 25 | main(); 26 | -------------------------------------------------------------------------------- /core-contracts/Clarinet.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = 'core-contracts' 3 | description = '' 4 | authors = [] 5 | telemetry = false 6 | cache_dir = '.cache' 7 | 8 | [[project.requirements]] 9 | contract_id = 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait' 10 | 11 | [[project.requirements]] 12 | contract_id = 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard' 13 | 14 | [contracts.multi-miner] 15 | path = 'contracts/output/mocknet/multi-miner.clar' 16 | clarity_version = 2 17 | epoch = 2.1 18 | 19 | [contracts.second-simple-ft] 20 | path = 'contracts/output/mocknet/helper/simple-ft.clar' 21 | clarity_version = 2 22 | epoch = 2.1 23 | 24 | [contracts.second-simple-nft] 25 | path = 'contracts/output/mocknet/helper/simple-nft.clar' 26 | clarity_version = 2 27 | epoch = 2.1 28 | 29 | [contracts.simple-ft] 30 | path = 'contracts/output/mocknet/helper/simple-ft.clar' 31 | clarity_version = 2 32 | epoch = 2.1 33 | 34 | [contracts.simple-nft] 35 | path = 'contracts/output/mocknet/helper/simple-nft.clar' 36 | clarity_version = 2 37 | epoch = 2.1 38 | 39 | [contracts.simple-nft-no-mint] 40 | path = 'contracts/output/mocknet/helper/simple-nft-no-mint.clar' 41 | clarity_version = 2 42 | epoch = 2.1 43 | 44 | [contracts.subnet-v3-0-1] 45 | path = 'contracts/output/mocknet/subnet.clar' 46 | clarity_version = 2 47 | epoch = 2.1 48 | 49 | [contracts.test-helpers] 50 | path = 'contracts/output/mocknet/helper/test-helpers.clar' 51 | clarity_version = 2 52 | epoch = 2.1 53 | 54 | [contracts.subnet-traits-v1] 55 | path = 'contracts/output/mocknet/helper/subnet-traits.clar' 56 | clarity_version = 2 57 | epoch = 2.1 58 | 59 | [contracts.sip-traits] 60 | path = 'contracts/output/mocknet/helper/sip-traits.clar' 61 | clarity_version = 2 62 | epoch = 2.1 63 | 64 | [repl.analysis] 65 | passes = [] 66 | 67 | [repl.analysis.check_checker] 68 | strict = false 69 | trusted_sender = false 70 | trusted_caller = false 71 | callee_filter = false 72 | -------------------------------------------------------------------------------- /core-contracts/README.md: -------------------------------------------------------------------------------- 1 | # Subnets Core Contracts 2 | 3 | This directory contains the contracts published to the Stacks L1 to implement a subnet. 4 | * _subnet.clar_: interface between the subnet and the L1 5 | * _multi-miner.clar_: implements a multi-miner for the subnet 6 | * _helper/*_: used for testing 7 | 8 | ## Running Tests 9 | 10 | To run the tests and generate a code coverage report, run this from the repository root: 11 | 12 | ```sh 13 | clarinet test --coverage --manifest-path=./core-contracts/Clarinet.toml --import-map=./core-contracts/import_map.json --allow-net --allow-read 14 | ``` 15 | 16 | Or if you have `just` installed: 17 | 18 | ```sh 19 | just clarinet-test # Run tests with locally installed Clarinet 20 | just clarinet-test-docker # Run tests with latest development build from DockerHub 21 | ``` 22 | 23 | To generate HTML from the code coverage report and view it: 24 | 25 | ```sh 26 | mkdir coverage 27 | cd coverage 28 | genhtml ../coverage.lcov 29 | # Open with your preferred browser 30 | brave index.html 31 | ``` 32 | -------------------------------------------------------------------------------- /core-contracts/contracts/config/common.yaml: -------------------------------------------------------------------------------- 1 | subnet_version_major: u3 2 | subnet_version_minor: u0 3 | subnet_version_patch: u1 4 | subnet_version_prerelease: none 5 | subnet_version_metadata: none 6 | subnet_contract: "subnet-v3-0-1" 7 | -------------------------------------------------------------------------------- /core-contracts/contracts/config/devnet.yaml: -------------------------------------------------------------------------------- 1 | nft_trait: "'ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.nft-trait.nft-trait" 2 | ft_trait: "'ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.sip-010-trait-ft-standard.sip-010-trait" 3 | mint_from_subnet_trait: "'ST13F481SBR0R7Z6NMMH8YV2FJJYXA5JPA0AD3HP9.subnet-traits-v1.mint-from-subnet-trait" 4 | -------------------------------------------------------------------------------- /core-contracts/contracts/config/mainnet.yaml: -------------------------------------------------------------------------------- 1 | nft_trait: "'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait" 2 | ft_trait: "'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait" 3 | mint_from_subnet_trait: ".subnet-traits-v1.mint-from-subnet-trait" 4 | -------------------------------------------------------------------------------- /core-contracts/contracts/config/mocknet.yaml: -------------------------------------------------------------------------------- 1 | nft_trait: "'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait" 2 | ft_trait: "'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait" 3 | mint_from_subnet_trait: ".subnet-traits-v1.mint-from-subnet-trait" 4 | -------------------------------------------------------------------------------- /core-contracts/contracts/config/testnet.yaml: -------------------------------------------------------------------------------- 1 | nft_trait: "'ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.nft-trait.nft-trait" 2 | ft_trait: "'ST1NXBK3K5YYMD6FD41MVNP3JS1GABZ8TRVX023PT.sip-010-trait-ft-standard.sip-010-trait" 3 | mint_from_subnet_trait: "'ST13F481SBR0R7Z6NMMH8YV2FJJYXA5JPA0AD3HP9.subnet-traits-v1.mint-from-subnet-trait" 4 | -------------------------------------------------------------------------------- /core-contracts/contracts/process_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | if (( $# < 3 )); then 6 | echo "Usage: $0 " 7 | exit 1 8 | fi 9 | 10 | in_dir="$1" 11 | shift 1 12 | 13 | out_dir="$1" 14 | shift 1 15 | 16 | # The rest of the args will be treated as YAML files 17 | yaml_files=("$@") 18 | shift $# 19 | 20 | # Create tmpfile for YAML, and remove it when script exits 21 | yaml_tmp=$(mktemp /tmp/mustache-template.XXXXXXXX.yaml) 22 | trap 'rm -f -- "$yaml_tmp"' INT TERM HUP EXIT 23 | 24 | # Combine all YAML 25 | echo "Using YAML files: ${yaml_files[*]}" 26 | cat "${yaml_files[@]}" > "$yaml_tmp" 27 | 28 | # Get list of files, null separated 29 | file_list=$(find "$in_dir" -type f | sed "s|^$in_dir/||") 30 | 31 | # Copy in_dir to out_dir, while processing template files 32 | for file in $file_list; do 33 | src_path="$in_dir/$file" 34 | dst_path="$out_dir/$file" 35 | mkdir -p "$(dirname "$dst_path")" 36 | case $file in 37 | # If file ends in ".mustache" run it through template engine 38 | *.mustache) 39 | # Strip suffix 40 | dst_path=${dst_path%.mustache} 41 | echo "Process template: $src_path -> $dst_path" 42 | mustache "$yaml_tmp" "$src_path" > "$dst_path" 43 | ;; 44 | # Else just copy 45 | *) 46 | echo "Copy file: $src_path -> $dst_path" 47 | cp -a "$src_path" "$dst_path" 48 | ;; 49 | esac 50 | done -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-ft-l2-no-deposit.clar: -------------------------------------------------------------------------------- 1 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 2 | 3 | (impl-trait 'ST000000000000000000002AMW42H.subnet.ft-trait) 4 | 5 | (define-fungible-token ft-token) 6 | 7 | ;; get the token balance of owner 8 | (define-read-only (get-balance (owner principal)) 9 | (ok (ft-get-balance ft-token owner))) 10 | 11 | ;; returns the total number of tokens 12 | (define-read-only (get-total-supply) 13 | (ok (ft-get-supply ft-token))) 14 | 15 | ;; returns the token name 16 | (define-read-only (get-name) 17 | (ok "ft-token")) 18 | 19 | ;; the symbol or "ticker" for this token 20 | (define-read-only (get-symbol) 21 | (ok "EXFT")) 22 | 23 | ;; the number of decimals used 24 | (define-read-only (get-decimals) 25 | (ok u0)) 26 | 27 | ;; Transfers tokens to a recipient 28 | (define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) 29 | (begin 30 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 31 | (try! (ft-transfer? ft-token amount sender recipient)) 32 | (print memo) 33 | (ok true) 34 | ) 35 | ) 36 | 37 | (define-read-only (get-token-uri) 38 | (ok none) 39 | ) 40 | 41 | (define-public (gift-tokens (amount uint) (recipient principal)) 42 | (begin 43 | (asserts! (is-eq tx-sender recipient) ERR_NOT_AUTHORIZED) 44 | (ft-mint? ft-token amount recipient) 45 | ) 46 | ) 47 | 48 | (impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset) 49 | 50 | ;; Called for deposit from the burnchain to the subnet 51 | (define-public (deposit-from-burnchain (amount uint) (recipient principal)) 52 | ERR_NOT_AUTHORIZED 53 | ) 54 | 55 | ;; Called for withdrawal from the subnet to the burnchain 56 | (define-public (burn-for-withdrawal (amount uint) (owner principal)) 57 | (begin 58 | (asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED) 59 | (ft-burn? ft-token amount owner) 60 | ) 61 | ) 62 | -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-ft-l2.clar: -------------------------------------------------------------------------------- 1 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 2 | 3 | (impl-trait 'ST000000000000000000002AMW42H.subnet.ft-trait) 4 | 5 | (define-fungible-token ft-token) 6 | 7 | ;; get the token balance of owner 8 | (define-read-only (get-balance (owner principal)) 9 | (ok (ft-get-balance ft-token owner))) 10 | 11 | ;; returns the total number of tokens 12 | (define-read-only (get-total-supply) 13 | (ok (ft-get-supply ft-token))) 14 | 15 | ;; returns the token name 16 | (define-read-only (get-name) 17 | (ok "ft-token")) 18 | 19 | ;; the symbol or "ticker" for this token 20 | (define-read-only (get-symbol) 21 | (ok "EXFT")) 22 | 23 | ;; the number of decimals used 24 | (define-read-only (get-decimals) 25 | (ok u0)) 26 | 27 | ;; Transfers tokens to a recipient 28 | (define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) 29 | (begin 30 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 31 | (try! (ft-transfer? ft-token amount sender recipient)) 32 | (print memo) 33 | (ok true) 34 | ) 35 | ) 36 | 37 | (define-read-only (get-token-uri) 38 | (ok none) 39 | ) 40 | 41 | (define-public (gift-tokens (amount uint) (recipient principal)) 42 | (begin 43 | (asserts! (is-eq tx-sender recipient) ERR_NOT_AUTHORIZED) 44 | (ft-mint? ft-token amount recipient) 45 | ) 46 | ) 47 | 48 | (impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset) 49 | 50 | ;; Called for deposit from the burnchain to the subnet 51 | (define-public (deposit-from-burnchain (amount uint) (recipient principal)) 52 | (begin 53 | (asserts! (is-eq tx-sender 'ST000000000000000000002AMW42H) ERR_NOT_AUTHORIZED) 54 | (ft-mint? ft-token amount recipient) 55 | ) 56 | ) 57 | 58 | ;; Called for withdrawal from the subnet to the burnchain 59 | (define-public (burn-for-withdrawal (amount uint) (owner principal)) 60 | (begin 61 | (asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED) 62 | (ft-burn? ft-token amount owner) 63 | ) 64 | ) 65 | -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-ft.clar: -------------------------------------------------------------------------------- 1 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 2 | 3 | (impl-trait .sip-traits.ft-trait) 4 | (impl-trait .subnet-traits-v1.mint-from-subnet-trait) 5 | 6 | (define-fungible-token ft-token) 7 | 8 | ;; get the token balance of owner 9 | (define-read-only (get-balance (owner principal)) 10 | (ok (ft-get-balance ft-token owner))) 11 | 12 | ;; returns the total number of tokens 13 | (define-read-only (get-total-supply) 14 | (ok (ft-get-supply ft-token))) 15 | 16 | ;; returns the token name 17 | (define-read-only (get-name) 18 | (ok "ft-token")) 19 | 20 | ;; the symbol or "ticker" for this token 21 | (define-read-only (get-symbol) 22 | (ok "EXFT")) 23 | 24 | ;; the number of decimals used 25 | (define-read-only (get-decimals) 26 | (ok u0)) 27 | 28 | ;; Implement mint-from-subnet trait 29 | (define-public (mint-from-subnet (amount uint) (sender principal) (recipient principal)) 30 | (begin 31 | ;; Check that the tx-sender is the provided sender 32 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 33 | 34 | (ft-mint? ft-token amount recipient) 35 | ) 36 | ) 37 | 38 | 39 | ;; Transfers tokens to a recipient 40 | (define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) 41 | (begin 42 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 43 | (try! (ft-transfer? ft-token amount sender recipient)) 44 | (print memo) 45 | (ok true) 46 | ) 47 | ) 48 | 49 | (define-read-only (get-token-uri) 50 | (ok none)) 51 | 52 | (define-public (gift-tokens (amount uint) (recipient principal)) 53 | (begin 54 | (asserts! (is-eq tx-sender recipient) ERR_NOT_AUTHORIZED) 55 | (ft-mint? ft-token amount recipient) 56 | ) 57 | ) -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-nft-l2-no-deposit.clar: -------------------------------------------------------------------------------- 1 | ;; Version of `simple-nft-l2.clar` in which deposit always fails 2 | 3 | (define-constant CONTRACT_OWNER tx-sender) 4 | (define-constant CONTRACT_ADDRESS (as-contract tx-sender)) 5 | 6 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 7 | 8 | (impl-trait 'ST000000000000000000002AMW42H.subnet.nft-trait) 9 | 10 | (define-data-var lastId uint u0) 11 | 12 | (define-non-fungible-token nft-token uint) 13 | 14 | 15 | ;; NFT trait functions 16 | (define-read-only (get-last-token-id) 17 | (ok (var-get lastId)) 18 | ) 19 | 20 | (define-read-only (get-owner (id uint)) 21 | (ok (nft-get-owner? nft-token id)) 22 | ) 23 | 24 | (define-read-only (get-token-uri (id uint)) 25 | (ok (some "unimplemented")) 26 | ) 27 | 28 | (define-public (transfer (id uint) (sender principal) (recipient principal)) 29 | (begin 30 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 31 | (nft-transfer? nft-token id sender recipient) 32 | ) 33 | ) 34 | 35 | ;; mint functions 36 | (define-public (mint-next (recipient principal)) 37 | (let 38 | ((newId (+ (var-get lastId) u1))) 39 | (var-set lastId newId) 40 | (nft-mint? nft-token newId recipient) 41 | ) 42 | ) 43 | 44 | (define-public (gift-nft (recipient principal) (id uint)) 45 | (begin 46 | (nft-mint? nft-token id recipient) 47 | ) 48 | ) 49 | 50 | (define-read-only (get-token-owner (id uint)) 51 | (nft-get-owner? nft-token id) 52 | ) 53 | 54 | (impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset) 55 | 56 | ;; Called for deposit from the burnchain to the subnet 57 | (define-public (deposit-from-burnchain (id uint) (recipient principal)) 58 | ERR_NOT_AUTHORIZED 59 | ) 60 | 61 | ;; Called for withdrawal from the subnet to the burnchain 62 | (define-public (burn-for-withdrawal (id uint) (owner principal)) 63 | (begin 64 | (asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED) 65 | (nft-burn? nft-token id owner) 66 | ) 67 | ) 68 | -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-nft-l2.clar: -------------------------------------------------------------------------------- 1 | (define-constant CONTRACT_OWNER tx-sender) 2 | (define-constant CONTRACT_ADDRESS (as-contract tx-sender)) 3 | 4 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 5 | 6 | (impl-trait 'ST000000000000000000002AMW42H.subnet.nft-trait) 7 | 8 | (define-data-var lastId uint u0) 9 | 10 | (define-non-fungible-token nft-token uint) 11 | 12 | 13 | ;; NFT trait functions 14 | (define-read-only (get-last-token-id) 15 | (ok (var-get lastId)) 16 | ) 17 | 18 | (define-read-only (get-owner (id uint)) 19 | (ok (nft-get-owner? nft-token id)) 20 | ) 21 | 22 | (define-read-only (get-token-uri (id uint)) 23 | (ok (some "unimplemented")) 24 | ) 25 | 26 | (define-public (transfer (id uint) (sender principal) (recipient principal)) 27 | (begin 28 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 29 | (nft-transfer? nft-token id sender recipient) 30 | ) 31 | ) 32 | 33 | ;; mint functions 34 | (define-public (mint-next (recipient principal)) 35 | (let 36 | ((newId (+ (var-get lastId) u1))) 37 | (var-set lastId newId) 38 | (nft-mint? nft-token newId recipient) 39 | ) 40 | ) 41 | 42 | (define-public (gift-nft (recipient principal) (id uint)) 43 | (begin 44 | (nft-mint? nft-token id recipient) 45 | ) 46 | ) 47 | 48 | (define-read-only (get-token-owner (id uint)) 49 | (nft-get-owner? nft-token id) 50 | ) 51 | 52 | (impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset) 53 | 54 | ;; Called for deposit from the burnchain to the subnet 55 | (define-public (deposit-from-burnchain (id uint) (recipient principal)) 56 | (begin 57 | (asserts! (is-eq tx-sender 'ST000000000000000000002AMW42H) ERR_NOT_AUTHORIZED) 58 | (nft-mint? nft-token id recipient) 59 | ) 60 | ) 61 | 62 | ;; Called for withdrawal from the subnet to the burnchain 63 | (define-public (burn-for-withdrawal (id uint) (owner principal)) 64 | (begin 65 | (asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED) 66 | (nft-burn? nft-token id owner) 67 | ) 68 | ) 69 | -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-nft-no-mint.clar: -------------------------------------------------------------------------------- 1 | ;; This is like `simple-nft.clar`, but does not support minting from a subnet. 2 | 3 | (define-constant CONTRACT_OWNER tx-sender) 4 | (define-constant CONTRACT_ADDRESS (as-contract tx-sender)) 5 | 6 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 7 | 8 | (impl-trait .sip-traits.nft-trait) 9 | 10 | (define-data-var lastId uint u0) 11 | (define-map CFG_BASE_URI bool (string-ascii 256)) 12 | 13 | (define-non-fungible-token nft-token uint) 14 | 15 | (define-read-only (get-last-token-id) 16 | (ok (var-get lastId)) 17 | ) 18 | 19 | (define-read-only (get-owner (id uint)) 20 | (ok (nft-get-owner? nft-token id)) 21 | ) 22 | 23 | (define-read-only (get-token-uri (id uint)) 24 | (ok (map-get? CFG_BASE_URI true)) 25 | ) 26 | 27 | (define-public (transfer (id uint) (sender principal) (recipient principal)) 28 | (begin 29 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 30 | (nft-transfer? nft-token id sender recipient) 31 | ) 32 | ) 33 | 34 | ;; test functions 35 | (define-public (test-mint (recipient principal)) 36 | (let 37 | ((newId (+ (var-get lastId) u1))) 38 | (var-set lastId newId) 39 | (nft-mint? nft-token newId recipient) 40 | ) 41 | ) 42 | 43 | (define-public (gift-nft (recipient principal) (id uint)) 44 | (begin 45 | (nft-mint? nft-token id recipient) 46 | ) 47 | ) 48 | -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/simple-nft.clar: -------------------------------------------------------------------------------- 1 | (define-constant CONTRACT_OWNER tx-sender) 2 | (define-constant CONTRACT_ADDRESS (as-contract tx-sender)) 3 | 4 | (define-constant ERR_NOT_AUTHORIZED (err u1001)) 5 | 6 | (impl-trait .sip-traits.nft-trait) 7 | (impl-trait .subnet-traits-v1.mint-from-subnet-trait) 8 | 9 | (define-data-var lastId uint u0) 10 | (define-map CFG_BASE_URI bool (string-ascii 256)) 11 | 12 | (define-non-fungible-token nft-token uint) 13 | 14 | (define-read-only (get-last-token-id) 15 | (ok (var-get lastId)) 16 | ) 17 | 18 | (define-read-only (get-owner (id uint)) 19 | (ok (nft-get-owner? nft-token id)) 20 | ) 21 | 22 | (define-read-only (get-token-uri (id uint)) 23 | (ok (map-get? CFG_BASE_URI true)) 24 | ) 25 | 26 | (define-public (transfer (id uint) (sender principal) (recipient principal)) 27 | (begin 28 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 29 | (nft-transfer? nft-token id sender recipient) 30 | ) 31 | ) 32 | 33 | ;; test functions 34 | (define-public (test-mint (recipient principal)) 35 | (let 36 | ((newId (+ (var-get lastId) u1))) 37 | (var-set lastId newId) 38 | (nft-mint? nft-token newId recipient) 39 | ) 40 | ) 41 | 42 | (define-public (mint-from-subnet (id uint) (sender principal) (recipient principal)) 43 | (begin 44 | ;; Check that the tx-sender is the provided sender 45 | (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED) 46 | 47 | (nft-mint? nft-token id recipient) 48 | ) 49 | ) 50 | 51 | (define-public (gift-nft (recipient principal) (id uint)) 52 | (begin 53 | (nft-mint? nft-token id recipient) 54 | ) 55 | ) -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/sip-traits.clar: -------------------------------------------------------------------------------- 1 | (define-trait nft-trait 2 | ( 3 | ;; Last token ID, limited to uint range 4 | (get-last-token-id () (response uint uint)) 5 | 6 | ;; URI for metadata associated with the token 7 | (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) 8 | 9 | ;; Owner of a given token identifier 10 | (get-owner (uint) (response (optional principal) uint)) 11 | 12 | ;; Transfer from the sender to a new principal 13 | (transfer (uint principal principal) (response bool uint)) 14 | ) 15 | ) 16 | 17 | (define-trait ft-trait 18 | ( 19 | ;; Transfer from the caller to a new principal 20 | (transfer (uint principal principal (optional (buff 34))) (response bool uint)) 21 | 22 | ;; the human readable name of the token 23 | (get-name () (response (string-ascii 32) uint)) 24 | 25 | ;; the ticker symbol, or empty if none 26 | (get-symbol () (response (string-ascii 32) uint)) 27 | 28 | ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token 29 | (get-decimals () (response uint uint)) 30 | 31 | ;; the balance of the passed principal 32 | (get-balance (principal) (response uint uint)) 33 | 34 | ;; the current total supply (which does not need to be a constant) 35 | (get-total-supply () (response uint uint)) 36 | 37 | ;; an optional URI that represents metadata of this token 38 | (get-token-uri () (response (optional (string-utf8 256)) uint)) 39 | ) 40 | ) -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/subnet-traits.clar: -------------------------------------------------------------------------------- 1 | ;; In order to support withdrawing an asset that was minted on a subnet, the 2 | ;; L1 contract must implement this trait. 3 | (define-trait mint-from-subnet-trait 4 | ( 5 | ;; Process a withdrawal from the subnet for an asset which does not yet 6 | ;; exist on this network, and thus requires a mint. 7 | (mint-from-subnet 8 | ( 9 | uint ;; asset-id (NFT) or amount (FT) 10 | principal ;; sender 11 | principal ;; recipient 12 | ) 13 | (response bool uint) 14 | ) 15 | ) 16 | ) -------------------------------------------------------------------------------- /core-contracts/contracts/templates/helper/test-helpers.clar: -------------------------------------------------------------------------------- 1 | ;; Contains functions used in testing the subnet contract. 2 | 3 | ;; Returns the `id-header-hash` of the chain tip. This is used for `clarinet` tests 4 | ;; where we do not yet have access to this value through the API. 5 | (define-read-only (get-id-header-hash) 6 | (ok (unwrap! (get-block-info? id-header-hash (- block-height u1)) (err u0))) 7 | ) 8 | -------------------------------------------------------------------------------- /core-contracts/import_map.json: -------------------------------------------------------------------------------- 1 | {"imports": {"crypto": "https://deno.land/std@0.119.0/node/crypto.ts"}} -------------------------------------------------------------------------------- /deployment/Dockerfile.circleci: -------------------------------------------------------------------------------- 1 | FROM circleci/rust 2 | 3 | WORKDIR /kcov/ 4 | 5 | RUN sudo apt-get update 6 | RUN sudo apt-get install cmake binutils-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev git 7 | 8 | ENV KCOV_VERSION 34 9 | RUN sudo git clone --single-branch --branch v$KCOV_VERSION https://github.com/SimonKagstrom/kcov.git 10 | RUN cd kcov && sudo cmake . && sudo make -j$(nproc) && sudo make install 11 | 12 | RUN cargo install cargo-kcov -------------------------------------------------------------------------------- /docs/feature-guides/trust-models.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Trust Models 3 | --- 4 | 5 | ## Overview 6 | 7 | The current subnet implementation uses a federated system of miners. This federation is fully trusted, but future work on the subnet feature will explore alternative trust models. 8 | 9 | In this fully-trusted federation model: 10 | 11 | - The federation is responsible for issuing subnet blocks. 12 | - Users can validate these blocks, but the subnet's federation still controls the blocks. 13 | - A majority of the federation must sign each block. 14 | - Federation signatures are validated on the L1 chain. 15 | -------------------------------------------------------------------------------- /docs/images/deposit-stx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/docs/images/deposit-stx.png -------------------------------------------------------------------------------- /docs/images/subnet-devnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/docs/images/subnet-devnet.png -------------------------------------------------------------------------------- /docs/images/subnet-miners.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/docs/images/subnet-miners.png -------------------------------------------------------------------------------- /docs/images/subnets-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/docs/images/subnets-architecture.png -------------------------------------------------------------------------------- /docs/images/subnets-deployment-confirmed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hirosystems/stacks-subnets/b0a722754e0031758fc507f1757d7c5fa18da488/docs/images/subnets-deployment-confirmed.png -------------------------------------------------------------------------------- /docs/miner-resource-recommendation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Miner Resource Recommendation 3 | --- 4 | 5 | # Miner Resource Recommendation 6 | 7 | These are our suggested miner resource requirements to spin up a Subnet Miner. 8 | 9 | ## Features 10 | 11 | - Higher CPU speed results in higher throughput and lower latency 12 | - Higher RAM will lead to faster transaction validation and faster blocks 13 | - An additional layer on Stacks warrants more disk space to accommodate the additional subnets’ blocks and microblocks 14 | 15 | ## What problem does it solve? 16 | 17 | The specifications below help you increase the transaction throughput by 4X times and reduce the block confirmation time from 10 minutes to 1 minute. 18 | 19 | ## Virtual Machine Specifications 20 | 21 | We assume a [Debian](https://www.debian.org/) host with `x86_64` architecture for the following example. Note that the commands may also work on any Debian-derived distribution. You can run your machine on Google Compute Engine(GCE) and choose the specifications below. 22 | 23 | :::note 24 | 25 | _Bitcoin chainstate is approximately 529 GB, and Stacks chainstate is approximately 84 GB._ 26 | 27 | ::: 28 | 29 | - Run on GCE n2-standard-4 (4 vCPUs, greater than or equal to 16 GB memory) instances with 2048 GB SSD 30 | - Annual cost is approximately $1100 per year 31 | - Minimum CPU greater than or equal to 4 vCPUs 32 | - Minimum memory greater than or equal to 16 GB Memory 33 | - Minimum storage is 2 TB Disk to allow chainstate growth 34 | 35 | ## Hardware Specifications 36 | 37 | The following are the hardware specifications for running a subnet on the mainnet. 38 | 39 | ### CPU 40 | 41 | - Processing speed greater than or equal to 2.8 GHz 42 | - CPU greater than or equal to 4 vCPUs 43 | 44 | ### RAM 45 | 46 | The minimum size of the RAM is 16 GB. 47 | 48 | ### Disk 49 | 50 | - NVMe-based Solid State Drive(SSD) storage: You can use local SSDs through Small Computer System Interface(SCSI). For higher performance in production settings, we recommend upgrading to NVMe interfaces: 51 | - high TBW (Total Bytes Written) 52 | - greater than or equal to 3.4 GB per second sequential read and sequential write performance 53 | - greater than or equal to 1 TB to allow for chainstate growth 54 | 55 | ### Networking 56 | 57 | - Preferred 1 GBit/s 58 | - Minimum: 300 MBit/s symmetric, commercial 59 | -------------------------------------------------------------------------------- /docs/rpc/api/contract/post-call-read-only-fn-fail.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "okay": false, 3 | "cause": "Unchecked(PublicFunctionNotReadOnly(..." 4 | } 5 | -------------------------------------------------------------------------------- /docs/rpc/api/contract/post-call-read-only-fn-success.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "okay": true, 3 | "result": "0x111..." 4 | } 5 | -------------------------------------------------------------------------------- /docs/rpc/api/contract/post-call-read-only-fn.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request to get contract source", 4 | "title": "ReadOnlyFunctionSuccessResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["okay"], 8 | "properties": { 9 | "okay": { 10 | "type": "boolean" 11 | }, 12 | "result": { 13 | "type": "string" 14 | }, 15 | "cause": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-account-data.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "balance": "0x0000000000000000000000000007a120", 3 | "locked": "0x0000000000000000000000000007a120", 4 | "unlock_height": 126, 5 | "nonce": 2867, 6 | "balance_proof": "0xabce", 7 | "nonce_proof": "0xabcd" 8 | } 9 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-account-data.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request for account data", 4 | "title": "AccountDataResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["balance", "locked", "unlock_height", "nonce", "balance_proof", "nonce_proof"], 8 | "properties": { 9 | "balance": { 10 | "type": "string" 11 | }, 12 | "locked": { 13 | "type": "string" 14 | }, 15 | "unlock_height": { 16 | "type": "integer" 17 | }, 18 | "nonce": { 19 | "type": "integer" 20 | }, 21 | "balance_proof": { 22 | "type": "string" 23 | }, 24 | "nonce_proof": { 25 | "type": "string" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-contract-data-map-entry.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": "0x0a0c000000010a6d6f6e737465722d69640100000000000000000000000000000001", 3 | "proof": "0x123..." 4 | } 5 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-contract-data-map-entry.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "Response of get data map entry request", 4 | "title": "MapEntryResponse", 5 | "type": "object", 6 | "required": ["data"], 7 | "properties": { 8 | "data": { 9 | "type": "string", 10 | "description": "Hex-encoded string of clarity value. It is always an optional tuple." 11 | }, 12 | "proof": { 13 | "type": "string", 14 | "description": "Hex-encoded string of the MARF proof for the data" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-contract-interface.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request to get contract interface", 4 | "title": "ContractInterfaceResponse", 5 | "type": "object", 6 | "required": ["functions", "variables", "maps", "fungible_tokens", "non_fungible_tokens"], 7 | "properties": { 8 | "functions": { 9 | "type": "array", 10 | "items": { 11 | "type": "object" 12 | }, 13 | "description": "List of defined methods" 14 | }, 15 | "variables": { 16 | "type": "array", 17 | "items": { 18 | "type": "object" 19 | }, 20 | "description": "List of defined variables" 21 | }, 22 | "maps": { 23 | "type": "array", 24 | "items": { 25 | "type": "object" 26 | }, 27 | "description": "List of defined data-maps" 28 | }, 29 | "fungible_tokens": { 30 | "type": "array", 31 | "items": { 32 | "type": "object" 33 | }, 34 | "description": "List of fungible tokens in the contract" 35 | }, 36 | "non_fungible_tokens": { 37 | "type": "array", 38 | "items": { 39 | "type": "object" 40 | }, 41 | "description": "List of non-fungible tokens in the contract" 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-contract-source.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": "(define-constant sender 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)\n(define-constant recipient 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)\n\n(define-fungible-token novel-token-19)\n(begin (ft-mint? novel-token-19 u12 sender))\n(begin (ft-transfer? novel-token-19 u2 sender recipient))\n\n(define-non-fungible-token hello-nft uint)\n(begin (nft-mint? hello-nft u1 sender))\n(begin (nft-mint? hello-nft u2 sender))\n(begin (nft-transfer? hello-nft u1 sender recipient))\n\n(define-public (test-emit-event)\n (begin\n (print \"Event! Hello world\")\n (ok u1)))\n(begin (test-emit-event))\n\n(define-public (test-event-types)\n (begin\n (unwrap-panic (ft-mint? novel-token-19 u3 recipient))\n (unwrap-panic (nft-mint? hello-nft u2 recipient))\n (unwrap-panic (stx-transfer? u60 tx-sender 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR))\n (unwrap-panic (stx-burn? u20 tx-sender))\n (ok u1)))\n\n(define-map store ((key (buff 32))) ((value (buff 32))))\n(define-public (get-value (key (buff 32)))\n (begin\n (match (map-get? store ((key key)))\n entry (ok (get value entry))\n (err 0))))\n(define-public (set-value (key (buff 32)) (value (buff 32)))\n (begin\n (map-set store ((key key)) ((value value)))\n (ok u1)))", 3 | "publish_height": 3196, 4 | "proof": "0000001104060000001ec4e..." 5 | } 6 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-contract-source.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request to get contract source", 4 | "title": "ContractSourceResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["source", "publish_height", "proof"], 8 | "properties": { 9 | "source": { 10 | "type": "string" 11 | }, 12 | "publish_height": { 13 | "type": "integer" 14 | }, 15 | "proof": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-fee-transfer.example.json: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-fee-transfer.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET fee estimates", 4 | "title": "CoreNodeFeeResponse", 5 | "type": "string", 6 | "additionalProperties": false 7 | } 8 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-ft-withdrawal.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "withdrawal_root": "0x02000000206794fd20ad2cf30ea11e7e1c5cfc236a920f672d99e02fa8351577db1cac71f8", 3 | "withdrawal_leaf_hash": "0x02000000205ea1394c234f8688feb6ff1e77250d70d5bb4970ce005024a18043c9c56859b1", 4 | "sibling_hashes": "0x0b000000010c0000000204686173680200000020df140d8faa513a8c7b5d3cecd0df8eb6459d196c945b6a73acd9bddb22d810470c69732d6c6566742d7369646504", 5 | } 6 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-ft-withdrawal.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request for FT withdrawal data", 4 | "title": "WithdrawalFtResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["withdrawal_root", "withdrawal_leaf_hash", "sibling_hashes"], 8 | "properties": { 9 | "withdrawal_root": { 10 | "type": "string" 11 | }, 12 | "withdrawal_leaf_hash": { 13 | "type": "string" 14 | }, 15 | "sibling_hashes": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-info.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "peer_version": 385875968, 3 | "pox_consensus": "17f76e597bab45646956f38dd39573085d72cbc0", 4 | "burn_block_height": 16, 5 | "stable_pox_consensus": "8e0561978fc5506b68a589c402dad97e862edb59", 6 | "stable_burn_block_height": 15, 7 | "server_version": "blockstack-core 0.0.1 => 23.0.0.0 (, release build, linux [x86_64])", 8 | "network_id": 2147483648, 9 | "parent_network_id": 3669344250, 10 | "stacks_tip_height": 15, 11 | "stacks_tip": "b1807a2d3f7f8c7922f7c1d60d7c34145ade05d789640dc7dc9ec1021e07bb54", 12 | "stacks_tip_consensus_hash": "17f76e597bab45646956f38dd39573085d72cbc0", 13 | "unanchored_tip": "0000000000000000000000000000000000000000000000000000000000000000", 14 | "exit_at_block_height": null 15 | } 16 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-nft-withdrawal.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "withdrawal_root": "0x0200000020898a1d67146f768bea82df555bebad41d2919518c843bdce83057f970efb3889", 3 | "withdrawal_leaf_hash": "0x0200000020a6b03891a27f3cbea3b64c24fed1740740785c8da960bb11cacb55333e8191bc", 4 | "sibling_hashes": "0x0b000000010c0000000204686173680200000020a6b03891a27f3cbea3b64c24fed1740740785c8da960bb11cacb55333e8191bc0c69732d6c6566742d7369646504" 5 | } 6 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-nft-withdrawal.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request for NFT withdrawal data", 4 | "title": "WithdrawalNftResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["withdrawal_root", "withdrawal_leaf_hash", "sibling_hashes"], 8 | "properties": { 9 | "withdrawal_root": { 10 | "type": "string" 11 | }, 12 | "withdrawal_leaf_hash": { 13 | "type": "string" 14 | }, 15 | "sibling_hashes": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-pox.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_id": "SP000000000000000000002Q6VF78.pox", 3 | "pox_activation_threshold_ustx": 52329761604388, 4 | "first_burnchain_block_height": 666050, 5 | "prepare_phase_block_length": 100, 6 | "reward_phase_block_length": 2000, 7 | "reward_slots": 4000, 8 | "rejection_fraction": 25, 9 | "total_liquid_supply_ustx": 1046595232087772, 10 | "current_cycle": { 11 | "id": 2, 12 | "min_threshold_ustx": 70000000000, 13 | "stacked_ustx": 202157971547640, 14 | "is_pox_active": true 15 | }, 16 | "next_cycle": { 17 | "id": 3, 18 | "min_threshold_ustx": 70000000000, 19 | "min_increment_ustx": 52329761604, 20 | "stacked_ustx": 162057034977640, 21 | "prepare_phase_start_block_height": 672250, 22 | "blocks_until_prepare_phase": 407, 23 | "reward_phase_start_block_height": 672350, 24 | "blocks_until_reward_phase": 507, 25 | "ustx_until_pox_rejection": 261648808021925 26 | }, 27 | "min_amount_ustx": 70000000000, 28 | "prepare_cycle_length": 100, 29 | "reward_cycle_id": 2, 30 | "reward_cycle_length": 2100, 31 | "rejection_votes_left_required": 261648808021925, 32 | "next_reward_cycle_in": 507 33 | } 34 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-stx-withdrawal.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "withdrawal_root": "0x0200000020898a1d67146f768bea82df555bebad41d2919518c843bdce83057f970efb3889", 3 | "withdrawal_leaf_hash": "0x0200000020a6b03891a27f3cbea3b64c24fed1740740785c8da960bb11cacb55333e8191bc", 4 | "sibling_hashes": "0x0b000000010c0000000204686173680200000020a6b03891a27f3cbea3b64c24fed1740740785c8da960bb11cacb55333e8191bc0c69732d6c6566742d7369646504" 5 | } 6 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/get-stx-withdrawal.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request for STX withdrawal data", 4 | "title": "WithdrawalStxResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["withdrawal_root", "withdrawal_leaf_hash", "sibling_hashes"], 8 | "properties": { 9 | "withdrawal_root": { 10 | "type": "string" 11 | }, 12 | "withdrawal_leaf_hash": { 13 | "type": "string" 14 | }, 15 | "sibling_hashes": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-block-proposal.error.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "Error response for block proposals", 4 | "title": "Error block proposal RPC response", 5 | "type": "object", 6 | "additionalProperties": true, 7 | "required": ["error_message"], 8 | "properties": { 9 | "error_message": { 10 | "type": "string" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-block-proposal.okay.example.json: -------------------------------------------------------------------------------- 1 | "0xb3b1bdf21ecb659e6929e65470a5493f8cfd57e7a6da58a7b453096a76670cf75b489bb8ef3e1aa920a05c139af63102150a732f9baa403ad8164d541b34bcdc00" 2 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-block-proposal.okay.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "POST response for block proposal (hex encoded signature)", 4 | "title": "Success response for block proposal", 5 | "type": "string", 6 | } 7 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-block-proposal.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "POST request for block proposals", 4 | "title": "Block proposal RPC request", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["message", "signature"], 8 | "properties": { 9 | "message": { 10 | "type": "string" 11 | }, 12 | "signature": { 13 | "type": "string" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-fee-transaction-response.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "cost_scalar_change_by_byte": 0.00476837158203125, 3 | "estimated_cost": { 4 | "read_count": 19, 5 | "read_length": 4814, 6 | "runtime": 7175000, 7 | "write_count": 2, 8 | "write_length": 1020 9 | }, 10 | "estimated_cost_scalar": 14, 11 | "estimations": [ 12 | { 13 | "fee": 17, 14 | "fee_rate": 1.2410714285714286 15 | }, 16 | { 17 | "fee": 125, 18 | "fee_rate": 8.958333333333332 19 | }, 20 | { 21 | "fee": 140, 22 | "fee_rate": 10 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-fee-transaction-response.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "POST response for estimated fee", 4 | "title": "TransactionFeeEstimateResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["estimated_cost", "estimated_cost_scalar", "estimated_fee_rates", "estimated_fees"], 8 | "properties": { 9 | "estimated_cost_scalar": { 10 | "type": "integer" 11 | }, 12 | "cost_scalar_change_by_byte": { 13 | "type": "number" 14 | }, 15 | "estimated_cost": { 16 | "type": "object", 17 | "additionalProperties": false, 18 | "required": ["read_count", "write_count", "read_length", "write_length", "runtime"], 19 | "properties": { 20 | "read_count": { "type": "integer" }, 21 | "read_length": { "type": "integer" }, 22 | "runtime": { "type": "integer" }, 23 | "write_count": { "type": "integer" }, 24 | "write_length": { "type": "integer" } 25 | } 26 | }, 27 | "estimations": { 28 | "type": "array", 29 | "items": { 30 | "type": "object", 31 | "properties": { 32 | "fee_rate": { 33 | "type": "number" 34 | }, 35 | "fee": { 36 | "type": "number" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-fee-transaction.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "estimated_len": 350, 3 | "transaction_payload": "021af942874ce525e87f21bbe8c121b12fac831d02f4086765742d696e666f0b7570646174652d696e666f00000000" 4 | } 5 | -------------------------------------------------------------------------------- /docs/rpc/api/core-node/post-fee-transaction.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "POST request for estimated fee", 4 | "title": "TransactionFeeEstimateRequest", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["transaction_payload"], 8 | "properties": { 9 | "transaction_payload": { 10 | "type": "string" 11 | }, 12 | "estimated_len": { 13 | "type": "integer" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/rpc/api/trait/get-is-trait-implemented.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "is_implemented": true 3 | } 4 | -------------------------------------------------------------------------------- /docs/rpc/api/trait/get-is-trait-implemented.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request to get trait implementation information", 4 | "title": "IsTraitImplementedSuccessResponse", 5 | "type": "object", 6 | "additionalProperties": false, 7 | "required": ["is_implemented"], 8 | "properties": { 9 | "is_implemented": { 10 | "type": "boolean" 11 | }, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/rpc/api/transaction/post-core-node-transactions-error.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "transaction rejected", 3 | "reason": "BadNonce", 4 | "reason_data": { 5 | "actual": 4, 6 | "expected": 0, 7 | "is_origin": true, 8 | "principal": "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH" 9 | }, 10 | "txid": "caf6fd60ae05b0c2d19ef14ab6a7670b1095d117fa7c80224c74e76214d0a791" 11 | } 12 | -------------------------------------------------------------------------------- /docs/rpc/api/transaction/post-core-node-transactions-error.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "description": "GET request that returns transactions", 4 | "title": "PostCoreNodeTransactionsError", 5 | "type": "object", 6 | "required": ["error", "reason", "reason_data", "txid"], 7 | "properties": { 8 | "error": { 9 | "type": "string", 10 | "description": "The error" 11 | }, 12 | "reason": { 13 | "type": "string", 14 | "description": "The reason for the error" 15 | }, 16 | "reason_data": { 17 | "type": "object", 18 | "description": "More details about the reason" 19 | }, 20 | "txid": { 21 | "type": "string", 22 | "description": "The relevant transaction id" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/rpc/entities/contracts/read-only-function-args.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "ReadOnlyFunctionArgs", 4 | "description": "Describes representation of a Type-0 Stacks 2.0 transaction. https://github.com/blockstack/stacks-blockchain/blob/master/sip/sip-005-blocks-and-transactions.md#type-0-transferring-an-asset", 5 | "type": "object", 6 | "required": ["sender", "arguments"], 7 | "properties": { 8 | "sender": { 9 | "type": "string", 10 | "description": "The simulated tx-sender" 11 | }, 12 | "arguments": { 13 | "type": "array", 14 | "description": "An array of hex serialized Clarity values", 15 | "items": { 16 | "type": "string" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /migration-verification/.dockerignore: -------------------------------------------------------------------------------- 1 | **/node_modules -------------------------------------------------------------------------------- /migration-verification/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a Dockerfile that performs automated validation of the migration process from Stacks 1.0 to Stacks 2.0. 2 | 3 | A sampling of STX balances and lockup schedules are tested. 4 | 5 | The following steps are automatically performed: 6 | 1. Checkout and install Stacks 1.0. 7 | 2. Run a Stacks 1.0 fast-sync to get caught up to the latest chain state (as of the latest hosted snapshot). 8 | 3. Trigger a fast-sync-dump similar to how it will be triggered from the name threshold. 9 | 4. Perform the chainstate export step from the fast-sync-dump. 10 | 5. Checkout the Stacks 2.0 source, and copy over the newly exported chainstate.txt, and build. 11 | 6. Query the Stacks 1.0 db for 1000 address balances, and ~1000 lockup schedules. 12 | 7. Spin up both a Stacks 1.0 and Stacks 2.0 node, and validate the address balances match using the account RPC endpoints: 13 | * Stacks 1.0: `/v1/accounts/{address}/STACKS/balance` 14 | * Stacks 2.0: `/v2/accounts/{address-in-testnet-format}` 15 | 8. Validate lockup schedules in Stacks 2.0 match the samples dumped from the Stacks 1.0, using a contract map lookup: 16 | * `/v2/map_entry/ST000000000000000000002AMW42H/lockup/lockups` 17 | 18 | 19 | 20 | ### Running 21 | This is a resources intensive process and can take upwards of an hour. 22 | 23 | Ensure Docker is allocated at least 70GB disk size and 4GB memory. 24 | 25 | Run the docker build: 26 | ```shell 27 | cd migration-verification 28 | DOCKER_BUILDKIT=1 BUILDKIT_PROGRESS=plain docker build --build-arg STACKS_V2_BRANCH= . 29 | ``` 30 | -------------------------------------------------------------------------------- /migration-verification/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@blockstack/test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "ts-node index.ts" 8 | }, 9 | "keywords": [], 10 | "author": "Matthew Little", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@stacks/transactions": "^1.0.0-beta.20", 14 | "@types/node": "^14.14.14", 15 | "@types/node-fetch": "^2.5.7", 16 | "c32check": "^1.1.2", 17 | "node-fetch": "^2.6.1", 18 | "ts-node": "^9.1.1", 19 | "typescript": "^4.1.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /migration-verification/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "strict": true, 6 | "skipLibCheck": true, 7 | "noEmit": true, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /net-test/README.md: -------------------------------------------------------------------------------- 1 | # Stacks Network Testing 2 | 3 | A rudimentary set of tools for testing multiple Stacks nodes at once, locally. 4 | Relevant files: 5 | 6 | * `bin/start.sh` -- start up a master node, a miner node, or a follower node, as 7 | well as ancilliary processes. 8 | * `bin/faucet.sh` -- a rudimentary Bitcoin faucet. 9 | * `bin/txload.sh` -- a rudimentary Stacks transaction generator and load-tester. 10 | * `etc/*.in` -- templates that `bin/start.sh` uses to create configuration 11 | files. 12 | 13 | To use, you will need to install `stacks-node`, `blockstack-cli`, 14 | `puppet-chain`, and `bin/faucet.sh` to somewhere in your `$PATH`. 15 | You will also need a recent `bitcoind` and `bitcoin-cli`. 16 | -------------------------------------------------------------------------------- /net-test/etc/bitcoin-neon-controller.toml.in: -------------------------------------------------------------------------------- 1 | [network] 2 | rpc_bind = "0.0.0.0:28443" 3 | block_time = 60000 4 | miner_address = "mmNe3BjtYa8ZWtpQxfpsE8aWKgHh77LYTT" 5 | faucet_address = "n3k15aVS4rEWhVYn4YfAFjD8Em5mmsducg" 6 | bitcoind_rpc_host = "127.0.0.1:18443" 7 | bitcoind_rpc_user = "blockstack" 8 | bitcoind_rpc_pass = "blockstacksystem" 9 | genesis_timestamp = @@BITCOIN_NEON_CONTROLLER_GENESIS_TIMESTAMP@@ 10 | whitelisted_rpc_calls = [ 11 | "listunspent", 12 | "importaddress", 13 | "sendrawtransaction", 14 | "getrawtransaction", 15 | "scantxoutset", 16 | "getrawmempool", 17 | "getblockstats", 18 | "getblockhash" 19 | ] 20 | 21 | [[blocks]] 22 | count = 1 23 | block_time = 20000 24 | ignore_txs = false 25 | 26 | # Faucet: 27 | # Private Key b20fea233f7718d956d2c5ed71889836ec872fec7d1de2068f19f40faf297f3001 28 | # Public Key 02327e09dc18fee1d51fe2b19b487e01eba4e6adcb325bf102213fce7bbdcde6bd 29 | # Address n3k15aVS4rEWhVYn4YfAFjD8Em5mmsducg 30 | # Format p2pkh 31 | # Network testnet 32 | # Compressed true 33 | 34 | # NOTE: the miner_address is the address of the Stacks master node's mining private key ("seed") 35 | 36 | # NOTE: the following lines are meant to be grep'ed by the node runner: 37 | # WIF cTYqAVPS7uJTAcxyzkXWjmRGoCjkPcb38wZVRjyXov1RiRDWPQj3 -------------------------------------------------------------------------------- /net-test/etc/bitcoin.conf.in: -------------------------------------------------------------------------------- 1 | server=1 2 | regtest=1 3 | rpcallowip=0.0.0.0/0 4 | rpcallowip=::/0 5 | rpcuser=blockstack 6 | rpcpassword=blockstacksystem 7 | txindex=1 8 | listen=1 9 | debug=1 10 | rpcserialversion=0 11 | datadir=@@BITCOIN_DATA_DIR@@ 12 | 13 | [regtest] 14 | bind=0.0.0.0:18444 15 | rpcbind=0.0.0.0:18443 16 | -------------------------------------------------------------------------------- /net-test/etc/stacks-follower.toml.in: -------------------------------------------------------------------------------- 1 | [node] 2 | rpc_bind = "0.0.0.0:@@STACKS_FOLLOWER_RPC_PORT@@" 3 | p2p_bind = "0.0.0.0:@@STACKS_FOLLOWER_P2P_PORT@@" 4 | bootstrap_node = "04ee0b1602eb18fef7986887a7e8769a30c9df981d33c8380d255edef003abdcd243a0eb74afdf6740e6c423e62aec631519a24cf5b1d62bf8a3e06ddc695dcb77@@@STACKS_BOOTSTRAP_IP@@:@@STACKS_BOOTSTRAP_PORT@@" 5 | deny_nodes = "@@STACKS_DENY_NODES@@" 6 | working_dir = "@@STACKS_CHAINSTATE_DIR@@" 7 | p2p_address = "@@STACKS_PUBLIC_IP@@:@@STACKS_FOLLOWER_P2P_PORT@@" 8 | 9 | [burnchain] 10 | chain = "bitcoin" 11 | mode = "krypton" 12 | peer_host = "@@BITCOIN_IP@@" 13 | rpc_port = 28443 14 | peer_port = 18444 15 | process_exit_at_block_height = @@PROCESS_EXIT_AT_BLOCK_HEIGHT@@ 16 | 17 | [connection_options] 18 | inv_sync_interval = 10 19 | download_interval = 10 20 | walk_interval = 10 21 | disable_inbound_handshakes = @@DISABLE_INBOUND_HANDSHAKES@@ 22 | disable_inbound_walks = @@DISABLE_INBOUND_WALKS@@ 23 | 24 | [[ustx_balance]] 25 | # Private key: b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 26 | address = "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH" 27 | amount = 10000000000000000 28 | [[ustx_balance]] 29 | # Private key: 3a4e84abb8abe0c1ba37cef4b604e73c82b1fe8d99015cb36b029a65099d373601 30 | address = "ST26FVX16539KKXZKJN098Q08HRX3XBAP541MFS0P" 31 | amount = 10000000000000000 32 | [[ustx_balance]] 33 | # Private key: 052cc5b8f25b1e44a65329244066f76c8057accd5316c889f476d0ea0329632c01 34 | address = "ST3CECAKJ4BH08JYY7W53MC81BYDT4YDA5M7S5F53" 35 | amount = 10000000000000000 36 | [[ustx_balance]] 37 | # Private key: 9aef533e754663a453984b69d36f109be817e9940519cc84979419e2be00864801 38 | address = "ST31HHVBKYCYQQJ5AQ25ZHA6W2A548ZADDQ6S16GP" 39 | amount = 10000000000000000 40 | 41 | -------------------------------------------------------------------------------- /net-test/etc/stacks-master.toml.in: -------------------------------------------------------------------------------- 1 | [node] 2 | rpc_bind = "0.0.0.0:20443" 3 | p2p_bind = "0.0.0.0:20444" 4 | seed = "bbd40688849e9d0f3bc3132a576835df11bb84b307a5a0588d8fecc4d6ba32d201" 5 | miner = @@STACKS_MASTER_IS_MINER@@ 6 | working_dir = "@@STACKS_CHAINSTATE_DIR@@" 7 | pox_sync_sample_secs = 10 8 | mine_microblocks = @@STACKS_MASTER_MINE_MICROBLOCKS@@ 9 | microblock_frequency = @@STACKS_MASTER_MICROBLOCK_FREQUENCY@@ 10 | max_microblocks = @@STACKS_MASTER_MAX_MICROBLOCKS@@ 11 | wait_time_for_microblocks = @@STACKS_MASTER_WAIT_FOR_MICROBLOCKS@@ 12 | p2p_address = "@@STACKS_PUBLIC_IP@@:20444" 13 | deny_nodes = "@@STACKS_DENY_NODES@@" 14 | 15 | [burnchain] 16 | chain = "bitcoin" 17 | mode = "krypton" 18 | peer_host = "0.0.0.0" 19 | rpc_port = 28443 20 | peer_port = 18444 21 | poll_time_secs = 5 22 | process_exit_at_block_height = @@PROCESS_EXIT_AT_BLOCK_HEIGHT@@ 23 | 24 | [connection_options] 25 | inv_sync_interval = 10 26 | download_interval = 10 27 | walk_interval = 10 28 | disable_inbound_handshakes = @@DISABLE_INBOUND_HANDSHAKES@@ 29 | disable_inbound_walks = @@DISABLE_INBOUND_WALKS@@ 30 | 31 | [[ustx_balance]] 32 | # Private key: b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 33 | address = "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH" 34 | amount = 10000000000000000 35 | [[ustx_balance]] 36 | # Private key: 3a4e84abb8abe0c1ba37cef4b604e73c82b1fe8d99015cb36b029a65099d373601 37 | address = "ST26FVX16539KKXZKJN098Q08HRX3XBAP541MFS0P" 38 | amount = 10000000000000000 39 | [[ustx_balance]] 40 | # Private key: 052cc5b8f25b1e44a65329244066f76c8057accd5316c889f476d0ea0329632c01 41 | address = "ST3CECAKJ4BH08JYY7W53MC81BYDT4YDA5M7S5F53" 42 | amount = 10000000000000000 43 | [[ustx_balance]] 44 | # Private key: 9aef533e754663a453984b69d36f109be817e9940519cc84979419e2be00864801 45 | address = "ST31HHVBKYCYQQJ5AQ25ZHA6W2A548ZADDQ6S16GP" 46 | amount = 10000000000000000 47 | 48 | -------------------------------------------------------------------------------- /net-test/etc/stacks-miner.toml.in: -------------------------------------------------------------------------------- 1 | [node] 2 | rpc_bind = "0.0.0.0:@@STACKS_MINER_RPC_PORT@@" 3 | p2p_bind = "0.0.0.0:@@STACKS_MINER_P2P_PORT@@" 4 | bootstrap_node = "04ee0b1602eb18fef7986887a7e8769a30c9df981d33c8380d255edef003abdcd243a0eb74afdf6740e6c423e62aec631519a24cf5b1d62bf8a3e06ddc695dcb77@@@STACKS_BOOTSTRAP_IP@@:@@STACKS_BOOTSTRAP_PORT@@" 5 | deny_nodes = "@@STACKS_DENY_NODES@@" 6 | seed = "@@STACKS_MINER_SEED@@" 7 | miner = true 8 | working_dir = "@@STACKS_CHAINSTATE_DIR@@" 9 | p2p_address = "@@STACKS_PUBLIC_IP@@:@@STACKS_MINER_P2P_PORT@@" 10 | pox_sync_sample_secs = 10 11 | mine_microblocks = @@STACKS_MINER_MINE_MICROBLOCKS@@ 12 | microblock_frequency = @@STACKS_MINER_MICROBLOCK_FREQUENCY@@ 13 | max_microblocks = @@STACKS_MINER_MAX_MICROBLOCKS@@ 14 | wait_time_for_microblocks = @@STACKS_MINER_WAIT_FOR_MICROBLOCKS@@ 15 | 16 | [burnchain] 17 | chain = "bitcoin" 18 | mode = "krypton" 19 | peer_host = "@@BITCOIN_IP@@" 20 | rpc_port = 28443 21 | peer_port = 18444 22 | poll_time_secs = 5 23 | process_exit_at_block_height = @@PROCESS_EXIT_AT_BLOCK_HEIGHT@@ 24 | 25 | [connection_options] 26 | inv_sync_interval = 10 27 | download_interval = 10 28 | walk_interval = 10 29 | disable_inbound_handshakes = @@DISABLE_INBOUND_HANDSHAKES@@ 30 | disable_inbound_walks = @@DISABLE_INBOUND_WALKS@@ 31 | 32 | [[ustx_balance]] 33 | # Private key: b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 34 | address = "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH" 35 | amount = 10000000000000000 36 | [[ustx_balance]] 37 | # Private key: 3a4e84abb8abe0c1ba37cef4b604e73c82b1fe8d99015cb36b029a65099d373601 38 | address = "ST26FVX16539KKXZKJN098Q08HRX3XBAP541MFS0P" 39 | amount = 10000000000000000 40 | [[ustx_balance]] 41 | # Private key: 052cc5b8f25b1e44a65329244066f76c8057accd5316c889f476d0ea0329632c01 42 | address = "ST3CECAKJ4BH08JYY7W53MC81BYDT4YDA5M7S5F53" 43 | amount = 10000000000000000 44 | [[ustx_balance]] 45 | # Private key: 9aef533e754663a453984b69d36f109be817e9940519cc84979419e2be00864801 46 | address = "ST31HHVBKYCYQQJ5AQ25ZHA6W2A548ZADDQ6S16GP" 47 | amount = 10000000000000000 48 | 49 | -------------------------------------------------------------------------------- /net-test/mnt/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NOW="$(date +%s)" 4 | mkdir -p "archive/$NOW" 5 | ls | while read NAME; do 6 | if [[ "$NAME" != "cleanup.sh" ]] && [[ "$NAME" != "archive" ]]; then 7 | echo "mv $NAME archive/$NOW" 8 | mv "$NAME" "archive/$NOW" 9 | fi 10 | done 11 | 12 | -------------------------------------------------------------------------------- /net-test/tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./config.sh 4 | set -uo pipefail 5 | 6 | SUCCEEDED=0 7 | for TESTNAME in $(ls test_*); do 8 | ( cd "$__MNT" && ./cleanup.sh ) 9 | echo "Running $TESTNAME" 10 | "./$TESTNAME" 11 | RC=$? 12 | echo "$TESTNAME exit $RC" 13 | 14 | if [ $RC -ne 0 ]; then 15 | SUCCEEDED=1 16 | fi 17 | done 18 | 19 | exit $SUCCEEDED 20 | -------------------------------------------------------------------------------- /net-test/tests/test_2_nat_miners.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This test creates a network that looks like this: 4 | # 5 | # Miner (NAT'ed) <-----> Non-mining Master (public) <-----> Miner (NAT'ed) 6 | # 7 | # NAT'ing is emulated by having each miner ban all other miners, so they never talk to each other. 8 | 9 | source ./config.sh 10 | PROCESS_EXIT_AT_BLOCK_HEIGHT=450 11 | 12 | source "$__BIN/start.sh" 13 | source ./testlib.sh 14 | 15 | set -uo pipefail 16 | 17 | NAME="test-2-nat-miners" 18 | 19 | with_master() { 20 | master_config "master-$NAME" "127.0.0.1" "false" 21 | } 22 | 23 | with_miner_1() { 24 | miner_config "miner-1-$NAME" "21443" "21444" 25 | } 26 | 27 | with_miner_2() { 28 | miner_config "miner-2-$NAME" "22443" "22444" 29 | } 30 | 31 | with_master 32 | set_inbound_walks "false" 33 | start_node & 34 | MASTER_PID=$! 35 | wait_node || exit_error "Master node failed to boot up" 36 | 37 | with_miner_1 38 | ban_peer "127.0.0.1" "22444" 39 | set_nat "true" 40 | start_node & 41 | MINER_1_PID=$! 42 | 43 | with_miner_2 44 | ban_peer "127.0.0.1" "21444" 45 | set_nat "true" 46 | start_node & 47 | MINER_2_PID=$! 48 | 49 | with_miner_1 50 | wait_node || exit_error "Miner node 1 failed to boot up" 51 | 52 | with_miner_2 53 | wait_node || exit_error "Miner node 2 failed to boot up" 54 | 55 | with_master 56 | wait_until_burn_block 300 || exit_error "Master node failed to reach block 300" 57 | 58 | with_miner_1 59 | wait_until_burn_block 300 || exit_error "Miner 1 failed to reach block 300" 60 | 61 | with_miner_2 62 | wait_until_burn_block 300 || exit_error "Miner 2 failed to reach block 300" 63 | 64 | wait_pids $MASTER_PID $MINER_1_PID $MINER_2_PID 65 | 66 | with_master 67 | check_chain_quality 90 90 100 68 | if [ $? -ne 0 ]; then 69 | exit_error "Chain quality check failed" 70 | fi 71 | exit 0 72 | 73 | -------------------------------------------------------------------------------- /release_notes/README.md: -------------------------------------------------------------------------------- 1 | Release Notes 2 | ============= 3 | 4 | This directory contains the release notes for each version of Blockstack Core. In particular, there are two types of changes in each release: 5 | 6 | * **Consensus-breaking Releases**: These are releases of Blockstack Core that change its consensus rules. 7 | Examples include adding new name opcodes, removing old ones, changing the types of transactions that are supported, which blockchain(s) are used, etc. 8 | Each consensus-breaking release is incompatible with all prior releases; old releases will not agree with new releases on the global name set. 9 | For this reason, **it is strongly recommended to run the latest Blockstack Core release.** 10 | 11 | * **Non-consenus-breaking Releases**: These are all other releases. They include bugfixes, reliability improvements, performance improvements, and so on. 12 | 13 | The consensus-breaking releases are: 14 | 15 | * [20.0](changelog-20.md): hard fork of 2018 16 | * [0.17](changelog-0.17.md): hard fork of 2017 17 | * [0.14](changelog-0.14.md): hard fork of 2016 18 | * initial release: hardfork of 2015; migration from Namecoin to Bitcoin 19 | 20 | Notes on Consensus 21 | ================== 22 | 23 | The Blockstack Core developers do their best to avoid consensus-breaking releases whenever possible. 24 | However, certain improvements and bugfixes cannot be done without them. 25 | As such, the project tries to limit consensus-breaking releases to one per year (in Q4), and only with extensive testing. 26 | Consensus-breaking changes are documented in the release notes, and will be publicly documented beforehand whenever possible. 27 | 28 | If a critical consensus-breaking bug or security vulnerability is found, a new consensus-breaking release may be made on the spot. 29 | If this happens, it will be documented here and announced publicly on the 30 | [Blockstack Forum](https://forum.blockstack.org) and on [Twitter](https://twitter.com/blockstack). 31 | 32 | A yearly consensus-breaking release is required in order to keep name and namespace prices reasonable. 33 | When Blockstack was first deployed, namespace prices were determined on a 1 BTC == $230 USD exchange. 34 | At a minimum, the consensus-breaking release must adjust the BTC prices to ensure that names and namespaces 35 | are neither too cheap (making squatting trivial) nor too expensive (making the system unusable). 36 | -------------------------------------------------------------------------------- /release_notes/changelog-0.14.3.md: -------------------------------------------------------------------------------- 1 | What's New in 0.14.3 2 | ==================== 3 | 4 | Release 0.14.3 brings many incremental improvements over 0.14.2. It does not 5 | break consensus; 0.14, 0.14.1, and 0.14.2 nodes are compatible with 0.14.3 nodes. 6 | 7 | This marks the beginning of a per-sprint release cycle. Release notes will be 8 | shorter between releases, since new releases will be scheduled every two to 9 | three weeks. 10 | 11 | Release Highlights 12 | -------------------------------- 13 | 14 | * **Gaia Performance Improvements.** The read and write paths of Gaia have been 15 | refactored to run many I/O operations in parallel. This leads to faster data 16 | interaction times, even for indexed storage systems like Dropbox. 17 | 18 | * **Support for Fast Registrations.** This release adds an `unsafe` attribute to 19 | registration requests which, when enabled, directs core's registrar to issue 20 | the blockstack transactions _preorder_, _register_, and _update_, with only 4, 21 | 1, and 1 confirmations respectively. To support this, core must ignore some 22 | of the safety checks, because our resolvers will not have processed the name 23 | before the _update_ is issued. 24 | 25 | * **Better Packaging for Test Mode.** This release makes it easier to get 26 | started testing Blockstack Core and Blockstack Browser alongside a Bitcoin 27 | node in `regtest` mode. Developers can register names and interact with storage 28 | without having to spend Bitcoin or wait hours for names to be registered. 29 | 30 | Selected Bugfixes and Fixes 31 | --------------------------- 32 | More information on bugfixes can be found in GitHub issues (#454-#488 span this release). 33 | 34 | * Improved performance of price checks 35 | * Added zero confirmation balance checks 36 | * In regtest, core will rewrite testnet adddresses so that browser does not need to "understand" testnet addresses 37 | * Fixed bad behavior of setting temporary wallet keys 38 | * Support for logging in without blockchain ID 39 | * Issue #469 : Blockstack Core used to die in error cases when it should be 40 | able to fail more gracefully. This release fixes several such cases. 41 | 42 | -------------------------------------------------------------------------------- /release_notes/changelog-0.14.4.md: -------------------------------------------------------------------------------- 1 | What's New in 0.14.4 2 | ==================== 3 | 4 | Release 0.14.4 brings some incremental improvements over 0.14.3, and 5 | initial support for subdomains. It does not break consensus; 0.14, 6 | 0.14.1, and 0.14.2 nodes are compatible with 0.14.3 nodes. 7 | 8 | Release Highlights 9 | -------------------------------- 10 | 11 | * **Initial Support for Subdomains.** This release includes initial support for 12 | looking up subdomains. The blockstack client parses and correctly resolves 13 | subdomain entries in zonefiles. This is done on the local client, with a cache 14 | stored (by default) in `/.blockstack/subdomains.db` 15 | 16 | * **Simple Subdomain Registrar.** This release includes a simple subdomain 17 | registrar which is configurable to accept subdomain registrations and include 18 | those registrations in a user's zonefile by issuing periodic UPDATE transactions. 19 | 20 | More information on the subdomain support is included in [/docs/subdomains.md] 21 | 22 | Selected Bugfixes and Fixes 23 | --------------------------- 24 | 25 | Information on bugfixes can be found in GitHub issues. The biggest bugfix over 0.14.3 26 | is an updating of the test framework to fix some integration tests which were previously 27 | failing. 28 | -------------------------------------------------------------------------------- /release_notes/changelog-0.16.0.md: -------------------------------------------------------------------------------- 1 | What's New in 0.16 2 | ================== 3 | 4 | Release 0.16 brings some improvements over 0.14.5. It does not 5 | break consensus; 0.14-0.14.5 nodes are compatible with 0.16 nodes. 6 | 7 | Release Highlights 8 | ------------------ 9 | 10 | * **Support for Gaia Hub Storage Provider.** This release adds support for 11 | connecting to our development gaia-hub. 12 | 13 | * **New API Endpoint for Getting Name Count.** This release adds support scripts 14 | to the `API` directory for supporting faster search indexing for new names. This 15 | also includes support for indexing subdomains. 16 | 17 | * **Include support better Support for using Client Payment Keys** This includes support 18 | for supplying a key to perform payment operations on behalf of a client, and a mock insight-api 19 | endpoint for obtaining balance for a particular address. 20 | 21 | * **Better Support for Configuring Bind Address/Port in Regtest** This adds support for 22 | setting bind addresses and ports. 23 | 24 | Note on Versioning 25 | ------------------ 26 | 27 | To better align blockstack-core versioning and blockstack-browser versioning, 28 | we skipped `0.15` entirely. 29 | 30 | -------------------------------------------------------------------------------- /release_notes/changelog-0.18.6: -------------------------------------------------------------------------------- 1 | What's New in 0.18.6 2 | ================== 3 | 4 | Release 0.18.6 brings several minor improvements to Blockstack 5 | Core. It is not a consensus-breaking release. 6 | 7 | Release Highlights 8 | ------------------ 9 | 10 | **Subdomain listing**: This release adds two new endpoints: 11 | `/v1/subdomains` - this returns a paginated list of all subdomains. 12 | `/v1/blockchains/:blockchainID/subdomains_count` - this returns the 13 | count of registered subdomains. 14 | 15 | **Pending subdomain handling**: This release adds support for 16 | instantaneous subdomain resolution by 301 redirection to 17 | registrar-specified resolver URLs. 18 | 19 | Getting Started 20 | --------------- 21 | 22 | This change _does not_ require a state-upgrade on the blockstack 23 | server, so you will not need to fast-sync to a new state. 24 | -------------------------------------------------------------------------------- /release_notes/changelog-20.md: -------------------------------------------------------------------------------- 1 | What's New in 20 2 | ================ 3 | 4 | Release 20 is a **consensus-breaking release** that introduces the first version 5 | of the Stacks blockchain. Versions 19 and prior are *incompatible* with this 6 | release and will diverge from v20 nodes. 7 | 8 | Release Highlights 9 | ------------------ 10 | 11 | **Native Stacks Token**. This release completes the first version of the Stacks 12 | blockchain. Details can be found on this [forum 13 | post](https://forum.blockstack.org/t/blockstack-annual-hard-fork-2018/6518). 14 | 15 | **Blockstack Accounts API**. This release adds `/v1/accounts` endpoints to the 16 | RESTful API for querying account balances and transaction histories. Please see 17 | the relevant [documentation](https://core.blockstack.org) for details. 18 | 19 | Getting Started 20 | --------------- 21 | 22 | The recommended way to get started with v20 is through its fast-sync mode. To 23 | migrate from a v19 node to a v20 node, we recommend the following steps: 24 | 25 | ``` 26 | # stop the old node 27 | $ blockstack-core stop 28 | $ mv ~/.blockstack-server ~/.blockstack-server.19 29 | 30 | # start the new node 31 | $ blockstack-core fast_sync 32 | $ blockstack-core start 33 | ``` 34 | 35 | The old chain state database directory structure has changed, and is 36 | incompatible with this new release. If you are 37 | upgrading from a v19 node or older, you will need to remove your `.blockstack-server` 38 | directory. 39 | -------------------------------------------------------------------------------- /release_notes/wishlist-0.15.md: -------------------------------------------------------------------------------- 1 | Wishlist for 0.15 2 | ================= 3 | 4 | This document lists the set of features scheduled for the 0.15 release, due in mid-September 2017. 5 | 6 | New Features 7 | ------------ 8 | 9 | * Automatic name renewal in the clients. 10 | 11 | Consensus-breaking Changes 12 | -------------------------- 13 | 14 | * Revert the namespace lifetime multiplier change in 0.14. 15 | 16 | * Adjust the price multiplier to preserve a $230 USD to 1 BTC exchange. 17 | 18 | * Make name transfers take up to a week to complete, and make them cancellable by either the sender or recipient. This is to limit the damage that can be done by a key compromise. 19 | 20 | * Allow the name owner to specify a "name administrator" key that can update and renew the name, but not transfer or revoke it. 21 | 22 | * Allow a name owner to specify a set of trusted revokers upon registration. Each revoker owns a key, and a threshold of them (e.g. 3 of 5) can transfer the name to a new address. After 30 days, the name will become usable again by the address's owner. The idea is that a name owner can give some of his/her friends a revoke key, and if the owner loses their key or has it compromised, his/her friends can forcibly transfer it back. The revoke keys are one-time-use. The 30 day window gives the owner time to give out new revoke keys, or (if the revokers were compromised) gives the owner time to register and establish a different name. 23 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | stable 2 | -------------------------------------------------------------------------------- /sample-contracts/names.clar: -------------------------------------------------------------------------------- 1 | (define-constant burn-address 'SP000000000000000000002Q6VF78) 2 | (define-private (price-function (name uint)) 3 | (if (< name u100000) u1000 u100)) 4 | 5 | (define-map name-map 6 | { name: uint } { owner: principal }) 7 | (define-map preorder-map 8 | { name-hash: (buff 20) } 9 | { buyer: principal, paid: uint }) 10 | 11 | (define-public (preorder 12 | (name-hash (buff 20)) 13 | (name-price uint)) 14 | (if (is-ok (contract-call? .tokens token-transfer 15 | burn-address name-price)) 16 | (begin (map-insert preorder-map 17 | (tuple (name-hash name-hash)) 18 | (tuple (paid name-price) 19 | (buyer tx-sender))) 20 | (ok u0)) 21 | (err "token payment failed."))) 22 | 23 | (define-public (register 24 | (recipient-principal principal) 25 | (name uint) 26 | (salt uint)) 27 | (let ((preorder-entry 28 | (unwrap! ;; name _must_ have been preordered. 29 | (map-get? preorder-map 30 | (tuple (name-hash (hash160 (xor name salt))))) 31 | (err "no preorder found"))) 32 | (name-entry 33 | (map-get? name-map (tuple (name name))))) 34 | (if (and 35 | ;; name shouldn't *already* exist 36 | (is-none name-entry) 37 | ;; preorder must have paid enough 38 | (<= (price-function name) 39 | (get paid preorder-entry)) 40 | ;; preorder must have been the current principal 41 | (is-eq tx-sender 42 | (get buyer preorder-entry))) 43 | (if (and 44 | (map-insert name-map 45 | (tuple (name name)) 46 | (tuple (owner recipient-principal))) 47 | (map-delete preorder-map 48 | (tuple (name-hash (hash160 (xor name salt)))))) 49 | (ok u0) 50 | (err "failed to insert new name entry")) 51 | (err "invalid name register")))) 52 | -------------------------------------------------------------------------------- /sample-contracts/tokens-ft-mint.clar: -------------------------------------------------------------------------------- 1 | (begin 2 | (as-contract 3 | (contract-call? 'S1G2081040G2081040G2081040G208105NK8PE5.tokens-ft mint! u100) 4 | ) 5 | ) 6 | -------------------------------------------------------------------------------- /sample-contracts/tokens-ft.clar: -------------------------------------------------------------------------------- 1 | (define-fungible-token tokens) 2 | (define-private (get-balance (account principal)) 3 | (ft-get-balance tokens account)) 4 | 5 | (define-private (token-credit! (account principal) (amount uint)) 6 | (ft-mint? tokens amount account)) 7 | 8 | (define-public (token-transfer (to principal) (amount uint)) 9 | (ft-transfer? tokens amount tx-sender to)) 10 | 11 | (define-public (mint! (amount uint)) 12 | (token-credit! tx-sender amount)) 13 | 14 | (token-credit! tx-sender u10300) 15 | (token-transfer 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR u10000) 16 | (token-transfer 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G u300) 17 | -------------------------------------------------------------------------------- /sample-contracts/tokens-mint.clar: -------------------------------------------------------------------------------- 1 | (begin 2 | (as-contract 3 | (contract-call? 'S1G2081040G2081040G2081040G208105NK8PE5.tokens mint! u100) 4 | ) 5 | ) 6 | -------------------------------------------------------------------------------- /sample-contracts/tokens.clar: -------------------------------------------------------------------------------- 1 | (define-map tokens { account: principal } { balance: uint }) 2 | (define-private (get-balance (account principal)) 3 | (default-to u0 (get balance (map-get? tokens (tuple (account account)))))) 4 | 5 | (define-private (token-credit! (account principal) (amount uint)) 6 | (if (<= amount u0) 7 | (err "must move positive balance") 8 | (let ((current-amount (get-balance account))) 9 | (begin 10 | (map-set tokens (tuple (account account)) 11 | (tuple (balance (+ amount current-amount)))) 12 | (ok amount))))) 13 | 14 | (define-public (token-transfer (to principal) (amount uint)) 15 | (let ((balance (get-balance tx-sender))) 16 | (if (or (> amount balance) (<= amount u0)) 17 | (err "must transfer positive balance and possess funds") 18 | (begin 19 | (map-set tokens (tuple (account tx-sender)) 20 | (tuple (balance (- balance amount)))) 21 | (token-credit! to amount))))) 22 | 23 | (define-public (mint! (amount uint)) 24 | (let ((balance (get-balance tx-sender))) 25 | (token-credit! tx-sender amount))) 26 | 27 | (token-credit! 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR u10000) 28 | (token-credit! 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G u300) 29 | -------------------------------------------------------------------------------- /sip/README.md: -------------------------------------------------------------------------------- 1 | # Stacks Improvement Proposals (SIPs) 2 | 3 | This directory formerly contained all of the in-progress Stacks Improvement Proposals before the Stacks 2.0 mainnet launched. 4 | 5 | The SIPs are now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-000-stacks-improvement-proposal-process.md: -------------------------------------------------------------------------------- 1 | # SIP-000 Stacks Improvement Proposal Process 2 | 3 | This document formerly contained SIP-000 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-000/sip-000-stacks-improvement-proposal-process.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-001-burn-election.md: -------------------------------------------------------------------------------- 1 | # SIP-001 Burn Election 2 | 3 | This document formerly contained SIP-001 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-002-smart-contract-language.md: -------------------------------------------------------------------------------- 1 | # SIP-002 Smart Contract Language 2 | 3 | This document formerly contained SIP-002 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-002/sip-002-smart-contract-language.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-003-peer-network.md: -------------------------------------------------------------------------------- 1 | # SIP-003 Peer Network 2 | 3 | This document formerly contained SIP-003 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-003/sip-003-peer-network.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-004-materialized-view.md: -------------------------------------------------------------------------------- 1 | # SIP-004 Cryptographic Committment to Materialized Views 2 | 3 | This document formerly contained SIP-004 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-004/sip-004-materialized-view.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-005-blocks-and-transactions.md: -------------------------------------------------------------------------------- 1 | # SIP-005 Blocks, Transactions, and Accounts 2 | 3 | This document formerly contained SIP-005 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-006-runtime-cost-assessment.md: -------------------------------------------------------------------------------- 1 | # SIP-006 Clarity Execution Cost Assessment 2 | 3 | This document formerly contained SIP-006 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-006/sip-006-runtime-cost-assessment.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-007-stacking-consensus.md: -------------------------------------------------------------------------------- 1 | # SIP-007 Stacking Consensus 2 | 3 | This document formerly contained SIP-007 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-007/sip-007-stacking-consensus.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /sip/sip-008-analysis-cost-assessment.md: -------------------------------------------------------------------------------- 1 | # SIP-008 Clarity Parsing and Analysis Cost Assessment 2 | 3 | This document formerly contained SIP-008 before the Stacks 2.0 mainnet launched. 4 | 5 | This SIP is now located in the [stacksgov/sips repository](https://github.com/stacksgov/sips/blob/main/sips/sip-008/sip-008-analysis-cost-assessment.md) as part of the [Stacks Community Governance organization](https://github.com/stacksgov). 6 | -------------------------------------------------------------------------------- /soar-db/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "soar-db" 3 | version = "0.1.0" 4 | authors = ["Aaron Blankstein "] 5 | edition = "2021" 6 | resolver = "2" 7 | 8 | [dependencies] 9 | lazy_static = "1.4.0" 10 | serde = "1" 11 | serde_derive = "1" 12 | serde_json = { version = "1.0", features = ["arbitrary_precision", "raw_value"] } 13 | slog = { version = "2.5.2", features = [ "max_level_trace" ] } 14 | clarity = { git = "https://github.com/stacks-network/stacks-blockchain.git", rev = "580e811223a389d38071dcb9fde79ab55cd6f685" } 15 | stacks-common = { git = "https://github.com/stacks-network/stacks-blockchain.git", rev = "580e811223a389d38071dcb9fde79ab55cd6f685" } 16 | # clarity = { package = "clarity", path = "../../../stacks-blockchain-develop/clarity" } 17 | # stacks-common = { package = "stacks-common", path = "../stacks-blockchain-develop/stacks-common" } 18 | 19 | [lib] 20 | name = "soar_db" 21 | path = "src/lib.rs" 22 | 23 | [features] 24 | default = [] 25 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/deposit_ft.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::DepositFtOp; 4 | use crate::chainstate::burn::operations::Error as op_error; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for DepositFtOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::DepositFt { 13 | ref l1_contract_id, 14 | ref subnet_contract_id, 15 | ref name, 16 | ref amount, 17 | ref sender, 18 | } = value.event 19 | { 20 | Ok(DepositFtOp { 21 | txid: value.txid.clone(), 22 | // use the StacksBlockId in the L1 event as the burnchain header hash 23 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 24 | l1_contract_id: l1_contract_id.clone(), 25 | subnet_contract_id: subnet_contract_id.clone(), 26 | name: name.clone(), 27 | amount: amount.clone(), 28 | sender: sender.clone(), 29 | }) 30 | } else { 31 | Err(op_error::InvalidInput) 32 | } 33 | } 34 | } 35 | 36 | impl DepositFtOp { 37 | pub fn check( 38 | &self, 39 | _burnchain: &Burnchain, 40 | _tx: &mut SortitionHandleTx, 41 | ) -> Result<(), op_error> { 42 | // good to go! 43 | Ok(()) 44 | } 45 | 46 | #[cfg(test)] 47 | pub fn set_burn_height(&mut self, _height: u64) {} 48 | } 49 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/deposit_nft.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::DepositNftOp; 4 | use crate::chainstate::burn::operations::Error as op_error; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for DepositNftOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::DepositNft { 13 | ref l1_contract_id, 14 | ref subnet_contract_id, 15 | ref id, 16 | ref sender, 17 | } = value.event 18 | { 19 | Ok(DepositNftOp { 20 | txid: value.txid.clone(), 21 | // use the StacksBlockId in the L1 event as the burnchain header hash 22 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 23 | l1_contract_id: l1_contract_id.clone(), 24 | subnet_contract_id: subnet_contract_id.clone(), 25 | id: id.clone(), 26 | sender: sender.clone(), 27 | }) 28 | } else { 29 | Err(op_error::InvalidInput) 30 | } 31 | } 32 | } 33 | 34 | impl DepositNftOp { 35 | pub fn check( 36 | &self, 37 | _burnchain: &Burnchain, 38 | _tx: &mut SortitionHandleTx, 39 | ) -> Result<(), op_error> { 40 | // good to go! 41 | Ok(()) 42 | } 43 | 44 | #[cfg(test)] 45 | pub fn set_burn_height(&mut self, _height: u64) {} 46 | } 47 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/deposit_stx.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::DepositStxOp; 4 | use crate::chainstate::burn::operations::Error as op_error; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for DepositStxOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::DepositStx { 13 | ref amount, 14 | ref sender, 15 | } = value.event 16 | { 17 | Ok(DepositStxOp { 18 | txid: value.txid.clone(), 19 | // use the StacksBlockId in the L1 event as the burnchain header hash 20 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 21 | amount: amount.clone(), 22 | sender: sender.clone(), 23 | }) 24 | } else { 25 | Err(op_error::InvalidInput) 26 | } 27 | } 28 | } 29 | 30 | impl DepositStxOp { 31 | pub fn check( 32 | &self, 33 | _burnchain: &Burnchain, 34 | _tx: &mut SortitionHandleTx, 35 | ) -> Result<(), op_error> { 36 | // good to go! 37 | Ok(()) 38 | } 39 | 40 | #[cfg(test)] 41 | pub fn set_burn_height(&mut self, _height: u64) {} 42 | } 43 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/register_asset.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::Error as op_error; 4 | use crate::chainstate::burn::operations::RegisterAssetOp; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for RegisterAssetOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::RegisterAsset { 13 | ref l1_contract_id, 14 | ref l2_contract_id, 15 | ref asset_type, 16 | } = value.event 17 | { 18 | Ok(RegisterAssetOp { 19 | txid: value.txid.clone(), 20 | // use the StacksBlockId in the L1 event as the burnchain header hash 21 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 22 | asset_type: asset_type.clone(), 23 | l1_contract_id: l1_contract_id.clone(), 24 | l2_contract_id: l2_contract_id.clone(), 25 | }) 26 | } else { 27 | Err(op_error::InvalidInput) 28 | } 29 | } 30 | } 31 | 32 | impl RegisterAssetOp { 33 | pub fn check( 34 | &self, 35 | _burnchain: &Burnchain, 36 | _tx: &mut SortitionHandleTx, 37 | ) -> Result<(), op_error> { 38 | // good to go! 39 | Ok(()) 40 | } 41 | 42 | #[cfg(test)] 43 | pub fn set_burn_height(&mut self, _height: u64) {} 44 | } 45 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/withdraw_ft.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::Error as op_error; 4 | use crate::chainstate::burn::operations::WithdrawFtOp; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for WithdrawFtOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::WithdrawFt { 13 | ref l1_contract_id, 14 | ref name, 15 | ref amount, 16 | ref recipient, 17 | } = value.event 18 | { 19 | Ok(WithdrawFtOp { 20 | txid: value.txid.clone(), 21 | // use the StacksBlockId in the L1 event as the burnchain header hash 22 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 23 | l1_contract_id: l1_contract_id.clone(), 24 | name: name.clone(), 25 | amount: amount.clone(), 26 | recipient: recipient.clone(), 27 | }) 28 | } else { 29 | Err(op_error::InvalidInput) 30 | } 31 | } 32 | } 33 | 34 | impl WithdrawFtOp { 35 | pub fn check( 36 | &self, 37 | _burnchain: &Burnchain, 38 | _tx: &mut SortitionHandleTx, 39 | ) -> Result<(), op_error> { 40 | // good to go! 41 | Ok(()) 42 | } 43 | 44 | #[cfg(test)] 45 | pub fn set_burn_height(&mut self, _height: u64) {} 46 | } 47 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/withdraw_nft.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::Error as op_error; 4 | use crate::chainstate::burn::operations::WithdrawNftOp; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for WithdrawNftOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::WithdrawNft { 13 | ref l1_contract_id, 14 | ref id, 15 | ref recipient, 16 | } = value.event 17 | { 18 | Ok(WithdrawNftOp { 19 | txid: value.txid.clone(), 20 | // use the StacksBlockId in the L1 event as the burnchain header hash 21 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 22 | l1_contract_id: l1_contract_id.clone(), 23 | id: id.clone(), 24 | recipient: recipient.clone(), 25 | }) 26 | } else { 27 | Err(op_error::InvalidInput) 28 | } 29 | } 30 | } 31 | 32 | impl WithdrawNftOp { 33 | pub fn check( 34 | &self, 35 | _burnchain: &Burnchain, 36 | _tx: &mut SortitionHandleTx, 37 | ) -> Result<(), op_error> { 38 | // good to go! 39 | Ok(()) 40 | } 41 | 42 | #[cfg(test)] 43 | pub fn set_burn_height(&mut self, _height: u64) {} 44 | } 45 | -------------------------------------------------------------------------------- /src/chainstate/burn/operations/withdraw_stx.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::{Burnchain, StacksSubnetOp, StacksSubnetOpType}; 2 | use crate::chainstate::burn::db::sortdb::SortitionHandleTx; 3 | use crate::chainstate::burn::operations::Error as op_error; 4 | use crate::chainstate::burn::operations::WithdrawStxOp; 5 | use clarity::types::chainstate::BurnchainHeaderHash; 6 | use std::convert::TryFrom; 7 | 8 | impl TryFrom<&StacksSubnetOp> for WithdrawStxOp { 9 | type Error = op_error; 10 | 11 | fn try_from(value: &StacksSubnetOp) -> Result { 12 | if let StacksSubnetOpType::WithdrawStx { 13 | ref amount, 14 | ref recipient, 15 | } = value.event 16 | { 17 | Ok(WithdrawStxOp { 18 | txid: value.txid.clone(), 19 | // use the StacksBlockId in the L1 event as the burnchain header hash 20 | burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()), 21 | amount: amount.clone(), 22 | recipient: recipient.clone(), 23 | }) 24 | } else { 25 | Err(op_error::InvalidInput) 26 | } 27 | } 28 | } 29 | 30 | impl WithdrawStxOp { 31 | pub fn check( 32 | &self, 33 | _burnchain: &Burnchain, 34 | _tx: &mut SortitionHandleTx, 35 | ) -> Result<(), op_error> { 36 | // good to go! 37 | Ok(()) 38 | } 39 | 40 | #[cfg(test)] 41 | pub fn set_burn_height(&mut self, _height: u64) {} 42 | } 43 | -------------------------------------------------------------------------------- /src/chainstate/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation 2 | // Copyright (C) 2020 Stacks Open Internet Foundation 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | use crate::util_lib::db; 18 | 19 | use crate::util_lib::db::Error as db_error; 20 | 21 | pub trait ChainstateDB { 22 | fn backup(backup_path: &String) -> Result<(), db_error>; 23 | } 24 | 25 | // needs to come _after_ the macro def above, since they both use this macro 26 | pub mod burn; 27 | pub mod coordinator; 28 | pub mod stacks; 29 | -------------------------------------------------------------------------------- /src/chainstate/stacks/events.rs: -------------------------------------------------------------------------------- 1 | use crate::burnchains::Txid; 2 | use crate::chainstate::burn::operations::BlockstackOperationType; 3 | use crate::chainstate::stacks::StacksMicroblockHeader; 4 | use crate::chainstate::stacks::StacksTransaction; 5 | use crate::codec::StacksMessageCodec; 6 | use crate::types::chainstate::StacksAddress; 7 | use clarity::vm::analysis::ContractAnalysis; 8 | use clarity::vm::costs::ExecutionCost; 9 | use clarity::vm::types::{ 10 | AssetIdentifier, PrincipalData, QualifiedContractIdentifier, StandardPrincipalData, Value, 11 | }; 12 | 13 | pub use clarity::vm::events::StacksTransactionEvent; 14 | 15 | #[derive(Debug, Clone, PartialEq)] 16 | pub enum TransactionOrigin { 17 | Stacks(StacksTransaction), 18 | Burn(BlockstackOperationType), 19 | } 20 | 21 | impl From for TransactionOrigin { 22 | fn from(o: StacksTransaction) -> TransactionOrigin { 23 | TransactionOrigin::Stacks(o) 24 | } 25 | } 26 | 27 | impl TransactionOrigin { 28 | pub fn txid(&self) -> Txid { 29 | match self { 30 | TransactionOrigin::Burn(tx) => tx.txid(), 31 | TransactionOrigin::Stacks(tx) => tx.txid(), 32 | } 33 | } 34 | pub fn serialize_to_vec(&self) -> Vec { 35 | match self { 36 | TransactionOrigin::Burn(tx) => tx.txid().as_bytes().to_vec(), 37 | TransactionOrigin::Stacks(tx) => tx.txid().as_bytes().to_vec(), 38 | } 39 | } 40 | } 41 | 42 | #[derive(Debug, Clone, PartialEq)] 43 | pub struct StacksTransactionReceipt { 44 | pub transaction: TransactionOrigin, 45 | pub events: Vec, 46 | pub post_condition_aborted: bool, 47 | pub result: Value, 48 | pub stx_burned: u128, 49 | pub contract_analysis: Option, 50 | pub execution_cost: ExecutionCost, 51 | pub microblock_header: Option, 52 | pub tx_index: u32, 53 | } 54 | -------------------------------------------------------------------------------- /src/clarity_cli_main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation 2 | // Copyright (C) 2020 Stacks Open Internet Foundation 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | #![allow(unused_imports)] 18 | #![allow(dead_code)] 19 | #![allow(non_camel_case_types)] 20 | #![allow(non_snake_case)] 21 | #![allow(non_upper_case_globals)] 22 | 23 | extern crate serde_json; 24 | extern crate subnet_lib; 25 | 26 | use std::env; 27 | use std::process; 28 | use subnet_lib::{clarity_cli as clarity, util::log}; 29 | 30 | fn main() { 31 | let argv: Vec = env::args().collect(); 32 | 33 | let result = clarity::invoke_command(&argv[0], &argv[1..]); 34 | match result { 35 | (exit_code, Some(output)) => { 36 | println!("{}", &serde_json::to_string(&output).unwrap()); 37 | process::exit(exit_code); 38 | } 39 | (exit_code, None) => { 40 | process::exit(exit_code); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/clarity_vm/mod.rs: -------------------------------------------------------------------------------- 1 | /// High level interfaces for interacting with the Clarity vm 2 | pub mod clarity; 3 | pub mod withdrawal; 4 | 5 | pub mod special; 6 | 7 | /// Stacks blockchain specific Clarity database implementations and wrappers 8 | pub mod database; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | -------------------------------------------------------------------------------- /src/clarity_vm/special.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation 2 | // Copyright (C) 2020 Stacks Open Internet Foundation 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | use clarity::vm::costs::cost_functions::ClarityCostFunction; 18 | use clarity::vm::costs::{CostTracker, MemoryConsumer}; 19 | use std::cmp; 20 | use std::convert::{TryFrom, TryInto}; 21 | 22 | use clarity::vm::contexts::{Environment, GlobalContext}; 23 | use clarity::vm::errors::Error; 24 | use clarity::vm::errors::{ 25 | CheckErrors, InterpreterError, InterpreterResult as Result, RuntimeErrorType, 26 | }; 27 | use clarity::vm::representations::{ClarityName, SymbolicExpression, SymbolicExpressionType}; 28 | use clarity::vm::types::{ 29 | BuffData, PrincipalData, QualifiedContractIdentifier, SequenceData, TupleData, TypeSignature, 30 | Value, 31 | }; 32 | 33 | use crate::chainstate::stacks::db::StacksChainState; 34 | use crate::chainstate::stacks::StacksMicroblockHeader; 35 | use crate::util_lib::boot::boot_code_id; 36 | 37 | use clarity::vm::events::{STXEventType, STXLockEventData, StacksTransactionEvent}; 38 | 39 | use stacks_common::util::hash::Hash160; 40 | 41 | use crate::vm::costs::runtime_cost; 42 | 43 | /// Handle special cases of contract-calls -- namely, those into PoX that should lock up STX 44 | pub fn handle_contract_call_special_cases( 45 | _global_context: &mut GlobalContext, 46 | _sender: Option<&PrincipalData>, 47 | _sponsor: Option<&PrincipalData>, 48 | _contract_id: &QualifiedContractIdentifier, 49 | _function_name: &str, 50 | _args: &[Value], 51 | _result: &Value, 52 | ) -> Result<()> { 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /src/clarity_vm/tests/ast.rs: -------------------------------------------------------------------------------- 1 | use crate::clarity_vm::{clarity::ClarityInstance, database::marf::MarfedKV}; 2 | use clarity::consts::CHAIN_ID_TESTNET; 3 | use clarity::vm::ast::build_ast_with_rules; 4 | use clarity::vm::test_util::{TEST_BURN_STATE_DB, TEST_HEADER_DB}; 5 | use clarity::vm::types::QualifiedContractIdentifier; 6 | use clarity::vm::ClarityVersion; 7 | use stacks_common::types::chainstate::StacksBlockId; 8 | use stacks_common::types::StacksEpochId; 9 | 10 | use crate::chainstate::stacks::index::ClarityMarfTrieId; 11 | use crate::vm::ast::ASTRules; 12 | 13 | fn dependency_edge_counting_runtime(iters: usize) -> u64 { 14 | let mut progn = "(define-private (a0) 1)".to_string(); 15 | for i in 1..iters { 16 | progn.push_str(&format!("\n(define-private (a{}) (begin", i)); 17 | for x in 0..i { 18 | progn.push_str(&format!(" (a{}) ", x)); 19 | } 20 | progn.push_str("))"); 21 | } 22 | 23 | let marf = MarfedKV::temporary(); 24 | let mut clarity_instance = ClarityInstance::new(false, CHAIN_ID_TESTNET, marf); 25 | 26 | clarity_instance 27 | .begin_test_genesis_block( 28 | &StacksBlockId::sentinel(), 29 | &StacksBlockId([0 as u8; 32]), 30 | &TEST_HEADER_DB, 31 | &TEST_BURN_STATE_DB, 32 | ) 33 | .commit_block(); 34 | 35 | let mut cost_track = clarity_instance 36 | .begin_block( 37 | &StacksBlockId([0 as u8; 32]), 38 | &StacksBlockId([1 as u8; 32]), 39 | &TEST_HEADER_DB, 40 | &TEST_BURN_STATE_DB, 41 | ) 42 | .commit_block(); 43 | 44 | let version = ClarityVersion::Clarity2; 45 | let epoch = StacksEpochId::Epoch21; 46 | build_ast_with_rules( 47 | &QualifiedContractIdentifier::transient(), 48 | &progn, 49 | &mut cost_track, 50 | version, 51 | epoch, 52 | ASTRules::PrecheckSize, 53 | ) 54 | .unwrap(); 55 | 56 | cost_track.get_total().runtime 57 | } 58 | 59 | #[test] 60 | fn test_edge_counting_runtime() { 61 | let ratio_4_8 = dependency_edge_counting_runtime(8) / dependency_edge_counting_runtime(4); 62 | let ratio_8_16 = dependency_edge_counting_runtime(16) / dependency_edge_counting_runtime(8); 63 | 64 | // this really is just testing for the non-linearity 65 | // in the runtime cost assessment (because the edge count in the dependency graph is going up O(n^2)). 66 | assert!(ratio_8_16 > ratio_4_8); 67 | } 68 | -------------------------------------------------------------------------------- /src/clarity_vm/tests/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation 2 | // Copyright (C) 2020 Stacks Open Internet Foundation 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | pub mod analysis_costs; 18 | pub mod ast; 19 | pub mod costs; 20 | pub mod epoch_switch; 21 | pub mod forking; 22 | pub mod large_contract; 23 | pub mod simple_tests; 24 | -------------------------------------------------------------------------------- /src/cost_estimates/tests/common.rs: -------------------------------------------------------------------------------- 1 | use crate::chainstate::burn::ConsensusHash; 2 | use crate::chainstate::stacks::db::{StacksEpochReceipt, StacksHeaderInfo}; 3 | use crate::chainstate::stacks::events::StacksTransactionReceipt; 4 | use clarity::vm::costs::ExecutionCost; 5 | use stacks_common::types::chainstate::TrieHash; 6 | use stacks_common::types::chainstate::{BlockHeaderHash, BurnchainHeaderHash, StacksWorkScore}; 7 | use stacks_common::util::hash::{to_hex, Hash160, MerkleTree, Sha512Trunc256Sum}; 8 | use stacks_common::util::vrf::VRFProof; 9 | 10 | use crate::chainstate::stacks::db::blocks::MessageSignatureList; 11 | use crate::chainstate::stacks::{ 12 | CoinbasePayload, StacksBlockHeader, StacksTransaction, TokenTransferMemo, TransactionAuth, 13 | TransactionContractCall, TransactionPayload, TransactionSpendingCondition, TransactionVersion, 14 | }; 15 | use crate::core::StacksEpochId; 16 | 17 | /// Make a block receipt from `tx_receipts` with some dummy values filled for test. 18 | #[cfg(test)] 19 | pub fn make_block_receipt(tx_receipts: Vec) -> StacksEpochReceipt { 20 | StacksEpochReceipt { 21 | header: StacksHeaderInfo { 22 | anchored_header: StacksBlockHeader { 23 | version: 1, 24 | total_work: StacksWorkScore { burn: 1, work: 1 }, 25 | proof: VRFProof::empty(), 26 | parent_block: BlockHeaderHash([0; 32]), 27 | parent_microblock: BlockHeaderHash([0; 32]), 28 | parent_microblock_sequence: 0, 29 | tx_merkle_root: Sha512Trunc256Sum([0; 32]), 30 | state_index_root: TrieHash([0; 32]), 31 | withdrawal_merkle_root: Sha512Trunc256Sum([0; 32]), 32 | microblock_pubkey_hash: Hash160([0; 20]), 33 | miner_signatures: MessageSignatureList::empty(), 34 | }, 35 | microblock_tail: None, 36 | stacks_block_height: 1, 37 | index_root: TrieHash([0; 32]), 38 | consensus_hash: ConsensusHash([2; 20]), 39 | burn_header_hash: BurnchainHeaderHash([1; 32]), 40 | burn_header_height: 2, 41 | burn_header_timestamp: 2, 42 | anchored_block_size: 1, 43 | withdrawal_tree: MerkleTree::empty(), 44 | }, 45 | tx_receipts, 46 | matured_rewards: vec![], 47 | matured_rewards_info: None, 48 | parent_microblocks_cost: ExecutionCost::zero(), 49 | anchored_block_cost: ExecutionCost::zero(), 50 | parent_burn_block_hash: BurnchainHeaderHash([0; 32]), 51 | parent_burn_block_height: 1, 52 | parent_burn_block_timestamp: 1, 53 | evaluated_epoch: StacksEpochId::Epoch20, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/cost_estimates/tests/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::cost_estimates::FeeRateEstimate; 2 | 3 | pub mod common; 4 | pub mod cost_estimators; 5 | pub mod fee_medians; 6 | pub mod fee_rate_fuzzer; 7 | pub mod fee_scalar; 8 | pub mod metrics; 9 | 10 | #[test] 11 | fn fee_rate_estimate_math_units() { 12 | let maximal_estimate = FeeRateEstimate { 13 | high: f64::MAX, 14 | middle: f64::MAX, 15 | low: f64::MAX, 16 | }; 17 | 18 | assert_eq!( 19 | maximal_estimate, 20 | maximal_estimate.clone() * f64::MAX, 21 | "Fee rate estimate math should saturate" 22 | ); 23 | assert_eq!( 24 | maximal_estimate, 25 | maximal_estimate.clone() + maximal_estimate.clone(), 26 | "Fee rate estimate math should saturate" 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/deps/README.md: -------------------------------------------------------------------------------- 1 | # Statically-Linked Dependencies 2 | 3 | In a bid to make this codebase safe against package churn, to minimize the 4 | number of external dependencies that need to be fetched, and to hedge against 5 | bugs in Cargo or remote hacks on crates.io, this directory will contain source 6 | snapshots of important libraries this codebase depends on. 7 | 8 | # Credits 9 | 10 | * The `bitcoin` package was produced by Andrew Poelstra (https://github.com/rust-bitcoin/rust-bitcoin). License is CC0. 11 | * The `httparse` package was produced by Sean McArthur 12 | (https://github.com/seanmonstar/httparse). License is MIT. 13 | * The `ctrlc` package was produced by Antti Keräne 14 | (https://github.com/Detegr/rust-ctrlc). License is MIT. 15 | -------------------------------------------------------------------------------- /src/deps/ctrlc/error.rs: -------------------------------------------------------------------------------- 1 | use crate::deps::ctrlc::platform; 2 | use std::fmt; 3 | 4 | /// Ctrl-C error. 5 | #[derive(Debug)] 6 | pub enum Error { 7 | /// Ctrl-C signal handler already registered. 8 | MultipleHandlers, 9 | /// Unexpected system error. 10 | System(std::io::Error), 11 | } 12 | 13 | impl Error { 14 | fn describe(&self) -> &str { 15 | match *self { 16 | Error::MultipleHandlers => "Ctrl-C signal handler already registered", 17 | Error::System(_) => "Unexpected system error", 18 | } 19 | } 20 | } 21 | 22 | impl From for Error { 23 | fn from(e: platform::Error) -> Error { 24 | let system_error = std::io::Error::new(std::io::ErrorKind::Other, e); 25 | Error::System(system_error) 26 | } 27 | } 28 | 29 | impl fmt::Display for Error { 30 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 31 | write!(f, "Ctrl-C error: {}", self.describe()) 32 | } 33 | } 34 | 35 | impl std::error::Error for Error { 36 | fn description(&self) -> &str { 37 | self.describe() 38 | } 39 | 40 | fn cause(&self) -> Option<&dyn std::error::Error> { 41 | match *self { 42 | Error::System(ref e) => Some(e), 43 | _ => None, 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/deps/ctrlc/platform/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 CtrlC developers 2 | // Licensed under the Apache License, Version 2.0 3 | // or the MIT 5 | // license , 6 | // at your option. All files in the project carrying such 7 | // notice may not be copied, modified, or distributed except 8 | // according to those terms. 9 | 10 | #[cfg(unix)] 11 | mod unix; 12 | 13 | #[cfg(windows)] 14 | mod windows; 15 | 16 | #[cfg(unix)] 17 | pub use self::unix::*; 18 | 19 | #[cfg(windows)] 20 | pub use self::windows::*; 21 | -------------------------------------------------------------------------------- /src/deps/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2020 Blockstack PBC, a public benefit corporation 2 | // Copyright (C) 2020 Stacks Open Internet Foundation 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | pub mod ctrlc; 18 | pub mod httparse; 19 | 20 | #[cfg(test)] 21 | pub mod httparse_tests; 22 | -------------------------------------------------------------------------------- /src/util_lib/boot.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryFrom; 2 | 3 | use crate::chainstate::stacks::db::StacksAccount; 4 | use crate::chainstate::stacks::{ 5 | SinglesigHashMode, SinglesigSpendingCondition, TransactionAuth, TransactionPublicKeyEncoding, 6 | TransactionSpendingCondition, 7 | }; 8 | use clarity::vm::database::STXBalance; 9 | use clarity::vm::types::{PrincipalData, QualifiedContractIdentifier}; 10 | use clarity::vm::ContractName; 11 | use stacks_common::types::chainstate::StacksAddress; 12 | use stacks_common::util::secp256k1::MessageSignature; 13 | 14 | pub fn boot_code_id(name: &str, mainnet: bool) -> QualifiedContractIdentifier { 15 | let addr = boot_code_addr(mainnet); 16 | QualifiedContractIdentifier::new( 17 | addr.into(), 18 | ContractName::try_from(name.to_string()).unwrap(), 19 | ) 20 | } 21 | 22 | pub fn boot_code_addr(mainnet: bool) -> StacksAddress { 23 | StacksAddress::burn_address(mainnet) 24 | } 25 | 26 | pub fn boot_code_tx_auth(boot_code_address: StacksAddress) -> TransactionAuth { 27 | TransactionAuth::Standard(TransactionSpendingCondition::Singlesig( 28 | SinglesigSpendingCondition { 29 | signer: boot_code_address.bytes.clone(), 30 | hash_mode: SinglesigHashMode::P2PKH, 31 | key_encoding: TransactionPublicKeyEncoding::Uncompressed, 32 | nonce: 0, 33 | tx_fee: 0, 34 | signature: MessageSignature::empty(), 35 | }, 36 | )) 37 | } 38 | 39 | pub fn boot_code_acc(boot_code_address: StacksAddress, boot_code_nonce: u64) -> StacksAccount { 40 | StacksAccount { 41 | principal: PrincipalData::Standard(boot_code_address.into()), 42 | nonce: boot_code_nonce, 43 | stx_balance: STXBalance::zero(), 44 | } 45 | } 46 | 47 | #[cfg(test)] 48 | pub fn boot_code_test_addr() -> StacksAddress { 49 | boot_code_addr(false) 50 | } 51 | -------------------------------------------------------------------------------- /src/util_lib/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | pub mod db; 3 | pub mod bloom; 4 | pub mod boot; 5 | pub mod strings; 6 | 7 | #[cfg(test)] 8 | pub mod test { 9 | use super::*; 10 | use stacks_common::util::get_epoch_time_secs; 11 | use stacks_common::util::sleep_ms; 12 | use std::panic; 13 | use std::process; 14 | use std::sync::mpsc::sync_channel; 15 | use std::thread; 16 | 17 | pub fn with_timeout(timeout_secs: u64, test_func: F) 18 | where 19 | F: FnOnce() -> () + std::marker::Send + 'static + panic::UnwindSafe, 20 | { 21 | let (sx, rx) = sync_channel(1); 22 | 23 | let t = thread::spawn(move || { 24 | let result = panic::catch_unwind(|| { 25 | test_func(); 26 | }); 27 | let _ = sx.send(result.is_ok()); 28 | }); 29 | 30 | // wait for test to finish 31 | let deadline = timeout_secs + get_epoch_time_secs(); 32 | let mut done = false; 33 | while get_epoch_time_secs() <= deadline { 34 | sleep_ms(1000); 35 | match rx.try_recv() { 36 | Ok(success) => { 37 | assert!(success); 38 | done = true; 39 | break; 40 | } 41 | Err(_) => {} 42 | } 43 | } 44 | 45 | if !done { 46 | panic!("Test timed out after {} seconds", timeout_secs); 47 | } 48 | t.join().unwrap(); 49 | } 50 | 51 | #[test] 52 | fn test_test_timeout() { 53 | with_timeout(2000000, || { 54 | eprintln!("timeout test start..."); 55 | sleep_ms(1000); 56 | eprintln!("timeout test end"); 57 | }) 58 | } 59 | 60 | #[test] 61 | #[should_panic] 62 | fn test_test_timeout_timeout() { 63 | with_timeout(1, || { 64 | eprintln!("timeout panic test start..."); 65 | sleep_ms(1000 * 1000); 66 | }) 67 | } 68 | 69 | #[test] 70 | #[should_panic] 71 | fn test_test_timeout_panic() { 72 | with_timeout(1000, || { 73 | panic!("force a panic"); 74 | }) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /stx-genesis/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stx-genesis" 3 | version = "0.1.0" 4 | authors = ["Matthew Little "] 5 | edition = "2018" 6 | resolver = "2" 7 | 8 | [dependencies] 9 | libflate = "1.0.3" 10 | 11 | [lib] 12 | name = "stx_genesis" 13 | path = "src/lib.rs" 14 | 15 | [build-dependencies] 16 | libflate = "1.0.3" 17 | sha2 = { version = "0.10" } 18 | -------------------------------------------------------------------------------- /stx-genesis/chainstate-test.txt.sha256: -------------------------------------------------------------------------------- 1 | 014402b47d53b0716402c172fa746adf308b03a826ebea91944a5eb6a304a823 -------------------------------------------------------------------------------- /stx-genesis/chainstate.txt.sha256: -------------------------------------------------------------------------------- 1 | 74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b -------------------------------------------------------------------------------- /stx-genesis/name_zonefiles-test.txt: -------------------------------------------------------------------------------- 1 | c5f5b4197c94d4561f6332160f624d728b0da8bf 2 | $ORIGIN 0.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/1A4aeTdM35rYtUoiCiV81jKwKyi1Egzb32/profile.json"\n\n 3 | 8961c32ad98df87af12b186c3d0be6ca22105936 4 | $ORIGIN 1.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/19i6q73cKHLFfZ12JmHqB6HaXZNWos2MeE/profile.json"\n\n 5 | 8ae7173b9a2f96521ba077bbcbe9b56b1cf2449f 6 | $ORIGIN 10.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/17MJkt1kfmV5SjWDeNmzjdJpawwCXn9kyY/profile.json"\n\n 7 | 3d0576cd134fa1ff8d54d8e2ef5da97f5cae36f2 8 | $ORIGIN 10x.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/1NND3tMZuSfq7TJ6cHuV2Z72ij2JnyaRoX/profile.json"\n\n 9 | 01a8c60c852b75f9c6417491ac89275fb9de774c 10 | $ORIGIN 111111111.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/17uym3RccQG97RQAETTHe32YPGAhq6A1qq/profile.json"\n\n 11 | ae34427289a8865028eb2d475dafb085060d5625 12 | $ORIGIN 123.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/1GmQ9hgopAeSinysvJzpSggSknEjJJtDkg/profile.json"\n\n 13 | c7b0bbeb92c2575a3e4a82632d8ec4b7fc86cc19 14 | $ORIGIN zinai.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/18cR3haFbmuYQVNcrCM9N1GvfPzDraQGN9/profile.json"\n\n 15 | da6a954fdf90c890966cde5ae808ca6c96082428 16 | $ORIGIN zlh.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/19QTJKJDiUuGcQaDqF3cixdEcvRffpggp4/profile.json"\n\n 17 | 578ed433dabeb24952c892d5f3fc0cd7b9844bb8 18 | $ORIGIN zone117x.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/1Nw25PemCRv24UQAcZdaj4uD11nkTCWRTE/profile.json"\n\n 19 | fa602059cb01dbe8d1885d8fc2a7c6b265c57e64 20 | $ORIGIN zumminer_crux.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://hub.cruxpay.com/1LyHVnkR3Dn227ywxEiYRRhL4AmiJF4sqJ/profile.json"\n\n 21 | f9569aa25b6325b0f2e3a5f9edb552cd98260f9b 22 | $ORIGIN zumminer_dev_crux.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://hub.cruxpay.com/15hvnWj74LiamdFnQW9PMvqnLAb6PQQnKt/profile.json"\n\n 23 | 853cd126478237bc7392e65091f7ffa5a1556a33 24 | $ORIGIN zumrai.id\n$TTL 3600\n_http._tcp IN URI 10 1 "https://gaia.blockstack.org/hub/1EPno1VcdGx89ukN2we4iVpnFtkHzw8i5d/profile.json"\n\n -------------------------------------------------------------------------------- /stx-genesis/name_zonefiles-test.txt.sha256: -------------------------------------------------------------------------------- 1 | a7082d1ad4cfbc28820120531e02fa8b318110dae82ea98d8775ffaf9df945e6 -------------------------------------------------------------------------------- /stx-genesis/name_zonefiles.txt.sha256: -------------------------------------------------------------------------------- 1 | a256860023e6e5a17e07cc647cb01fe75605ecd70a648d9608be3f635874be0e -------------------------------------------------------------------------------- /testnet/puppet-chain/.dockerignore: -------------------------------------------------------------------------------- 1 | Dockerfile 2 | target -------------------------------------------------------------------------------- /testnet/puppet-chain/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "puppet-chain" 3 | version = "0.1.0" 4 | authors = ["Ludo Galabru "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | async-h1 = "2.3.2" 9 | async-std = { version = "1.6", features = ["attributes"] } 10 | base64 = "0.12.0" 11 | http-types = "2.12" 12 | serde = "1" 13 | serde_derive = "1" 14 | serde_json = { version = "1.0", features = ["arbitrary_precision"] } 15 | toml = "0.5" 16 | rand = "0.7.2" 17 | -------------------------------------------------------------------------------- /testnet/puppet-chain/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:bullseye as builder 2 | 3 | WORKDIR /src 4 | COPY . . 5 | 6 | RUN rustup target add x86_64-unknown-linux-musl && \ 7 | apt-get update && apt-get install -y musl-tools 8 | 9 | RUN CC=musl-gcc \ 10 | CC_x86_64_unknown_linux_musl=musl-gcc \ 11 | CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc \ 12 | cargo build --release --target x86_64-unknown-linux-musl 13 | 14 | FROM alpine:latest 15 | WORKDIR / 16 | COPY --from=builder /src/target/x86_64-unknown-linux-musl/release/puppet-chain /bin/ 17 | COPY config.toml.default /etc/puppet-chain/Config.toml 18 | EXPOSE 3000 19 | CMD ["/bin/puppet-chain", "/etc/puppet-chain/Config.toml"] 20 | -------------------------------------------------------------------------------- /testnet/puppet-chain/README.md: -------------------------------------------------------------------------------- 1 | # Puppet chain 2 | 3 | ## Getting started 4 | 5 | ```bash 6 | $ cat helium.conf 7 | chain=regtest 8 | disablewallet=0 9 | txindex=1 10 | server=1 11 | rpcuser=helium-node 12 | rpcpassword=secret 13 | 14 | // Start bitcoind 15 | $ bitcoind -conf=helium.conf 16 | 17 | // Start puppet-chain 18 | $ DYNAMIC_GENESIS_TIMESTAMP=1 cargo run local-leader.toml.default 19 | ``` 20 | 21 | ## Setup block range config 22 | 23 | With the following config: 24 | 25 | ``` 26 | [[blocks]] 27 | count = 1 28 | block_time = 20000 29 | ignore_txs = false 30 | 31 | [[blocks]] 32 | count = 2 33 | block_time = 1000 34 | ignore_txs = true 35 | 36 | 37 | [[blocks]] 38 | count = 10 39 | block_time = 30000 40 | ignore_txs = false 41 | 42 | ``` 43 | 44 | **Puppet-chain** will: 45 | 1) mine 1 block, forward all incoming transactions during the next 20 seconds, then 46 | 2) mine 1 block, buffer submitted transactions and wait 1 second, 47 | 3) mine 1 block, buffer submitted transactions and wait 1 second, 48 | 4) mine 1 block, submit all the transactions received during 2) and 3) and wait 30 seconds, 49 | ... 50 | -------------------------------------------------------------------------------- /testnet/puppet-chain/config.toml.default: -------------------------------------------------------------------------------- 1 | [network] 2 | rpc_bind = "0.0.0.0:18443" 3 | block_time = 7000 4 | miner_address = "mx2uds6sgnn9znABQ6iDSSmXY9K5D4SHF9" 5 | faucet_address = "n2pGfZaAVztWqFzuy8iLS3VSuHB2SimWUR" 6 | bitcoind_rpc_host = "127.0.0.1:18443" 7 | bitcoind_rpc_user = "helium-node" 8 | bitcoind_rpc_pass = "secret" 9 | genesis_timestamp = 1588615296 10 | whitelisted_rpc_calls = [ 11 | "listunspent", 12 | "importaddress", 13 | "sendrawtransaction", 14 | "getrawtransaction", 15 | "scantxoutset", 16 | "getrawmempool", 17 | "getblockhash", 18 | ] -------------------------------------------------------------------------------- /testnet/puppet-chain/local-leader.toml.default: -------------------------------------------------------------------------------- 1 | [network] 2 | rpc_bind = "0.0.0.0:28443" 3 | block_time = 30000 4 | miner_address = "mtFzK54XtpktHj7fKonFExEPEGkUMsiXdy" 5 | faucet_address = "mrzLDS7LT3otAnpiRWGYkWipdnAZJaXAZQ" 6 | bitcoind_rpc_host = "127.0.0.1:18443" 7 | bitcoind_rpc_user = "helium-node" 8 | bitcoind_rpc_pass = "secret" 9 | genesis_timestamp = 1590765126 10 | whitelisted_rpc_calls = [ 11 | "listunspent", 12 | "importaddress", 13 | "sendrawtransaction", 14 | "getrawtransaction", 15 | "scantxoutset", 16 | "getrawmempool", 17 | "getblockhash", 18 | ] 19 | 20 | [[blocks]] 21 | count = 1 22 | block_time = 10000 23 | ignore_txs = false 24 | 25 | [[blocks]] 26 | count = 3 27 | block_time = 20000 28 | ignore_txs = false 29 | 30 | [[blocks]] 31 | count = 2 32 | block_time = 1000 33 | ignore_txs = true 34 | 35 | [[blocks]] 36 | count = 3 37 | block_time = 20000 38 | ignore_txs = true 39 | 40 | [[blocks]] 41 | count = 2 42 | block_time = 1000 43 | ignore_txs = true 44 | 45 | [[blocks]] 46 | count = 3 47 | block_time = 20000 48 | ignore_txs = false 49 | 50 | [[blocks]] 51 | count = 2 52 | block_time = 1000 53 | ignore_txs = true 54 | 55 | [[blocks]] 56 | count = 3 57 | block_time = 20000 58 | ignore_txs = false 59 | 60 | [[blocks]] 61 | count = 2 62 | block_time = 1000 63 | ignore_txs = true 64 | 65 | [[blocks]] 66 | count = 3 67 | block_time = 20000 68 | ignore_txs = false 69 | 70 | [[blocks]] 71 | count = 2 72 | block_time = 1000 73 | ignore_txs = true 74 | 75 | 76 | 77 | # Faucet: 78 | # Private Key cTYqAVPS7uJTAcxyzkXWjmRGoCjkPcb38wZVRjyXov1RiRDWPQj3 79 | # Public Key 02327e09dc18fee1d51fe2b19b487e01eba4e6adcb325bf102213fce7bbdcde6bd 80 | # Address n3k15aVS4rEWhVYn4YfAFjD8Em5mmsducg 81 | # Format p2pkh 82 | # Network testnet 83 | # Compressed true -------------------------------------------------------------------------------- /testnet/stacks-node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subnet-node" 3 | version = "0.4.0" 4 | authors = ["Ludo Galabru "] 5 | edition = "2021" 6 | resolver = "2" 7 | 8 | [dependencies] 9 | lazy_static = "1.4.0" 10 | pico-args = "0.3.1" 11 | rand = "0.7.3" 12 | serde = "1" 13 | serde_derive = "1" 14 | serde_json = { version = "1.0", features = ["arbitrary_precision", "raw_value"] } 15 | stacks = { package = "stacks-subnets", path = "../../." } 16 | stx_genesis = { package = "stx-genesis", path = "../../stx-genesis/."} 17 | toml = "0.5.6" 18 | async-h1 = "2.3.2" 19 | async-std = { version = "1.6", features = ["attributes"] } 20 | http-types = "2.12" 21 | base64 = "0.12.0" 22 | backtrace = "0.3.50" 23 | libc = "0.2" 24 | slog = { version = "2.5.2", features = [ "max_level_trace" ] } 25 | clarity = { git = "https://github.com/stacks-network/stacks-blockchain.git", tag = "2.4.0.0.0" } 26 | stacks-common = { git = "https://github.com/stacks-network/stacks-blockchain.git", tag = "2.4.0.0.0" } 27 | # clarity = { package = "clarity", path = "../../../stacks-blockchain-develop/clarity" } 28 | # stacks-common = { package = "stacks-common", path = "../stacks-blockchain-develop/stacks-common" } 29 | tokio = { version = "=1.15.0", features = ["full"] } 30 | warp = "0.3" 31 | 32 | [dependencies.reqwest] 33 | version = "0.11.9" 34 | default-features = false 35 | features = ["blocking", "json", "rustls-tls"] 36 | 37 | [dependencies.rusqlite] 38 | version = "=0.24.2" 39 | features = ["blob", "serde_json", "i128_blob", "bundled", "trace"] 40 | 41 | [dev-dependencies] 42 | ring = "0.16.19" 43 | 44 | [dev-dependencies.rusqlite] 45 | version = "=0.24.2" 46 | features = ["blob", "serde_json", "i128_blob", "bundled", "trace"] 47 | 48 | [[bin]] 49 | name = "subnet-node" 50 | path = "src/main.rs" 51 | 52 | [features] 53 | monitoring_prom = ["stacks/monitoring_prom"] 54 | slog_json = ["stacks/slog_json", "stacks-common/slog_json", "clarity/slog_json"] 55 | prod-genesis-chainstate = [] 56 | default = [] 57 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/local-follower-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | rpc_bind = "127.0.0.1:30443" 3 | p2p_bind = "127.0.0.1:30444" 4 | bootstrap_node = "04ee0b1602eb18fef7986887a7e8769a30c9df981d33c8380d255edef003abdcd243a0eb74afdf6740e6c423e62aec631519a24cf5b1d62bf8a3e06ddc695dcb77@127.0.0.1:20444" 5 | pox_sync_sample_secs = 10 6 | wait_time_for_microblocks = 0 7 | 8 | [burnchain] 9 | chain = "bitcoin" 10 | mode = "krypton" 11 | peer_host = "127.0.0.1" 12 | rpc_port = 18443 13 | peer_port = 18444 14 | 15 | # Used for sending events to a local stacks-blockchain-api service 16 | # [[events_observer]] 17 | # endpoint = "localhost:3700" 18 | # retry_count = 255 19 | # events_keys = ["*"] 20 | 21 | [[ustx_balance]] 22 | # "mnemonic": "point approve language letter cargo rough similar wrap focus edge polar task olympic tobacco cinnamon drop lawn boring sort trade senior screen tiger climb", 23 | # "privateKey": "539e35c740079b79f931036651ad01f76d8fe1496dbd840ba9e62c7e7b355db001", 24 | # "btcAddress": "n1htkoYKuLXzPbkn9avC2DJxt7X85qVNCK", 25 | address = "ST3EQ88S02BXXD0T5ZVT3KW947CRMQ1C6DMQY8H19" 26 | amount = 100000000000000 27 | 28 | [[ustx_balance]] 29 | # "mnemonic": "laugh capital express view pull vehicle cluster embark service clerk roast glance lumber glove purity project layer lyrics limb junior reduce apple method pear", 30 | # "privateKey": "075754fb099a55e351fe87c68a73951836343865cd52c78ae4c0f6f48e234f3601", 31 | # "btcAddress": "n2ZGZ7Zau2Ca8CLHGh11YRnLw93b4ufsDR", 32 | address = "ST3KCNDSWZSFZCC6BE4VA9AXWXC9KEB16FBTRK36T" 33 | amount = 100000000000000 34 | 35 | [[ustx_balance]] 36 | # "mnemonic": "level garlic bean design maximum inhale daring alert case worry gift frequent floor utility crowd twenty burger place time fashion slow produce column prepare", 37 | # "privateKey": "374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001", 38 | # "btcAddress": "mhY4cbHAFoXNYvXdt82yobvVuvR6PHeghf", 39 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 40 | amount = 100000000000000 41 | 42 | [[ustx_balance]] 43 | # "mnemonic": "drop guess similar uphold alarm remove fossil riot leaf badge lobster ability mesh parent lawn today student olympic model assault syrup end scorpion lab", 44 | # "privateKey": "26f235698d02803955b7418842affbee600fc308936a7ca48bf5778d1ceef9df01", 45 | # "btcAddress": "mkEDDqbELrKYGUmUbTAyQnmBAEz4V1MAro", 46 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 47 | amount = 100000000000000 48 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/local-leader-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | rpc_bind = "127.0.0.1:20443" 3 | p2p_bind = "127.0.0.1:20444" 4 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 5 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | miner = true 7 | prometheus_bind = "127.0.0.1:4000" 8 | pox_sync_sample_secs = 10 9 | wait_time_for_microblocks = 0 10 | 11 | [burnchain] 12 | chain = "bitcoin" 13 | mode = "krypton" 14 | peer_host = "127.0.0.1" 15 | rpc_port = 18443 16 | peer_port = 18444 17 | 18 | [[ustx_balance]] 19 | # "mnemonic": "point approve language letter cargo rough similar wrap focus edge polar task olympic tobacco cinnamon drop lawn boring sort trade senior screen tiger climb", 20 | # "privateKey": "539e35c740079b79f931036651ad01f76d8fe1496dbd840ba9e62c7e7b355db001", 21 | # "btcAddress": "n1htkoYKuLXzPbkn9avC2DJxt7X85qVNCK", 22 | address = "ST3EQ88S02BXXD0T5ZVT3KW947CRMQ1C6DMQY8H19" 23 | amount = 100000000000000 24 | 25 | [[ustx_balance]] 26 | # "mnemonic": "laugh capital express view pull vehicle cluster embark service clerk roast glance lumber glove purity project layer lyrics limb junior reduce apple method pear", 27 | # "privateKey": "075754fb099a55e351fe87c68a73951836343865cd52c78ae4c0f6f48e234f3601", 28 | # "btcAddress": "n2ZGZ7Zau2Ca8CLHGh11YRnLw93b4ufsDR", 29 | address = "ST3KCNDSWZSFZCC6BE4VA9AXWXC9KEB16FBTRK36T" 30 | amount = 100000000000000 31 | 32 | [[ustx_balance]] 33 | # "mnemonic": "level garlic bean design maximum inhale daring alert case worry gift frequent floor utility crowd twenty burger place time fashion slow produce column prepare", 34 | # "privateKey": "374b6734eaff979818c5f1367331c685459b03b1a2053310906d1408dc928a0001", 35 | # "btcAddress": "mhY4cbHAFoXNYvXdt82yobvVuvR6PHeghf", 36 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 37 | amount = 100000000000000 38 | 39 | [[ustx_balance]] 40 | # "mnemonic": "drop guess similar uphold alarm remove fossil riot leaf badge lobster ability mesh parent lawn today student olympic model assault syrup end scorpion lab", 41 | # "privateKey": "26f235698d02803955b7418842affbee600fc308936a7ca48bf5778d1ceef9df01", 42 | # "btcAddress": "mkEDDqbELrKYGUmUbTAyQnmBAEz4V1MAro", 43 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 44 | amount = 100000000000000 45 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/mainnet-follower-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444" 6 | 7 | [burnchain] 8 | chain = "bitcoin" 9 | mode = "mainnet" 10 | peer_host = "bitcoind.stacks.co" 11 | username = "blockstack" 12 | password = "blockstacksystem" 13 | rpc_port = 8332 14 | peer_port = 8333 15 | 16 | # Used for sending events to a local stacks-blockchain-api service 17 | # [[events_observer]] 18 | # endpoint = "localhost:3700" 19 | # retry_count = 255 20 | # events_keys = ["*"] 21 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/mainnet-miner-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | seed = "" 6 | local_peer_seed = "" 7 | miner = true 8 | bootstrap_node = "02da7a464ac770ae8337a343670778b93410f2f3fef6bea98dd1c3e9224459d36b@seed-0.mainnet.stacks.co:20444,02afeae522aab5f8c99a00ddf75fbcb4a641e052dd48836408d9cf437344b63516@seed-1.mainnet.stacks.co:20444,03652212ea76be0ed4cd83a25c06e57819993029a7b9999f7d63c36340b34a4e62@seed-2.mainnet.stacks.co:20444" 9 | 10 | [burnchain] 11 | chain = "bitcoin" 12 | mode = "mainnet" 13 | peer_host = "127.0.0.1" 14 | username = "" 15 | password = "" 16 | rpc_port = 8332 17 | peer_port = 8333 18 | satoshis_per_byte = 100 19 | burn_fee_cap = 20000 20 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/mocknet-follower-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | bootstrap_node = "04ee0b1602eb18fef7986887a7e8769a30c9df981d33c8380d255edef003abdcd243a0eb74afdf6740e6c423e62aec631519a24cf5b1d62bf8a3e06ddc695dcb77@127.0.0.1:20444" 6 | wait_time_for_microblocks = 10000 7 | use_test_genesis_chainstate = true 8 | 9 | [burnchain] 10 | chain = "bitcoin" 11 | mode = "mocknet" 12 | 13 | # Used for sending events to a local stacks-blockchain-api service 14 | # [[events_observer]] 15 | # endpoint = "localhost:3700" 16 | # retry_count = 255 17 | # events_keys = ["*"] 18 | 19 | [[ustx_balance]] 20 | address = "ST3EQ88S02BXXD0T5ZVT3KW947CRMQ1C6DMQY8H19" 21 | amount = 100000000000000 22 | 23 | [[ustx_balance]] 24 | address = "ST3KCNDSWZSFZCC6BE4VA9AXWXC9KEB16FBTRK36T" 25 | amount = 100000000000000 26 | 27 | [[ustx_balance]] 28 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 29 | amount = 100000000000000 30 | 31 | [[ustx_balance]] 32 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 33 | amount = 100000000000000 34 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/mocknet-miner-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:30443" 4 | p2p_bind = "0.0.0.0:30444" 5 | seed = "0000000000000000000000000000000000000000000000000000000000000000" 6 | local_peer_seed = "0000000000000000000000000000000000000000000000000000000000000000" 7 | miner = true 8 | use_test_genesis_chainstate = true 9 | 10 | [burnchain] 11 | chain = "bitcoin" 12 | mode = "mocknet" 13 | 14 | [[ustx_balance]] 15 | address = "ST3EQ88S02BXXD0T5ZVT3KW947CRMQ1C6DMQY8H19" 16 | amount = 100000000000000 17 | 18 | [[ustx_balance]] 19 | address = "ST3KCNDSWZSFZCC6BE4VA9AXWXC9KEB16FBTRK36T" 20 | amount = 100000000000000 21 | 22 | [[ustx_balance]] 23 | address = "STB2BWB0K5XZGS3FXVTG3TKS46CQVV66NAK3YVN8" 24 | amount = 100000000000000 25 | 26 | [[ustx_balance]] 27 | address = "STSTW15D618BSZQB85R058DS46THH86YQQY6XCB7" 28 | amount = 100000000000000 29 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | scrape_configs: 5 | - job_name: 'prometheus' 6 | static_configs: 7 | - targets: ['127.0.0.1:9090'] 8 | - job_name: 'stacks-node-leader' 9 | static_configs: 10 | - targets: ['127.0.0.1:4000'] 11 | - job_name: 'stacks-node-follower' 12 | static_configs: 13 | - targets: ['127.0.0.1:5000'] 14 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/regtest-follower-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | bootstrap_node = "048dd4f26101715853533dee005f0915375854fd5be73405f679c1917a5d4d16aaaf3c4c0d7a9c132a36b8c5fe1287f07dad8c910174d789eb24bdfb5ae26f5f27@regtest.stacks.co:20444" 6 | wait_time_for_microblocks = 10000 7 | 8 | [burnchain] 9 | chain = "bitcoin" 10 | mode = "krypton" 11 | peer_host = "bitcoind.regtest.stacks.co" 12 | username = "blockstack" 13 | password = "blockstacksystem" 14 | rpc_port = 18443 15 | peer_port = 18444 16 | 17 | # Used for sending events to a local stacks-blockchain-api service 18 | # [[events_observer]] 19 | # endpoint = "localhost:3700" 20 | # retry_count = 255 21 | # events_keys = ["*"] 22 | 23 | [[ustx_balance]] 24 | address = "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2" 25 | amount = 10000000000000000 26 | 27 | [[ustx_balance]] 28 | address = "ST319CF5WV77KYR1H3GT0GZ7B8Q4AQPY42ETP1VPF" 29 | amount = 10000000000000000 30 | 31 | [[ustx_balance]] 32 | address = "ST221Z6TDTC5E0BYR2V624Q2ST6R0Q71T78WTAX6H" 33 | amount = 10000000000000000 34 | 35 | [[ustx_balance]] 36 | address = "ST2TFVBMRPS5SSNP98DQKQ5JNB2B6NZM91C4K3P7B" 37 | amount = 10000000000000000 38 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/testnet-follower-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | bootstrap_node = "047435c194e9b01b3d7f7a2802d6684a3af68d05bbf4ec8f17021980d777691f1d51651f7f1d566532c804da506c117bbf79ad62eea81213ba58f8808b4d9504ad@testnet.stacks.co:20444" 6 | wait_time_for_microblocks = 10000 7 | 8 | [burnchain] 9 | chain = "bitcoin" 10 | mode = "xenon" 11 | peer_host = "bitcoind.testnet.stacks.co" 12 | username = "blockstack" 13 | password = "blockstacksystem" 14 | rpc_port = 18332 15 | peer_port = 18333 16 | 17 | # Used for sending events to a local stacks-blockchain-api service 18 | # [[events_observer]] 19 | # endpoint = "localhost:3700" 20 | # retry_count = 255 21 | # events_keys = ["*"] 22 | 23 | [[ustx_balance]] 24 | address = "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2" 25 | amount = 10000000000000000 26 | 27 | [[ustx_balance]] 28 | address = "ST319CF5WV77KYR1H3GT0GZ7B8Q4AQPY42ETP1VPF" 29 | amount = 10000000000000000 30 | 31 | [[ustx_balance]] 32 | address = "ST221Z6TDTC5E0BYR2V624Q2ST6R0Q71T78WTAX6H" 33 | amount = 10000000000000000 34 | 35 | [[ustx_balance]] 36 | address = "ST2TFVBMRPS5SSNP98DQKQ5JNB2B6NZM91C4K3P7B" 37 | amount = 10000000000000000 38 | -------------------------------------------------------------------------------- /testnet/stacks-node/conf/testnet-miner-conf.toml: -------------------------------------------------------------------------------- 1 | [node] 2 | # working_dir = "/dir/to/save/chainstate" 3 | rpc_bind = "0.0.0.0:20443" 4 | p2p_bind = "0.0.0.0:20444" 5 | seed = "" 6 | local_peer_seed = "" 7 | miner = true 8 | bootstrap_node = "047435c194e9b01b3d7f7a2802d6684a3af68d05bbf4ec8f17021980d777691f1d51651f7f1d566532c804da506c117bbf79ad62eea81213ba58f8808b4d9504ad@testnet.stacks.co:20444" 9 | wait_time_for_microblocks = 10000 10 | 11 | [burnchain] 12 | chain = "bitcoin" 13 | mode = "xenon" 14 | peer_host = "127.0.0.1" 15 | username = "" 16 | password = "" 17 | rpc_port = 18332 18 | peer_port = 18333 19 | 20 | [[ustx_balance]] 21 | address = "ST2QKZ4FKHAH1NQKYKYAYZPY440FEPK7GZ1R5HBP2" 22 | amount = 10000000000000000 23 | 24 | [[ustx_balance]] 25 | address = "ST319CF5WV77KYR1H3GT0GZ7B8Q4AQPY42ETP1VPF" 26 | amount = 10000000000000000 27 | 28 | [[ustx_balance]] 29 | address = "ST221Z6TDTC5E0BYR2V624Q2ST6R0Q71T78WTAX6H" 30 | amount = 10000000000000000 31 | 32 | [[ustx_balance]] 33 | address = "ST2TFVBMRPS5SSNP98DQKQ5JNB2B6NZM91C4K3P7B" 34 | amount = 10000000000000000 35 | -------------------------------------------------------------------------------- /testnet/stacks-node/src/burnchains/tests/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::rand::RngCore; 2 | use stacks::vm::Value as ClarityValue; 3 | use stacks::{ 4 | burnchains::{ 5 | events::{ContractEvent, NewBlock, NewBlockTxEvent, TxEventType}, 6 | Txid, 7 | }, 8 | types::chainstate::StacksBlockId, 9 | util::hash::to_hex, 10 | vm::types::{QualifiedContractIdentifier, TupleData}, 11 | }; 12 | 13 | mod commitment; 14 | pub mod db_indexer; 15 | 16 | pub fn random_sortdb_test_dir() -> String { 17 | let mut rng = rand::thread_rng(); 18 | let mut buf = [0u8; 32]; 19 | rng.fill_bytes(&mut buf); 20 | format!("/tmp/stacks-node-tests/sortdb/test-{}", to_hex(&buf)) 21 | } 22 | 23 | /// Creates a `NewBlock` using hash created as `[block_idx; 32]`, and parent hash 24 | /// `[parent_block_idx; 32]`. The `block-commit` in the underlying contract is also `[block_idx; 32]`. 25 | /// The time stamp of the created block is `block_idx`. 26 | fn make_test_new_block( 27 | block_height: u64, 28 | block_idx: u8, 29 | parent_block_idx: u8, 30 | contract_identifier: QualifiedContractIdentifier, 31 | ) -> NewBlock { 32 | let tx_event = { 33 | let mocked_txid = Txid([0; 32]); 34 | let topic = "print".into(); 35 | let value = TupleData::from_data(vec![ 36 | ( 37 | "event".into(), 38 | ClarityValue::string_ascii_from_bytes("block-commit".as_bytes().to_vec()).unwrap(), 39 | ), 40 | ( 41 | "block-commit".into(), 42 | ClarityValue::buff_from([block_idx; 32].to_vec()).unwrap(), 43 | ), 44 | ]) 45 | .expect("Should be a legal Clarity tuple") 46 | .into(); 47 | 48 | let contract_event = Some(ContractEvent { 49 | topic, 50 | contract_identifier, 51 | value, 52 | }); 53 | 54 | NewBlockTxEvent { 55 | txid: mocked_txid, 56 | event_index: 0, 57 | committed: true, 58 | event_type: TxEventType::ContractEvent, 59 | contract_event, 60 | } 61 | }; 62 | 63 | let new_block = NewBlock { 64 | block_height, 65 | burn_block_time: block_idx as u64, 66 | index_block_hash: StacksBlockId([block_idx; 32]), 67 | parent_index_block_hash: StacksBlockId([parent_block_idx; 32]), 68 | events: vec![tx_event], 69 | }; 70 | 71 | new_block 72 | } 73 | -------------------------------------------------------------------------------- /testnet/stacks-node/src/genesis_data.rs: -------------------------------------------------------------------------------- 1 | // Uses the full production genesis chainstate.txt data when compiled regularly, .e.g. `cargo build`. 2 | // Uses a small test chainstate.txt file when tests are ran regularly, .e.g. `cargo test`. 3 | // The production file can be used in tests by specifying the `prod-genesis-chainstate` feature 4 | // flag, .e.g. `cargo test --features prod-genesis-chainstate` 5 | 6 | #[cfg(any(not(test), feature = "prod-genesis-chainstate"))] 7 | pub const USE_TEST_GENESIS_CHAINSTATE: bool = false; 8 | 9 | #[cfg(all(test, not(feature = "prod-genesis-chainstate")))] 10 | pub const USE_TEST_GENESIS_CHAINSTATE: bool = true; 11 | -------------------------------------------------------------------------------- /testnet/stacks-node/src/monitoring/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_variables)] 2 | 3 | pub use stacks::monitoring::{increment_errors_emitted_counter, increment_warning_emitted_counter}; 4 | 5 | #[cfg(feature = "monitoring_prom")] 6 | mod prometheus; 7 | 8 | pub fn start_serving_monitoring_metrics(bind_address: String) { 9 | info!("Start serving prometheus metrics"); 10 | #[cfg(feature = "monitoring_prom")] 11 | prometheus::start_serving_prometheus_metrics(bind_address); 12 | } 13 | -------------------------------------------------------------------------------- /testnet/stacks-node/src/monitoring/prometheus.rs: -------------------------------------------------------------------------------- 1 | use async_std::net::{TcpListener, TcpStream}; 2 | use async_std::prelude::*; 3 | use async_std::task; 4 | use stacks::prometheus::{gather, Encoder, TextEncoder}; 5 | 6 | use http_types::{Body, Response, StatusCode}; 7 | 8 | pub fn start_serving_prometheus_metrics(bind_address: String) { 9 | let addr = bind_address.clone(); 10 | 11 | async_std::task::block_on(async { 12 | let listener = TcpListener::bind(addr) 13 | .await 14 | .expect("Prometheus monitoring: unable to bind address"); 15 | let addr = format!( 16 | "http://{}", 17 | listener 18 | .local_addr() 19 | .expect("Prometheus monitoring: unable to get addr") 20 | ); 21 | info!("Prometheus monitoring: server listening on {}", addr); 22 | 23 | let mut incoming = listener.incoming(); 24 | while let Some(stream) = incoming.next().await { 25 | let stream = match stream { 26 | Ok(stream) => stream, 27 | Err(err) => { 28 | error!( 29 | "Prometheus monitoring: unable to open socket and serve metrics - {:?}", 30 | err 31 | ); 32 | continue; 33 | } 34 | }; 35 | let addr = addr.clone(); 36 | 37 | task::spawn(async { 38 | if let Err(err) = accept(stream).await { 39 | eprintln!("{}", err); 40 | } 41 | }); 42 | } 43 | }); 44 | } 45 | 46 | async fn accept(stream: TcpStream) -> http_types::Result<()> { 47 | debug!("Handle Prometheus polling ({})", stream.peer_addr()?); 48 | async_h1::accept(stream.clone(), |_| async { 49 | let encoder = TextEncoder::new(); 50 | let metric_families = gather(); 51 | let mut buffer = vec![]; 52 | encoder.encode(&metric_families, &mut buffer).unwrap(); 53 | 54 | let mut response = Response::new(StatusCode::Ok); 55 | response.append_header("Content-Type", encoder.format_type()); 56 | response.set_body(Body::from(buffer)); 57 | 58 | Ok(response) 59 | }) 60 | .await?; 61 | Ok(()) 62 | } 63 | -------------------------------------------------------------------------------- /testnet/stacks-node/src/operations.rs: -------------------------------------------------------------------------------- 1 | use stacks::util::secp256k1::{MessageSignature, Secp256k1PrivateKey, Secp256k1PublicKey}; 2 | use stacks::{burnchains::PrivateKey, util::hash::hex_bytes}; 3 | 4 | pub struct BurnchainOpSigner { 5 | secret_key: Secp256k1PrivateKey, 6 | is_one_off: bool, 7 | is_disposed: bool, 8 | usages: u8, 9 | } 10 | 11 | impl BurnchainOpSigner { 12 | pub fn new(secret_key: Secp256k1PrivateKey, is_one_off: bool) -> BurnchainOpSigner { 13 | BurnchainOpSigner { 14 | secret_key, 15 | usages: 0, 16 | is_one_off, 17 | is_disposed: false, 18 | } 19 | } 20 | 21 | pub fn get_sk_as_wif(&self) -> String { 22 | let hex_encoded = self.secret_key.to_hex(); 23 | let mut as_bytes = hex_bytes(&hex_encoded).unwrap(); 24 | as_bytes.insert(0, 0x80); 25 | stacks::address::b58::check_encode_slice(&as_bytes) 26 | } 27 | 28 | pub fn get_sk(&self) -> &Secp256k1PrivateKey { 29 | &self.secret_key 30 | } 31 | 32 | pub fn get_sk_as_hex(&self) -> String { 33 | self.secret_key.to_hex() 34 | } 35 | 36 | pub fn get_public_key(&self) -> Secp256k1PublicKey { 37 | let public_key = Secp256k1PublicKey::from_private(&self.secret_key); 38 | public_key 39 | } 40 | 41 | pub fn sign_message(&mut self, hash: &[u8]) -> Option { 42 | if self.is_disposed { 43 | return None; 44 | } 45 | 46 | let signature = match self.secret_key.sign(hash) { 47 | Ok(r) => r, 48 | _ => return None, 49 | }; 50 | self.usages += 1; 51 | 52 | if self.is_one_off && self.usages == 1 { 53 | self.is_disposed = true; 54 | } 55 | 56 | Some(signature) 57 | } 58 | 59 | pub fn dispose(&mut self) { 60 | self.is_disposed = true; 61 | } 62 | } 63 | 64 | #[cfg(test)] 65 | mod test { 66 | use stacks::util::secp256k1::Secp256k1PrivateKey; 67 | 68 | use super::BurnchainOpSigner; 69 | 70 | #[test] 71 | fn test_wif() { 72 | let examples = [( 73 | "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D", 74 | "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", 75 | )]; 76 | for (secret_key, expected_wif) in examples.iter() { 77 | let secp_k = Secp256k1PrivateKey::from_hex(secret_key).unwrap(); 78 | let op_signer = BurnchainOpSigner::new(secp_k, false); 79 | assert_eq!(expected_wif, &op_signer.get_sk_as_wif()); 80 | } 81 | } 82 | } 83 | --------------------------------------------------------------------------------