Skip to content

build: ⬆️ Upgrade polkadot-sdk deps to stable2503#671

Merged
ffarall merged 98 commits intomainfrom
feat/polkadot-upgrade-stable2503
Mar 13, 2026
Merged

build: ⬆️ Upgrade polkadot-sdk deps to stable2503#671
ffarall merged 98 commits intomainfrom
feat/polkadot-upgrade-stable2503

Conversation

@snowmead
Copy link
Copy Markdown
Contributor

@snowmead snowmead commented Jan 30, 2026

Notable changes:

  • Downgraded rust toolchain version from 1.91 to 1.90

     # Rust 1.90 is required due to polkadot-sdk stable2503 compatibility.
     # Rust 1.91+ breaks pallet-revive-fixtures compilation with error:
     #   "target-pointer-width: invalid type: string '64', expected u16"
     # This is because polkavm-linker generates target specs with "target-pointer-width": "64" (string),
     # but Rust 1.91 (PR #144443) changed this to require an integer: "target-pointer-width": 64.
     # polkadot-sdk stable2503 was tested with Rust 1.84.1; 1.90 is the latest compatible version.
     channel = "1.90"

    Changes were also caused by this change due to clippy warnings that were not present in 1.91.

  • derive DecodeWithMemTracking for RuntimeCall paritytech/polkadot-sdk#7634:

    DecodeWithMemTracking trait derivation was added to RuntimeCall. This change would have been simply inherited if sp-trie updated their CompactProof type which we use extensively in the codebase.

    To satisfy the bound, proof types at extrinsic boundaries now use Vec<Vec<u8>> instead of CompactProof (aliased as CompactProofEncodedNodes. This represents the encoded_nodes field of a compact proof which implements DecodeWithMemTracking by the parity-scale-code crate. The conversion to CompactProof is done internally when needed for trie operations.

    This was one of the two solutions that posed the least amount of code changes and is easier to change once CompactProof implements the new trait. The other more intrusive way was wrapping the CompactProof in a struct which implements the trait, but this lead to many changes that were hard to track.

    Note: This is a temporary workaround. Once CompactProof implements DecodeWithMemTracking upstream in sp-trie, this change will be reverted to use CompactProof directly again. Add DecodeWithMemTracking derive to CompactProof paritytech/polkadot-sdk#11028

  • Remove usage of sp-std from Substrate paritytech/polkadot-sdk#7043

    sp-std crate is deprecated and all uses of it in the codebase have been replaced with the alloc or core equivalent imports.

  • Implement cumulus StorageWeightReclaim as wrapping transaction extension + frame system ReclaimWeight paritytech/polkadot-sdk#6140

    Wrapped transaction extensions for both parachain and solochain-evm runtimes with StorageWeightReclaim. StorageWeightReclaim is meant to be used as a wrapping of the whole transaction extension pipeline, and will take into account all proof size accurately.

    /// The TransactionExtension to the basic transaction logic.
    pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
      Runtime,
      (
          frame_system::CheckNonZeroSender<Runtime>,
          frame_system::CheckSpecVersion<Runtime>,
          frame_system::CheckTxVersion<Runtime>,
          frame_system::CheckGenesis<Runtime>,
          frame_system::CheckEra<Runtime>,
          frame_system::CheckNonce<Runtime>,
          frame_system::CheckWeight<Runtime>,
          pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
          frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
      ),
    >;
  • Frontier EVM / ProofSizeExt on solochain-evm:

    Frontier EVM (stable2503) introduced get_proof_size() host function calls at multiple points in the EVM runner to measure actual proof size via the ProofSizeExt host extension. If ProofSizeExt is present during block building but absent during block import on syncing nodes, get_proof_size() returns different values on each path, leading to different gas/weight calculations, different state roots, and digest mismatch panics.

    To fix this, two changes were made to the solochain-evm node service:

    • Block building: ProposerFactory::with_proof_recording (instead of ProposerFactory::new) to register ProofSizeExt during block authoring.
    • Block import: sc_service::new_full_parts_record_import(..., true) (instead of new_full_parts) so that the Client registers ProofSizeExt during block import on syncing BSP/MSP nodes, matching the block building path.
  • runtimes: presets are provided as config patches paritytech/polkadot-sdk#6349:

    Genesis config preset files have been migrated to use the new build_struct_json_patch! macro instead of the previous pattern of constructing a full RuntimeGenesisConfig struct and serializing it with serde_json::to_value().

    Before:

    let config = RuntimeGenesisConfig {
        balances: BalancesConfig { ... },
        ..Default::default()
    };
    serde_json::to_value(config).expect("Could not build genesis config.")

    After:

    use frame_support::build_struct_json_patch;
    build_struct_json_patch!(RuntimeGenesisConfig {
        balances: BalancesConfig { ... },
    })
  • client/net: Use litep2p as the default network backend paritytech/polkadot-sdk#8461

    Substrate based chains are now configured to use litep2p as the network backend (before was libp2p)

    While litep2p implements the same wire protocol and is interoperable with libp2p nodes, several behavioral differences required fixes:

    • GRANDPA notification keepalive: In dev mode with manual sealing, the GRANDPA voter is not started but its notification protocol is still registered for P2P negotiation. litep2p kills all P2P connections if any registered notification protocol's service handle is dropped (unlike libp2p which tolerates this). A keepalive task was added that drains GRANDPA notification events without running consensus, keeping the protocol handler alive for the lifetime of the node.

    • Chunk uploader retry count: litep2p maps transient connectivity errors (ConnectionClosed, SubstreamClosed, dial-failed, etc.) to RequestFailure::Refused instead of RequestFailure::NotConnected. The chunk uploader's retry limit for Refused errors was increased from 3 to 30 to handle peer recovery scenarios during file uploads.

    • Integration tests: Integration tests were modified to take into account hew new Refused error propagation which changed timing and logging assertions in the tests.

⚠️ Breaking Changes ⚠️

  • Short description

    The transaction extension pipeline (SignedExtra / TxExtension) must now be wrapped with cumulus_pallet_weight_reclaim::StorageWeightReclaim. This wrapper measures PoV size before and after execution and reclaims unused storage weight, including weight consumed by the extensions themselves. Runtimes must also implement cumulus_pallet_weight_reclaim::Config.

    This affects:

    • The SignedExtra / TxExtension type alias
    • The from_minimal_extension implementation (must wrap the inner extension tuple)
    • The compute_signed_extra_implicit runtime API implementation (same wrapping)
  • Who is affected

    • Downstream runtimes that integrate StorageHub pallets and define their own transaction extension pipeline
    • Client code that implements ExtensionOperations::from_minimal_extension
  • Suggested code changes

    Type alias:

    Before:

    pub type SignedExtra = (
        frame_system::CheckNonZeroSender<Runtime>,
        frame_system::CheckSpecVersion<Runtime>,
        frame_system::CheckTxVersion<Runtime>,
        frame_system::CheckGenesis<Runtime>,
        frame_system::CheckEra<Runtime>,
        frame_system::CheckNonce<Runtime>,
        frame_system::CheckWeight<Runtime>,
        pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
        frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
    );

    After:

    pub type SignedExtra = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
        Runtime,
        (
            frame_system::CheckNonZeroSender<Runtime>,
            frame_system::CheckSpecVersion<Runtime>,
            frame_system::CheckTxVersion<Runtime>,
            frame_system::CheckGenesis<Runtime>,
            frame_system::CheckEra<Runtime>,
            frame_system::CheckNonce<Runtime>,
            frame_system::CheckWeight<Runtime>,
            pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
            frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
        ),
    >;

    from_minimal_extension:

    Before:

    fn from_minimal_extension(minimal: MinimalExtension) -> Self {
        (
            frame_system::CheckNonZeroSender::<Runtime>::new(),
            frame_system::CheckSpecVersion::<Runtime>::new(),
            frame_system::CheckTxVersion::<Runtime>::new(),
            frame_system::CheckGenesis::<Runtime>::new(),
            frame_system::CheckEra::<Runtime>::from(minimal.era),
            frame_system::CheckNonce::<Runtime>::from(minimal.nonce),
            frame_system::CheckWeight::<Runtime>::new(),
            pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(minimal.tip),
            frame_metadata_hash_extension::CheckMetadataHash::new(false),
        )
    }

    After:

    fn from_minimal_extension(minimal: MinimalExtension) -> Self {
        let inner = (
            frame_system::CheckNonZeroSender::<Runtime>::new(),
            frame_system::CheckSpecVersion::<Runtime>::new(),
            frame_system::CheckTxVersion::<Runtime>::new(),
            frame_system::CheckGenesis::<Runtime>::new(),
            frame_system::CheckEra::<Runtime>::from(minimal.era),
            frame_system::CheckNonce::<Runtime>::from(minimal.nonce),
            frame_system::CheckWeight::<Runtime>::new(),
            pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(minimal.tip),
            frame_metadata_hash_extension::CheckMetadataHash::new(false),
        );
        cumulus_pallet_weight_reclaim::StorageWeightReclaim::new(inner)
    }

    New pallet config required:

    impl cumulus_pallet_weight_reclaim::Config for Runtime {
        type WeightInfo = ();
    }

  • Short description

    For EVM runtimes using Frontier, both block building and block import must now register the ProofSizeExt host extension. Frontier EVM (stable2503) calls get_proof_size() at multiple points during EVM execution. If ProofSizeExt is present during block building but absent during block import on syncing nodes, get_proof_size() returns different values on each path, leading to different gas/weight calculations, different state roots, and digest mismatch panics.

    Two changes are needed in the node service:

    1. ProposerFactory::new must be replaced with ProposerFactory::with_proof_recording
    2. sc_service::new_full_parts must be replaced with sc_service::new_full_parts_record_import with proof recording enabled
  • Who is affected

    • Downstream node implementations that run Frontier EVM (solochain-evm or any EVM-enabled runtime)

    Non-EVM runtimes (e.g. parachain-only) are not affected by this specific change, though using with_proof_recording is still recommended for accurate StorageWeightReclaim operation.

  • Suggested code changes

    Block building — ProposerFactory:

    Before:

    let proposer_factory = sc_basic_authorship::ProposerFactory::new(
        task_manager.spawn_handle(),
        client.clone(),
        transaction_pool.clone(),
        prometheus_registry.as_ref(),
        telemetry.as_ref().map(|t| t.handle()),
    );

    After:

    let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording(
        task_manager.spawn_handle(),
        client.clone(),
        transaction_pool.clone(),
        prometheus_registry.as_ref(),
        telemetry.as_ref().map(|t| t.handle()),
    );

    Block import — Client initialization:

    Before:

    let (client, backend, keystore_container, task_manager) =
        sc_service::new_full_parts::<Block, RuntimeApi, _>(
            config,
            telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
            executor,
        )?;

    After:

    let (client, backend, keystore_container, task_manager) =
        sc_service::new_full_parts_record_import::<Block, RuntimeApi, _>(
            config,
            telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
            executor,
            true, // enable proof recording on import
        )?;

  • Short description

    StorageHub now targets polkadot-sdk stable2503 and frontier stable2503. Downstream consumers must align their polkadot-sdk and frontier dependency versions. This brings several inherited breaking changes from the Polkadot SDK upgrade.

  • Who is affected

    • All downstream runtimes and node implementations that depend on StorageHub crates
  • Suggested code changes

    • sp_std deprecated (polkadot-sdk#7043): Replace all sp_std::* imports with alloc::* or core::* equivalents. Add extern crate alloc; where needed.

      // Before
      use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
      
      // After
      extern crate alloc;
      use alloc::{collections::BTreeMap, vec::Vec};
    • Genesis config presets (polkadot-sdk#6349): Migrate from serde_json::to_value() to the build_struct_json_patch! macro.

      // Before
      let config = RuntimeGenesisConfig {
          balances: BalancesConfig { ... },
          ..Default::default()
      };
      serde_json::to_value(config).expect("Could not build genesis config.")
      
      // After
      use frame_support::build_struct_json_patch;
      build_struct_json_patch!(RuntimeGenesisConfig {
          balances: BalancesConfig { ... },
      })
    • pallet_session::Config: Add type DisablingStrategy = ();

    • DecodeWithMemTracking (polkadot-sdk#7634): Custom types used at extrinsic boundaries or in RuntimeCall must derive DecodeWithMemTracking from the parity-scale-codec crate.

    • litep2p default network backend (polkadot-sdk#8461): Substrate chains now use litep2p instead of libp2p by default. While litep2p is wire-compatible with libp2p, behavioral differences exist (e.g. notification protocol handling, error mapping for request-response).


Open with Devin

@snowmead snowmead added B5-clientnoteworthy Changes should be mentioned client-related release notes B7-runtimenoteworthy Changes should be noted in any runtime-upgrade release notes breaking Needs to be mentioned in breaking changes D2-noauditneeded🙈 PR doesn't need to be audited labels Jan 30, 2026
snowmead and others added 6 commits January 30, 2026 15:06
This commit fixes multiple build issues that arose from the polkadot-sdk
stable2503 upgrade when running `cargo test --features runtime-benchmarks`.

Changes:

1. Downgrade Rust to 1.90 (from 1.91)
   - polkavm-linker generates target specs with "target-pointer-width": "64" (string)
   - Rust 1.91 (PR #144443) changed this to require an integer
   - Added documentation explaining this incompatibility in rust-toolchain.toml

2. Add `extern crate alloc;` to pallets
   - Required after polkadot-sdk PR #7043 removed sp-std
   - Added to: bucket-nfts, file-system, providers

3. Fix benchmark helper trait bounds
   - pallet_nfts now requires BenchmarkHelper impl for test signature types
   - Added TestNftsBenchmarkHelper to payment-streams and file-system precompile mocks

4. Fix proofs-dealer benchmark constraints
   - Changed ForestVerifier proof type from CompactProof to ShpCompactProof
   - ShpCompactProof implements DecodeWithMemTracking required by stable2503

5. Trim runtime benchmarks to StorageHub pallets only
   - Removed frame_system, pallet_balances, and other non-StorageHub pallets
   - Reduces benchmark maintenance burden

6. Remove rococo-native feature from polkadot-cli
   - Avoids pallet-xcm -> pallet-revive dependency chain
   - External relay chain via zombienet/RPC still works

7. Add runtime-benchmarks feature to file-system precompile
   - Required for proper feature propagation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
  1. Set XcmEventEmitter to pallet_xcm::Pallet<Runtime> in parachain and xcm-simulator XCM configs for proper XCM event emission

  2. Update relay token reserve transfer test to reflect stable2503 behavior:
    - Network native asset reserve transfers are now blocked at pallet_xcm
 level with InvalidAssetUnknownReserve (Asset Hub Migration prep, PR #9544)
    - Test now expects failure at source rather than at destination
    - Balances remain unchanged since transfer is rejected early
After the polkadot-sdk stable2503 upgrade, the frame-metadata version changed
which made type decoding stricter. Polkadot.js now uses the metadata-derived
types (camelCase) instead of custom type definitions (snake_case).

Changes:
- Update ValueProposition and ValuePropositionWithId to use camelCase field names
  to match the auto-generated lookup types from runtime metadata
- Change pricePerGigaUnitOfDataPerBlock type from u64 to u128 to match runtime
- Add missing commitment and available fields to ValueProposition
- Update debt-collection.test.ts to use the new camelCase field names
- Regenerate api-augment types from updated metadata
- Bump types-bundle to 0.3.3
- Bump api-augment to 0.3.3

This fixes the error:
"Cannot read properties of undefined (reading 'price_per_giga_unit_of_data_per_block')"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@snowmead snowmead force-pushed the feat/polkadot-upgrade-stable2503 branch from b14657e to e34bb6f Compare February 2, 2026 18:08
snowmead and others added 10 commits February 2, 2026 14:08
…sfers

After polkadot-sdk stable2503, transfer_assets is disabled for network native
asset reserve transfers (#9544). Replace the test that verified failure with
a working transfer using execute with explicit XCM instructions.

The test now demonstrates the recommended approach:
- InitiateReserveWithdraw to relay chain (withdraws from sovereign account)
- InitiateTeleport to StorageHub (teleport to system chain)
- DepositAsset to beneficiary

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…types

Replace ShpCompactProof with Vec<Vec<u8>> (aliased as CompactProofEncodedNodes)
for proof types at extrinsic boundaries. This is required because polkadot-sdk
stable2503+ requires DecodeWithMemTracking for extrinsic parameters, which
CompactProof does not implement.

Changes:
- Remove ShpCompactProof struct from shp-traits
- Add CompactProofEncodedNodes type alias for Vec<Vec<u8>>
- Update CommitmentVerifier and TrieProofDeltaApplier trait implementations
  to use CompactProofEncodedNodes as the Proof type
- Convert Vec<Vec<u8>> to CompactProof internally when needed for trie ops
- Update all mock implementations, tests, and benchmarks accordingly
@snowmead snowmead force-pushed the feat/polkadot-upgrade-stable2503 branch from e342b67 to 3f0c4a6 Compare February 3, 2026 16:02
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Comment thread xcm-simulator/src/tests.rs
Comment thread sdk/scripts/build-common.js
Comment thread test/suites/integration/msp/sync-deletion-catchup.test.ts Outdated
Comment thread test/suites/integration/msp/catch-up-storage.test.ts Outdated
Comment thread node/src/service.rs
Comment thread client/src/tasks/shared/chunk_uploader.rs
Comment thread backend/lib/src/data/rpc/client.rs Outdated
Copy link
Copy Markdown
Collaborator

@ffarall ffarall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes to make sure minor fixes are applied before merging

snowmead and others added 3 commits March 12, 2026 15:56
@ffarall ffarall self-requested a review March 12, 2026 21:03
snowmead and others added 6 commits March 13, 2026 11:20
Previous tests drain the user's balance via payment stream charges
during MSP catch-up, causing the MSP to detect insolvency and reject
new storage requests with OperationNotAllowedWithInsolventUser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ffarall ffarall merged commit f0d9399 into main Mar 13, 2026
74 of 76 checks passed
@ffarall ffarall deleted the feat/polkadot-upgrade-stable2503 branch March 13, 2026 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B5-clientnoteworthy Changes should be mentioned client-related release notes B7-runtimenoteworthy Changes should be noted in any runtime-upgrade release notes breaking Needs to be mentioned in breaking changes D2-noauditneeded🙈 PR doesn't need to be audited

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants