Skip to content

Version pallet-revive storage types#11990

Open
0xOmarA wants to merge 29 commits into
0xOmarA/versioning-typesfrom
0xOmarA/versioned-storage
Open

Version pallet-revive storage types#11990
0xOmarA wants to merge 29 commits into
0xOmarA/versioning-typesfrom
0xOmarA/versioned-storage

Conversation

@0xOmarA
Copy link
Copy Markdown
Contributor

@0xOmarA 0xOmarA commented May 5, 2026

Description

This pull request is part of the pallet-revive versioning effort described in #11923 and closes #11943.

This PR builds on top of the versioned-types work. It does not introduce the pallet-revive-types crate or the versioning proc macros. Instead, it starts using that infrastructure to separate pallet-revive execution types from the types encoded into storage.

The main change is the introduction and adoption of StorageCodecWrapper<ExecutionType, StorageType>. The wrapper lets pallet-revive continue operating on execution-facing types while delegating SCALE encoding, decoding, metadata, and encoded-size behavior to explicit storage-facing types.

This PR also:

  • adds type-system helpers for extracting FRAME storage value and map types.
  • adds the #[versioned_type(encode_like = "...")] helper to the existing versioned type macro.
  • moves pallet-revive storage declarations onto versioned storage models.
  • updates migrations, benchmarks, tests, RPC helpers, and EVM compatibility code to work with the wrapped storage values.
  • removes SCALE codec derives from execution-only types where possible.
  • adds compatibility tests against pre-storage-versioning metadata and old generated types.

The goal is to make the storage boundary explicit without changing the existing storage wire layout.

Integration

Downstream projects should not need a storage migration for existing pallet-revive data as a result of this PR. The storage declarations now use wrapped versioned storage models, but the encoded bytes are intended to remain compatible with the pre-versioning layout.

Code that directly imports pallet-revive internals may need to account for StorageCodecWrapper at storage boundaries. Most pallet execution code should continue to work with the execution-facing values exposed by the wrapper through Deref, as_inner, into_inner, conversions, and mutation helpers.

Important

The intended integration behavior is that storage bytes do not change. The added tests compare the new versioned storage models against pre-versioning metadata and also compare full current Revive storage metadata against the old metadata fixture.

Note

This PR is one step toward the final versioning model. Some execution-facing types still need codec implementations because they are still used at runtime API or other boundary surfaces. The direction is to keep moving those codec responsibilities to explicit boundary types.

Review Notes

StorageCodecWrapper<ExecutionType, StorageType> is the storage-boundary adapter added by this PR. It stores both representations:

pub struct StorageCodecWrapper<ExecutionType, StorageType> {
	inner: ExecutionType,
	codable: StorageType,
}

inner is the value pallet code works with. codable is the cached storage representation used for SCALE encoding, MaxEncodedLen, and TypeInfo. This type sits exactly at the boundary seen in the diagram below:

image

The wrapper keeps both values synchronized by requiring mutations to go through mutate or try_mutate. Those methods update the execution value and then refresh the cached storage value by converting the execution type into the storage type.

Warning

StorageCodecWrapper is intended for storage boundaries only. It should not become a general-purpose execution wrapper; its job is specifically to make one type encode and decode as another type.

The storage declarations in pallet-revive now use the wrapper for storage items that need explicit storage models. For example, execution code can still work with types like CodeInfo<T>, while storage metadata and encoding are driven by storage_types::CodeInfoV2<...>.

The encode_like macro addition exists because several new storage models intentionally preserve the old byte representation of existing source types. The macro emits codec::EncodeLike<Target> impls for the listed source types, so existing FRAME storage APIs can continue accepting byte-compatible values without forcing call sites to manually construct the storage model first.

Tip

Review StorageCodecWrapper first, then review how each pallet storage declaration uses it. That is the core mechanism for separating execution-facing and storage-facing types.

Tests

The tests in this PR protect against accidentally changing the SCALE bytes used for existing pallet-revive storage while introducing versioned storage models and storage wrappers. If these tests pass, they prove that the new storage-facing types and the current runtime storage metadata remain compatible with the pre-storage-versioning layout that existing chains and off-chain clients expect.

  • pallet-revive-types tests compare individual new storage types against old metadata-generated types and assert cross-decode/identical encoding behavior.
  • revive-dev-runtime tests compare the full current Revive storage metadata against a checked-in pre-storage-versioning fixture by SCALE wire layout.

Tip

The storage compatibility tests are the main guardrail for this PR. They are intended to make wrapper adoption safe by proving that the new storage models still match the old SCALE layout.

0xOmarA added 23 commits May 1, 2026 12:59
Added a wrapper for all storage keys and values which will be used to
have separation between the storage types and the execution types while
trying our best to keep the "illusion" that what's stored in storage is
the execution type.

We try to balance this out to make sure that this illusion is maintained
so long as it's not hurtful for it to be maintained and revealed only
when its needed.
Previously, there was no way for us, in the type-system, to determine
what types were being used in storage. This commit introduces simple
traits and some simple "type-system functions" which answer questions
like "given this StorageValue type, what's the actual value being used
here".
This commit adds the very first usage of versioned storage for the
`DebugSettings` type.
This commit adds an `encode_like` attribute to the define_versioned_type
macro which allows us to automatically derive `EncodeLike` for the types
we define.

This is useful to get us to minimize some of the changes we're making as
we version the storage types so that some call-sites do not need to be
modified.
This commit adds tests to ensure that the new storage types added in
#11956 do encode and
decode in the same way as the previous types which we used to use for
storage.
@0xOmarA 0xOmarA requested a review from a team as a code owner May 5, 2026 22:01
@0xOmarA 0xOmarA added the T7-smart_contracts This PR/Issue is related to smart contracts. label May 5, 2026
@0xOmarA 0xOmarA linked an issue May 5, 2026 that may be closed by this pull request
@0xOmarA
Copy link
Copy Markdown
Contributor Author

0xOmarA commented May 5, 2026

/cmd prdoc --audience runtime_dev --bump minor

0xOmarA added 3 commits May 6, 2026 20:20
This is a change which is motivated by the fact that the various macros
used by pallets create a `storage_types` module whose name conflicted
with the existing `storage_types` alias we had been using.

This commit just makes a simple rename from `storage_types` into
`revive_storage_types`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T7-smart_contracts This PR/Issue is related to smart contracts.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[pallet-revive] Storage Versioning

1 participant