// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of subxt.
//
// subxt is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// subxt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see .
//! For querying runtime storage.
use codec::{
Decode,
Encode,
};
use sp_core::storage::{
StorageChangeSet,
StorageData,
StorageKey,
};
pub use sp_runtime::traits::SignedExtension;
pub use sp_version::RuntimeVersion;
use std::marker::PhantomData;
use crate::{
metadata::{
Metadata,
MetadataError,
},
rpc::Rpc,
Config,
Error,
StorageHasher,
};
/// Storage entry trait.
pub trait StorageEntry {
/// Pallet name.
const PALLET: &'static str;
/// Storage name.
const STORAGE: &'static str;
/// Type of the storage entry value.
type Value: Decode;
/// Get the key data for the storage.
fn key(&self) -> StorageEntryKey;
}
/// The prefix of the key to a [`StorageEntry`]
pub struct StorageKeyPrefix(Vec);
impl StorageKeyPrefix {
/// Create the storage key prefix for a [`StorageEntry`]
pub fn new() -> Self {
let mut bytes = sp_core::twox_128(T::PALLET.as_bytes()).to_vec();
bytes.extend(&sp_core::twox_128(T::STORAGE.as_bytes())[..]);
Self(bytes)
}
/// Convert the prefix into a [`StorageKey`]
pub fn to_storage_key(self) -> StorageKey {
StorageKey(self.0)
}
}
/// Storage key.
pub enum StorageEntryKey {
/// Plain key.
Plain,
/// Map key(s).
Map(Vec),
}
impl StorageEntryKey {
/// Construct the final [`sp_core::storage::StorageKey`] for the storage entry.
pub fn final_key(&self, prefix: StorageKeyPrefix) -> sp_core::storage::StorageKey {
let mut bytes = prefix.0;
if let Self::Map(map_keys) = self {
for map_key in map_keys {
bytes.extend(Self::hash(&map_key.hasher, &map_key.value))
}
}
sp_core::storage::StorageKey(bytes)
}
fn hash(hasher: &StorageHasher, bytes: &[u8]) -> Vec {
match hasher {
StorageHasher::Identity => bytes.to_vec(),
StorageHasher::Blake2_128 => sp_core::blake2_128(bytes).to_vec(),
StorageHasher::Blake2_128Concat => {
// copied from substrate Blake2_128Concat::hash since StorageHasher is not public
sp_core::blake2_128(bytes)
.iter()
.chain(bytes)
.cloned()
.collect()
}
StorageHasher::Blake2_256 => sp_core::blake2_256(bytes).to_vec(),
StorageHasher::Twox128 => sp_core::twox_128(bytes).to_vec(),
StorageHasher::Twox256 => sp_core::twox_256(bytes).to_vec(),
StorageHasher::Twox64Concat => {
sp_core::twox_64(bytes)
.iter()
.chain(bytes)
.cloned()
.collect()
}
}
}
}
/// Storage key for a Map.
pub struct StorageMapKey {
value: Vec,
hasher: StorageHasher,
}
impl StorageMapKey {
/// Create a new [`StorageMapKey`] with the encoded data and the hasher.
pub fn new(value: &T, hasher: StorageHasher) -> Self {
Self {
value: value.encode(),
hasher,
}
}
}
/// Client for querying runtime storage.
#[derive(Clone)]
pub struct StorageClient<'a, T: Config> {
rpc: &'a Rpc,
metadata: &'a Metadata,
iter_page_size: u32,
}
impl<'a, T: Config> StorageClient<'a, T> {
/// Create a new [`StorageClient`]
pub fn new(rpc: &'a Rpc, metadata: &'a Metadata, iter_page_size: u32) -> Self {
Self {
rpc,
metadata,
iter_page_size,
}
}
/// Fetch the value under an unhashed storage key
pub async fn fetch_unhashed(
&self,
key: StorageKey,
hash: Option,
) -> Result