Add storage_version() and runtime_wasm_code() to storage (#1111)

* add storage_version function

* get runtime code

* add tests

* clippy fix

* just support CODE, remove other well known keys

* remove u16 wrapper
This commit is contained in:
Tadeo Hepperle
2023-08-10 15:40:38 +02:00
committed by GitHub
parent b97acc5df6
commit 9723a50969
4 changed files with 72 additions and 4 deletions
+39 -1
View File
@@ -3,6 +3,7 @@
// see LICENSE for license details.
use super::storage_address::{StorageAddress, Yes};
use crate::{
client::OnlineClientT,
error::{Error, MetadataError},
@@ -10,6 +11,7 @@ use crate::{
rpc::types::{StorageData, StorageKey},
Config,
};
use codec::Decode;
use derivative::Derivative;
use std::{future::Future, marker::PhantomData};
use subxt_metadata::{PalletMetadata, StorageEntryMetadata, StorageEntryType};
@@ -237,6 +239,42 @@ where
})
}
}
/// The storage version of a pallet.
/// The storage version refers to the `frame_support::traits::Metadata::StorageVersion` type.
pub async fn storage_version(&self, pallet_name: impl AsRef<str>) -> Result<u16, Error> {
// check that the pallet exists in the metadata:
self.client
.metadata()
.pallet_by_name(pallet_name.as_ref())
.ok_or_else(|| MetadataError::PalletNameNotFound(pallet_name.as_ref().into()))?;
// construct the storage key. This is done similarly in `frame_support::traits::metadata::StorageVersion::storage_key()`.
pub const STORAGE_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__STORAGE_VERSION__:";
let mut key_bytes: Vec<u8> = vec![];
key_bytes.extend(&sp_core_hashing::twox_128(pallet_name.as_ref().as_bytes()));
key_bytes.extend(&sp_core_hashing::twox_128(
STORAGE_VERSION_STORAGE_KEY_POSTFIX,
));
// fetch the raw bytes and decode them into the StorageVersion struct:
let storage_version_bytes = self.fetch_raw(&key_bytes).await?.ok_or_else(|| {
format!(
"Unexpected: entry for storage version in pallet \"{}\" not found",
pallet_name.as_ref()
)
})?;
u16::decode(&mut &storage_version_bytes[..]).map_err(Into::into)
}
/// Fetches the Wasm code of the runtime.
pub async fn runtime_wasm_code(&self) -> Result<Vec<u8>, Error> {
// note: this should match the `CODE` constant in `sp_core::storage::well_known_keys`
const CODE: &str = ":code";
self.fetch_raw(CODE.as_bytes()).await?.ok_or_else(|| {
format!("Unexpected: entry for well known key \"{CODE}\" not found").into()
})
}
}
/// Iterates over key value pairs in a map.
@@ -338,7 +376,7 @@ fn validate_storage(
hash: [u8; 32],
) -> Result<(), Error> {
let Some(expected_hash) = pallet.storage_hash(storage_name) else {
return Err(MetadataError::IncompatibleCodegen.into())
return Err(MetadataError::IncompatibleCodegen.into());
};
if expected_hash != hash {
return Err(MetadataError::IncompatibleCodegen.into());