node-2.0.0-rc.4
Pre-releaseMidnight Node 2.0.0-rc.4
Cumulative note. Unlike a normal release-candidate note (delta-only), this one is the superset of the entire 2.0.0 line —
2.0.0-alpha.1+2.0.0-rc.1+2.0.0-rc.2+2.0.0-rc.3+2.0.0-rc.4— framed as the full change set from the last final release,node-1.0.0, tonode-2.0.0-rc.4. This is expected to be the final release candidate of the 2.0.0 line. Per-pre-release deltas remain available in their own release notes (alpha.1, rc.1, rc.2, rc.3).
⛔ This release cannot upgrade mainnet — there is no mechanism by which it could. The 2.0.0 line is a binary-only, fresh-chain development line: it ships no on-chain runtime upgrade and no ledger 8 → 9 state migration, so no existing chain — mainnet included — can be forked, migrated, or rolled forward onto it. Mainnet's genesis state and chain-spec are byte-identical across the whole 2.0.0 line (
genesis_state_mainnet.mnandres/mainnet/chain-spec.jsonare unchanged fromnode-1.0.0); nothing in this line regenerates a mainnet artifact. Mainnet stays on the 1.0.x / ledger-8 line and is untouched. A 2.0.0 binary can only bootstrap a fresh ledger-9 genesis (dev / devnet / stagenet) — which is a new chain, not mainnet.
Metadata
- Type of release: major (release-candidate pre-release)
- Date: 2026-07-09
- Ships in bundle: TBD — rc pre-release (not bundled)
- Git tag: node-2.0.0-rc.4
- Environment: Development ledger-9 networks only — local env, Devnet, Stagenet. Deployed ledger-8 networks (mainnet, preprod, preview, qanet, govnet, perfnet) are not targets of this line. For the full compatibility matrix, see the release notes overview.
- Upgrade scope: binary only — no on-chain runtime upgrade occurs; the node binary carries its bundled runtime and is not compatible with existing networks, so chains start fresh
- Reset required: Yes — fresh chain required; no in-place upgrade from any prior node version (including earlier 2.0.0 pre-releases) is supported in this line
- Governance action required: No (deployed as a fresh chain); enabling the Cardano→Midnight bridge later requires a governance action — it ships inert
- Mainnet upgrade possible: No — structurally impossible (no runtime upgrade path, no ledger 8→9 migration; mainnet artifacts untouched)
- Sister-line note: The 1.0.x maintenance line (e.g.
node-1.0.1-rc.2) continues in parallel for networks staying on ledger 8, including mainnet. The 2.0.0 line is a fresh-chain development line and is not an upgrade target for 1.0.x chains yet.
High-level summary
Cumulative state of the Midnight Node 2.0.0 line through rc.4, expected to be the final RC. The line moves the ledger to version 9 (9.1.0.0-rc.3 at this rc), lands the (still-inert) Cardano→Midnight bridge pallet plus toolkit commands, removes unused partner-chains pallets, bumps the Rust toolchain to 1.95, and carries a large batch of Least Authority audit-hardening fixes across node and toolkit. It adds a dual v1/v2 ZK proving pipeline, on-chain contract IR (ContractOperation V4), substantial sync-performance work, guaranteed-segment-only ledger-9 validation, multi-destination toolkit transfers, fixed genesis pool generation, a fixed bridge claim path, cNIGHT contract-identifier root extrinsics, benchmarks/weights for the bridge pallets, a recreated devnet genesis, and a new stagenet network. rc.3 folds the L7/L8 (2.x) and L9 (3.x) crypto stacks into a single zkir crate and bumps the ledger patch set to 9.1.0.0-rc.3 (state encoding v17 → v18, revised cost-model factors). rc.4 regenerates the stagenet genesis + chain-spec, fixes node startup argument parsing (custom RunMidnight flags such as --no-hardware-benchmarks are accepted again), and moves devnet to a 7-seat committee (D-parameter 7:0) with a cleared NIGHT token_asset_name.
This is a binary-only release: the node binary carries its own bundled runtime, so no on-chain runtime upgrade happens. It is not compatible with existing networks — there is no migration from ledger 8 and no in-place upgrade from any prior node version: 2.0.0 chains must start fresh. Mainnet cannot be upgraded by this release under any circumstances. (For reference, the bundled runtime reports spec_version 002_000_000 and transaction_version 4, vs 1_000_000 / 3 in node 1.0.0; the runtime WASM is byte-identical across rc.2 → rc.4.)
Audience
These release notes are intended for:
- Operators evaluating or running the 2.0.0 development line (local env, devnet, stagenet) — a fresh-chain start is mandatory; no rolling upgrade, and specifically no mainnet upgrade, is supported.
- Developers who build and sign extrinsics —
transaction_versionis 4; extrinsics signed against the 1.0.0 runtime (tx version 3) no longer decode. - Toolkit users who generate transactions, manage wallets, or rehearse the Cardano→Midnight bridge flow against ledger
9.1.0.0-rc.3. - Integrators decoding runtime metadata or ledger state — metadata was regenerated for ledger 9.1 (new parameters; on-chain
ContractOperationV4). - Administrators maintaining genesis state and chain-specs — devnet and stagenet were regenerated; ledger-state encoding moved v17 → v18.
Dependencies
- Ledger: 9.1.0.0-rc.3 (
midnight-ledger-v9, crate tagcrate-ledger-9.1.0.0-rc.3). No v8 → v9 migration path; incompatible with ledger-8 chain state and with 2.0.0-rc.2 payloads. - CompactC: the toolkit defaults to 0.31.0.
transaction_version4: signed extrinsics built against the 1.0.0 runtime (tx version 3) will not decode.- Runtime metadata: regenerated for ledger 9.1 (new
max_contract_metadata_sizeparameter; on-chainContractOperationformat changed; new cNIGHT contract-identifier root extrinsics). Unchanged since rc.2 — the rc.3/rc.4 ledger and config changes do not alter pallet storage or extrinsics. Re-pull metadata before pointing tooling at a 2.0.0 chain.
Downstream impact (cascading effects): indexers, wallets, and SDKs that decode runtime metadata or ledger-8 state must be rebuilt against the 2.0.0 metadata / ledger 9.1 before they can follow a 2.0.0 chain. Payloads built against rc.2 (ledger 9.1.0.0-rc.2) will not validate under rc.3/rc.4. The C2M bridge is inert, so no downstream bridge integration is active yet. Deployed ledger-8 networks (mainnet, preprod, preview, qanet, govnet, perfnet) read via the L7/L8 stacks and are entirely unaffected by this line.
For all other interop questions, see the bundle dependency matrix.
Deployment information
- Upgrade scope: binary only — there is no on-chain runtime upgrade. The runtime is baked into the node binary and is incompatible with existing networks, so deployment is a fresh chain, not an in-place upgrade.
- Reset required: Yes — fresh chain. Ledger 9 has no state transition from ledger 8, and this line supports no in-place upgrade from any prior node version (including
2.0.0-alpha.1through2.0.0-rc.3). Genesis state and chain-specs were regenerated for ledger 9.1 (ledger-state encoding v18); devnet and stagenet genesis were recreated. Mixed pre-v9/post-v9 handling in block replay and toolkit caching remains deliberately relaxed and unsupported. - Mainnet: cannot be upgraded — no path exists. Mainnet runs ledger 8 on the 1.0.x line; a 2.0.0 node can neither join nor migrate it. Mainnet genesis/chain-spec are untouched by the entire 2.0.0 line.
- Governance action required: No — deploys as a fresh chain, not an on-chain upgrade. A future non-2.0.0 line will require an on-chain runtime upgrade once ledger-8 → 9 state-migration work is complete, at which point existing chains roll forward instead of resetting. Separately, enabling the C2M bridge requires a governance action (setting the bridge
MainChainScriptsaddresses + a data checkpoint); until then the bridge inherent-data provider reportsInerteverywhere. - Downtime / coordination: Not an in-place upgrade — existing chains cannot roll forward. New development networks bootstrap from fresh genesis. No coordination with mainnet operators is required or possible.
Artifacts
- Docker:
midnightntwrk/midnight-node:2.0.0-rc.4 - Docker:
midnightntwrk/midnight-node-toolkit:2.0.0-rc.4 - Git tree hash:
5c34f67538f20811d876f6463cf9aca5a3bc4fc9
docker pull midnightntwrk/midnight-node:2.0.0-rc.4
docker pull midnightntwrk/midnight-node-toolkit:2.0.0-rc.4Note: like
2.0.0-rc.1/rc.2/rc.3(and unlike2.0.0-alpha.1), this rc does not publish a standalone runtime WASM release asset — only the node and toolkit binaries (linux-amd64/linux-arm64tarballs) andSHA256SUMS.
What changed
Cumulative new features, improvements, and fixes across the 2.0.0 line (1.0.0 → 2.0.0-rc.4):
- Ledger 9 — new ledger major; no migration from ledger 8, so 2.0.0 chains start fresh (#1604); bumped to 9.1.0.0-rc.2 with a dual v1/v2 ZK proving pipeline, on-chain contract IR and
ContractOperationV4, ECDSA domain-separator change, and a newmax_contract_metadata_sizeparameter (#1692); then to 9.1.0.0-rc.3 folding the L7/L8 (2.x) and L9 (3.x) crypto stacks into onezkircrate, with state encoding v17 → v18 and revised cost-model factors (#1738). - Cardano→Midnight bridge (inert) — new
c2m-bridgepallet, genesis/runtime config, transfer classification, pre-approvals, subminimal-transfer holds, claim-path fix, benchmarks/weights, and a toolkitbridge-transfercommand (#1386, #1333, #1513, #1477, #1393, #1608, #1697, #1635, #1340). - cNIGHT contract-identifier root extrinsics — set Cardano contract identifiers on-chain to exercise contract upgradeability in fork/local-env testing (#1602).
- Sync performance — bulk-read cNIGHT observation cache (genesis→tip ~3 h 19 m) (#1436), epoch-nonce + federated-ops caches (#1551), cNIGHT UTXO overestimate 64× → 4× (#1367), Midnight parity-db fork (#1478), db-sync autovacuum tuning (#1434).
- Ledger-9 guaranteed-only validation — mempool and block-inclusion pre-checks dry-run only the guaranteed segment on ledger 9 (#1454).
- New / regenerated networks + genesis — recreate
devnetgenesis + chain-spec (#1698); addstagenet(Cardano Preview, 7 permissioned validators) (#1707); regeneratestagenetgenesis + chain-spec (#1858); devnet 7-seat committee (D-parameter 7:0) + cleared NIGHTtoken_asset_namefor devnet/qanet/preview/preprod (#1834); prevent empty locked pool +--allow-empty-pools, testnet pools mirror mainnet (#1675). - Node startup — parse custom
RunMidnightargs (e.g.--no-hardware-benchmarks,--rpc-max-finality-subscriptions) before applying config overrides (#1767/#1795). - Removed unused partner-chains pallets and their CLI commands (#1562).
SessionInfoApiruntime API exposing the substrate session index (#1534);storage_separationconfig option (#1278).- Toolkit — multi-destination
single-tx(#1560),--coin-selection,--input-utxopinning,--print-system-tx-hex, batched cache warmup (#1457, #1404, #1473, #1603), dual-stack verifier-key + intent-envelope adaptation for ledger9.1.0.0-rc.3(#1738). - Rust 1.95 toolchain (#1363); toolkit CompactC default 0.31.0 (#1555).
- Granular ledger error variants surfaced through pallet + RPC error reporting (#1449, #1475, #916, #1359).
- A batch of Least Authority audit-hardening fixes across node and toolkit.
| Change | Upgrade Type | PR |
|---|---|---|
| Ledger 9 support | Runtime upgrade | #1604 |
Bump ledger to 9.1.0.0-rc.2 (dual v1/v2 ZK pipeline, ContractOperation V4, max_contract_metadata_size) |
Runtime upgrade | #1692 |
Bump ledger to 9.1.0.0-rc.3 (fold crypto stacks into one zkir; encoding v17→v18; cost-model factors) |
Node upgrade + Toolkit | #1738 |
Added c2m-bridge pallet |
Runtime upgrade | #1386 |
| C2M bridge: genesis / runtime configuration | Runtime upgrade | #1333 |
| C2M bridge: Reserve Transfer classification | Runtime upgrade | #1513 |
C2M bridge: pre-approvals filter (→ treasury + UnapprovedTransfer) |
Runtime upgrade | #1477 |
| C2M bridge: hold + flush subminimal transfers | Runtime upgrade | #1393 |
| C2M bridge: STAR denomination fix | Runtime upgrade | #1608 |
| C2M bridge: fix claim path | Runtime upgrade | #1697 |
C2M bridge: benchmarks + weights (pallet_c2m_bridge, pallet_partner_chains_bridge) |
Runtime upgrade | #1635 |
| cNIGHT contract-identifier root extrinsics (upgradeability testing) | Runtime upgrade | #1602 |
| Remove unused partner-chains pallets + commands | Runtime upgrade | #1562 |
SessionInfoApi runtime API |
Runtime upgrade | #1534 |
| cnight-observation: panic → typed error on inherent decode | Runtime upgrade | #1234 |
| federated-authority: keep motion removal on failed dispatch | Runtime upgrade | #938 |
| cNIGHT observation UTXO capacity −16× (API v2 gated) | Runtime upgrade | #1367 |
| cNight observation: bounded storage (unbounded-alloc fix) | Runtime upgrade | #1423 |
Throttle AccountUsage storage-migration refactor |
Runtime upgrade | #1526 |
| Granular ledger error variants in pallet error reporting | Runtime upgrade | #1449 |
| Session-change error log when D-parameter below permissioned count | Runtime upgrade | #1506 |
| cnight-observation genesis panic diagnostics | Runtime upgrade | #1466 |
Prevent empty locked pool in genesis; --allow-empty-pools; testnet pools mirror mainnet |
Runtime upgrade | #1675 |
Recreate devnet genesis state/block + chain-spec |
Runtime upgrade | #1698 |
| Update Rust toolchain to 1.95 | Runtime upgrade (mixed) | #1363 |
Add stagenet network genesis + chain specs |
Node upgrade | #1707 |
Regenerate stagenet genesis + chain-spec |
Node upgrade | #1858 |
Devnet 7-seat committee (D-parameter 7:0) + cleared NIGHT token_asset_name (devnet/qanet/preview/preprod) |
Node upgrade | #1834 |
Parse RunMidnight args before applying config overrides (--no-hardware-benchmarks, --rpc-max-finality-subscriptions) |
Node upgrade | #1767, #1795 |
| Bulk-read cNIGHT observation cache (genesis→tip sync ~3 h 19 m) | Node upgrade | #1436 |
| Epoch-nonce + federated-ops caches (sync perf) | Node upgrade | #1551 |
Ledger-9 apply_guaranteed_only guaranteed-segment validation |
Node upgrade | #1454 |
| Bound GRANDPA + BEEFY finality subscription fan-out | Node upgrade | #1075 |
| Enforce TLS cert + hostname validation for DB connections | Node upgrade | #1104 |
Verify removal of WalletSeed Default implementation |
Node upgrade | #1109 |
Return ContractNotPresent for missing contracts |
Node upgrade | #916 |
Surface ContractNotPresent through midnight_contractState RPC |
Node upgrade | #1475 |
Return BeneficiaryNotFound in get_unclaimed_amount |
Node upgrade | #1359 |
| Per-session validator committee-membership log | Node upgrade | #1534 |
| Reject block headers with duplicate mainchain-ref-hash digests | Node upgrade | #1617 |
| Complete zeroization of secret buffers | Node upgrade | #1379 |
Default unsafe_allow_symlinks to false when missing |
Node upgrade | #1600 |
| parity-db: Midnight fork (lower flush threshold, ahash) | Node upgrade | #1478 |
| Silence cNIGHT observation noise logs | Node upgrade | #1324 |
| Run hardware benchmarks on node startup | Node upgrade | #1394 |
| Midnight-specific reference hardware profile | Node upgrade | #1511 |
| Log sanitized db-sync startup probe results | Node upgrade | #1411 |
| Tune autovacuum on db-sync hot tables | Node upgrade | #1434 |
Eliminate deadlock in LedgerContext::with_wallets_from_seeds |
Node upgrade | #1471 |
New storage_separation config option |
Node upgrade | #1278 |
Toolkit single-tx multiple-destination support |
Toolkit | #1560 |
Toolkit bridge-transfer command |
Toolkit | #1340 |
Toolkit contract-address --untagged cleanup |
Toolkit | #1486 |
| Enforce derivation-path role validation in wallet constructors | Toolkit | #1076 |
| Improve wallet seed / keypair / address code quality | Toolkit | #1217 |
--coin-selection flag on coin-selecting commands |
Toolkit | #1457 |
Batched dust_balance::execute_many for cache warmup |
Toolkit | #1603 |
--input-utxo pinning for generate-txs single-tx |
Toolkit | #1404 |
--print-system-tx-hex for update-ledger-parameters |
Toolkit | #1473 |
| Harden coin-selection arithmetic with checked operations | Toolkit | #1293 |
| Enforce EOF on untagged CLI parser path (ADR-0022) | Toolkit | #1437 |
Abstract transaction builders over a BuilderContext trait |
Toolkit | #1605 |
Fix dust-balance snapshot tagged at block_height = 0 under dust_warp |
Toolkit | #1574 |
| Lock redb fetch cache against concurrent toolkit processes | Toolkit | #1493 |
| Terminal-status sender error handling | Toolkit | #1323 |
Dispatch toolkit-js variants by compactc version |
Toolkit | #1555 |
Fix stack overflow in trusted_deserialize_tagged |
Toolkit | #1576 |
| Update default CompactC version to 0.31.0 | Toolkit | #1555 |
| Restore cNIGHT observation e2e coverage against Cardano Preview | Infrastructure | #1578, #1613 |
| Initial CI for fork testing | Infrastructure | #1353 |
| fork-network workflow: node-upgrade option | Infrastructure | #1469 |
| local-files secrets mode for mock authorities | Infrastructure | #1287 |
| Remove Kubernetes + AWS coupling from local-environment | Infrastructure | #1470 |
local-env: patch cnight mapping_validator_address from compiled contracts |
Infrastructure | #1653 |
| e2e tests for C2M bridge | Infrastructure | #1654 |
| C2M-bridge subminimal-transfer edge-case tests | Infrastructure | #1677 |
| Nightly cNIGHT e2e job runs in a container | Infrastructure | #1658 |
| compactc: arbitrary compact dependency via submodule in CI | Infrastructure | #1662 |
qanet e2e reads contracts from reserve-contracts submodule |
Infrastructure | #1666 |
| Remove local-env + e2e-tests in partner-chains | Infrastructure | #1351 |
e2e regression coverage for genesis_extrinsics parsing |
Infrastructure | #1516 |
| Per-test tracing logger for the e2e suite | Infrastructure | #1564 |
| Local fork-testing for the 1.0.0 release train | Infrastructure | #1522 |
| Read e2e contract values from runtime-values | Infrastructure | #1348 |
| Split e2e suite into per-topic module files | Infrastructure | #1565 |
| Remove unused/outdated ddosnet network | Infrastructure | #1343 |
New features
Ledger 9 (9.1.0.0-rc.3)
Description: Moves the node, runtime, and toolkit onto ledger version 9, ending at 9.1.0.0-rc.3 (midnight-ledger-v9) at this rc. There is no state transition from ledger 8 — an existing ledger-8 chain (mainnet included) cannot be hard-forked or migrated, so 2.0.0 chains must start fresh; mixed pre-v9/post-v9 handling in block replay and toolkit caching is deliberately relaxed and unsupported. Why ledger 9, not 8.1: 8.1 was a minor (storage stability + wallet WASM bindings); ledger 9 supplies the primitives 2.0.0 is built around — the UnlockToTreasury system transaction (locked pool → treasury), ECDSA signatures for the Cardano bridge, and an explicit governed fee price floor — plus split-phase execution and panic/cost-heuristic hardening. The 9.1.0.0-rc.2 bump added a dual v1/v2 ZK proving pipeline (zk-stdlib v2 / circuits v7): zkir holds v1 or v2 prover keys behind VersionedInnerPK and defaults to v1; the ledger gains ProofVersioned::V3 for zk-stdlib-v2 proofs, and proof_verify dispatches v1/v2 by proof version while zswap verification stays on v1 for backwards compatibility. On-chain, ContractOperation gains a v3 verifier-key field (ContractOperationVersion::V4) and an ir field (contract IR on chain), with per-entry-point metadata checks capped by the new max_contract_metadata_size runtime parameter. coin-structure updates the ECDSA domain separator. The 9.1.0.0-rc.3 bump then folds the L7/L8 (2.x) and L9 (3.x) crypto stacks into a single midnight-zkir 2.2.0 (proving V0/V1 and V2 circuits), moves the ledger-state serialization encoding v17 → v18, adds IrInsert/IrRemove on-chain IR maintenance (L9-only), and replaces the parallelism_factor cost-model parameter with three FixedPoint factors (validation_factor 0.25, guaranteed_factor 1.0, fallible_factor 1.0) on new-ledger networks. Runtime metadata and undeployed genesis/test fixtures were regenerated. Runtime upgrade (ledger 9 major); the rc.2 → rc.3 patch bump is a node/toolkit upgrade — the runtime WASM is byte-identical, as the ledger is reached via host calls.
PR: #1604 (ledger 9), #1692 (9.1.0.0-rc.2), #1738 (9.1.0.0-rc.3)
Reference: ledger 9.1.0.0-rc.3 changelog · what the Ledger 9 upgrade unlocks
Cardano→Midnight bridge (inert)
Description: Introduces the c2m-bridge pallet, a stateful TransferHandler built on the partner-chains bridge pallet that holds the Midnight-specific bridge logic: it classifies Cardano transfers by distinguishing Reserve Validator and ICS Validator inputs (closing a metadata-spoofing attack on the M.R pool), redirects unapproved user transfers to the treasury while emitting UnapprovedTransfer, accumulates subminimal transfers and flushes them as one once a configured threshold is met, and treats amounts as STAR end-to-end (no NIGHT denomination conversion). The claim path was fixed (#1697) and the bridge pallets gained benchmarks + weights (#1635). Governance dispatchables set_subminimal_transfers_config and add_approved_mc_tx_hashes configure it. A toolkit bridge-transfer command submits the corresponding Cardano transaction. The bridge ships inert — its inherent-data provider reports Inert in every environment, and a governance action (setting MainChainScripts addresses + a data checkpoint) is required to enable it. Full surface (pallet extrinsics/events/storage, bridge-transfer flags, SessionInfoApi) is documented in the engineering notes. Runtime upgrade (+ Toolkit).
PR: #1386, #1333, #1513, #1477, #1393, #1608, #1697, #1635, #1340
cNIGHT contract-identifier root extrinsics
Description: Adds root extrinsics to set the Cardano cNIGHT contract identifiers on-chain, closing a gap in contract-upgradeability testing. The intended flow forks a network into local-env, swaps the contract UTXO to keep the same address while pointing at the contract's staging track, and lets the node observe the logic-round increment and adjust logic for the new version. Runtime upgrade.
PR: #1602
SessionInfoApi runtime API
Description: A new midnight-primitives-session-info::SessionInfoApi runtime API exposes current_session_index() -> u32, backed by pallet_partner_chains_session::Pallet::current_index(). Node-side code can now read the substrate session index through a typed runtime API instead of reaching into pallet storage directly. Requires a metadata rebuild. Runtime upgrade.
PR: #1534
Toolkit transaction-generation controls
Description: Adds operator-facing controls to the transaction generator: generate-txs single-tx now accepts multiple --destination-address entries, each with its own shielded/unshielded amount and token type, so one transaction can pay several recipients across both token types (#1560); --coin-selection <largest-first|smallest-first> orders coin/UTXO selection (largest-first default minimises inputs; smallest-first consolidates dust); --input-utxo <intent_hash>#<n> pins exact UTXOs as inputs, bypassing greedy selection; --print-system-tx-hex builds and prints the update-ledger-parameters system-transaction payload without submitting (no council/TC keys needed); and dust_balance::execute_many warms the wallet cache for many seeds in a single shared block replay. Toolkit.
PR: #1560, #1457, #1404, #1473, #1603
New features requiring configuration updates
storage_separation config option
Required updates:
- Set
storage_separation = "separate"(default) or"unified"in node config (TOML key, or theSTORAGE_SEPARATIONenvironment variable). There is no CLI flag. - Choose the value at chain initialisation — it cannot be changed on an existing database.
Impact: unified stores Midnight ledger and Substrate items in a single ParityDb instance, reducing the chance of cross-instance data-integrity errors on unexpected process termination. Switching modes against a populated database fails at open with IncompatibleColumnConfig; the node prints a clear error and you must delete the chain-data directory and resync. See the storage_separation operator guide.
PR: #1278
Genesis pool configuration (--allow-empty-pools)
Required updates:
- Chain-spec / genesis generation now rejects an empty reserve, ICS, locked, or treasury pool unless you pass
--allow-empty-pools. Previously, an absent reserve config silently assigned all remaining supply to the reserve pool, leaving the locked pool empty. - All
res/*environment configs now carry valid (non-zero) Reserve and ICS values and mirror mainnet pool amounts; regenerate any custom chain-specs from the updated configs.
Impact: New chain-specs will have a correctly funded locked pool. Durable-environment genesis states are unchanged except Preview, whose existing genesis/chain-spec is still wrong (config is now correct) and will likely need a reset. Runtime upgrade (genesis/chainspec) + Toolkit.
PR: #1675
stagenet network (added + regenerated)
Required updates:
- A
stagenetpreset (res/cfg/stagenet.toml) runs on Cardano Preview with 7 permissioned validators and governance split across a technical committee (validators 1-3) and council (validators 4-6). - Genesis ledger state (
res/genesis/genesis_{state,block}_stagenet.mn), chain-specs (res/stagenet/chain-spec{,-raw,-abridged}.json), and Earthfile targetsgenerate-stagenet-genesis-seeds/rebuild-genesis-state-stagenetship with it. Genesis + chain-spec were regenerated at rc.4 (#1858) — any stagenet reset must use the rc.4 artifacts.
Impact: Operators can target stagenet directly. The cNIGHT observation state starts empty and is observed forward from genesis; reserve and ICS/treasury pools carry nominal genesis amounts (ledger 9 requires non-empty pools). Node upgrade (network config).
Devnet committee + NIGHT token name
Required updates:
- Devnet now runs a 7-seat committee (D-parameter 7:0, up from 6) to keep GRANDPA quorum healthy; regenerate devnet genesis/chain-spec from the updated config.
- The NIGHT
token_asset_nameis cleared to""for devnet, qanet, preview, and preprod (backport of #1730). Tooling that keyed off the previous asset name on those networks must be updated.
Impact: Affects the four development/test networks only; deployed mainnet configuration is untouched. Node upgrade (network config).
PR: #1834
Improvements
- Ledger 9.1.0.0-rc.3 patch bump: folds the L7/L8 (2.x) vs L9 (3.x) crypto-stack split into one
midnight-zkir2.2.0 crate (proves V0/V1 and V2 circuits), retiring the frozenzkir-2.1.0workspace dep; provides the dropped upstreamverifier_key()locally so it works across all ledger versions; addsSingleUpdate::IrInsert/IrRemove(L9-only on-chain IR maintenance); and swaps theparallelism_factorcost parameter forvalidation_factor/guaranteed_factor/fallible_factor. Toolkit adapts: dual-stackContractOperationverifier-key slot selection (fixesVerifierKeyNotSeton v1 contracts),dust_actionsfolded into theIntentSigningEnvelopebeforedata_to_sign/signing (fixesInvalidDustRegistrationSignature/IntentSignatureVerificationFailure), and!Send-safe proving via aspawn_blockingcurrent-thread runtime (#1738). - Node startup:
RunMidnightwrapper flags (--no-hardware-benchmarks,--rpc-max-finality-subscriptions, …) are now parsed before config overrides are applied to the underlyingsc_cli::RunCmd, instead of being stripped/rejected (#1767/#1795). - Sync performance: bulk-read cNIGHT observation cache replaces per-query db-sync round-trips with an in-memory sliding-window cache, syncing mainnet genesis→tip in ~3 h 19 m (~572 k blocks) (#1436); epoch-nonce and federated-ops caches address residual slow-sync hot paths (#1551); the per-transaction UTXO overestimate drops from 64× to 4× (runtime-API-v2 gated so validators can't diverge mid-rollout) (#1367); the workspace
parity-dbswitches to the Midnight fork with a lower background-flush threshold andahash(#1478);autovacuum_analyze_scale_factoris tuned (0.1 → 0.01) on hot db-sync tables to avoid >400s worst-case query plans (#1434). - Validation efficiency: on ledger 9, mempool
validate_transactionand block-inclusion pre-checks dry-run only the guaranteed transaction segment viaapply_guaranteed_onlyinstead of a fullapply()that also executed the fallible segment; ledger 7/8 keep the full-apply()path (#1454). - Bridge weights:
pallet_c2m_bridgeandpallet_partner_chains_bridgegained generated benchmarks and weights (#1635). - Observability: per-session log of whether the local AURA key is in the active committee (#1534); error log when the D-parameter is below the permissioned candidate count (#1506); sanitized db-sync startup probe timings (#1411); hardware benchmarks on startup against a Midnight reference profile, with
--no-hardware-benchmarksto opt out (#1394, #1511); actionable cnight-observation genesis-failure diagnostics naming the offending chain-spec field (#1466). - Log hygiene: demote per-UTXO cNIGHT "no registration" / "no create event" warnings to
traceand drop no-signal address debug lines (#1324). - Error reporting: granular inner-cause variants for
InvalidError/MalformedError/SystemTransactionError(stable codes 212–250, metadata rebuild required) (#1449);ContractNotPresentdistinguishable from empty state, end-to-end through themidnight_contractStateRPC (#916, #1475);BeneficiaryNotFoundvs zero unclaimed reward (#1359). - Block validation: reject headers carrying more than one
mcshpre-runtime digest, mirroringsc-consensus-aura(#1617). - Toolkit UX / robustness:
contract-address --untaggedhidden from--helpwith its deprecation warning routed throughlog::warn!and--tagged --untaggednow a parse error (#1486); advisory lock on the redb fetch cache to stop concurrent-process corruption (#1493);stacker-based fix for stack overflow intrusted_deserialize_taggedon long chains (#1576); terminal-status sender error handling (#1323);BuilderContexttrait so builders no longer require a full local chain replay (#1605); dispatch toolkit-js bycompactcversion rather than ledger version (#1555).
Deprecations
None.
Breaking changes
⚠️ This is a major release:spec_version1_000_000 → 002_000_000,transaction_version3 → 4, and ledger 8 → 9 with no migration path. Existing chains cannot roll forward — start fresh. No in-place upgrade from any prior node version (including2.0.0-alpha.1through2.0.0-rc.3) is supported. Mainnet cannot be upgraded onto this line at all.
Mainnet (and any ledger-8 chain) cannot be upgraded
What changed: The 2.0.0 line ships no on-chain runtime-upgrade path and no ledger 8 → 9 state migration.
What breaks: There is no way to move mainnet — or any existing ledger-8 chain — onto a 2.0.0 node. A 2.0.0 binary loading a ledger-8 mainnet chain-spec cannot apply ledger-8 state under ledger 9. Mainnet remains on the 1.0.x / ledger-8 line.
Required actions:
- Keep mainnet on the 1.0.x line (
node-1.0.1-rc.2and successors). Do not deploy a 2.0.0 binary to a mainnet validator expecting an upgrade — none occurs. - Use 2.0.0 only for fresh development networks (local env, devnet, stagenet).
transaction_version bumped 3 → 4
What changed: The runtime transaction version moved from 3 (node 1.0.0) to 4.
What breaks: Signed extrinsics constructed against the 1.0.0 runtime metadata will no longer decode/validate. Any tooling, SDK, or service that builds and signs extrinsics must refresh its metadata.
Required actions:
- Rebuild runtime metadata against 2.0.0 and regenerate any codegen/types derived from it.
- Re-sign or re-construct pending extrinsics with the new metadata.
- Pin integrators to the 2.0.0 metadata before pointing them at a 2.0.0 chain.
Ledger 9 — no migration from ledger 8
What changed: The ledger moves to version 9 (9.1.0.0-rc.3 at this rc); this line ships no v8 → v9 state transition or hard-fork.
What breaks: An existing ledger-8 chain cannot be upgraded in place. Block replay and toolkit caching across the v8/v9 boundary are unsupported.
Required actions:
- Start a fresh ledger-9 chain from genesis.
- Do not point ledger-8 state, snapshots, or caches at a 2.0.0 binary.
rc.3+ is not compatible with rc.2
What changed: The 9.1.0.0-rc.2 → 9.1.0.0-rc.3 ledger bump changes the ledger-state serialization encoding (v17 → v18), the cost-model parameters, the intent signing envelope (dust folded into data_to_sign), and the contract verifier-key layout (dual-stack v2/v3 slots) (#1738).
What breaks: A new-ledger network running rc.2 cannot fork or migrate to rc.3/rc.4 — there is no upgrade path between the pre-releases. Transactions and ledger state serialized against rc.2 will not validate or decode under rc.3/rc.4.
Required actions:
- Reset new-ledger networks (dev/devnet/stagenet) and regenerate genesis state + chain-spec at the v18 encoding before running rc.3/rc.4.
- Rebuild any toolkit-generated fixtures/transactions against ledger
9.1.0.0-rc.3.
Partner-chains pallets removed
What changed: Partner-chains pallets not used by Midnight, and their related CLI commands, were removed (#1562).
What breaks: Any caller of those pallets' extrinsics or the removed CLI commands. Their storage no longer exists in the runtime.
Required actions:
- Drop usage of the removed extrinsics/commands. A fresh chain is required anyway, so no storage migration is involved.
Known issues
No state transition / upgrade path into 2.0.0
Description: The 2.0.0 line runs ledger 9 but ships no migration or hard-fork path from ledger 8, and no in-place upgrade from any prior node version (including earlier 2.0.0 pre-releases). Only a fresh ledger-9 chain can be started, and no ledger-8 chain — mainnet included — can be moved onto it. Mixed pre-v9/post-v9 handling in block replay and toolkit caching is deliberately relaxed and unsupported; tests requiring intent[v7] or a v8 → v9 hard-fork are ignored.
Issue: #1579
Workaround (if any): Start a fresh chain. Migration / hard-fork support is planned for a later line, not this one.
Links and references
- PRs: full set on the GitHub release pages for alpha.1, rc.1, rc.2, rc.3, and rc.4; every change above links its PR inline.
- Engineering docs:
- Migration guides: not produced — a fresh chain is required; there is no upgrade path from ledger 8 / mainnet. A migration guide will accompany the future line that introduces an on-chain upgrade path.
- API documentation: new
SessionInfoApi(current_session_index() -> u32); themidnight_contractStateRPC now surfacesContractNotPresent; ledger 9.1 regenerated runtime metadata (newmax_contract_metadata_sizeparameter; on-chainContractOperationV4; new cNIGHT contract-identifier root extrinsics). See the engineering notes. - GitHub release: https://github.com/midnightntwrk/midnight-node/releases/tag/node-2.0.0-rc.4
- Known issues board: https://github.com/midnightntwrk/midnight-node/issues?q=is%3Aissue+is%3Aopen+label%3Abug
Fixed defect list
| Defect number | Description |
|---|---|
| PM-19967 | Unbounded GRANDPA/BEEFY finality subscription fan-out could exhaust node resources (#1075) |
| PM-20015 | Wallet constructors accepted derivation paths with mismatched roles (#1076) |
| PM-22023 | DB connections allowed insecure SSL modes / unverified TLS (#1104) |
| PM-22024 | Residual all-zero WalletSeed Default needed removal verification (#1109) |
| PM-21799 | Malformed cnight-observation inherent data could panic all validators and halt the chain (#1234) |
| PM-22085 | Approved-but-failed federated-authority motions became permanently stuck (#938) |
| PM-21800 | Deadlock in LedgerContext::with_wallets_from_seeds (reentrant mutex) (#1471) |
| PM-21801 | get_unclaimed_amount returned Ok(0) for absent beneficiaries (#1359) |
| PM-19896 | cnight-observation genesis panics gave no actionable diagnostics (#1466) |
| PM-22034 | Incomplete zeroization of secret buffers after conversion (#1379) |
| PM-22018 | Unchecked arithmetic in coin selection could overflow/panic (#1293) |
| PM-22028 | Untagged CLI parser accepted trailing bytes (silent-fallback ambiguity) (#1437) |
| PM-22038 | Secret material lacked Zeroize/redacted Debug; unneeded Copy/Clone (#1217) |
| #116 | Unbounded allocation storing cNight mappings per user (#1423) |
| #1573 | dust-balance snapshot saved at block_height = 0 under dust_warp, corrupting later replays (#1574) |
| #1401 | Concurrent toolkit processes corrupted the shared redb fetch cache (#1493) |
| #1575 | Stack overflow in trusted_deserialize_tagged on long-running chains (#1576) |
| #1607 | C2M bridge applied an unnecessary NIGHT denomination to STAR amounts (#1608) |
| #1599 | New binary failed to start against an older default.toml missing unsafe_allow_symlinks (#1600) |
| #1674 | Genesis generation left the locked pool empty when reserve config was absent (assigned all remaining supply to the reserve pool) (#1675) |
| #1531 | Slow node sync from missing epoch-nonce / federated-ops caching (#1551) |
| #1158 | Slow genesis→tip sync from per-query db-sync round-trips for cNIGHT observation data (#1436) |
| #1609 | qanet e2e tests panicked at startup when local-env docker artefacts were absent (#1666) |
| C2M bridge claim | Bridge claim path was broken on an earlier untested code path (#1697) |
| Node startup args | RunMidnight wrapper flags (--no-hardware-benchmarks, --rpc-max-finality-subscriptions) were rejected before config overrides were applied (#1767, #1795) |
Other Changes
- Regenerated the
stagenetgenesis + chain-spec (#1858) and moved devnet to a 7-seat committee with a cleared NIGHTtoken_asset_nameacross devnet/qanet/preview/preprod (#1834). - cNIGHT observation e2e coverage restored against Cardano Preview, with a multi-hour
await_cnight_observationswatermark helper and a Postgres-backed shared fetch cache on qanet (#1578, #1613). - fork-network workflow gained a node-upgrade option (#1469); initial CI for fork testing (#1353); local fork-testing for the 1.0.0 release train (#1522).
- compactc: arbitrary compact dependency now supported via submodule in CI, alongside the release-based flow (#1662).
- e2e tests added for the C2M bridge (#1654) and its subminimal-transfer edge cases (#1677); local-env patches the cNIGHT
mapping_validator_addressfrom freshly compiled contracts (#1653); the nightly cNIGHT e2e job runs inside a container (#1658); qanet e2e reads contracts from thereserve-contractssubmodule (#1666). - e2e suite housekeeping: regression coverage for
genesis_extrinsicsparsing (#1516), per-test tracing logger (#1564), per-topic module split (#1565), contract values read from runtime-values (#1348). - Infra cleanup: local-files secrets mode for mock authorities (#1287); Kubernetes + AWS coupling removed from local-environment (#1470); local-env + e2e-tests removed from partner-chains (#1351); unused ddosnet network removed (#1343).