Skip to content

Commit

Permalink
Add block-centric Storage API (#774)
Browse files Browse the repository at this point in the history
* blocks: Add storage method

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Add support for runtime API calls and expose it to the blocks API

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* storage: Add storage type for block centric API

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Adjust subxt to the new Storage interface

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

* Fix clippy

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
  • Loading branch information
lexnv authored Jan 20, 2023
1 parent 4155850 commit e4e9562
Show file tree
Hide file tree
Showing 17 changed files with 608 additions and 388 deletions.
4 changes: 2 additions & 2 deletions examples/examples/concurrent_storage_requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

// For storage requests, we can join futures together to
// await multiple futures concurrently:
let a_fut = api.storage().fetch(&staking_bonded, None);
let b_fut = api.storage().fetch(&staking_ledger, None);
let a_fut = api.storage().at(None).await?.fetch(&staking_bonded);
let b_fut = api.storage().at(None).await?.fetch(&staking_ledger);
let (a, b) = join!(a_fut, b_fut);

println!("{a:?}, {b:?}");
Expand Down
11 changes: 9 additions & 2 deletions examples/examples/dynamic_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
let account = api
.storage()
.fetch_or_default(&storage_address, None)
.at(None)
.await?
.fetch_or_default(&storage_address)
.await?
.to_value()?;
println!("Bob's account details: {account}");

// 4. Dynamic storage iteration (the dynamic equivalent to the fetch_all_accounts example).

let storage_address = subxt::dynamic::storage_root("System", "Account");
let mut iter = api.storage().iter(storage_address, 10, None).await?;
let mut iter = api
.storage()
.at(None)
.await?
.iter(storage_address, 10)
.await?;
while let Some((key, account)) = iter.next().await? {
println!("{}: {}", hex::encode(key), account.to_value()?);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/examples/fetch_all_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let address = polkadot::storage().system().account_root();

let mut iter = api.storage().iter(address, 10, None).await?;
let mut iter = api.storage().at(None).await?.iter(address, 10).await?;

while let Some((key, account)) = iter.next().await? {
println!("{}: {}", hex::encode(key), account.data.free);
Expand Down
19 changes: 16 additions & 3 deletions examples/examples/fetch_staking_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = OnlineClient::<PolkadotConfig>::new().await?;

let active_era_addr = polkadot::storage().staking().active_era();
let era = api.storage().fetch(&active_era_addr, None).await?.unwrap();
let era = api
.storage()
.at(None)
.await?
.fetch(&active_era_addr)
.await?
.unwrap();
println!(
"Staking active era: index: {:?}, start: {:?}",
era.index, era.start
Expand All @@ -52,13 +58,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let controller_acc_addr = polkadot::storage().staking().bonded(&alice_stash_id);
let controller_acc = api
.storage()
.fetch(&controller_acc_addr, None)
.at(None)
.await?
.fetch(&controller_acc_addr)
.await?
.unwrap();
println!(" account controlled by: {:?}", controller_acc);

let era_reward_addr = polkadot::storage().staking().eras_reward_points(era.index);
let era_result = api.storage().fetch(&era_reward_addr, None).await?;
let era_result = api
.storage()
.at(None)
.await?
.fetch(&era_reward_addr)
.await?;
println!("Era reward points: {:?}", era_result);

Ok(())
Expand Down
21 changes: 16 additions & 5 deletions examples/examples/storage_iterating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
{
let key_addr = polkadot::storage().xcm_pallet().version_notifiers_root();

let mut iter = api.storage().iter(key_addr, 10, None).await?;
let mut iter = api.storage().at(None).await?.iter(key_addr, 10).await?;

println!("\nExample 1. Obtained keys:");
while let Some((key, value)) = iter.next().await? {
Expand All @@ -52,14 +52,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Fetch at most 10 keys from below the prefix XcmPallet' VersionNotifiers.
let keys = api
.storage()
.fetch_keys(&key_addr.to_root_bytes(), 10, None, None)
.at(None)
.await?
.fetch_keys(&key_addr.to_root_bytes(), 10, None)
.await?;

println!("Example 2. Obtained keys:");
for key in keys.iter() {
println!("Key: 0x{}", hex::encode(key));

if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
if let Some(storage_data) =
api.storage().at(None).await?.fetch_raw(&key.0).await?
{
// We know the return value to be `QueryId` (`u64`) from inspecting either:
// - polkadot code
// - polkadot.rs generated file under `version_notifiers()` fn
Expand All @@ -86,13 +90,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// `twox_128("XcmPallet") ++ twox_128("VersionNotifiers") ++ twox_64(2u32) ++ 2u32`
println!("\nExample 3\nQuery key: 0x{}", hex::encode(&query_key));

let keys = api.storage().fetch_keys(&query_key, 10, None, None).await?;
let keys = api
.storage()
.at(None)
.await?
.fetch_keys(&query_key, 10, None)
.await?;

println!("Obtained keys:");
for key in keys.iter() {
println!("Key: 0x{}", hex::encode(key));

if let Some(storage_data) = api.storage().fetch_raw(&key.0, None).await? {
if let Some(storage_data) =
api.storage().at(None).await?.fetch_raw(&key.0).await?
{
// We know the return value to be `QueryId` (`u64`) from inspecting either:
// - polkadot code
// - polkadot.rs generated file under `version_notifiers()` fn
Expand Down
7 changes: 7 additions & 0 deletions subxt/src/blocks/block_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
events,
rpc::types::ChainBlockResponse,
runtime_api::RuntimeApi,
storage::Storage,
};
use derivative::Derivative;
use futures::lock::Mutex as AsyncMutex;
Expand Down Expand Up @@ -91,6 +92,12 @@ where
))
}

/// Work with storage.
pub fn storage(&self) -> Storage<T, C> {
let block_hash = self.hash();
Storage::new(self.client.clone(), block_hash)
}

/// Execute a runtime API call at this block.
pub async fn runtime_api(&self) -> Result<RuntimeApi<T, C>, Error> {
Ok(RuntimeApi::new(self.client.clone(), self.hash()))
Expand Down
19 changes: 19 additions & 0 deletions subxt/src/rpc/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,25 @@ impl<T: Config> Rpc<T> {
Ok(metadata)
}

/// Execute a runtime API call.
pub async fn call(
&self,
function: String,
call_parameters: Option<&[u8]>,
at: Option<T::Hash>,
) -> Result<types::Bytes, Error> {
let call_parameters = call_parameters.unwrap_or_default();

let bytes: types::Bytes = self
.client
.request(
"state_call",
rpc_params![function, to_hex(call_parameters), at],
)
.await?;
Ok(bytes)
}

/// Fetch system properties
pub async fn system_properties(&self) -> Result<types::SystemProperties, Error> {
self.client
Expand Down
7 changes: 5 additions & 2 deletions subxt/src/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
mod storage_address;
mod storage_client;
mod storage_map_key;
mod storage_type;

pub mod utils;

pub use storage_client::{
pub use storage_client::StorageClient;

pub use storage_type::{
KeyIter,
StorageClient,
Storage,
};

// Re-export as this is used in the public API in this module:
Expand Down
Loading

0 comments on commit e4e9562

Please sign in to comment.