Reference implementation of the Stacks blockchain in Rust.
Stacks 2.0 is a layer-1 blockchain that connects to Bitcoin for security and enables decentralized apps and predictable smart contracts. Stacks 2.0 implements Proof of Transfer (PoX) mining that anchors to Bitcoin security. Leader election happens at the Bitcoin blockchain and Stacks (STX) miners write new blocks on the separate Stacks blockchain. With PoX there is no need to modify Bitcoin to enable smart contracts and apps around it. See this page for more details and resources.
Blockstack Topic/Tech | Where to learn more more |
---|---|
Stacks 2.0 | master branch |
Stacks 1.0 | legacy branch |
Use the package | our core docs |
Develop a Blockstack App | our developer docs |
Use a Blockstack App | our browser docs |
Blockstack PBC the company | our website |
Normal releases in this repository that add features such as improved RPC endpoints, improved boot-up time, new event
observer fields or event types, etc., are released on a monthly schedule. The currently staged changes for such releases
are in the develop branch. It is generally safe to run
a stacks-node
from that branch, though it has received less rigorous testing than release tags. If bugs are found in
the develop
branch, please do report them as issues on this repository.
For fixes that impact the correct functioning or liveness of the network, hotfixes may be issued. These are patches to the main branch which are backported to the develop branch after merging. These hotfixes are categorized by priority according to the following rubric:
- High Priority. Any fix for an issue that could deny service to the network as a whole, e.g., an issue where a particular kind of invalid transaction would cause nodes to stop processing requests or shut down unintentionally. Any fix for an issue that could cause honest miners to produce invalid blocks.
- Medium Priority. Any fix for an issue that could cause miners to waste funds
- Low Priority. Any fix for an issue that could deny service to individual nodes
This repository uses a 5 part version number.
X.Y.Z.A.n
X = 2 and does not change in practice unless there’s another Stacks 2.0 type event
Y increments on consensus-breaking changes
Z increments on non-consensus-breaking changes that require a fresh chainstate (akin to semantic MAJOR)
A increments on non-consensus-breaking changes that do not require a fresh chainstate, but introduce new features (akin to semantic MINOR)
n increments on patches and hot-fixes (akin to semantic PATCH)
For example, a node operator running version 2.0.10.0.0
would not need to wipe and refresh their chainstate
to upgrade to 2.0.10.1.0
or 2.0.10.0.1
. However, upgrading to 2.0.11.0.0
would require a new chainstate.
- SIP 001: Burn Election
- SIP 002: Clarity, a language for predictable smart contracts
- SIP 003: Peer Network
- SIP 004: Cryptographic Committment to Materialized Views
- SIP 005: Blocks, Transactions, and Accounts
- SIP 006: Clarity Execution Cost Assessment
- SIP 007: Stacking Consensus
- SIP 008: Clarity Parsing and Analysis Cost Assessment
Stacks improvement proposals (SIPs) are aimed at describing the implementation of the Stacks blockchain, as well as proposing improvements. They should contain concise technical specifications of features or standards and the rationale behind it. SIPs are intended to be the primary medium for proposing new features, for collecting community input on a system-wide issue, and for documenting design decisions.
See SIP 000 for more details.
The SIPs are now located in the stacksgov/sips repository as part of the Stacks Community Governance organization.
-
Krypton is a Stacks 2 testnet with a fixed, two-minute block time, called
regtest
. Regtest is generally unstable for regular use, and is reset often. See the regtest documentation for more information on using regtest. -
Xenon is the Stacks 2 public testnet, which runs PoX against the Bitcoin testnet. It is the full implementation of the Stacks 2 blockchain, and should be considered a stable testnet for developing Clarity smart contracts. See the testnet documentation for more information on the public testnet.
-
Mainnet is the fully functional Stacks 2 blockchain, see the Stacks overview for information on running a Stacks node, mining, stacking, and writing Clarity smart contracts.
The first step is to ensure that you have Rust and the support software installed.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
For building on Windows, follow the rustup installer instructions at https://rustup.rs/
From there, you can clone this repository:
git clone --depth=1 https://github.com/blockstack/stacks-blockchain.git
cd stacks-blockchain
Then build the project:
cargo build
Run the tests:
cargo test testnet -- --test-threads=1
Here, we have generated a keypair that will be used for signing the upcoming transactions:
cargo run --bin blockstack-cli generate-sk --testnet
# Output
# {
# secretKey: "b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001",
# publicKey: "02781d2d3a545afdb7f6013a8241b9e400475397516a0d0f76863c6742210539b5",
# stacksAddress: "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH"
# }
This keypair is already registered in the testnet-follower-conf.toml
file, so it can be used as presented here.
We will interact with the following simple contract kv-store
. In our examples, we will assume this contract is saved to ./kv-store.clar
:
(define-map store { key: (string-ascii 32) } { value: (string-ascii 32) })
(define-public (get-value (key (string-ascii 32)))
(match (map-get? store { key: key })
entry (ok (get value entry))
(err 0)))
(define-public (set-value (key (string-ascii 32)) (value (string-ascii 32)))
(begin
(map-set store { key: key } { value: value })
(ok true)))
We want to publish this contract on chain, then issue some transactions that interact with it by setting some keys and getting some values, so we can observe read and writes.
Our first step is to generate and sign, using your private key, the transaction that will publish the contract kv-store
.
To do that, we will use the subcommand:
cargo run --bin blockstack-cli publish --help
With the following arguments:
cargo run --bin blockstack-cli publish b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 515 0 kv-store ./kv-store.clar --testnet
The 515
is the transaction fee, denominated in microSTX. Right now, the
testnet requires one microSTX per byte minimum, and this transaction should be
less than 515 bytes.
The third argument 0
is a nonce, that must be increased monotonically with each new transaction.
This command will output the binary format of the transaction. In our case, we want to pipe this output and dump it to a file that will be used later in this tutorial.
cargo run --bin blockstack-cli publish b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 515 0 kv-store ./kv-store.clar --testnet | xxd -r -p > tx1.bin
You can observe the state machine in action locally by running:
cargo testnet start --config=./testnet/stacks-node/conf/testnet-follower-conf.toml
testnet-follower-conf.toml
is a configuration file that you can use for setting genesis balances or configuring Event observers. You can grant an address an initial account balance by adding the following entries:
[[ustx_balance]]
address = "ST2VHM28V9E5QCRD6C73215KAPSBKQGPWTEE5CMQT"
amount = 100000000
The address
field is the Stacks testnet address, and the amount
field is the
number of microSTX to grant to it in the genesis block. The addresses of the
private keys used in the tutorial below are already added.
Assuming that the testnet is running, we can publish our kv-store
contract.
In another terminal (or file explorer), you can move the tx1.bin
generated earlier, to the mempool:
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @./tx1.bin http://localhost:20443/v2/transactions
In the terminal window running the testnet, you can observe the state machine's reactions.
Now that our contract has been published on chain, let's try to submit some read / write transactions.
We will start by trying to read the value associated with the key foo
.
To do that, we will use the subcommand:
cargo run --bin blockstack-cli contract-call --help
With the following arguments:
cargo run --bin blockstack-cli contract-call b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 500 1 ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH kv-store get-value -e \"foo\" --testnet | xxd -r -p > tx2.bin
contract-call
generates and signs a contract-call transaction.
We can submit the transaction by moving it to the mempool path:
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @./tx2.bin http://localhost:20443/v2/transactions
Similarly, we can generate a transaction that would be setting the key foo
to the value bar
:
cargo run --bin blockstack-cli contract-call b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 500 2 ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH kv-store set-value -e \"foo\" -e \"bar\" --testnet | xxd -r -p > tx3.bin
And submit it by moving it to the mempool path:
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @./tx3.bin http://localhost:20443/v2/transactions
Finally, we can issue a third transaction, reading the key foo
again, for ensuring that the previous transaction has successfully updated the state machine:
cargo run --bin blockstack-cli contract-call b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001 500 3 ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH kv-store get-value -e \"foo\" --testnet | xxd -r -p > tx4.bin
And submit this last transaction by moving it to the mempool path:
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @./tx4.bin http://localhost:20443/v2/transactions
Congratulations, you can now write your own smart contracts with Clarity.
Officially supported platforms: Linux 64-bit
, MacOS 64-bit
, Windows 64-bit
.
Platforms with second-tier status (builds are provided but not tested): Linux ARMv7
, Linux ARM64
.
Beyond this Github project, Blockstack maintains a public forum and an opened Discord channel. In addition, the project maintains a mailing list which sends out community announcements.
The greater Blockstack community regularly hosts in-person meetups. The project's YouTube channel includes videos from some of these meetups, as well as video tutorials to help new users get started and help developers wrap their heads around the system's design.
For help cross-compiling on memory-constrained devices, please see the community supported documentation here: Cross Compiling.
You can learn more by visiting the Blockstack Website and checking out the documentation:
You can also read the technical papers:
- "PoX: Proof of Transfer Mining with Bitcoin", May 2020
- "The Blockstack Decentralized Computing Network", May 2019
If you have high-level questions about Blockstack, try searching our forum and start a new question if your question is not answered there.
PRs must include test coverage. However, if your PR includes large tests or tests which cannot run in parallel
(which is the default operation of the cargo test
command), these tests should be decorated with #[ignore]
.
If you add #[ignore]
tests, you should add your branch to the filters for the all_tests
job in our circle.yml
(or if you are working on net code or marf code, your branch should be named such that it matches the existing
filters there).
A test should be marked #[ignore]
if:
- It does not always pass
cargo test
in a vanilla environment (i.e., it does not need to run with--test-threads 1
). - Or, it runs for over a minute via a normal
cargo test
execution (thecargo test
command will warn if this is not the case).
This repository uses the default rustfmt formatting style. PRs will be checked against rustfmt
and will fail if not
properly formatted.
You can check the formatting locally via:
cargo fmt --all -- --check
You can automatically reformat your commit via:
cargo fmt --all
The code and documentation copyright are attributed to blockstack.org for the year of 2020.
This code is released under the GPL v3 license, and the docs are released under the Creative Commons license.