Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

State Diff Recorder + Guard #240

Open
ggwpez opened this issue Dec 1, 2022 · 8 comments
Open

State Diff Recorder + Guard #240

ggwpez opened this issue Dec 1, 2022 · 8 comments
Labels
D2-substantial Can be fixed by an experienced coder with a working knowledge of the codebase. I5-enhancement An additional feature request. T1-FRAME This PR/Issue is related to core FRAME, the framework.

Comments

@ggwpez
Copy link
Member

ggwpez commented Dec 1, 2022

In migrations and tests it is sometimes desirable to know and restrict which storage keys change. Further it is nice to get a diff of all changes, if some unexpected changes happened.
For example a pallet migration would whitelist all storage keys with a specific prefix as "expected to change". Then later on when the migration finishes it is possible to assert that only exactly these keys changed. Otherwise a diff is printed and it panics.

Migration example of Pallet where OtherPallet can also change but nothing else:

let state_guard = StateDiffGuard::builder()
           .must_change(Prefix(Pallet::storage_prefix())
           .can_change(Prefix(OtherPallet::storage_prefix())
           .must_not_change(AnythingElse)
           .build();

// Run the migration with all the changes.

// Dropping will panic and print the *diff* iff there are unexpected changed.
sp_std::mem::drop(state_guard);

You could also try it without a builder and instead use single assert! statements, but then something like AnythingElse does not work anymore. The builder pattern helps here by holding a context.

cc @cor @kianenigma

@kianenigma
Copy link
Contributor

Nice!

I see two general ways to go about this: either try and use a proof recorded with externalities, and try and extract the list of keys changed from the proof, although this might be a bit cumbersome. Perhaps we can use a custom proof recorded.

Or, implement alternative sp_io::storage implementations that track every key written to. But this will also have its own array of difficulties.

@ggwpez
Copy link
Member Author

ggwpez commented Dec 3, 2022

Or, implement alternative sp_io::storage implementations that track every key written to. But this will also have its own array of difficulties.

I think it is trivial to do via iterating sp_storage::next_key at the beginning and end of the test/migration.

@kianenigma
Copy link
Contributor

kianenigma commented Dec 5, 2022

Also we should have a guard that makes sure all storage is decodable. This is how I would go about it:

@@ -1737,8 +1737,24 @@ type Migrations = (
        pallet_nomination_pools::migration::v2::MigrateToV2<Runtime>,
        pallet_alliance::migration::Migration<Runtime>,
        pallet_contracts::Migration<Runtime>,
+       DecodeAll<Runtime>,
 );

+struct DecodeAll;
+impl OnRuntimeUpgrade for DecodeAll {
+       fn on_runtime_upgrade() -> Weight {
+               //
+       }
+
+       #[cfg(feature = "try-runtime")]
+       fn post_upgrade(_state: Vec<u8>) -> Result<(), &'static str> {
+               // - iterate metadata
+               // - list all storage keys
+               // - decode all of ths
+               Ok(())
+       }
+}

@ggwpez
Copy link
Member Author

ggwpez commented Dec 5, 2022

Also we should have a guard that makes sure all storage is decodable

This is what i created this issue for #241

@juangirini juangirini transferred this issue from paritytech/substrate Aug 24, 2023
@the-right-joyce the-right-joyce added I5-enhancement An additional feature request. T1-FRAME This PR/Issue is related to core FRAME, the framework. D2-substantial Can be fixed by an experienced coder with a working knowledge of the codebase. and removed J0-enhancement labels Aug 25, 2023
@dastansam
Copy link
Contributor

dastansam commented Apr 8, 2024

@ggwpez this is an interesting one, would like to work on it. I am guessing StorageNoopGuard be used as an inspiration, right?

@ggwpez
Copy link
Member Author

ggwpez commented Apr 9, 2024

I am guessing StorageNoopGuard be used as an inspiration, right?

Yea, but its rather small. It is a big design space, but starting small with a good foundation should be fine since it can then be extended later. Note that this is rather difficult to get right first try, but if you can do it then its great 😄
I did not mark it as mentor as i dont really know how/what to do either, so its a bit of trial and error.

@dastansam
Copy link
Contributor

I am guessing StorageNoopGuard be used as an inspiration, right?

Yea, but its rather small. It is a big design space, but starting small with a good foundation should be fine since it can then be extended later. Note that this is rather difficult to get right first try, but if you can do it then its great 😄 I did not mark it as mentor as i dont really know how/what to do either, so its a bit of trial and error.

yeah, I see. I was thinking of writing something that simply checks if must change prefixes are actually changed. And then gradually tackle the AnythingElse and can_change cases, and the difference. This should be simple enough, no? Or maybe I am missing something?

@ggwpez
Copy link
Member Author

ggwpez commented Apr 9, 2024

yeah, I see. I was thinking of writing something that simply checks if must change prefixes are actually changed. And then gradually tackle the AnythingElse and can_change cases, and the difference. This should be simple enough, no? Or maybe I am missing something?

Yes sounds fine. One way would be to take a snapshot of the storage and then compare it. Maybe creating a storage transaction could also work 🤔 yea just try it out a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
D2-substantial Can be fixed by an experienced coder with a working knowledge of the codebase. I5-enhancement An additional feature request. T1-FRAME This PR/Issue is related to core FRAME, the framework.
Projects
Status: 📕 Backlog
Status: Draft
Status: Backlog
Development

No branches or pull requests

5 participants