Git tag: node-1.0.1
Components
- 📦
node-1.0.1 - 🧰
toolkit-1.0.0 - ⚙️
runtime-1.0.0
Added
Upgrade ledger from 8.0.2 to 8.1.0-rc.1 (#1301) (#node)
Bumps the midnight-ledger dependency from 8.0.2 to 8.1.0-rc.1, picking up
new ledger types and conversion support.
Changed
Add regression tests for nonce/nullifier distinction in zswap serialization (#1128, PM-22025) (#toolkit)
Add unit tests verifying that serialized zswap local state uses the coin
nonce (randomness), not the nullifier (spend identifier), for the nonce
field. Addresses Least Authority Q1 2026 Node DIFF audit Issue E.
PR: #1128
JIRA: https://shielded.atlassian.net/browse/PM-22025
Redact database connection details from error logs (#1067, PM-19904) (#node)
Database connection error messages no longer include the host, port, or database name at error level. Full connection details are available at debug log level for authorized troubleshooting.
PR: #1067
JIRA: https://shielded.atlassian.net/browse/PM-19904
Implements handler for C-to-M brige (#1188) (#node, #runtime)
Updates bridge to emit events.
Updates call by adding McTxHash to each transfer.
Updates handler API: handler is expected to return a value that is attached to events.
Implements the handler in Midnight runtime.
Add validation for `networkId` on node boot to avoid mismatch with genesis state (#1265, PM-22422) (#node, #binary)
Adds validation to ensure the networkId set in the chainspec matches the
networkId used to generate the genesis state.
PR: #1265
Fix for: https://shielded.atlassian.net/browse/PM-22422
Speed up cNight db-sync observation queries (#1365) (#node)
Pre-query coarse tx / tx_out / ma_tx_out id bounds for the requested
block-range window, then constrain the four cNight observation queries
(registration, deregistration, asset create, asset spend) by primary-key
range so postgres can prune rows before doing expensive joins. Extends the
same tx.id bounding to the tx_in-keyed spend/deregistration queries.
PR: #1365
Fix DustWallet spend state propagation (#877, PM-20016) (#toolkit)
Fix DustWallet::speculative_spend to return the updated DustLocalState
alongside spends, and extend mark_spent to commit the state atomically
with nullifier recording. This ensures DustLocalState::spend's
pending_until flags are propagated, preventing utxos() from returning
already-spent outputs in consecutive spend operations.
Addresses Least Authority audit finding Issue AO.
PR: #877
JIRA: https://shielded.atlassian.net/browse/PM-20016
Align node and runtime with polkadot-stable2512-3 SDK (#1262) (#node, #runtime)
Bumps Substrate dependencies to the polkadot-stable2512-3 tag and updates call sites for breaking API changes: Core::execute_block and BlockBuilder::check_inherents now use LazyBlock; SpawnTasksParams requires tracing_execute_block (set to None unless trace RPC is wired); MmrApi v3 gains generate_ancestry_proof while BeefyApi no longer exposes it; pallet-version test mock implements Core with LazyBlock. Partner-chains and lockfiles are updated in line with the same SDK line.
Align node, runtime, relay, and partner-chains with polkadot-stable2603 SDK (#1299) (#node, #runtime, #partner-chains)
Bumps Substrate dependencies to the polkadot-stable2603 tag and updates call sites for breaking API changes:
- Workspace: All
polkadot-stable2512-3git deps moved topolkadot-stable2603;tracing-subscriberpinned to=0.3.19(required bysp-tracingon this line) with toolkit using the workspace entry. - Node:
sc_service::build_networkgainsspawn_essential_handle;new_full_parts_with_genesis_builderkeeps the six-argument signature (no Grandpa pruning filters argument—unlikenew_full_parts). - Runtime:
sp_session::SessionKeys::generate_session_keysnow takesowner: Vec<u8>and returnsOpaqueGeneratedSessionKeys; opaque keygeneratecalls pass&owner. - Partner-chains (vendored subtree): Aura
ProposerusesProposeArgs; demo node usesGrandpaPruningFilterwithnew_full_partsandspawn_essential_handle; toolkit inherent errors useDebuginstead ofsp_runtime::RuntimeDebugwhere needed. - Ledger / primitives:
RuntimeDebugderives replaced withcore::fmt::Debugwheresp_runtime::RuntimeDebug/frame_support::RuntimeDebugwere removed. - Pallets:
RuntimeDebugNoBoundreplaced withDebugNoBound(e.g. federated-authority, throttle). - Relay (BEEFY):
BeefySignatureHasherremoved;SignedCommitment::verify_signaturescalled with a single inferred authority type parameter.
Partner-chains Cargo.toml / README / changelog are aligned with the same SDK tag where applicable.
Early weight check in midnight pallet pre_dispatch (#1305) (#node)
Add an early block weight check in ValidateUnsigned::pre_dispatch before
expensive ledger validation. Substrate's Bare extrinsic path runs the pallet's
pre_dispatch before the CheckWeight extension, which means transactions that
won't fit in the block still undergo costly ledger validation before being
rejected. The new check mirrors the logic in calculate_consumed_weight and
exits early with ExhaustsResources when the block is full.
PR: #1305
Speed up toolkit syncing (#1263) (#toolkit)
Batch block-number-to-hash RPC calls into a single request instead of one call per block, reducing round trips during sync. Also simplifies several function parameters across the fetcher.
PR: #1263
📦 Node
Git tag: node-1.0.1
Docker Images
DockerHub
$ docker pull midnightntwrk/midnight-node:1.0.1Added
Add per-SQL-query Prometheus timing for midnight data source queries (#904, PM-22100) (#node)
Midnight-specific data sources (cNight observation, federated authority,
candidates) now record individual Prometheus timing histograms for each
SQL query executed against DBSync. 13 sub-query timers provide per-query
latency visibility at :9615/metrics under the
midnight_data_source_query_time_elapsed metric with query_name labels.
PR: #904
JIRA: https://shielded.atlassian.net/browse/PM-22100
Add `rpc.discover` endpoint with OpenRPC v1.4 API specification (PM-6402, #869) (#client, #node, #rpc, #api)
Registers a standards-compliant rpc.discover JSON-RPC method that returns a complete OpenRPC v1.4 document describing the node's API. Enables client code generation, request validation, and developer discoverability without reading source code.
- 16 custom Midnight methods fully documented with parameter types, return types, error definitions, and descriptions
- 52 standard Substrate methods listed as reference entries
- JSON Schema type definitions generated via
schemarsfor all RPC response types - Static
docs/openrpc.jsoncommitted for offline access - CI drift-detection tests ensure the schema stays in sync with registered methods
Jira: https://shielded.atlassian.net/browse/PM-6402
PR: #869
Point to midnightntwrk partner chains fork (#948, PM-22099) (#node)
Partner chains dependencies now reference the midnightntwrk fork instead of the upstream IOG repository, enabling independent release cadence and HF preparation.
PR: #948
JIRA: https://shielded.atlassian.net/browse/PM-22099
Changed
Add `unsafe_allow_symlinks` config option when loading files (#1372) (#node)
The new unsafe_allow_symlinks config option permits the use of symlinks when loading configuration files on node boot. Disabled by default to prevent symlink attacks.
PR: #1372
Bump vulnerable dependencies (#1079, PM-22035) (#node, #toolkit)
Update rustls-webpki 0.103.4 to 0.103.10 (RUSTSEC-2026-0049: faulty CRL
distribution point matching) and testcontainers 0.25 to 0.27, pulling
astral-tokio-tar 0.5.6 to 0.6.0 (RUSTSEC-2026-0066: insufficient PAX
extension validation).
PR: #1079
JIRA: https://shielded.atlassian.net/browse/PM-22035
Reject unsupported system transaction types (#840, PM-19971) (#audit, #client)
The get_system_tx_type function previously used a wildcard match arm that
silently labeled unrecognized SystemTransaction variants as "unknown" for
Prometheus metrics. This changes the function to return an explicit error
(SystemTransactionError::UnknownError, code 204) for unrecognized variants,
ensuring they are rejected before processing. Known variants are unaffected.
PR: #840
Ticket: https://shielded.atlassian.net/browse/PM-19971
Remove stale cost model stubs and re-enable integration test (#839, PM-19968) (#audit, #ledger)
Remove the // TODO COST MODEL: comment and #[allow(unused_variables)]
annotation left over from the original stub implementation of
get_transaction_cost, and prefix the unused block_context parameter with
an underscore. Re-enable the test_get_mn_transaction_fee integration test
that was ignored while the function was still a stub.
PR: #839
Ticket: https://shielded.atlassian.net/browse/PM-19968
Clean up Postgresql connection (#1029, PM-19924) (#node)
Add ssl_root_cert configuration option
PR: #1029
JIRA: https://shielded.atlassian.net/browse/PM-19924
Improve logging for ledger transaction errors (#961, PM-22311) (#node)
Add warning log when a transaction is malformed to aid debugging.
PR: #961
JIRA: https://shielded.atlassian.net/browse/PM-22311
Harden bot workflows against TOCTOU and expression injection (#848, PM-22117) (#ci, #security)
Fix compound TOCTOU vulnerability (M-F001) and expression injection findings (M-F002, M-F003, M-F004) in four comment-triggered bot workflows. Switch checkout from branch name to commit SHA, remove .envrc sourcing in favor of explicit EARTHLY_CONFIG, and migrate user-supplied inputs to env: block indirection.
PR: #848
Ticket: https://shielded.atlassian.net/browse/PM-22117
Bump srtool image to Rust 1.93.0 for konst 0.4.3 MSRV compatibility (#1497) (#ci)
midnight-storage-core 1.2.0-rc.3 pulled in konst 0.4.3, which raised its MSRV
to Rust 1.89. The srtool image was pinned to paritytech/srtool:1.88.0-0.18.3,
so deterministic runtime WASM builds failed at the cargo dependency check before
producing any artifact. Bumping both srtool-build and srtool-info targets to
paritytech/srtool:1.93.0-0.18.4 restores the build. The toolchain change also
shifts the deterministic build baseline — downstream consumers verifying srtool
digests should re-anchor against the new image.
PR: #1497
Cache multi_asset.id to avoid excessive joins (#934, PM-21995) (#node)
Add an in-memory cache for multi_asset.id lookups, replacing repeated JOIN multi_asset in
db-sync queries with a single cached lookup per (policy, name) pair. This eliminates the
multi_asset join from registration, deregistration, asset create/spend, and candidate token
queries, reducing query complexity and improving observation performance.
PR: #934
JIRA: https://shielded.atlassian.net/browse/PM-21995
Remaining CI/CD security hardening (permissions, data flow, actionlint) (#861, PM-22116) (#ci)
Add permissions restrictions to precompiles and actionlint workflows, remediate tainted data flow in release-image.yml.
PR: #861
Ticket: https://shielded.atlassian.net/browse/PM-22116
Use content hashes for Docker image tags (#783) (#node, #ci)
Replace 8-char commit hashes with 12-char tree content hashes in image tags.
Identical source trees now produce the same tag, allowing CI to skip redundant
builds when the tree hasn't changed (e.g. merge commits, cherry-picks, reverts).
A force_rebuild input provides an escape hatch when needed.
PR: #783
Fix chain-state truncation after unclean shutdown (#1140) (#node)
Explicitly drop the Substrate database backend after the tokio runtime shuts
down, ensuring parity-db's WAL pipeline is fully drained on SIGTERM. Without
this, leaked Arc references in aborted async tasks could prevent the Drop impl
from running, causing silent chain-state truncation on next startup.
PR: #1140
Drop ledger default storage on node shutdown (#886, PM-22219) (#ledger, #node)
Call midnight_node_ledger::drop_all_default_storage() after run_node_until_exit returns so DB-backed default storages are explicitly released during graceful shutdown.
PR: #886
Ticket: https://shielded.atlassian.net/browse/PM-22219
Default `unsafe_allow_symlinks` to `false` when missing from config (#1601) (#node)
Add #[serde(default)] to MetaCfg::unsafe_allow_symlinks so the field
falls back to false instead of producing a missing field config error
at startup. This restores compatibility for deployments running a new node
binary against an older default.toml that predates the field.
Permissions hardening across all workflow files (#855, PM-22119) (#ci)
PR: #855
Ticket: https://shielded.atlassian.net/browse/PM-22119
Reduce cNIGHT observation address logging level (#905) (#node)
Downgrade non-bech32 and no-delegation-part Cardano address logs from error to debug in cNIGHT observation data source, as these are expected for certain address types.
PR: #905
Regenerate preview genesis and chain-spec for non-empty Locked pool (#1699)
Preview's reserve and ICS genesis configs were empty (total_amount: 0),
which produced an empty Locked pool at genesis and breaks the C-to-M
bridge. Pool balances are set at genesis and cannot be changed at runtime,
so preview requires a reset. Populate the reserve and ICS configs and
regenerate the preview genesis state and chain-spec.
After the reset the Locked pool holds 16,799,999,999,126,012 STARS
(MAX_SUPPLY - reserve - treasury) and the 24,000,000,000 NIGHT supply
invariant holds.
Remove hard-fork test ledger version dependencies (#1024, PM-22109) (#node)
Remove the *-hf ledger dependencies and all cfg(hardfork_test) /
cfg(hardfork_test_rollback) conditional compilation infrastructure.
Hard-fork e2e tests no longer require building a separate node with an
older ledger version.
PR: #1024
JIRA: https://shielded.atlassian.net/browse/PM-22109
Migrate Renovate to org-wide hardened preset (#1118, SRE-2078) (#sre)
Replace interim hardening config with the shared github>midnightntwrk/renovate-config
preset. Delegates supply chain hardening (7-day cooldown, strict internal checks
filter, OSV vulnerability scanning, major version gating) to the org preset.
Retains Earthfile custom manager and git-submodules support.
PR: #1118
JIRA: https://shielded.atlassian.net/browse/SRE-2078
Slim down node Docker image by ~200 MB using multi-stage build (#897) (#node, #docker, #ci)
Multi-stage Dockerfile for the node image so gcc and the build toolchain
(gcc-c++, cmake, make, git, wget, libtool, autoconf, automake) are confined
to a builder stage and excluded from the runtime image. Only the compiled
libfaketime .so is copied across. Also removes non-deterministic
microdnf -y update (base image is pinned by digest) and pins libfaketime
to v0.9.10 so the base layer is cacheable between builds.
PR: #897
Validate genesis file type and size before reading (#832, PM-19964) (#audit)
Reject symlinks, non-regular files, and oversized files (>10 MB) before
reading genesis and configuration files in the cfg module. Addresses
Least Authority audit Issue AI (unbounded reads in Cfg::load_spec).
PR: #832
JIRA: https://shielded.atlassian.net/browse/PM-19964
⚙️ Runtime
Git tag: runtime-1.0.0
Added
Changed
Add proposal_weight_bound parameter to motion_close (#1032, PM-22326) (#runtime)
The motion_close extrinsic previously declared a constant weight that did not
account for the inner call dispatched as Root when a motion is approved.
Substrate can only refund weight post-dispatch, never increase it, so the inner
call's weight was never pre-charged. This adds a proposal_weight_bound parameter
following the pallet_collective::close pattern, ensuring the declared weight
includes the inner call's weight upfront. The extrinsic is also made
DispatchClass::Operational to match the other governance extrinsics. Toolkit and
upgrader are updated to pass the new parameter.
PR: #1032
Ticket: https://shielded.atlassian.net/browse/PM-22326
Bump midnight-ledger from 8.1.0-rc.1 to 8.1.0 (#1510) (#node)
Promotes the Ledger 8 pin from the release candidate (crate-ledger-8.1.0-rc.1)
to the final ledger-8.1.0 tag. Headline upstream changes: storage-core 1.2.0
gains an incremental garbage collector and shared-ParityDB-backend access, plus
fixes for a race condition in force_as_arc, an Sp serialization panic, a
memory leak in pending Updates, and a lock-ordering violation. midnight-ledger
itself adds finer-grained WASM wallet bindings (wallet-facing only).
All midnight-ledger workspace crates are now resolved from crates.io at their
8.1.0 release versions; the previous [patch.crates-io] block pinning them to
the ledger-8.1.0 git tag has been removed now that the 8.1.0 crates are
published.
PR: #1510
Use generated benchmark weights in runtime (#1495) (#runtime)
Connects generated runtime benchmark weights so the runtime uses measured
weights for core FRAME and local runtime pallets instead of generic defaults.
Includes GRANDPA, BEEFY MMR, timestamp, migrations, scheduler, preimage, tx-pause, council and technical committee
collectives and memberships, session validator management, federated authority
and observation, system parameters, and cNIGHT observation.
Add per-account transaction count limit to throttle pallet (#1060, PM-22377) (#runtime)
Extends the existing per-account throttle to also enforce a maximum number of transactions (MaxTxs) within each rolling block window, alongside the existing byte limit. The AccountUsage storage is migrated from a 2-field tuple to a UsageStats struct (adding txs_used). Includes a storage migration that clears the old map on upgrade.
PR: #1060
Ticket: https://shielded.atlassian.net/browse/PM-22377
Migrate from SignedExtension to TransactionExtension (#597) (#runtime)
Migrates the runtime from the deprecated SignedExtra type alias to the new
TxExtension pattern, adding AuthorizeCall and WeightReclaim extensions.
Implements the required offchain transaction creation traits
(CreateTransaction, CreateBare, CreateSignedTransaction,
CreateAuthorizedTransaction) and updates the benchmarking harness to match.
PR: #597
🧰 Toolkit
Git tag: toolkit-1.0.0
Docker Images
DockerHub
$ docker pull midnightntwrk/midnight-node-toolkit:1.0.0Added
Add `--log-json` structured logger flag, use pretty log output by default (#859, PM-22220) (#toolkit)
Default log output is now human-readable with colored level labels.
Pass --log-json to get structured JSON output for machine parsing.
PR: #859
Ticket: https://shielded.atlassian.net/browse/PM-22220
Add Cardano hard fork script for local-env (#1326) (#local-env, #cardano)
Adds a hard fork script (hardfork-pv11.sh) to advance the local Cardano
devnet from protocol version 10 to 11. Includes governance key generation,
Conway genesis patching, and automated voting across all three governance
bodies (CC, SPO, DRep).
Enable contract_custom builder for ledger 7 (#864, PM-22229) (#toolkit)
The contract_custom transaction builder now works on chains still at ledger
version 7, removing the previous "not supported for ledger 7" error.
PR: #864
JIRA: https://shielded.atlassian.net/browse/PM-22229
Add support for node `0.20.1` runtime version (PM-22050, #827) (#toolkit)
We should've already had support for this version - it was missing, this change adds it.
Ticket: https://shielded.atlassian.net/browse/PM-22050
PR: #827
Add batch-single-tx command for bulk transaction generation (#820, #939, PM-22103) (#toolkit)
New batch-single-tx subcommand that generates multiple transactions from a JSON specification file. Supports per-transfer output files and configurable concurrency, with parallel ZK proving via tokio::task::spawn_blocking.
PR:
Add show-block command to toolkit (#1068, PM-22388) (#toolkit)
Diagnostic command to inspect individual blocks — view metadata and deserialized transactions. Reads from the fetch cache first, falling back to live node RPC on cache miss. Supports human-readable and JSON output.
PR: #1068
JIRA: https://shielded.atlassian.net/browse/PM-22388
Add option when generating intents to write out the contract on-chain state (#946, PM-22230) (#toolkit)
Adds support for multiple Ledger stacks to toolkit-js.
When called from the command-line, toolkit-js will default to the latest ledger version (and consequently the associated version of Compact.js that supports it), but this can be overridden by applying the LEDGER_VERSION=d environment variable. For example, to use a Compact.js that is built against Ledger 7, set LEDGER_VERSION=7 in the environment.
PR: #946
Ticket: https://shielded.atlassian.net/browse/PM-22230
Add support for zswap state chaining (#879, PM-20404) (#toolkit)
Support for zswap state chaining in batched intents.
PR: #879
Ticket: https://shielded.atlassian.net/browse/PM-20404
Add file-based wallet and ledger state caching to toolkit (#820, #939, PM-22103) (#toolkit)
Introduces a two-tier file cache that persists ledger snapshots and per-wallet state across toolkit runs, eliminating the need to replay the full chain on every invocation. Ledger snapshots (postcard encoding, zstd-compressed, ~1.4 compression) are stored once per block height and shared across wallets; per-wallet state (postcard encoded) is keyed by seed hash. Write to .tmp, then atomic rename pattern prevents data corruption on concurrent writes on POSIX.
Includes a trusted deserialization path that computes hashes in a single bottom-up pass for self-generated cache data, bypassing the two-pass security verification and cutting deserialization time by half. Similarly, fast serialization calls serialize_to_node_list() once instead of twice cutting serialization time by half.
Stale snapshot garbage collection reads only the first 8 bytes of wallet files headers to extract block height without full deserialization.
New CLI flags: --ledger-state-db <path> to set the cache directory (default: ledger_state_db), and --fetch-only-cached for offline operation from a pre-populated cache.
PR:
Changed
Add --verbose and --quiet flags to toolkit CLI (#859, PM-22220) (#toolkit)
Added --verbose / -v (debug level) and --quiet / -q (warn level) global
flags to the toolkit CLI. Default log level is info. Per-batch fetch log messages
have been demoted from info to debug level, reducing noise while keeping high-level
progress visible.
PR: #859
Ticket: https://shielded.atlassian.net/browse/PM-22220
Bound intent file reads to 64 MB maximum size (#874) (#toolkit)
Add a file size check before reading intent files in IntentCustom::new_from_file,
rejecting files that exceed 64 MB. Prevents unbounded memory allocation from
oversized intent files.
PR: #874
Replace unchecked arithmetic in offer creation with checked operations (#942, PM-20206) (#toolkit)
Replace as i128 casts and unchecked addition in offer delta calculation and
balance accumulation with TryFrom, checked_add, and checked_sub. Overflow
or truncation now returns an explicit OfferBuildError instead of silently
producing incorrect values. Addresses Least Authority audit Issue AL.
PR: #942
JIRA: https://shielded.atlassian.net/browse/PM-20206
Replace unchecked addition in wallet seed increment with checked_add (#1081, PM-20017) (#toolkit)
Return result rather than panicing. Overflow now returns an explicit error instead
of producing a colliding seed that could lead to duplicate key derivation.
Addresses Least Authority audit Issue AL.
PR: #1081
JIRA: https://shielded.atlassian.net/browse/PM-20017
Cleanup nullifier/nonce use in fork export path and redact new_authority in CLI logging (#1074) (#toolkit)
Fix remaining nullifier/nonce use in the fork-aware export path
where the nullifier was incorrectly serialized as the nonce
in EncodedShieldedCoinInfo. This mirrors the fix from PR #895.
Also convert the maintain-contract new_authority parameter from a positional CLI
argument to a named flag (--new-authority).
PR: #1074
Remove verbose println! logging from ledger helpers (#936, PM-22084) (#audit, #toolkit)
Replace unconditional println! calls in intent.rs, transaction.rs,
and proving.rs with structured log:: macros gated by RUST_LOG.
Remove the sensitive intent structure dump that exposed privacy-critical
transaction internals to stdout.
PR: #936
Ticket: https://shielded.atlassian.net/browse/PM-22084
Propagate errors from save_intents_to_file (#873, PM-20209) (#audit, #toolkit)
save_intents_to_file previously reported success even when serialization or
file writing failed, silently producing incomplete intent files. Errors are now
propagated to callers, and any partially written files are cleaned up on failure.
PR: #873
JIRA: https://shielded.atlassian.net/browse/PM-20209
Use cryptographically secure RNG for parent block hash fallback (#878, PM-20205) (#toolkit)
Replace non-cryptographic RNG with OsRng for parent_block_hash generation in TransactionWithContext
PR: #878
Ticket: https://shielded.atlassian.net/browse/PM-20205
Replace expect calls with Result error propagation in ledger state updates (#927, PM-19977) (#toolkit, #security)
Replace expect calls in update_from_block and update_from_tx with proper Result-based error propagation to prevent panics and mutex poisoning. Addresses audit finding Issue AB.
PR: #927
JIRA: https://shielded.atlassian.net/browse/PM-19977
Clear toolkit SBOM critical and npm audit high findings on release/node-1.0.1 (#1987) (#toolkit, #security)
Backports the dependency/tooling hygiene fixes needed to make the +audit and
toolkit SBOM scan checks pass on the release/node-1.0.1 branch. These findings
are environmental (newly published advisories against stale lockfiles / a stale
bundled npm), not caused by any product code change.
- Bumped the pinned
npm install -g npm@11.11.0tonpm@11.18.0across the
Earthfile targets (toolkit-image,audit-npm,audit-yarn,fix-lock-npm).
npm 11.18.0 vendorstar@7.5.19, clearing the critical toolkit-image SBOM
finding (GHSA-23hp-3jrh-7fpw,tar@7.5.9) plus the other flagged npm-bundled
packages. Mirrors main #1919. local-environment/package-lock.json:npm audit fixclears 5 high findings
(axios, brace-expansion, form-data, js-yaml, ws). Supersedes main #1981, which
only bumped brace-expansion.util/toolkit-js/package-lock.json:npm audit fixclears postcss, undici and
ws; aviteoverride (^7.3.6, within vitest 3.2.6's existing range) clears the
remaining high without a vitest major bump.
PR: #1987
Upgrade subxt from v0.44 to v0.50 (#1229) (#toolkit, #relay)
Migrate the toolkit, upgrader, relay, and e2e tests to the subxt v0.50
block-centric API. This includes new transaction types, granular error
handling, async metadata access, and updated storage/event APIs.
Bump vitest to 3.2.6 to fix critical vulnerability blocking release image scans (#1841) (#toolkit, #security, #dependencies)
The toolkit SBOM vulnerability scan fails on GHSA-5xrq-8626-4rwp (Critical,
"When Vitest UI server is listening, arbitrary file can be read and executed")
in vitest 3.2.4, which is baked into the toolkit image via toolkit-js
devDependencies. This blocked the Publish multi-arch image job on
release/node-1.0.1, so the content-hash-tagged multi-arch manifest was never
created and the Create Release workflow failed with "image not found".
Bumps vitest 3.2.4 -> 3.2.6 (the patched release on the 3.x line).
PR: #1841
Restore long-form CLI flags for governance key arguments (#875, PM-22246)
Add --council-members and --technical-committee-members long-form flags to the runtime-upgrade and update-ledger-parameters toolkit commands. Previously only the short forms (-c, -t) were available.
PR: #875
JIRA: https://shielded.atlassian.net/browse/PM-22246
Fix missing `persist()` on context fork causing `not in arena` errors (#881, PM-22124) (#toolkit)
PR: #881
Ticket: https://shielded.atlassian.net/browse/PM-22124
Fix panic if the first block doesn't have any midnight transactions. (#1045, PM-22361) (#toolkit)
It scans all blocks instead of the first one. For an RPC source it queries get_network_id API.
PR: #1045
Ticket: https://shielded.atlassian.net/browse/PM-22361
Fix hitting recursion depth on context fork (#881, PM-22253) (#toolkit)
Toolkit now uses get_lazy rather than get to avoid loading the entire ledger state when forking the context.
PR: #881
Ticket: https://shielded.atlassian.net/browse/PM-22253
Change default cache location to `./toolkit_cache` instead of `./toolkit.db` (#939, PM-22103) (#toolkit)
This was required because we now have two separate caches - one for the fetch cache, the other for the wallet state cache.
PR: #939
Ticket: https://shielded.atlassian.net/browse/PM-22103
Add `--seeds` options to `fetch` subcommand to allow caching wallet states (#939, PM-22103) (#toolkit)
PR: #939
Ticket: https://shielded.atlassian.net/browse/PM-22103
Fix Dust address format to match the specification (#190, #1059, PM-22375) (#toolkit)
- Corrected the prefix from
dust-addrtodust(source: midnightntwrk/midnight-architecture#190) - Use
untagged_serialization(source: https://github.com/midnightntwrk/midnight-architecture/blob/main/components/WalletEngine/Specification.md#dust-address)
PR: #1059
Ticket: https://shielded.atlassian.net/browse/PM-22375
Fix using the nullifier as the nonce when encoding zswap state (#895, PM-21923) (#toolkit)
PR: #895
Ticket: https://shielded.atlassian.net/browse/PM-21923
Toolkit images are now versioned independently (#1261) (#toolkit)
The midnight-node-toolkit Docker image is now versioned from its own
util/toolkit/Cargo.toml instead of sharing the node version from
node/Cargo.toml. Release tags for toolkit-only releases use the
toolkit-X.Y.Z format.
PR: #1261
Drop `structured_logger` in favour of `tracing_subscriber`; Breaking JSON structured log format change (#899) (#toolkit)
Format now looks like:
{"timestamp":"2026-03-10T17:26:45.103688Z","level":"INFO","fields":{"message":"spawning 20 fetch workers","log.target":"midnight_node_toolkit::fetcher","log.module_path":"midnight_node_toolkit::fetcher","log.file":"util/toolkit/src/fetcher.rs","log.line":171},"target":"midnight_node_toolkit::fetcher"}
PR: #899
Support multiple shielded coin input in `single-tx`, `batch-single-tx` and `batches` (PM-22405, #1216) (#toolkit)
Multiple shielded amounts spread in coins of small values will now be combined to produce the required output amount.
Fixes: https://shielded.atlassian.net/browse/PM-22405
PR: #1216
Improve toolkit block replay and transaction generation performance (#820, #939, PM-22103) (#toolkit)
Batches state-change events during block replay for wallet initialization, using biased tokio::select! to prioritize new work from fetch workers and reduce incremental processing overhead. Adds a --replay-concurrency CLI parameter (defaults to CPU core count) and uses Rayon-based parallel wallet updates during replay.
Adds structured [perf] logging for timing instrumentation of key operations. Includes a change from BSON encoding to postcard which cuts the size of cached blocks by half and cached ledger states by ~8 and graceful failure when the wallet has insufficient DUST balance.
PRs:
Use tracing for structured log fields (#1230) (#toolkit)
Switched key-value log calls from log to tracing so structured fields
are emitted by tracing-subscriber instead of being silently dropped.
PR: #1230
Add support for fallible contract calls (PM-19839, #888) (#toolkit)
Ticket: https://shielded.atlassian.net/browse/PM-19839
PR: #888
Add support for fallible inputs (PM-22302, #966) (#toolkit)
Ticket: https://shielded.atlassian.net/browse/PM-22302
PR: #966
Fix `--verbose` flag, add `--verbose-fetch` and `--verbose-ledger`; Can override with `RUST_LOG` (#899, PM-22273) (#toolkit)
These new flags allow the user to quickly modify verbosity of toolkit components.
PR: #899
Ticket: https://shielded.atlassian.net/browse/PM-22273
Tagged Changes
#api
📦 Node
Added
Add `rpc.discover` endpoint with OpenRPC v1.4 API specification (PM-6402, #869) (#client, #node, #rpc, #api)
Registers a standards-compliant rpc.discover JSON-RPC method that returns a complete OpenRPC v1.4 document describing the node's API. Enables client code generation, request validation, and developer discoverability without reading source code.
- 16 custom Midnight methods fully documented with parameter types, return types, error definitions, and descriptions
- 52 standard Substrate methods listed as reference entries
- JSON Schema type definitions generated via
schemarsfor all RPC response types - Static
docs/openrpc.jsoncommitted for offline access - CI drift-detection tests ensure the schema stays in sync with registered methods
Jira: https://shielded.atlassian.net/browse/PM-6402
PR: #869
#audit
📦 Node
Changed
Reject unsupported system transaction types (#840, PM-19971) (#audit, #client)
The get_system_tx_type function previously used a wildcard match arm that
silently labeled unrecognized SystemTransaction variants as "unknown" for
Prometheus metrics. This changes the function to return an explicit error
(SystemTransactionError::UnknownError, code 204) for unrecognized variants,
ensuring they are rejected before processing. Known variants are unaffected.
PR: #840
Ticket: https://shielded.atlassian.net/browse/PM-19971
Remove stale cost model stubs and re-enable integration test (#839, PM-19968) (#audit, #ledger)
Remove the // TODO COST MODEL: comment and #[allow(unused_variables)]
annotation left over from the original stub implementation of
get_transaction_cost, and prefix the unused block_context parameter with
an underscore. Re-enable the test_get_mn_transaction_fee integration test
that was ignored while the function was still a stub.
PR: #839
Ticket: https://shielded.atlassian.net/browse/PM-19968
Validate genesis file type and size before reading (#832, PM-19964) (#audit)
Reject symlinks, non-regular files, and oversized files (>10 MB) before
reading genesis and configuration files in the cfg module. Addresses
Least Authority audit Issue AI (unbounded reads in Cfg::load_spec).
PR: #832
JIRA: https://shielded.atlassian.net/browse/PM-19964
🧰 Toolkit
Changed
Remove verbose println! logging from ledger helpers (#936, PM-22084) (#audit, #toolkit)
Replace unconditional println! calls in intent.rs, transaction.rs,
and proving.rs with structured log:: macros gated by RUST_LOG.
Remove the sensitive intent structure dump that exposed privacy-critical
transaction internals to stdout.
PR: #936
Ticket: https://shielded.atlassian.net/browse/PM-22084
Propagate errors from save_intents_to_file (#873, PM-20209) (#audit, #toolkit)
save_intents_to_file previously reported success even when serialization or
file writing failed, silently producing incomplete intent files. Errors are now
propagated to callers, and any partially written files are cleaned up on failure.
PR: #873
JIRA: https://shielded.atlassian.net/browse/PM-20209
#binary
Changed
Add validation for `networkId` on node boot to avoid mismatch with genesis state (#1265, PM-22422) (#node, #binary)
Adds validation to ensure the networkId set in the chainspec matches the
networkId used to generate the genesis state.
PR: #1265
Fix for: https://shielded.atlassian.net/browse/PM-22422
#cardano
🧰 Toolkit
Added
Add Cardano hard fork script for local-env (#1326) (#local-env, #cardano)
Adds a hard fork script (hardfork-pv11.sh) to advance the local Cardano
devnet from protocol version 10 to 11. Includes governance key generation,
Conway genesis patching, and automated voting across all three governance
bodies (CC, SPO, DRep).
#chainspec
📦 Node
Changed
#ci
📦 Node
Changed
Harden bot workflows against TOCTOU and expression injection (#848, PM-22117) (#ci, #security)
Fix compound TOCTOU vulnerability (M-F001) and expression injection findings (M-F002, M-F003, M-F004) in four comment-triggered bot workflows. Switch checkout from branch name to commit SHA, remove .envrc sourcing in favor of explicit EARTHLY_CONFIG, and migrate user-supplied inputs to env: block indirection.
PR: #848
Ticket: https://shielded.atlassian.net/browse/PM-22117
Bump srtool image to Rust 1.93.0 for konst 0.4.3 MSRV compatibility (#1497) (#ci)
midnight-storage-core 1.2.0-rc.3 pulled in konst 0.4.3, which raised its MSRV
to Rust 1.89. The srtool image was pinned to paritytech/srtool:1.88.0-0.18.3,
so deterministic runtime WASM builds failed at the cargo dependency check before
producing any artifact. Bumping both srtool-build and srtool-info targets to
paritytech/srtool:1.93.0-0.18.4 restores the build. The toolchain change also
shifts the deterministic build baseline — downstream consumers verifying srtool
digests should re-anchor against the new image.
PR: #1497
Remaining CI/CD security hardening (permissions, data flow, actionlint) (#861, PM-22116) (#ci)
Add permissions restrictions to precompiles and actionlint workflows, remediate tainted data flow in release-image.yml.
PR: #861
Ticket: https://shielded.atlassian.net/browse/PM-22116
Use content hashes for Docker image tags (#783) (#node, #ci)
Replace 8-char commit hashes with 12-char tree content hashes in image tags.
Identical source trees now produce the same tag, allowing CI to skip redundant
builds when the tree hasn't changed (e.g. merge commits, cherry-picks, reverts).
A force_rebuild input provides an escape hatch when needed.
PR: #783
Permissions hardening across all workflow files (#855, PM-22119) (#ci)
PR: #855
Ticket: https://shielded.atlassian.net/browse/PM-22119
Slim down node Docker image by ~200 MB using multi-stage build (#897) (#node, #docker, #ci)
Multi-stage Dockerfile for the node image so gcc and the build toolchain
(gcc-c++, cmake, make, git, wget, libtool, autoconf, automake) are confined
to a builder stage and excluded from the runtime image. Only the compiled
libfaketime .so is copied across. Also removes non-deterministic
microdnf -y update (base image is pinned by digest) and pins libfaketime
to v0.9.10 so the base layer is cacheable between builds.
PR: #897
#client
📦 Node
Added
Add `rpc.discover` endpoint with OpenRPC v1.4 API specification (PM-6402, #869) (#client, #node, #rpc, #api)
Registers a standards-compliant rpc.discover JSON-RPC method that returns a complete OpenRPC v1.4 document describing the node's API. Enables client code generation, request validation, and developer discoverability without reading source code.
- 16 custom Midnight methods fully documented with parameter types, return types, error definitions, and descriptions
- 52 standard Substrate methods listed as reference entries
- JSON Schema type definitions generated via
schemarsfor all RPC response types - Static
docs/openrpc.jsoncommitted for offline access - CI drift-detection tests ensure the schema stays in sync with registered methods
Jira: https://shielded.atlassian.net/browse/PM-6402
PR: #869
Changed
Reject unsupported system transaction types (#840, PM-19971) (#audit, #client)
The get_system_tx_type function previously used a wildcard match arm that
silently labeled unrecognized SystemTransaction variants as "unknown" for
Prometheus metrics. This changes the function to return an explicit error
(SystemTransactionError::UnknownError, code 204) for unrecognized variants,
ensuring they are rejected before processing. Known variants are unaffected.
PR: #840
Ticket: https://shielded.atlassian.net/browse/PM-19971
#dependencies
🧰 Toolkit
Changed
Bump vitest to 3.2.6 to fix critical vulnerability blocking release image scans (#1841) (#toolkit, #security, #dependencies)
The toolkit SBOM vulnerability scan fails on GHSA-5xrq-8626-4rwp (Critical,
"When Vitest UI server is listening, arbitrary file can be read and executed")
in vitest 3.2.4, which is baked into the toolkit image via toolkit-js
devDependencies. This blocked the Publish multi-arch image job on
release/node-1.0.1, so the content-hash-tagged multi-arch manifest was never
created and the Create Release workflow failed with "image not found".
Bumps vitest 3.2.4 -> 3.2.6 (the patched release on the 3.x line).
PR: #1841
#docker
📦 Node
Changed
Slim down node Docker image by ~200 MB using multi-stage build (#897) (#node, #docker, #ci)
Multi-stage Dockerfile for the node image so gcc and the build toolchain
(gcc-c++, cmake, make, git, wget, libtool, autoconf, automake) are confined
to a builder stage and excluded from the runtime image. Only the compiled
libfaketime .so is copied across. Also removes non-deterministic
microdnf -y update (base image is pinned by digest) and pins libfaketime
to v0.9.10 so the base layer is cacheable between builds.
PR: #897
#ledger
📦 Node
Changed
Remove stale cost model stubs and re-enable integration test (#839, PM-19968) (#audit, #ledger)
Remove the // TODO COST MODEL: comment and #[allow(unused_variables)]
annotation left over from the original stub implementation of
get_transaction_cost, and prefix the unused block_context parameter with
an underscore. Re-enable the test_get_mn_transaction_fee integration test
that was ignored while the function was still a stub.
PR: #839
Ticket: https://shielded.atlassian.net/browse/PM-19968
Drop ledger default storage on node shutdown (#886, PM-22219) (#ledger, #node)
Call midnight_node_ledger::drop_all_default_storage() after run_node_until_exit returns so DB-backed default storages are explicitly released during graceful shutdown.
PR: #886
Ticket: https://shielded.atlassian.net/browse/PM-22219
#local-env
🧰 Toolkit
Added
Add Cardano hard fork script for local-env (#1326) (#local-env, #cardano)
Adds a hard fork script (hardfork-pv11.sh) to advance the local Cardano
devnet from protocol version 10 to 11. Includes governance key generation,
Conway genesis patching, and automated voting across all three governance
bodies (CC, SPO, DRep).
#node
Added
Upgrade ledger from 8.0.2 to 8.1.0-rc.1 (#1301) (#node)
Bumps the midnight-ledger dependency from 8.0.2 to 8.1.0-rc.1, picking up
new ledger types and conversion support.
Changed
Redact database connection details from error logs (#1067, PM-19904) (#node)
Database connection error messages no longer include the host, port, or database name at error level. Full connection details are available at debug log level for authorized troubleshooting.
PR: #1067
JIRA: https://shielded.atlassian.net/browse/PM-19904
Implements handler for C-to-M brige (#1188) (#node, #runtime)
Updates bridge to emit events.
Updates call by adding McTxHash to each transfer.
Updates handler API: handler is expected to return a value that is attached to events.
Implements the handler in Midnight runtime.
Add validation for `networkId` on node boot to avoid mismatch with genesis state (#1265, PM-22422) (#node, #binary)
Adds validation to ensure the networkId set in the chainspec matches the
networkId used to generate the genesis state.
PR: #1265
Fix for: https://shielded.atlassian.net/browse/PM-22422
Speed up cNight db-sync observation queries (#1365) (#node)
Pre-query coarse tx / tx_out / ma_tx_out id bounds for the requested
block-range window, then constrain the four cNight observation queries
(registration, deregistration, asset create, asset spend) by primary-key
range so postgres can prune rows before doing expensive joins. Extends the
same tx.id bounding to the tx_in-keyed spend/deregistration queries.
PR: #1365
Align node and runtime with polkadot-stable2512-3 SDK (#1262) (#node, #runtime)
Bumps Substrate dependencies to the polkadot-stable2512-3 tag and updates call sites for breaking API changes: Core::execute_block and BlockBuilder::check_inherents now use LazyBlock; SpawnTasksParams requires tracing_execute_block (set to None unless trace RPC is wired); MmrApi v3 gains generate_ancestry_proof while BeefyApi no longer exposes it; pallet-version test mock implements Core with LazyBlock. Partner-chains and lockfiles are updated in line with the same SDK line.
Align node, runtime, relay, and partner-chains with polkadot-stable2603 SDK (#1299) (#node, #runtime, #partner-chains)
Bumps Substrate dependencies to the polkadot-stable2603 tag and updates call sites for breaking API changes:
- Workspace: All
polkadot-stable2512-3git deps moved topolkadot-stable2603;tracing-subscriberpinned to=0.3.19(required bysp-tracingon this line) with toolkit using the workspace entry. - Node:
sc_service::build_networkgainsspawn_essential_handle;new_full_parts_with_genesis_builderkeeps the six-argument signature (no Grandpa pruning filters argument—unlikenew_full_parts). - Runtime:
sp_session::SessionKeys::generate_session_keysnow takesowner: Vec<u8>and returnsOpaqueGeneratedSessionKeys; opaque keygeneratecalls pass&owner. - Partner-chains (vendored subtree): Aura
ProposerusesProposeArgs; demo node usesGrandpaPruningFilterwithnew_full_partsandspawn_essential_handle; toolkit inherent errors useDebuginstead ofsp_runtime::RuntimeDebugwhere needed. - Ledger / primitives:
RuntimeDebugderives replaced withcore::fmt::Debugwheresp_runtime::RuntimeDebug/frame_support::RuntimeDebugwere removed. - Pallets:
RuntimeDebugNoBoundreplaced withDebugNoBound(e.g. federated-authority, throttle). - Relay (BEEFY):
BeefySignatureHasherremoved;SignedCommitment::verify_signaturescalled with a single inferred authority type parameter.
Partner-chains Cargo.toml / README / changelog are aligned with the same SDK tag where applicable.
Early weight check in midnight pallet pre_dispatch (#1305) (#node)
Add an early block weight check in ValidateUnsigned::pre_dispatch before
expensive ledger validation. Substrate's Bare extrinsic path runs the pallet's
pre_dispatch before the CheckWeight extension, which means transactions that
won't fit in the block still undergo costly ledger validation before being
rejected. The new check mirrors the logic in calculate_consumed_weight and
exits early with ExhaustsResources when the block is full.
PR: #1305
📦 Node
Added
Add per-SQL-query Prometheus timing for midnight data source queries (#904, PM-22100) (#node)
Midnight-specific data sources (cNight observation, federated authority,
candidates) now record individual Prometheus timing histograms for each
SQL query executed against DBSync. 13 sub-query timers provide per-query
latency visibility at :9615/metrics under the
midnight_data_source_query_time_elapsed metric with query_name labels.
PR: #904
JIRA: https://shielded.atlassian.net/browse/PM-22100
Add `rpc.discover` endpoint with OpenRPC v1.4 API specification (PM-6402, #869) (#client, #node, #rpc, #api)
Registers a standards-compliant rpc.discover JSON-RPC method that returns a complete OpenRPC v1.4 document describing the node's API. Enables client code generation, request validation, and developer discoverability without reading source code.
- 16 custom Midnight methods fully documented with parameter types, return types, error definitions, and descriptions
- 52 standard Substrate methods listed as reference entries
- JSON Schema type definitions generated via
schemarsfor all RPC response types - Static
docs/openrpc.jsoncommitted for offline access - CI drift-detection tests ensure the schema stays in sync with registered methods
Jira: https://shielded.atlassian.net/browse/PM-6402
PR: #869
Point to midnightntwrk partner chains fork (#948, PM-22099) (#node)
Partner chains dependencies now reference the midnightntwrk fork instead of the upstream IOG repository, enabling independent release cadence and HF preparation.
PR: #948
JIRA: https://shielded.atlassian.net/browse/PM-22099
Changed
Add `unsafe_allow_symlinks` config option when loading files (#1372) (#node)
The new unsafe_allow_symlinks config option permits the use of symlinks when loading configuration files on node boot. Disabled by default to prevent symlink attacks.
PR: #1372
Bump vulnerable dependencies (#1079, PM-22035) (#node, #toolkit)
Update rustls-webpki 0.103.4 to 0.103.10 (RUSTSEC-2026-0049: faulty CRL
distribution point matching) and testcontainers 0.25 to 0.27, pulling
astral-tokio-tar 0.5.6 to 0.6.0 (RUSTSEC-2026-0066: insufficient PAX
extension validation).
PR: #1079
JIRA: https://shielded.atlassian.net/browse/PM-22035
Clean up Postgresql connection (#1029, PM-19924) (#node)
Add ssl_root_cert configuration option
PR: #1029
JIRA: https://shielded.atlassian.net/browse/PM-19924
Improve logging for ledger transaction errors (#961, PM-22311) (#node)
Add warning log when a transaction is malformed to aid debugging.
PR: #961
JIRA: https://shielded.atlassian.net/browse/PM-22311
Cache multi_asset.id to avoid excessive joins (#934, PM-21995) (#node)
Add an in-memory cache for multi_asset.id lookups, replacing repeated JOIN multi_asset in
db-sync queries with a single cached lookup per (policy, name) pair. This eliminates the
multi_asset join from registration, deregistration, asset create/spend, and candidate token
queries, reducing query complexity and improving observation performance.
PR: #934
JIRA: https://shielded.atlassian.net/browse/PM-21995
Use content hashes for Docker image tags (#783) (#node, #ci)
Replace 8-char commit hashes with 12-char tree content hashes in image tags.
Identical source trees now produce the same tag, allowing CI to skip redundant
builds when the tree hasn't changed (e.g. merge commits, cherry-picks, reverts).
A force_rebuild input provides an escape hatch when needed.
PR: #783
Fix chain-state truncation after unclean shutdown (#1140) (#node)
Explicitly drop the Substrate database backend after the tokio runtime shuts
down, ensuring parity-db's WAL pipeline is fully drained on SIGTERM. Without
this, leaked Arc references in aborted async tasks could prevent the Drop impl
from running, causing silent chain-state truncation on next startup.
PR: #1140
Drop ledger default storage on node shutdown (#886, PM-22219) (#ledger, #node)
Call midnight_node_ledger::drop_all_default_storage() after run_node_until_exit returns so DB-backed default storages are explicitly released during graceful shutdown.
PR: #886
Ticket: https://shielded.atlassian.net/browse/PM-22219
Default `unsafe_allow_symlinks` to `false` when missing from config (#1601) (#node)
Add #[serde(default)] to MetaCfg::unsafe_allow_symlinks so the field
falls back to false instead of producing a missing field config error
at startup. This restores compatibility for deployments running a new node
binary against an older default.toml that predates the field.
Reduce cNIGHT observation address logging level (#905) (#node)
Downgrade non-bech32 and no-delegation-part Cardano address logs from error to debug in cNIGHT observation data source, as these are expected for certain address types.
PR: #905
Remove hard-fork test ledger version dependencies (#1024, PM-22109) (#node)
Remove the *-hf ledger dependencies and all cfg(hardfork_test) /
cfg(hardfork_test_rollback) conditional compilation infrastructure.
Hard-fork e2e tests no longer require building a separate node with an
older ledger version.
PR: #1024
JIRA: https://shielded.atlassian.net/browse/PM-22109
Slim down node Docker image by ~200 MB using multi-stage build (#897) (#node, #docker, #ci)
Multi-stage Dockerfile for the node image so gcc and the build toolchain
(gcc-c++, cmake, make, git, wget, libtool, autoconf, automake) are confined
to a builder stage and excluded from the runtime image. Only the compiled
libfaketime .so is copied across. Also removes non-deterministic
microdnf -y update (base image is pinned by digest) and pins libfaketime
to v0.9.10 so the base layer is cacheable between builds.
PR: #897
⚙️ Runtime
Changed
Bump midnight-ledger from 8.1.0-rc.1 to 8.1.0 (#1510) (#node)
Promotes the Ledger 8 pin from the release candidate (crate-ledger-8.1.0-rc.1)
to the final ledger-8.1.0 tag. Headline upstream changes: storage-core 1.2.0
gains an incremental garbage collector and shared-ParityDB-backend access, plus
fixes for a race condition in force_as_arc, an Sp serialization panic, a
memory leak in pending Updates, and a lock-ordering violation. midnight-ledger
itself adds finer-grained WASM wallet bindings (wallet-facing only).
All midnight-ledger workspace crates are now resolved from crates.io at their
8.1.0 release versions; the previous [patch.crates-io] block pinning them to
the ledger-8.1.0 git tag has been removed now that the 8.1.0 crates are
published.
PR: #1510
#partner-chains
Changed
Align node, runtime, relay, and partner-chains with polkadot-stable2603 SDK (#1299) (#node, #runtime, #partner-chains)
Bumps Substrate dependencies to the polkadot-stable2603 tag and updates call sites for breaking API changes:
- Workspace: All
polkadot-stable2512-3git deps moved topolkadot-stable2603;tracing-subscriberpinned to=0.3.19(required bysp-tracingon this line) with toolkit using the workspace entry. - Node:
sc_service::build_networkgainsspawn_essential_handle;new_full_parts_with_genesis_builderkeeps the six-argument signature (no Grandpa pruning filters argument—unlikenew_full_parts). - Runtime:
sp_session::SessionKeys::generate_session_keysnow takesowner: Vec<u8>and returnsOpaqueGeneratedSessionKeys; opaque keygeneratecalls pass&owner. - Partner-chains (vendored subtree): Aura
ProposerusesProposeArgs; demo node usesGrandpaPruningFilterwithnew_full_partsandspawn_essential_handle; toolkit inherent errors useDebuginstead ofsp_runtime::RuntimeDebugwhere needed. - Ledger / primitives:
RuntimeDebugderives replaced withcore::fmt::Debugwheresp_runtime::RuntimeDebug/frame_support::RuntimeDebugwere removed. - Pallets:
RuntimeDebugNoBoundreplaced withDebugNoBound(e.g. federated-authority, throttle). - Relay (BEEFY):
BeefySignatureHasherremoved;SignedCommitment::verify_signaturescalled with a single inferred authority type parameter.
Partner-chains Cargo.toml / README / changelog are aligned with the same SDK tag where applicable.
#relay
🧰 Toolkit
Changed
#rpc
📦 Node
Added
Add `rpc.discover` endpoint with OpenRPC v1.4 API specification (PM-6402, #869) (#client, #node, #rpc, #api)
Registers a standards-compliant rpc.discover JSON-RPC method that returns a complete OpenRPC v1.4 document describing the node's API. Enables client code generation, request validation, and developer discoverability without reading source code.
- 16 custom Midnight methods fully documented with parameter types, return types, error definitions, and descriptions
- 52 standard Substrate methods listed as reference entries
- JSON Schema type definitions generated via
schemarsfor all RPC response types - Static
docs/openrpc.jsoncommitted for offline access - CI drift-detection tests ensure the schema stays in sync with registered methods
Jira: https://shielded.atlassian.net/browse/PM-6402
PR: #869
#runtime
Changed
Implements handler for C-to-M brige (#1188) (#node, #runtime)
Updates bridge to emit events.
Updates call by adding McTxHash to each transfer.
Updates handler API: handler is expected to return a value that is attached to events.
Implements the handler in Midnight runtime.
Align node and runtime with polkadot-stable2512-3 SDK (#1262) (#node, #runtime)
Bumps Substrate dependencies to the polkadot-stable2512-3 tag and updates call sites for breaking API changes: Core::execute_block and BlockBuilder::check_inherents now use LazyBlock; SpawnTasksParams requires tracing_execute_block (set to None unless trace RPC is wired); MmrApi v3 gains generate_ancestry_proof while BeefyApi no longer exposes it; pallet-version test mock implements Core with LazyBlock. Partner-chains and lockfiles are updated in line with the same SDK line.
Align node, runtime, relay, and partner-chains with polkadot-stable2603 SDK (#1299) (#node, #runtime, #partner-chains)
Bumps Substrate dependencies to the polkadot-stable2603 tag and updates call sites for breaking API changes:
- Workspace: All
polkadot-stable2512-3git deps moved topolkadot-stable2603;tracing-subscriberpinned to=0.3.19(required bysp-tracingon this line) with toolkit using the workspace entry. - Node:
sc_service::build_networkgainsspawn_essential_handle;new_full_parts_with_genesis_builderkeeps the six-argument signature (no Grandpa pruning filters argument—unlikenew_full_parts). - Runtime:
sp_session::SessionKeys::generate_session_keysnow takesowner: Vec<u8>and returnsOpaqueGeneratedSessionKeys; opaque keygeneratecalls pass&owner. - Partner-chains (vendored subtree): Aura
ProposerusesProposeArgs; demo node usesGrandpaPruningFilterwithnew_full_partsandspawn_essential_handle; toolkit inherent errors useDebuginstead ofsp_runtime::RuntimeDebugwhere needed. - Ledger / primitives:
RuntimeDebugderives replaced withcore::fmt::Debugwheresp_runtime::RuntimeDebug/frame_support::RuntimeDebugwere removed. - Pallets:
RuntimeDebugNoBoundreplaced withDebugNoBound(e.g. federated-authority, throttle). - Relay (BEEFY):
BeefySignatureHasherremoved;SignedCommitment::verify_signaturescalled with a single inferred authority type parameter.
Partner-chains Cargo.toml / README / changelog are aligned with the same SDK tag where applicable.
⚙️ Runtime
Changed
Add proposal_weight_bound parameter to motion_close (#1032, PM-22326) (#runtime)
The motion_close extrinsic previously declared a constant weight that did not
account for the inner call dispatched as Root when a motion is approved.
Substrate can only refund weight post-dispatch, never increase it, so the inner
call's weight was never pre-charged. This adds a proposal_weight_bound parameter
following the pallet_collective::close pattern, ensuring the declared weight
includes the inner call's weight upfront. The extrinsic is also made
DispatchClass::Operational to match the other governance extrinsics. Toolkit and
upgrader are updated to pass the new parameter.
PR: #1032
Ticket: https://shielded.atlassian.net/browse/PM-22326
Use generated benchmark weights in runtime (#1495) (#runtime)
Connects generated runtime benchmark weights so the runtime uses measured
weights for core FRAME and local runtime pallets instead of generic defaults.
Includes GRANDPA, BEEFY MMR, timestamp, migrations, scheduler, preimage, tx-pause, council and technical committee
collectives and memberships, session validator management, federated authority
and observation, system parameters, and cNIGHT observation.
Add per-account transaction count limit to throttle pallet (#1060, PM-22377) (#runtime)
Extends the existing per-account throttle to also enforce a maximum number of transactions (MaxTxs) within each rolling block window, alongside the existing byte limit. The AccountUsage storage is migrated from a 2-field tuple to a UsageStats struct (adding txs_used). Includes a storage migration that clears the old map on upgrade.
PR: #1060
Ticket: https://shielded.atlassian.net/browse/PM-22377
Migrate from SignedExtension to TransactionExtension (#597) (#runtime)
Migrates the runtime from the deprecated SignedExtra type alias to the new
TxExtension pattern, adding AuthorizeCall and WeightReclaim extensions.
Implements the required offchain transaction creation traits
(CreateTransaction, CreateBare, CreateSignedTransaction,
CreateAuthorizedTransaction) and updates the benchmarking harness to match.
PR: #597
#security
📦 Node
Changed
Harden bot workflows against TOCTOU and expression injection (#848, PM-22117) (#ci, #security)
Fix compound TOCTOU vulnerability (M-F001) and expression injection findings (M-F002, M-F003, M-F004) in four comment-triggered bot workflows. Switch checkout from branch name to commit SHA, remove .envrc sourcing in favor of explicit EARTHLY_CONFIG, and migrate user-supplied inputs to env: block indirection.
PR: #848
Ticket: https://shielded.atlassian.net/browse/PM-22117
🧰 Toolkit
Changed
Replace expect calls with Result error propagation in ledger state updates (#927, PM-19977) (#toolkit, #security)
Replace expect calls in update_from_block and update_from_tx with proper Result-based error propagation to prevent panics and mutex poisoning. Addresses audit finding Issue AB.
PR: #927
JIRA: https://shielded.atlassian.net/browse/PM-19977
Clear toolkit SBOM critical and npm audit high findings on release/node-1.0.1 (#1987) (#toolkit, #security)
Backports the dependency/tooling hygiene fixes needed to make the +audit and
toolkit SBOM scan checks pass on the release/node-1.0.1 branch. These findings
are environmental (newly published advisories against stale lockfiles / a stale
bundled npm), not caused by any product code change.
- Bumped the pinned
npm install -g npm@11.11.0tonpm@11.18.0across the
Earthfile targets (toolkit-image,audit-npm,audit-yarn,fix-lock-npm).
npm 11.18.0 vendorstar@7.5.19, clearing the critical toolkit-image SBOM
finding (GHSA-23hp-3jrh-7fpw,tar@7.5.9) plus the other flagged npm-bundled
packages. Mirrors main #1919. local-environment/package-lock.json:npm audit fixclears 5 high findings
(axios, brace-expansion, form-data, js-yaml, ws). Supersedes main #1981, which
only bumped brace-expansion.util/toolkit-js/package-lock.json:npm audit fixclears postcss, undici and
ws; aviteoverride (^7.3.6, within vitest 3.2.6's existing range) clears the
remaining high without a vitest major bump.
PR: #1987
Bump vitest to 3.2.6 to fix critical vulnerability blocking release image scans (#1841) (#toolkit, #security, #dependencies)
The toolkit SBOM vulnerability scan fails on GHSA-5xrq-8626-4rwp (Critical,
"When Vitest UI server is listening, arbitrary file can be read and executed")
in vitest 3.2.4, which is baked into the toolkit image via toolkit-js
devDependencies. This blocked the Publish multi-arch image job on
release/node-1.0.1, so the content-hash-tagged multi-arch manifest was never
created and the Create Release workflow failed with "image not found".
Bumps vitest 3.2.4 -> 3.2.6 (the patched release on the 3.x line).
PR: #1841
#sre
📦 Node
Changed
Migrate Renovate to org-wide hardened preset (#1118, SRE-2078) (#sre)
Replace interim hardening config with the shared github>midnightntwrk/renovate-config
preset. Delegates supply chain hardening (7-day cooldown, strict internal checks
filter, OSV vulnerability scanning, major version gating) to the org preset.
Retains Earthfile custom manager and git-submodules support.
PR: #1118
JIRA: https://shielded.atlassian.net/browse/SRE-2078
#toolkit
Changed
Add regression tests for nonce/nullifier distinction in zswap serialization (#1128, PM-22025) (#toolkit)
Add unit tests verifying that serialized zswap local state uses the coin
nonce (randomness), not the nullifier (spend identifier), for the nonce
field. Addresses Least Authority Q1 2026 Node DIFF audit Issue E.
PR: #1128
JIRA: https://shielded.atlassian.net/browse/PM-22025
Fix DustWallet spend state propagation (#877, PM-20016) (#toolkit)
Fix DustWallet::speculative_spend to return the updated DustLocalState
alongside spends, and extend mark_spent to commit the state atomically
with nullifier recording. This ensures DustLocalState::spend's
pending_until flags are propagated, preventing utxos() from returning
already-spent outputs in consecutive spend operations.
Addresses Least Authority audit finding Issue AO.
PR: #877
JIRA: https://shielded.atlassian.net/browse/PM-20016
Speed up toolkit syncing (#1263) (#toolkit)
Batch block-number-to-hash RPC calls into a single request instead of one call per block, reducing round trips during sync. Also simplifies several function parameters across the fetcher.
PR: #1263
📦 Node
Changed
Bump vulnerable dependencies (#1079, PM-22035) (#node, #toolkit)
Update rustls-webpki 0.103.4 to 0.103.10 (RUSTSEC-2026-0049: faulty CRL
distribution point matching) and testcontainers 0.25 to 0.27, pulling
astral-tokio-tar 0.5.6 to 0.6.0 (RUSTSEC-2026-0066: insufficient PAX
extension validation).
PR: #1079
JIRA: https://shielded.atlassian.net/browse/PM-22035
🧰 Toolkit
Added
Add `--log-json` structured logger flag, use pretty log output by default (#859, PM-22220) (#toolkit)
Default log output is now human-readable with colored level labels.
Pass --log-json to get structured JSON output for machine parsing.
PR: #859
Ticket: https://shielded.atlassian.net/browse/PM-22220
Enable contract_custom builder for ledger 7 (#864, PM-22229) (#toolkit)
The contract_custom transaction builder now works on chains still at ledger
version 7, removing the previous "not supported for ledger 7" error.
PR: #864
JIRA: https://shielded.atlassian.net/browse/PM-22229
Add support for node `0.20.1` runtime version (PM-22050, #827) (#toolkit)
We should've already had support for this version - it was missing, this change adds it.
Ticket: https://shielded.atlassian.net/browse/PM-22050
PR: #827
Add batch-single-tx command for bulk transaction generation (#820, #939, PM-22103) (#toolkit)
New batch-single-tx subcommand that generates multiple transactions from a JSON specification file. Supports per-transfer output files and configurable concurrency, with parallel ZK proving via tokio::task::spawn_blocking.
PR:
Add show-block command to toolkit (#1068, PM-22388) (#toolkit)
Diagnostic command to inspect individual blocks — view metadata and deserialized transactions. Reads from the fetch cache first, falling back to live node RPC on cache miss. Supports human-readable and JSON output.
PR: #1068
JIRA: https://shielded.atlassian.net/browse/PM-22388
Add option when generating intents to write out the contract on-chain state (#946, PM-22230) (#toolkit)
Adds support for multiple Ledger stacks to toolkit-js.
When called from the command-line, toolkit-js will default to the latest ledger version (and consequently the associated version of Compact.js that supports it), but this can be overridden by applying the LEDGER_VERSION=d environment variable. For example, to use a Compact.js that is built against Ledger 7, set LEDGER_VERSION=7 in the environment.
PR: #946
Ticket: https://shielded.atlassian.net/browse/PM-22230
Add support for zswap state chaining (#879, PM-20404) (#toolkit)
Support for zswap state chaining in batched intents.
PR: #879
Ticket: https://shielded.atlassian.net/browse/PM-20404
Add file-based wallet and ledger state caching to toolkit (#820, #939, PM-22103) (#toolkit)
Introduces a two-tier file cache that persists ledger snapshots and per-wallet state across toolkit runs, eliminating the need to replay the full chain on every invocation. Ledger snapshots (postcard encoding, zstd-compressed, ~1.4 compression) are stored once per block height and shared across wallets; per-wallet state (postcard encoded) is keyed by seed hash. Write to .tmp, then atomic rename pattern prevents data corruption on concurrent writes on POSIX.
Includes a trusted deserialization path that computes hashes in a single bottom-up pass for self-generated cache data, bypassing the two-pass security verification and cutting deserialization time by half. Similarly, fast serialization calls serialize_to_node_list() once instead of twice cutting serialization time by half.
Stale snapshot garbage collection reads only the first 8 bytes of wallet files headers to extract block height without full deserialization.
New CLI flags: --ledger-state-db <path> to set the cache directory (default: ledger_state_db), and --fetch-only-cached for offline operation from a pre-populated cache.
PR:
Changed
Add --verbose and --quiet flags to toolkit CLI (#859, PM-22220) (#toolkit)
Added --verbose / -v (debug level) and --quiet / -q (warn level) global
flags to the toolkit CLI. Default log level is info. Per-batch fetch log messages
have been demoted from info to debug level, reducing noise while keeping high-level
progress visible.
PR: #859
Ticket: https://shielded.atlassian.net/browse/PM-22220
Bound intent file reads to 64 MB maximum size (#874) (#toolkit)
Add a file size check before reading intent files in IntentCustom::new_from_file,
rejecting files that exceed 64 MB. Prevents unbounded memory allocation from
oversized intent files.
PR: #874
Replace unchecked arithmetic in offer creation with checked operations (#942, PM-20206) (#toolkit)
Replace as i128 casts and unchecked addition in offer delta calculation and
balance accumulation with TryFrom, checked_add, and checked_sub. Overflow
or truncation now returns an explicit OfferBuildError instead of silently
producing incorrect values. Addresses Least Authority audit Issue AL.
PR: #942
JIRA: https://shielded.atlassian.net/browse/PM-20206
Replace unchecked addition in wallet seed increment with checked_add (#1081, PM-20017) (#toolkit)
Return result rather than panicing. Overflow now returns an explicit error instead
of producing a colliding seed that could lead to duplicate key derivation.
Addresses Least Authority audit Issue AL.
PR: #1081
JIRA: https://shielded.atlassian.net/browse/PM-20017
Cleanup nullifier/nonce use in fork export path and redact new_authority in CLI logging (#1074) (#toolkit)
Fix remaining nullifier/nonce use in the fork-aware export path
where the nullifier was incorrectly serialized as the nonce
in EncodedShieldedCoinInfo. This mirrors the fix from PR #895.
Also convert the maintain-contract new_authority parameter from a positional CLI
argument to a named flag (--new-authority).
PR: #1074
Remove verbose println! logging from ledger helpers (#936, PM-22084) (#audit, #toolkit)
Replace unconditional println! calls in intent.rs, transaction.rs,
and proving.rs with structured log:: macros gated by RUST_LOG.
Remove the sensitive intent structure dump that exposed privacy-critical
transaction internals to stdout.
PR: #936
Ticket: https://shielded.atlassian.net/browse/PM-22084
Propagate errors from save_intents_to_file (#873, PM-20209) (#audit, #toolkit)
save_intents_to_file previously reported success even when serialization or
file writing failed, silently producing incomplete intent files. Errors are now
propagated to callers, and any partially written files are cleaned up on failure.
PR: #873
JIRA: https://shielded.atlassian.net/browse/PM-20209
Use cryptographically secure RNG for parent block hash fallback (#878, PM-20205) (#toolkit)
Replace non-cryptographic RNG with OsRng for parent_block_hash generation in TransactionWithContext
PR: #878
Ticket: https://shielded.atlassian.net/browse/PM-20205
Replace expect calls with Result error propagation in ledger state updates (#927, PM-19977) (#toolkit, #security)
Replace expect calls in update_from_block and update_from_tx with proper Result-based error propagation to prevent panics and mutex poisoning. Addresses audit finding Issue AB.
PR: #927
JIRA: https://shielded.atlassian.net/browse/PM-19977
Clear toolkit SBOM critical and npm audit high findings on release/node-1.0.1 (#1987) (#toolkit, #security)
Backports the dependency/tooling hygiene fixes needed to make the +audit and
toolkit SBOM scan checks pass on the release/node-1.0.1 branch. These findings
are environmental (newly published advisories against stale lockfiles / a stale
bundled npm), not caused by any product code change.
- Bumped the pinned
npm install -g npm@11.11.0tonpm@11.18.0across the
Earthfile targets (toolkit-image,audit-npm,audit-yarn,fix-lock-npm).
npm 11.18.0 vendorstar@7.5.19, clearing the critical toolkit-image SBOM
finding (GHSA-23hp-3jrh-7fpw,tar@7.5.9) plus the other flagged npm-bundled
packages. Mirrors main #1919. local-environment/package-lock.json:npm audit fixclears 5 high findings
(axios, brace-expansion, form-data, js-yaml, ws). Supersedes main #1981, which
only bumped brace-expansion.util/toolkit-js/package-lock.json:npm audit fixclears postcss, undici and
ws; aviteoverride (^7.3.6, within vitest 3.2.6's existing range) clears the
remaining high without a vitest major bump.
PR: #1987
Upgrade subxt from v0.44 to v0.50 (#1229) (#toolkit, #relay)
Migrate the toolkit, upgrader, relay, and e2e tests to the subxt v0.50
block-centric API. This includes new transaction types, granular error
handling, async metadata access, and updated storage/event APIs.
Bump vitest to 3.2.6 to fix critical vulnerability blocking release image scans (#1841) (#toolkit, #security, #dependencies)
The toolkit SBOM vulnerability scan fails on GHSA-5xrq-8626-4rwp (Critical,
"When Vitest UI server is listening, arbitrary file can be read and executed")
in vitest 3.2.4, which is baked into the toolkit image via toolkit-js
devDependencies. This blocked the Publish multi-arch image job on
release/node-1.0.1, so the content-hash-tagged multi-arch manifest was never
created and the Create Release workflow failed with "image not found".
Bumps vitest 3.2.4 -> 3.2.6 (the patched release on the 3.x line).
PR: #1841
Fix missing `persist()` on context fork causing `not in arena` errors (#881, PM-22124) (#toolkit)
PR: #881
Ticket: https://shielded.atlassian.net/browse/PM-22124
Fix panic if the first block doesn't have any midnight transactions. (#1045, PM-22361) (#toolkit)
It scans all blocks instead of the first one. For an RPC source it queries get_network_id API.
PR: #1045
Ticket: https://shielded.atlassian.net/browse/PM-22361
Fix hitting recursion depth on context fork (#881, PM-22253) (#toolkit)
Toolkit now uses get_lazy rather than get to avoid loading the entire ledger state when forking the context.
PR: #881
Ticket: https://shielded.atlassian.net/browse/PM-22253
Change default cache location to `./toolkit_cache` instead of `./toolkit.db` (#939, PM-22103) (#toolkit)
This was required because we now have two separate caches - one for the fetch cache, the other for the wallet state cache.
PR: #939
Ticket: https://shielded.atlassian.net/browse/PM-22103
Add `--seeds` options to `fetch` subcommand to allow caching wallet states (#939, PM-22103) (#toolkit)
PR: #939
Ticket: https://shielded.atlassian.net/browse/PM-22103
Fix Dust address format to match the specification (#190, #1059, PM-22375) (#toolkit)
- Corrected the prefix from
dust-addrtodust(source: midnightntwrk/midnight-architecture#190) - Use
untagged_serialization(source: https://github.com/midnightntwrk/midnight-architecture/blob/main/components/WalletEngine/Specification.md#dust-address)
PR: #1059
Ticket: https://shielded.atlassian.net/browse/PM-22375
Fix using the nullifier as the nonce when encoding zswap state (#895, PM-21923) (#toolkit)
PR: #895
Ticket: https://shielded.atlassian.net/browse/PM-21923
Toolkit images are now versioned independently (#1261) (#toolkit)
The midnight-node-toolkit Docker image is now versioned from its own
util/toolkit/Cargo.toml instead of sharing the node version from
node/Cargo.toml. Release tags for toolkit-only releases use the
toolkit-X.Y.Z format.
PR: #1261
Drop `structured_logger` in favour of `tracing_subscriber`; Breaking JSON structured log format change (#899) (#toolkit)
Format now looks like:
{"timestamp":"2026-03-10T17:26:45.103688Z","level":"INFO","fields":{"message":"spawning 20 fetch workers","log.target":"midnight_node_toolkit::fetcher","log.module_path":"midnight_node_toolkit::fetcher","log.file":"util/toolkit/src/fetcher.rs","log.line":171},"target":"midnight_node_toolkit::fetcher"}
PR: #899
Support multiple shielded coin input in `single-tx`, `batch-single-tx` and `batches` (PM-22405, #1216) (#toolkit)
Multiple shielded amounts spread in coins of small values will now be combined to produce the required output amount.
Fixes: https://shielded.atlassian.net/browse/PM-22405
PR: #1216
Improve toolkit block replay and transaction generation performance (#820, #939, PM-22103) (#toolkit)
Batches state-change events during block replay for wallet initialization, using biased tokio::select! to prioritize new work from fetch workers and reduce incremental processing overhead. Adds a --replay-concurrency CLI parameter (defaults to CPU core count) and uses Rayon-based parallel wallet updates during replay.
Adds structured [perf] logging for timing instrumentation of key operations. Includes a change from BSON encoding to postcard which cuts the size of cached blocks by half and cached ledger states by ~8 and graceful failure when the wallet has insufficient DUST balance.
PRs:
Use tracing for structured log fields (#1230) (#toolkit)
Switched key-value log calls from log to tracing so structured fields
are emitted by tracing-subscriber instead of being silently dropped.
PR: #1230
Add support for fallible contract calls (PM-19839, #888) (#toolkit)
Ticket: https://shielded.atlassian.net/browse/PM-19839
PR: #888
Add support for fallible inputs (PM-22302, #966) (#toolkit)
Ticket: https://shielded.atlassian.net/browse/PM-22302
PR: #966
Fix `--verbose` flag, add `--verbose-fetch` and `--verbose-ledger`; Can override with `RUST_LOG` (#899, PM-22273) (#toolkit)
These new flags allow the user to quickly modify verbosity of toolkit components.
PR: #899
Ticket: https://shielded.atlassian.net/browse/PM-22273