This release contains bugfixes and improvements to the stacks-node and stacks-signer binaries, ensuring more consistent block production.
This release is compatible with chainstate directories from 4.0.x.
This release is recommended for all Stacks node and signer operators.
This release includes the following changes:
https://github.com/stacks-network/stacks-core/blob/4.0.0/CHANGELOG.md
Important ⚠️
This release includes the activation logic for the 4.0.0 hard-fork. It is compatible with prior chainstates, but after the hard-fork activation height, nodes running 4.0.0 and 3.4.x will diverge. Node operators * MUST * upgrade before the activation height.
Activation height selected is BTC block 960,230 expected to land on July 29, 2026 at around 03:00 UTC.
Added
- Clarity 6: Add variadic
concatbuilt-in - Adds two new Clarity 6 native functions:
verify-merkle-proof, which checks a Bitcoin-style merkle inclusion proof against a known root using double-SHA-256, andget-bitcoin-tx-output?, which parses a serialized Bitcoin transaction (with or without SegWit witness data) and returns the output at a given index along with the canonical, witness-stripped txid in internal byte order - Adds the ability to pause claiming of rewards in pox-5. This is an irreversable action, which can only be taken by the "pause admin", which is set initially at 4.0 activation.
- Added ed25519-verify to clarity6
- Adds a new epoch, epoch 4.0, which deploys pox-5, and a new Clarity version, Clarity 6, along with related boilerplate code.
- Complete L1 bitcoin staking integration tests, including both normal exit after the timelock expires, and early exit.
- pox-5: support seamless rollovers between bond and STX-only staking positions. A staker may now
register-for-bondfor the bond that starts immediately after their current bond ends or at the same cycle at which their STX-only staking unlocks. They can alsostakeSTX-only while their existing bond/stake is ending. In these cases, the STX lock is carried forward (amount may go up or down) with no release. sBTC for the bond is also rolled forward via net transfer (or refunded on bond → stake). These rollovers are restricted to the bond L1 unlock window (last half cycle). - Added
printevents for all interesting actions on the pox-5 contract and also improved the return values for some. - The
/v2/poxRPC response now includespox_5_sbtc_contractandpox_5_sbtc_registry_contract, the sBTC token and registry contract identifiers that this node's PoX-5 references. On mainnet these are the canonical sBTC contracts; on non-mainnet they reflect the node's configuration. - Add support to the pox-locking library for PoX-5.
- Added a private function,
transfer-from-reserveto pox-5 to allow a consensus transfer of sBTC from the reserve. - Added per-block
problematic_txsmarkers to the Nakamoto block header (Epoch 4.0+), letting miners flag transactions to skip during replay. The field is gated on a new header version, so pre-4.0 block serialization and hashes are unchanged, and the header version is now validated against the block's epoch. Until the policies are set, signers will reject any transactions in this list. - Added secp256k1-decompress? to clarity6
- Added transaction-level
StakingandPoxpost-conditions, and matching in-contractwith-staking/with-poxallowances.Stakingconstrains how much STX a principal may stake (lock for PoX) during a transaction.Poxgates the state-altering PoX-5 operations that act on a principal's existing position:unstake,unstake-sbtc,update-bond-registration, andannounce-l1-early-exit, and is presence-based (block / allow / require). Both are only valid in Stacks epoch 4.0 and later, and inDeny/Originatorpost-condition mode an uncovered stake or PoX action fails the transaction. In Clarity 6 thewith-stackingallowance was renamed towith-staking(the oldwith-stackingspelling remains valid in Clarity 4 and 5). - Updated the print event inside
register-for-bondto include the transaction info for L1 lockups.
Changed
- Added
.cost-votingdisablement gate beginning from epoch 4.0 - Updated coinbase intervals for Epoch 4.0
- Recalibrated all Clarity 6 (Epoch 4.0) runtime cost functions in
costs_5.rsusing Callgrind instruction-count measurements fromclarity-cost-bench. Arithmetic, tuple, sequence, hash, crypto, and store operations now have bench-derived linear formulas instead of forwarding to the Clarity 4 values, with a calibration baseline of 1 cost unit = 80,000 CPU instructions (a clean round value chosen to place the base overhead of any Clarity call at ≈38 units). - Doubled the Clarity read budget (
read_lengthandread_count) for Stacks Epoch 4.0 blocks, via a newBLOCK_LIMIT_MAINNET_40cost limit. All other block limit dimensions (write and runtime) remain unchanged from Epoch 2.1 onward. - Add additional Clarity value sanitization pass to function invocations in Epoch 4.0
- Contract analysis now charges the runtime cost of
AnalysisUseTraitEntrywhen a trait is resolved from the contract under analysis. This closes a metering asymmetry between the two lookup paths and applies starting with Epoch 4.0. - Allow pox-5 L1 BTC lockups to use timelock unlock heights greater than or equal to the bond's minimum L1 unlock height.
- Restructure the pox-5 L1 BTC lockup witness script: the early-exit branch now requires revealing the 32-byte
sha256(to-consensus-buff? staker)preimage alongside the early-unlock signature. - Updated the
stacks-signer generate-staking-signaturecommand to generate PoX-5 signer grant signatures. - Reduced the per-cycle
readCountcost of pox-5stake(and the other staking entry points that fold over lock cycles) by de-duplicating redundant map reads insettle-rewardsand skippingsettle-staker-rewardswhen the staker holds no shares in that cycle. A max-length (96-cycle)stakenow costs ~2,336 readCount instead of ~3,104 (~15.6% vs ~20.7% of the tenure-block budget), raising worst-case throughput from ~4 to ~6 such transactions per block. - pox-5:
announce-l1-early-exitis now callable by the staker themselves, not the bond's early-unlock admin. Theearly-unlock-adminfield is removed fromprotocol-bondsand from thesetup-bondparameter list, since no on-chain code path consumes it anymore. Re-announcing for the same bond returns the newERR_L1_EARLY_EXIT_ALREADY_ANNOUNCED. The new read-onlyhas-announced-l1-early-exitexposes per-staker announcement state for off-chain consumers and gates the re-entry assert on-chain. - Reject
unstake-sbtcandannounce-l1-early-exitcalls during a prepare phase. - The node and
stacks-signernow share a single version (stacks_node_versioninversions.toml) and ship in one combined GitHub release: one set of binary archives (containing both binaries) plus thestacks-coreandstacks-signerdocker images, all tagged with the same version. The separatestacks_signer_version, thesigner-x.x.xrelease tags, and the independentrelease/signer-x.x.xrelease path have been removed. - Use new variadic
concatin the pox-5 contract.
Fixed
- Updates to pox-5 to prevent a scenario where a bond participant could switch signers, but that switch would cause the new signer to immediately start getting rewards, even though their signing power isn't updated yet.
- Fixed an issue related to signer managers not being able to withdrawal their accumulated fees.
- Consensus now rejects blocks that contain transactions with non-normalized "high S" secp256k1 signatures. This is a requirement of SIP 005, but was never correctly implemented. This change applies starting with Epoch 4.0.
- Prevent counting duplicate lockups in pox-5
register-for-bond. - In
signer-manager.clar, the functioncheck-pox-addrwasn't used. Now, it is used to check when a staker has passed apox-addras part of their calldata. - Fixed an issue related to how current and future cycle rewards state is managed after unstaking.
- Fixed an error where there could be an arithmetic underflow if a staker claimed rewards before the signer claimed their own first. Instead, we now explicitly return an error.
- Remove the faulty
reward-cycle-to-unlock-heightfrom pox-5. - Return rejected sBTC withdrawal amounts to stakers and let admins sweep orphaned fee-refund dust in the pox-5 reference signer-manager. The admin sweep now subtracts outstanding withdrawal liability so it can never sweep funds owed to stakers, and accepted withdrawals are retired via the permissionless
settle-accepted-withdrawalto release their liability. - Handle reward cycle with no STX-only stakers (all excess rewards go to the reserve).
- In Epoch 4.0 (PoX-5), the Clarity asset map now sums concurrent stacking entries for the same principal within a transaction (both within a frame and when merging frames) instead of rejecting the block. The pre-Epoch-4.0 soft-fork behavior (rejecting PoX assetmap overwrites) is unchanged.
- Fixed PoX-5 L1 lockup CLTV height serialization so large unlock heights cannot truncate to lower Bitcoin script numbers.
- Re-check the signer key grant at every pox-5 new-stake entry point (
register-for-bond,update-bond-registration,stake,stake-update), so revoking a grant withrevoke-signer-grantnow disables an already-registered signer manager from accepting any new stake. Previously revocation only blocked futureregister-signercalls, leaving a deprecated or buggy manager free to keep accumulating delegated STX and re-enter the signer set; its existing obligations still settle and wind down as the backing bonds/stakes expire. - Fixed PoX-5 L1 lockup script construction to reject Bitcoin
CHECKLOCKTIMEVERIFYvalues that would be interpreted as Unix timestamps instead of block heights. - Allow only the signer to call
grant-signer-key. Without this check someone could grief the signer, by watching for their call toregister-selfin the mempool, grabbing thesigner-key, and then frontrunning a call togrant-signer-key, causing the signer's call to fail withERR_SIGNER_KEY_GRANT_USED. - Require that
revoke-signer-grantis called directly only, not indirectly through any contract. - Starting in Epoch 4.0, signer signatures on a Nakamoto block must be strictly ordered by the signer's index in the reward set. Previously a bug only compared each signature against the first signer's index, so only a partial ordering was enforced. The pre-Epoch-4.0 behavior is preserved for blocks validated before the activation so that historical blocks and un-upgraded peers validate identically.
- Gate the pox-5 callback functions in the sample signer-manager contract so that they can only be called directly by pox-5.
- Updates the max-fee settable by the signer to be 99.99%, to prevent accounting issues.
- Fix an off-by-one in the Clarity
mapbuilt-in over unequal-length sequences. The fix is consensus-breaking and epoch-gated, activating in Epoch 4.0. - Do not allow functions that modify the staker/signer set during the prepare phase.
- The miner-spend estimators (
get_miner_spendCLI helper andMinerStats) now model block-commit outputs using the PoX-5 waterfall single-output scheme when active, matching the relayer. - Surface cost-tracking errors raised during Clarity trait-compliance type-checking instead of masking them as
IncompatibleTrait. The fix is consensus-breaking and epoch-gated, activating in Epoch 4.0. - Fix tuple
mergeproducing an oversized value: starting in Epoch 4.0, amergewhose combined size exceeds the maximum value size is rejected cleanly withValueTooLargeat the merge site (in both static analysis and at runtime), instead of aborting the block. Behavior in earlier epochs is unchanged. - Fix
uint-to-buff-lein pox-5 contract to handle values >255 correctly. - Fix the minimum threshold reported by /v2/pox when pox-5 is the active contract.
- Tightens the Clarity 6
verify-merkle-proofbuiltin so that it rejects CVE-2012-2459-style "inflatedtx-count" forgeries that relocate the last real leaf of an odd-sized tree into the duplicated-padding region (e.g. presenting the same real Bitcoin tx as(tx-index 3, tx-count 4)against the merkle root of a 3-tx block). - Replaced
timedependency in logging code withchronoto allow it to work properly in Wasm builds.
Removed
- Removed the
allow-contract-caller,disallow-contract-caller, andcheck-caller-allowedfunctions and theallowance-contract-callersmap frompox-5. Stacking methods may now be invoked through any contract-caller; stackers protect themselves with the in-contractwith-stacking/with-poxallowances or transaction-levelStaking/Poxpost-conditions instead.
Docker images have been published to GitHub Container Registry:
stacks-core
- Debian (glibc): https://github.com/stacks-network/stacks-core/pkgs/container/stacks-core/1030102630?tag=4.0.0
docker pull ghcr.io/stacks-network/stacks-core:4.0.0@sha256:91b2c2701a425e57052baca51b30234bf9af02fa118a5a4586022e7d0ecc303f- Alpine (musl): https://github.com/stacks-network/stacks-core/pkgs/container/stacks-core/1030103121?tag=4.0.0-alpine
docker pull ghcr.io/stacks-network/stacks-core:4.0.0-alpine@sha256:c237cdbfe023be061312b0c7d20207e761df9272b926d22c3819ee295eb348bastacks-signer
- Debian (glibc): https://github.com/stacks-network/stacks-signer/pkgs/container/stacks-signer/1030102553?tag=4.0.0
docker pull ghcr.io/stacks-network/stacks-signer:4.0.0@sha256:7ee8914ccc732432206fa65d59522dee06d1d374bf201c6c9c379e385f3cdee9- Alpine (musl): https://github.com/stacks-network/stacks-signer/pkgs/container/stacks-signer/1030101387?tag=4.0.0-alpine
docker pull ghcr.io/stacks-network/stacks-signer:4.0.0-alpine@sha256:ff32d5e695055b9baaffb0f88f536319474e4f9d9e64d67bef44cd10ba23532c