Skip to content

Add DecodeWithMemTracking derive to CompactProof#11028

Merged
bkchr merged 4 commits intoparitytech:masterfrom
snowmead:add-decode-mem-tracking
Feb 10, 2026
Merged

Add DecodeWithMemTracking derive to CompactProof#11028
bkchr merged 4 commits intoparitytech:masterfrom
snowmead:add-decode-mem-tracking

Conversation

@snowmead
Copy link
Copy Markdown
Contributor

@snowmead snowmead commented Feb 9, 2026

Description

Add DecodeWithMemTracking derive to CompactProof in substrate/primitives/trie/src/storage_proof.rs.

StorageProof already derived DecodeWithMemTracking but CompactProof in the same file was missed.

Integration

No integration changes required for downstream projects. CompactProof now implements DecodeWithMemTracking, which is a strictly additive trait implementation. Existing code using CompactProof will continue to work as before.

Review Notes

Single-line change adding DecodeWithMemTracking to the derive macro list on CompactProof:

-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct CompactProof {
     pub encoded_nodes: Vec<Vec<u8>>,
 }

CompactProof only contains Vec<Vec<u8>>, which already implements DecodeWithMemTracking, so the derive works without any manual implementation.

@cla-bot-2021
Copy link
Copy Markdown

cla-bot-2021 bot commented Feb 9, 2026

User @claude, please sign the CLA here.

@bkchr
Copy link
Copy Markdown
Member

bkchr commented Feb 10, 2026

@snowmead please remove claude from the commit to make the CLA check happy.

@bkchr bkchr added the T17-primitives Changes to primitives that are not covered by any other label. label Feb 10, 2026
@bkchr
Copy link
Copy Markdown
Member

bkchr commented Feb 10, 2026

/cmd prdoc --audience runtime_dev --bump patch

snowmead and others added 2 commits February 10, 2026 08:10
`StorageProof` already derived `DecodeWithMemTracking` but `CompactProof`
in the same file was missed. The import was already present.
@snowmead snowmead force-pushed the add-decode-mem-tracking branch from 70f7c6e to d8bae7b Compare February 10, 2026 13:11
@snowmead
Copy link
Copy Markdown
Contributor Author

@bkchr can we cherry pick this change to stable2503 branch and onward?

Upgrading to stable2503 required us to make many changes in our substrate chain to no longer use CompactProof as an extrinsic parameter.

@bkchr bkchr added this pull request to the merge queue Feb 10, 2026
@bkchr bkchr added A4-backport-stable2503 Pull request must be backported to the stable2503 release branch A4-backport-stable2506 Pull request must be backported to the stable2506 release branch A4-backport-stable2509 Pull request must be backported to the stable2509 release branch A4-backport-stable2512 Pull request must be backported to the stable2512 release branch labels Feb 10, 2026
Merged via the queue into paritytech:master with commit fbddee8 Feb 10, 2026
277 of 285 checks passed
paritytech-release-backport-bot bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Add `DecodeWithMemTracking` derive to `CompactProof` in
`substrate/primitives/trie/src/storage_proof.rs`.

`StorageProof` already derived `DecodeWithMemTracking` but
`CompactProof` in the same file was missed.

## Integration

No integration changes required for downstream projects. `CompactProof`
now implements `DecodeWithMemTracking`, which is a strictly additive
trait implementation. Existing code using `CompactProof` will continue
to work as before.

## Review Notes

Single-line change adding `DecodeWithMemTracking` to the derive macro
list on `CompactProof`:

```diff
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct CompactProof {
     pub encoded_nodes: Vec<Vec<u8>>,
 }
```

`CompactProof` only contains `Vec<Vec<u8>>`, which already implements
`DecodeWithMemTracking`, so the derive works without any manual
implementation.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit fbddee8)
@paritytech-release-backport-bot
Copy link
Copy Markdown

Successfully created backport PR for stable2503:

paritytech-release-backport-bot bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Add `DecodeWithMemTracking` derive to `CompactProof` in
`substrate/primitives/trie/src/storage_proof.rs`.

`StorageProof` already derived `DecodeWithMemTracking` but
`CompactProof` in the same file was missed.

## Integration

No integration changes required for downstream projects. `CompactProof`
now implements `DecodeWithMemTracking`, which is a strictly additive
trait implementation. Existing code using `CompactProof` will continue
to work as before.

## Review Notes

Single-line change adding `DecodeWithMemTracking` to the derive macro
list on `CompactProof`:

```diff
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct CompactProof {
     pub encoded_nodes: Vec<Vec<u8>>,
 }
```

`CompactProof` only contains `Vec<Vec<u8>>`, which already implements
`DecodeWithMemTracking`, so the derive works without any manual
implementation.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit fbddee8)
@paritytech-release-backport-bot
Copy link
Copy Markdown

Successfully created backport PR for stable2506:

paritytech-release-backport-bot bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Add `DecodeWithMemTracking` derive to `CompactProof` in
`substrate/primitives/trie/src/storage_proof.rs`.

`StorageProof` already derived `DecodeWithMemTracking` but
`CompactProof` in the same file was missed.

## Integration

No integration changes required for downstream projects. `CompactProof`
now implements `DecodeWithMemTracking`, which is a strictly additive
trait implementation. Existing code using `CompactProof` will continue
to work as before.

## Review Notes

Single-line change adding `DecodeWithMemTracking` to the derive macro
list on `CompactProof`:

```diff
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct CompactProof {
     pub encoded_nodes: Vec<Vec<u8>>,
 }
```

`CompactProof` only contains `Vec<Vec<u8>>`, which already implements
`DecodeWithMemTracking`, so the derive works without any manual
implementation.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit fbddee8)
@paritytech-release-backport-bot
Copy link
Copy Markdown

Successfully created backport PR for stable2509:

paritytech-release-backport-bot bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Add `DecodeWithMemTracking` derive to `CompactProof` in
`substrate/primitives/trie/src/storage_proof.rs`.

`StorageProof` already derived `DecodeWithMemTracking` but
`CompactProof` in the same file was missed.

## Integration

No integration changes required for downstream projects. `CompactProof`
now implements `DecodeWithMemTracking`, which is a strictly additive
trait implementation. Existing code using `CompactProof` will continue
to work as before.

## Review Notes

Single-line change adding `DecodeWithMemTracking` to the derive macro
list on `CompactProof`:

```diff
-#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
 pub struct CompactProof {
     pub encoded_nodes: Vec<Vec<u8>>,
 }
```

`CompactProof` only contains `Vec<Vec<u8>>`, which already implements
`DecodeWithMemTracking`, so the derive works without any manual
implementation.

---------

Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit fbddee8)
@paritytech-release-backport-bot
Copy link
Copy Markdown

Successfully created backport PR for stable2512:

EgorPopelyaev pushed a commit that referenced this pull request Feb 11, 2026
Backport #11028 into `stable2503` from snowmead.

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

Co-authored-by: Michael Assaf <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
EgorPopelyaev added a commit that referenced this pull request Feb 12, 2026
Backport #11028 into `stable2509` from snowmead.

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

---------

Co-authored-by: Michael Assaf <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Egor_P <[email protected]>
EgorPopelyaev pushed a commit that referenced this pull request Feb 12, 2026
Backport #11028 into `stable2506` from snowmead.

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

Co-authored-by: Michael Assaf <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
EgorPopelyaev added a commit that referenced this pull request Feb 12, 2026
Backport #11028 into `stable2512` from snowmead.

See the
[documentation](https://github.com/paritytech/polkadot-sdk/blob/master/docs/BACKPORT.md)
on how to use this bot.

<!--
  # To be used by other automation, do not modify:
  original-pr-number: #${pull_number}
-->

---------

Co-authored-by: Michael Assaf <[email protected]>
Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Egor_P <[email protected]>
ffarall added a commit to Moonsong-Labs/storage-hub that referenced this pull request Mar 13, 2026
### Notable changes:

* Downgraded rust toolchain version from `1.91` to `1.90`

  ```toml
   # 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.

* 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`](https://github.com/Moonsong-Labs/storage-hub/pull/671/files#diff-c35139710c5462fa6b2f0c0376c749266f0edfc94da2acf58ddecab8c39de37dR27-R32).
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.
paritytech/polkadot-sdk#11028

* 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.

* 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.

  ```rust
  /// 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.

- 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:

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

  After:

  ```rust
  use frame_support::build_struct_json_patch;
  build_struct_json_patch!(RuntimeGenesisConfig {
      balances: BalancesConfig { ... },
  })
  ```

* 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:

  ```rust
  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:

  ```rust
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:

  ```rust
  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:

  ```rust
  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:

  ```rust
  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:

  ```rust
  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:

  ```rust
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:

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

  After:

  ```rust
  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](paritytech/polkadot-sdk#7043)):
Replace all `sp_std::*` imports with `alloc::*` or `core::*`
equivalents. Add `extern crate alloc;` where needed.

    ```rust
    // 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](paritytech/polkadot-sdk#6349)):
Migrate from `serde_json::to_value()` to the `build_struct_json_patch!`
macro.

    ```rust
    // 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](paritytech/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](paritytech/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).


<!-- devin-review-badge-begin -->

---

<a href="https://app.devin.ai/review/moonsong-labs/storage-hub/pull/671"
target="_blank">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
  </picture>
</a>
<!-- devin-review-badge-end -->

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
Co-authored-by: Facundo Farall <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A4-backport-stable2503 Pull request must be backported to the stable2503 release branch A4-backport-stable2506 Pull request must be backported to the stable2506 release branch A4-backport-stable2509 Pull request must be backported to the stable2509 release branch A4-backport-stable2512 Pull request must be backported to the stable2512 release branch T17-primitives Changes to primitives that are not covered by any other label.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants