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

storage: Decode keys of storage entry iterations #1669

Open
lexnv opened this issue Jul 3, 2024 · 2 comments
Open

storage: Decode keys of storage entry iterations #1669

lexnv opened this issue Jul 3, 2024 · 2 comments

Comments

@lexnv
Copy link
Collaborator

lexnv commented Jul 3, 2024

Fetching a query of all systems' accounts storage().system().account_iter() returns a key value struct:

  • keys contain ()
  • key_bytes contains twox System twox AccountIter [remaining-key-of-the-account]
  • value contains the account value

/// A pair of keys and values together with all the bytes that make up the storage address.
/// `keys` is `None` if non-concat hashers are used. In this case the keys could not be extracted back from the key_bytes.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct StorageKeyValuePair<T: Address> {
/// The bytes that make up the address of the storage entry.
pub key_bytes: Vec<u8>,
/// The keys that can be used to construct the address of this storage entry.
pub keys: T::Keys,
/// The value of the storage entry.
pub value: T::Target,
}

From the user's perspective, the keys field makes it a bit harder to reason about the final key we provide.
In this example, keys field does not return the account ID part of the key.

In codegen, we pass () as keys to the account_iter fn. However, we know that the keys field in this case is similar to the account fn:

:subxt::ext::subxt_core::storage::address::StaticStorageKey::new(
   ::subxt::ext::subxt_core::utils::AccountId32(pub [u8; 32])
)

Example to reproduce this:

#![allow(missing_docs)]

use std::str::FromStr;
use subxt::ext::codec::Decode;
use subxt::utils::{AccountId32, H256};
use subxt::{Config, OnlineClient, SubstrateConfig};

type ChainConfig = SubstrateConfig;

#[subxt::subxt(runtime_metadata_insecure_url = "wss://rococo-asset-hub-rpc.polkadot.io")]
pub mod asset_hub {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client =
        OnlineClient::<ChainConfig>::from_url("wss://rococo-asset-hub-rpc.polkadot.io").await?;

    let storage = client.storage().at_latest().await.unwrap();

    // Build a storage query to iterate over account information.
    let storage_query = asset_hub::storage().system().account_iter();

    // Get back an iterator of results (here, we are fetching 10 items at
    // a time from the node, but we always iterate over one at a time).
    let mut results = storage.iter(storage_query.clone()).await?;
    while let Some(Ok(kv)) = results.next().await {
        println!("Decoded key(s): {:?}", kv.keys);
        println!("Decoded key_bytes: {:?}", hex::encode(kv.key_bytes));
        println!("Value: {:?}", kv.value);
    }

    Ok(())
}
@mateuszaaa
Copy link

any hints how to actually decode storage_key ?

@jsdw
Copy link
Collaborator

jsdw commented Nov 4, 2024

You get the decoded keys back in the above example already, is kv.keys. Subxt doesn't currently provide an easy way to decode the key bytes into something different, but one possibility is to use frame-decode to give more control over how to decode the key bytes ie using https://docs.rs/frame-decode/latest/frame_decode/storage/fn.decode_storage_key.html.

I expect that this will be integrated into Subxt at some point ie #1801, at which point we should probably expose some nicer methods for accessing and decoding storage keys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants