This release contains the changes from polkadot-stable2609 to polkadot-stable2609-1.
ℹ️ Please note: this is a patch release for the latest stable version stable2609. If your nodes are already running on this stable release, you should upgrade to this patch version to get the latest fixes.
ℹ️ Due to the decommissioning of the Debian bullseye build, starting from the stable release stable2612, all published binaries will be built on the Debian bookworm distribution. Please see the instructions on the Polkadot Forum
Once published, polkadot-stable2609-1 will also be tagged as polkadot-v1.25.1; the node version for this release is v1.25.1.
The following crates were updated to the corresponding versions:
Changed crates:
📦 The complete changelog with full descriptions is attached to this release as CHANGELOG.md, and in machine-readable form as changelog.json.
💥 Breaking Changes
3 changes are breaking according to Rust SemVer (each bumps the major version of at least one crate). Details in the 💥-marked entries below.
- Smart Contracts (Revive): #13419 Fix
eth_subscribe("newHeads")in the ETH RPC (pallet-revive-eth-rpc) - Smart Contracts (Revive): #13598 asset-conversion: treat frozen or blocked pools as unusable (
pallet-asset-conversion) - Node: #13637 Check the validation data (
polkadot-node-primitives)
Changelog
Bridges
🛠️ Runtime Dev
#12569: Preserve Snowbridge v1 inbound liveness when the Asset Hub sovereign is empty
Also for Runtime User
Snowbridge v1 inbound messages now burn the teleported Asset Hub execution fee from the relayer's Bridge Hub account instead of requiring funds in the Asset Hub sovereign account on Bridge Hub. The Asset Hub sovereign reimburses the relayer best-effort for the burned fee plus delivery reward when it has enough reducible balance.
This preserves the existing funded-sovereign economics while preventing an empty Asset Hub sovereign from stalling the Ethereum-to-Polkadot inbound channel. In the empty-sovereign case, the message is still processed and the nonce advances, but the relayer is not reimbursed.
Crates: snowbridge-pallet-inbound-queue (patch), snowbridge-beacon-primitives (none), bridge-hub-westend-runtime (patch)
#13640: snowbridge: restore unchecked sync committee key parsing
Restore unchecked deserialization for authenticated Ethereum sync committee public keys. Repeating the G1 subgroup check for all 512 keys makes committee-update calls exceed the synchronous Bridge Hub block budget and stalls Snowbridge at committee rotation.
Crates: snowbridge-beacon-primitives (patch), bridge-hub-westend-runtime (patch)
XCM
🛠️ Runtime Dev
#13601: Fix user losing remainder of swapped funds when pool liquidity goes below ED
pallet-asset-conversion's SwapCredit::swap_tokens_for_exact_tokens split credit_in into the amount to swap and the change, and returned only the amount to swap if the swap then failed. The change was dropped inside the storage transaction that is rolled back on failure, so the caller lost it. The full credit_in is now returned on failure, as documented.
Crates: staging-xcm-executor (patch), staging-xcm-builder (none), pallet-asset-conversion (patch)
Smart Contracts (Revive)
🛠️ Runtime Dev
💥 #13598: asset-conversion: treat frozen or blocked pools as unusable
A pool frozen or blocked for one of its assets could still be used. A frozen pool was one-way, and a blocked pool was still quoted although swaps through it failed.
Such pools are now rejected in both directions with a new PoolUnavailable error. Pools that were drained to their minimum balance are not affected.
Breaking: pallet-asset-conversion
Other crates: pallet-asset-conversion-precompiles (patch)
#13039: [pallet-revive] Enforce the storage deposit limit before recording the charge
charge_deposit now checks the storage deposit limit before recording a charge instead of recording it and resetting the whole meter on overflow. This keeps the transaction's other storage charges in place when a contract termination's deposit charge would exceed the limit, so those writes are charged and held rather than committed without a deposit.
Crates: pallet-revive (patch), pallet-revive-fixtures (minor)
#13085: [pallet-revive] System.terminate deletes the contract despite locks, freezes and holds
Also for Runtime User
No migration or configuration change is needed.
seal_terminate_logic still measures one storage deposit refund and the teardown. The refund now runs when System.terminate is called instead of at the end of the call stack, and each teardown step runs in its own storage layer. The pallet_revive weights are not regenerated for this release and no benchmark was run on it. The existing seal_terminate_logic weight is 222.45M ps ref_time, 6713 bytes proof size and 7 storage reads. The measurement after this change on master is 235.88M ps, 6348 bytes and 6 reads. The ref_time here is about 6% below that measurement, while the proof size and reads are above it. …
Crates: pallet-revive (patch), pallet-revive-uapi (patch), pallet-revive-fixtures (minor)
#13413: pallet-revive: fix callerIsRoot and callerIsOrigin across delegate calls
Also for Runtime User
No configuration or migration is needed. The change applies to deployed contracts with the runtime upgrade that includes it.
Crates: pallet-revive (patch), pallet-revive-fixtures (minor), pallet-revive-uapi (patch)
🔧 Node Dev
💥 #13419: Fix eth_subscribe("newHeads") in the ETH RPC
Also for Node Operator
eth_subscribe("newHeads") is now accepted. It was previously rejected with an invalid-params error because the server only accepted the non-standard newBlockHeaders name, which is no longer accepted.
newHeads notifications now include difficulty and mixHash. Clients such as alloy require both fields to decode a block header.
Breaking: pallet-revive-eth-rpc
Assets
🛠️ Runtime Dev
#12318: pallet-balances: Clean up empty reserves & do not send the same event twice
When reserves are cleared, the corresponding storage should be cleaned up as well. So, we do not run into MaxReserves with only empty reserves. This pull request also fixes the double sending of the same event when slashing a reserved amount.
Crates: pallet-balances (patch)
#12674: Small balance fixes
Fix account preservation below the existential deposit, hold release and transfer handling, empty hold cleanup, and dust handling when removing freezes or locks. Prevent aggregate balance overflow and preserve inactive issuance when deactivating funds.
Crates: pallet-balances (patch), frame-support (patch), pallet-assets (patch)
#13627: pallet-psm: reduce debt by the amount actually burned on redeem
redeem burns the internal asset with Preservation::Expendable. When the redeemer is left below the internal asset's min_balance, burn_from also burns that remainder and lowers the issuance by more than effective_internal_net, while PsmDebt only dropped by effective_internal_net. A plain redeem could therefore leave the issuance below the debt, failing the try_state check and keeping the debt from ever reaching zero. …
Crates: pallet-psm (patch)
Node
🔧 Node Dev
💥 #13637: Check the validation data
Candidate validation now ensures that the PersistedValidationData hash matches the persisted_validation_data_hash in the candidate descriptor, which is the one checked on chain. Candidates failing this check are rejected with the new InvalidCandidate::PersistedValidationDataMismatch.
Breaking: polkadot-node-primitives
Other crates: polkadot-node-core-candidate-validation (patch)
#13043: Slot based: Ensure we do not build two blocks on the same relay parent
The collator protocol would silently drop such a block and let the parachain get stuck for some time.
Crates: cumulus-client-consensus-aura (patch)
#13437: statement-store: enforce allowance against best and finalized blocks
Also for Node Operator
Allowance enforcement now checks each account against the larger of its best-block and finalized-block allowances. Submission checks only the best block, so enforcing the finalized allowance alone evicted, and banned for up to 48h, statements accepted after an allowance increase that was not finalized yet.
Crates: sc-statement-store (patch)
🖥️ Node Operator
#13525: relay-chain-rpc: go back to preferred connection
--relay-chain-rpc-urls is now a priority list. While on a fallback endpoint, the node checks the endpoints listed before it every 5 minutes and switches back to the first one that is reachable and has caught up with the best block, instead of staying on the fallback until that connection fails. Reconnecting no longer waits for requests on the old connection, and an endpoint whose subscriptions fail is skipped instead of stopping the node.
Crates: cumulus-relay-chain-rpc-interface (patch), cumulus-client-cli (patch)
#13562: collator-discovery: keep a reserved peer whose address set changed
The collator-discovery reserved-peer refresh removed peers by multiaddr: when a selected peer republished its authority-discovery record with a different address set, every address that disappeared turned into a removal of that peer, while the addresses that stayed produced no addition, so the peer silently lost its reservation until its record changed again. A collator restart triggers exactly this, because the node publishes its record before it has discovered all of its external addresses. The refresh now removes only the peers that have no address left in the current selection; a peer whose addresses changed keeps its reservation and receives the new addresses.
Crates: cumulus-client-collator-discovery (patch)
FRAME & Runtime
🛠️ Runtime Dev
#13421: frame-support: make #[stored] work in crates without a direct derive-where dependency
#[frame_support::stored] passes crate = frame_support::derive_where to derive_where, so the code it generates uses the frame-support re-export and compiles in crates that do not depend on derive-where directly.
Crates: frame-support-procedural (patch)
Rust compiler versions
The crates and node binaries in this release were built and tested with the following rustc toolchain; other versions may work.
- Rust Stable:
1.93.0
Docker images
The docker images for the binaries of this release can be found on Docker Hub (available a few minutes after the release has been published), all tagged with stable2609-1:
You may also pull them with:
docker pull parity/polkadot:stable2609-1
docker pull parity/polkadot-parachain:stable2609-1
docker pull parity/polkadot-omni-node:stable2609-1
docker pull parity/chain-spec-builder:stable2609-1
docker pull parity/eth-rpc:stable2609-1