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.4/CHANGELOG.md
⚠️ Breaking Changes
- Removed
reset_replay_set_after_fork_blocksandvalidate_with_replay_txconfig from signer toml. - removed
replay_transactionsconfig from miner toml. - From Epoch 4.1, versioned smart-contract deploys (the
VersionedSmartContractpayload, which pins a Clarity version) are rejected as statically invalid: deploy new contracts with the unversionedSmartContractpayload, which uses the epoch's default Clarity version (Clarity 7 in Epoch 4.1).
Added
- Added public and custom Bitcoin signet support with chain ID
0x80000001and signernetwork = "signet". Each deployment requires its own working directory. See Bitcoin signet. - Add a self-contained Docker source build with node and signer image targets, the repository toolchain, cargo-chef dependency caching, and selectable release profiles.
- Adds a new Clarity version, Clarity 7, which is the default Clarity version from Epoch 4.1, along with related boilerplate code.
- From Epoch 4.1: a public or read-only function may take a reserved name to implement a method of an
impl-trait'd trait whose Clarity version still had the name free, keeping legacy traits (e.g.slice?,stacks-block-height) implementable. Inside the contract the native keeps its meaning; the implementation is reached throughcontract-call?and trait dispatch, and a keyword-named one can also be applied directly. A function under a reserved name that matches no such method fails withNameAlreadyUsed. - From Epoch 4.1:
define-traitrejects method names that are currently reserved; only traits from a Clarity version where the name was still free can make it implementable. - Added the apparent sender to each PoX transaction in the
/new_burn_blockevent payload. - Added a stacks-marf crate
Changed
- Bumped Rust to 1.98.0
- Shrank a number of root error types through
Boxing of large variants to satisfy theclippy::result_large_errlint, which may be API-breaking for some downstream library consumers. - Accept slices and borrowed paths in Rust helper APIs and use standard conversion and formatting traits.
- Error messages (receipt
vm_error, block-proposal and signer rejection reasons, read-only callcause, Clarity diagnostics, related logs) are now clamped to 4096 bytes at construction, bounding the size of receipts, event payloads, and logs. - Tuple and list values embedded in those messages now render their contents in Clarity syntax, e.g.
Tuple((tuple (a u1)))instead ofTuple(TupleData { type_signature: ..., data_map: {...} }); the type signature is no longer included. - Cargo, Nix, and the release tooling now use
workspace.package.versioninCargo.tomlas the single node and signer release version. - Removed
versions.toml; external tooling should read the workspace package version fromCargo.toml, and thestacks-node,stacks-signer, andstacks-inspectCargo package versions, includingstacks-signer -V, now report the release version instead of placeholder values. - Remove the unused reader type parameter from
ChainsCoordinatorand the indexer argument fromChainsCoordinator::run, and update downstream callers' type annotations and calls. - Remove broad dead-code and test-only unused-code allowances, obsolete helpers, unused imports, and unused state from Clarity, restrict internal fixtures to test builds while retaining downstream test utilities, and strengthen principal, trait, parser, and contract-initialization test coverage.
- Moved Clarity transaction framing into the
claritycrate for reuse by external consumers with evaluation hooks. - Drop tx-replay behavior from signer logic.
- Drop tx-replay behaviour from node/miner
/v3/tenures/fork_infono longer returns the Nakamoto blocks of each tenure:nakamoto_blocksis now alwaysnull. The field is deprecated and will be removed in a future release.- Remove obsolete private HTTP request decoding and signal-handler code from libsigner, including its direct libc dependency, broad dead-code allowances, and redundant crate imports, while preserving block-event deserialization validation.
- The chainstate snapshot module now converts
util_lib::dberrors into MARF errors explicitly rather than through aFromimpl, in preparation for moving the MARF into its own crate. No behaviour change. - Remove the crate-wide dead-code allowance and unused Windows signal alias from stacks-common, retain C32 decoding coverage through a test-only helper, and expand named-enum macro tests to cover variant and name enumeration.
- Remove unused stackslib chainstate and core helpers and test fixtures, clean up unused imports across stackslib, scope test-only helpers to tests, and restore the PoX sunset regression test.
- Remove unused internal networking and mempool code and obsolete test helpers from stackslib.
- Replace complex Clarity callback signatures with documented aliases and return argument-check costs and results through the named ArgumentCheckOutcome type.
Fixed
- Fixed long delay between shutdown signal (Ctrl-C or SIGTERM) and actual stop while the node was working on catching up to chain tip.
clarity-cliandstacks-inspectnow print an error and exit with status 1 when a file they were asked to read is missing or unreadable, instead of panicking with a backtrace. This coversstacks-inspectcommands such asdecode-blockandpost-stackerdb, which share the same read helpers.- Fixed
replace-at?with a zero-length buffer or string element making the transaction rejectable. Starting in epoch 4.1, a statically empty element is rejected at type-check time and a runtime-empty element fails with an includable error. - Signers now honor a superseded-tenure reorg permit only for blocks on the branch the permit was granted to: the permitting tenure, or a tenure built directly on it.
- Fixed signers signing re-proposed blocks from cached validation without pre-commit and conflict checks. Post-validation checks now exclude the block itself from the local signed-tip comparison and preserve rejection reasons so transient failures can be retried.
- Apply the pox-5 overrides from the config in stacks-inspect, ensuring that block replay has the correct settings and can properly match the node's behavior in epoch 4.0+.
- Fixed Wasm signature recovery to decode
MessageSignaturein VRS order, restoring transaction, public-key, and microblock-signature verification. - Fixed
Secp256k1PublicKey::verify()on Wasm rejecting every valid signature for an uncompressed public key. - Fixed
secp256k1_verify()on Wasm accepting high-S signatures, which made Clarity'ssecp256k1-verifyreturntruein simnet for signatures that are rejected on chain. - Fixed Wasm low-S validation rejecting
s == (n - 1) / 2, the largest canonical low-S value, which the native backend accepts. - Fixed Wasm signing producing high-S signatures at the low-S boundary, preserving the recovery ID when normalizing signatures.
- Fixed Wasm public-key verification to return
Ok(false)for a key mismatch before rejecting high-S signatures, matching the native backend. - Signers now roll the reported tenure extend timestamp forward to
now + idle_timeoutwhen accepting a tenure extend block. Previously the rollover only fired on tenure start blocks, so accept responses for extend blocks carried an already-past timestamp and miners proposed the next extend early, which signers rejected withInvalidTenureExtendbefore accepting the retry.
Removed
- Removed the deprecated
.cost-votingexecution machinery following its Epoch 4.0 disablement by SIP-044.
Docker images have been published to GitHub Container Registry:
stacks-core
- Debian (glibc): https://github.com/stacks-network/stacks-core/pkgs/container/stacks-core/1286903435?tag=4.0.4
docker pull ghcr.io/stacks-network/stacks-core:4.0.4@sha256:a35bf7468139469c3da248f37396d59eed51f9c4df86a9b28df73814d13d38fa- Alpine (musl): https://github.com/stacks-network/stacks-core/pkgs/container/stacks-core/1286901654?tag=4.0.4-alpine
docker pull ghcr.io/stacks-network/stacks-core:4.0.4-alpine@sha256:40bccabe2a45168ddecde0d3e78190c1303368c6f20e511dd783bf6044d60188stacks-signer
- Debian (glibc): https://github.com/stacks-network/stacks-signer/pkgs/container/stacks-signer/1286899276?tag=4.0.4
docker pull ghcr.io/stacks-network/stacks-signer:4.0.4@sha256:af346187bc779d75daef47baaa12a0ece7fda78b5357f338d2db5536dd176608- Alpine (musl): https://github.com/stacks-network/stacks-signer/pkgs/container/stacks-signer/1286899413?tag=4.0.4-alpine
docker pull ghcr.io/stacks-network/stacks-signer:4.0.4-alpine@sha256:89a174f913c633f4312152355fa955905534f4fe351c2569a0c496191b3c5316