Child trie api changes BREAKING (#4857)

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
cheme
2020-04-20 15:21:22 +02:00
committed by GitHub
parent 7d9aa81bfc
commit 4ffcf98d8d
64 changed files with 1514 additions and 1655 deletions
+111 -103
View File
@@ -28,7 +28,7 @@ use rpc::{Result as RpcResult, futures::{Future, future::result}};
use sc_rpc_api::Subscriptions;
use sc_client::{light::{blockchain::RemoteBlockchain, fetcher::Fetcher}};
use sp_core::{Bytes, storage::{StorageKey, StorageData, StorageChangeSet}};
use sp_core::{Bytes, storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet}};
use sp_version::RuntimeVersion;
use sp_runtime::traits::Block as BlockT;
@@ -37,6 +37,7 @@ use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
use self::error::{Error, FutureResult};
pub use sc_rpc_api::state::*;
pub use sc_rpc_api::child_state::*;
use sc_client_api::{ExecutorProvider, StorageProvider, BlockchainEvents, Backend};
use sp_blockchain::{HeaderMetadata, HeaderBackend};
@@ -103,49 +104,6 @@ pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
.map(|x| x.map(|x| x.0.len() as u64)))
}
/// Returns the keys with prefix from a child storage, leave empty to get all the keys
fn child_storage_keys(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>>;
/// Returns a child storage entry at a specific block's state.
fn child_storage(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<StorageData>>;
/// Returns the hash of a child storage entry at a block's state.
fn child_storage_hash(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>>;
/// Returns the size of a child storage entry at a block's state.
fn child_storage_size(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<u64>> {
Box::new(self.child_storage(block, child_storage_key, child_info, child_type, key)
.map(|x| x.map(|x| x.0.len() as u64)))
}
/// Returns the runtime metadata as an opaque blob.
fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes>;
@@ -204,7 +162,7 @@ pub trait StateBackend<Block: BlockT, Client>: Send + Sync + 'static
pub fn new_full<BE, Block: BlockT, Client>(
client: Arc<Client>,
subscriptions: Subscriptions,
) -> State<Block, Client>
) -> (State<Block, Client>, ChildState<Block, Client>)
where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
@@ -214,9 +172,11 @@ pub fn new_full<BE, Block: BlockT, Client>(
+ ProvideRuntimeApi<Block> + Send + Sync + 'static,
Client::Api: Metadata<Block, Error = sp_blockchain::Error>,
{
State {
backend: Box::new(self::state_full::FullState::new(client, subscriptions)),
}
let child_backend = Box::new(
self::state_full::FullState::new(client.clone(), subscriptions.clone())
);
let backend = Box::new(self::state_full::FullState::new(client, subscriptions));
(State { backend }, ChildState { backend: child_backend })
}
/// Create new state API that works on light node.
@@ -225,7 +185,7 @@ pub fn new_light<BE, Block: BlockT, Client, F: Fetcher<Block>>(
subscriptions: Subscriptions,
remote_blockchain: Arc<dyn RemoteBlockchain<Block>>,
fetcher: Arc<F>,
) -> State<Block, Client>
) -> (State<Block, Client>, ChildState<Block, Client>)
where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
@@ -235,14 +195,20 @@ pub fn new_light<BE, Block: BlockT, Client, F: Fetcher<Block>>(
+ Send + Sync + 'static,
F: Send + Sync + 'static,
{
State {
backend: Box::new(self::state_light::LightState::new(
let child_backend = Box::new(self::state_light::LightState::new(
client.clone(),
subscriptions.clone(),
remote_blockchain.clone(),
fetcher.clone(),
));
let backend = Box::new(self::state_light::LightState::new(
client,
subscriptions,
remote_blockchain,
fetcher,
)),
}
));
(State { backend }, ChildState { backend: child_backend })
}
/// State API with subscriptions support.
@@ -307,50 +273,6 @@ impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
self.backend.storage_size(block, key)
}
fn child_storage(
&self,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<StorageData>> {
self.backend.child_storage(block, child_storage_key, child_info, child_type, key)
}
fn child_storage_keys(
&self,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key_prefix: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Vec<StorageKey>> {
self.backend.child_storage_keys(block, child_storage_key, child_info, child_type, key_prefix)
}
fn child_storage_hash(
&self,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<Block::Hash>> {
self.backend.child_storage_hash(block, child_storage_key, child_info, child_type, key)
}
fn child_storage_size(
&self,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<u64>> {
self.backend.child_storage_size(block, child_storage_key, child_info, child_type, key)
}
fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes> {
self.backend.metadata(block)
}
@@ -402,12 +324,98 @@ impl<Block, Client> StateApi<Block::Hash> for State<Block, Client>
}
}
/// Child state backend API.
pub trait ChildStateBackend<Block: BlockT, Client>: Send + Sync + 'static
where
Block: BlockT + 'static,
Client: Send + Sync + 'static,
{
/// Returns the keys with prefix from a child storage,
/// leave prefix empty to get all the keys.
fn storage_keys(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>>;
/// Returns a child storage entry at a specific block's state.
fn storage(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<StorageData>>;
/// Returns the hash of a child storage entry at a block's state.
fn storage_hash(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>>;
/// Returns the size of a child storage entry at a block's state.
fn storage_size(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<u64>> {
Box::new(self.storage(block, storage_key, key)
.map(|x| x.map(|x| x.0.len() as u64)))
}
}
/// Child state API with subscriptions support.
pub struct ChildState<Block, Client> {
backend: Box<dyn ChildStateBackend<Block, Client>>,
}
impl<Block, Client> ChildStateApi<Block::Hash> for ChildState<Block, Client>
where
Block: BlockT + 'static,
Client: Send + Sync + 'static,
{
type Metadata = crate::metadata::Metadata;
fn storage(
&self,
storage_key: PrefixedStorageKey,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<StorageData>> {
self.backend.storage(block, storage_key, key)
}
fn storage_keys(
&self,
storage_key: PrefixedStorageKey,
key_prefix: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Vec<StorageKey>> {
self.backend.storage_keys(block, storage_key, key_prefix)
}
fn storage_hash(
&self,
storage_key: PrefixedStorageKey,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<Block::Hash>> {
self.backend.storage_hash(block, storage_key, key)
}
fn storage_size(
&self,
storage_key: PrefixedStorageKey,
key: StorageKey,
block: Option<Block::Hash>
) -> FutureResult<Option<u64>> {
self.backend.storage_size(block, storage_key, key)
}
}
fn client_err(err: sp_blockchain::Error) -> Error {
Error::Client(Box::new(err))
}
const CHILD_RESOLUTION_ERROR: &str = "Unexpected child info and type";
fn child_resolution_error() -> sp_blockchain::Error {
sp_blockchain::Error::Msg(CHILD_RESOLUTION_ERROR.to_string())
}
+80 -63
View File
@@ -29,7 +29,8 @@ use sc_client_api::backend::Backend;
use sp_blockchain::{Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata, HeaderBackend};
use sc_client::BlockchainEvents;
use sp_core::{
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet, ChildInfo},
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet,
ChildInfo, ChildType, PrefixedStorageKey},
};
use sp_version::RuntimeVersion;
use sp_runtime::{
@@ -38,7 +39,7 @@ use sp_runtime::{
use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
use super::{StateBackend, error::{FutureResult, Error, Result}, client_err, child_resolution_error};
use super::{StateBackend, ChildStateBackend, error::{FutureResult, Error, Result}, client_err};
use std::marker::PhantomData;
use sc_client_api::{CallExecutor, StorageProvider, ExecutorProvider};
@@ -308,66 +309,6 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
.map_err(client_err)))
}
fn child_storage_keys(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.child_storage_keys(
&BlockId::Hash(block),
&child_storage_key,
ChildInfo::resolve_child_info(child_type, &child_info.0[..])
.ok_or_else(child_resolution_error)?,
&prefix,
))
.map_err(client_err)))
}
fn child_storage(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<StorageData>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.child_storage(
&BlockId::Hash(block),
&child_storage_key,
ChildInfo::resolve_child_info(child_type, &child_info.0[..])
.ok_or_else(child_resolution_error)?,
&key,
))
.map_err(client_err)))
}
fn child_storage_hash(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.child_storage_hash(
&BlockId::Hash(block),
&child_storage_key,
ChildInfo::resolve_child_info(child_type, &child_info.0[..])
.ok_or_else(child_resolution_error)?,
&key,
))
.map_err(client_err)))
}
fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes> {
Box::new(result(
self.block_or_best(block)
@@ -493,7 +434,7 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
let block = self.client.info().best_hash;
let changes = keys
.into_iter()
.map(|key| self.storage(Some(block.clone()).into(), key.clone())
.map(|key| StateBackend::storage(self, Some(block.clone()).into(), key.clone())
.map(|val| (key.clone(), val))
.wait()
.unwrap_or_else(|_| (key, None))
@@ -530,6 +471,82 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
}
}
impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block, Client> where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block, Error = sp_blockchain::Error> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static,
Client::Api: Metadata<Block, Error = sp_blockchain::Error>,
{
fn storage_keys(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
None => return Err("Invalid child storage key".into()),
};
self.client.child_storage_keys(
&BlockId::Hash(block),
&child_info,
&prefix,
)
})
.map_err(client_err)))
}
fn storage(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<StorageData>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
None => return Err("Invalid child storage key".into()),
};
self.client.child_storage(
&BlockId::Hash(block),
&child_info,
&key,
)
})
.map_err(client_err)))
}
fn storage_hash(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
None => return Err("Invalid child storage key".into()),
};
self.client.child_storage_hash(
&BlockId::Hash(block),
&child_info,
&key,
)
})
.map_err(client_err)))
}
}
/// Splits passed range into two subranges where:
/// - first range has at least one element in it;
/// - second range (optionally) starts at given `middle` element.
+64 -65
View File
@@ -48,17 +48,19 @@ use sc_client::{
},
};
use sp_core::{
Bytes, OpaqueMetadata, storage::{StorageKey, StorageData, StorageChangeSet},
Bytes, OpaqueMetadata,
storage::{StorageKey, PrefixedStorageKey, StorageData, StorageChangeSet},
};
use sp_version::RuntimeVersion;
use sp_runtime::{generic::BlockId, traits::{Block as BlockT, HashFor}};
use super::{StateBackend, error::{FutureResult, Error}, client_err};
use super::{StateBackend, ChildStateBackend, error::{FutureResult, Error}, client_err};
/// Storage data map of storage keys => (optional) storage value.
type StorageMap = HashMap<StorageKey, Option<StorageData>>;
/// State API backend for light nodes.
#[derive(Clone)]
pub struct LightState<Block: BlockT, F: Fetcher<Block>, Client> {
client: Arc<Client>,
subscriptions: Subscriptions,
@@ -233,69 +235,7 @@ impl<Block, F, Client> StateBackend<Block, Client> for LightState<Block, F, Clie
block: Option<Block::Hash>,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>> {
Box::new(self
.storage(block, key)
.and_then(|maybe_storage|
result(Ok(maybe_storage.map(|storage| HashFor::<Block>::hash(&storage.0))))
)
)
}
fn child_storage_keys(
&self,
_block: Option<Block::Hash>,
_child_storage_key: StorageKey,
_child_info: StorageKey,
_child_type: u32,
_prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>> {
Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient))))
}
fn child_storage(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<StorageData>> {
let block = self.block_or_best(block);
let fetcher = self.fetcher.clone();
let child_storage = resolve_header(&*self.remote_blockchain, &*self.fetcher, block)
.then(move |result| match result {
Ok(header) => Either::Left(fetcher.remote_read_child(RemoteReadChildRequest {
block,
header,
storage_key: child_storage_key.0,
child_info: child_info.0,
child_type,
keys: vec![key.0.clone()],
retry_count: Default::default(),
}).then(move |result| ready(result
.map(|mut data| data
.remove(&key.0)
.expect("successful result has entry for all keys; qed")
.map(StorageData)
)
.map_err(client_err)
))),
Err(error) => Either::Right(ready(Err(error))),
});
Box::new(child_storage.boxed().compat())
}
fn child_storage_hash(
&self,
block: Option<Block::Hash>,
child_storage_key: StorageKey,
child_info: StorageKey,
child_type: u32,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>> {
Box::new(self
.child_storage(block, child_storage_key, child_info, child_type, key)
Box::new(StateBackend::storage(self, block, key)
.and_then(|maybe_storage|
result(Ok(maybe_storage.map(|storage| HashFor::<Block>::hash(&storage.0))))
)
@@ -518,6 +458,65 @@ impl<Block, F, Client> StateBackend<Block, Client> for LightState<Block, F, Clie
}
}
impl<Block, F, Client> ChildStateBackend<Block, Client> for LightState<Block, F, Client>
where
Block: BlockT,
Client: BlockchainEvents<Block> + HeaderBackend<Block> + Send + Sync + 'static,
F: Fetcher<Block> + 'static
{
fn storage_keys(
&self,
_block: Option<Block::Hash>,
_storage_key: PrefixedStorageKey,
_prefix: StorageKey,
) -> FutureResult<Vec<StorageKey>> {
Box::new(result(Err(client_err(ClientError::NotAvailableOnLightClient))))
}
fn storage(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<StorageData>> {
let block = self.block_or_best(block);
let fetcher = self.fetcher.clone();
let child_storage = resolve_header(&*self.remote_blockchain, &*self.fetcher, block)
.then(move |result| match result {
Ok(header) => Either::Left(fetcher.remote_read_child(RemoteReadChildRequest {
block,
header,
storage_key,
keys: vec![key.0.clone()],
retry_count: Default::default(),
}).then(move |result| ready(result
.map(|mut data| data
.remove(&key.0)
.expect("successful result has entry for all keys; qed")
.map(StorageData)
)
.map_err(client_err)
))),
Err(error) => Either::Right(ready(Err(error))),
});
Box::new(child_storage.boxed().compat())
}
fn storage_hash(
&self,
block: Option<Block::Hash>,
storage_key: PrefixedStorageKey,
key: StorageKey,
) -> FutureResult<Option<Block::Hash>> {
Box::new(ChildStateBackend::storage(self, block, storage_key, key)
.and_then(|maybe_storage|
result(Ok(maybe_storage.map(|storage| HashFor::<Block>::hash(&storage.0))))
)
)
}
}
/// Resolve header by hash.
fn resolve_header<Block: BlockT, F: Fetcher<Block>>(
remote_blockchain: &dyn RemoteBlockchain<Block>,
+24 -31
View File
@@ -21,7 +21,7 @@ use self::error::Error;
use std::sync::Arc;
use assert_matches::assert_matches;
use futures01::stream::Stream;
use sp_core::{storage::{well_known_keys, ChildInfo}, ChangesTrieConfiguration};
use sp_core::{storage::ChildInfo, ChangesTrieConfiguration};
use sp_core::hash::H256;
use sc_block_builder::BlockBuilderProvider;
use sp_io::hashing::blake2_256;
@@ -32,26 +32,28 @@ use substrate_test_runtime_client::{
};
use sp_runtime::generic::BlockId;
const CHILD_INFO: ChildInfo<'static> = ChildInfo::new_default(b"unique_id");
const STORAGE_KEY: &[u8] = b"child";
fn prefixed_storage_key() -> PrefixedStorageKey {
let child_info = ChildInfo::new_default(&STORAGE_KEY[..]);
child_info.prefixed_storage_key()
}
#[test]
fn should_return_storage() {
const KEY: &[u8] = b":mock";
const VALUE: &[u8] = b"hello world";
const STORAGE_KEY: &[u8] = b":child_storage:default:child";
const CHILD_VALUE: &[u8] = b"hello world !";
let child_info = ChildInfo::new_default(STORAGE_KEY);
let mut core = tokio::runtime::Runtime::new().unwrap();
let client = TestClientBuilder::new()
.add_extra_storage(KEY.to_vec(), VALUE.to_vec())
.add_extra_child_storage(STORAGE_KEY.to_vec(), CHILD_INFO, KEY.to_vec(), CHILD_VALUE.to_vec())
.add_extra_child_storage(&child_info, KEY.to_vec(), CHILD_VALUE.to_vec())
.build();
let genesis_hash = client.genesis_hash();
let client = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor())));
let (client, child) = new_full(Arc::new(client), Subscriptions::new(Arc::new(core.executor())));
let key = StorageKey(KEY.to_vec());
let storage_key = StorageKey(STORAGE_KEY.to_vec());
let (child_info, child_type) = CHILD_INFO.info();
let child_info = StorageKey(child_info.to_vec());
assert_eq!(
client.storage(key.clone(), Some(genesis_hash).into()).wait()
@@ -69,7 +71,7 @@ fn should_return_storage() {
);
assert_eq!(
core.block_on(
client.child_storage(storage_key, child_info, child_type, key, Some(genesis_hash).into())
child.storage(prefixed_storage_key(), key, Some(genesis_hash).into())
.map(|x| x.map(|x| x.0.len()))
).unwrap().unwrap() as usize,
CHILD_VALUE.len(),
@@ -79,45 +81,36 @@ fn should_return_storage() {
#[test]
fn should_return_child_storage() {
let (child_info, child_type) = CHILD_INFO.info();
let child_info = StorageKey(child_info.to_vec());
let child_info = ChildInfo::new_default(STORAGE_KEY);
let core = tokio::runtime::Runtime::new().unwrap();
let client = Arc::new(substrate_test_runtime_client::TestClientBuilder::new()
.add_child_storage("test", "key", CHILD_INFO, vec![42_u8])
.add_child_storage(&child_info, "key", vec![42_u8])
.build());
let genesis_hash = client.genesis_hash();
let client = new_full(client, Subscriptions::new(Arc::new(core.executor())));
let child_key = StorageKey(
well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().chain(b"test").cloned().collect()
);
let (_client, child) = new_full(client, Subscriptions::new(Arc::new(core.executor())));
let child_key = prefixed_storage_key();
let key = StorageKey(b"key".to_vec());
assert_matches!(
client.child_storage(
child.storage(
child_key.clone(),
child_info.clone(),
child_type,
key.clone(),
Some(genesis_hash).into(),
).wait(),
Ok(Some(StorageData(ref d))) if d[0] == 42 && d.len() == 1
);
assert_matches!(
client.child_storage_hash(
child.storage_hash(
child_key.clone(),
child_info.clone(),
child_type,
key.clone(),
Some(genesis_hash).into(),
).wait().map(|x| x.is_some()),
Ok(true)
);
assert_matches!(
client.child_storage_size(
child.storage_size(
child_key.clone(),
child_info.clone(),
child_type,
key.clone(),
None,
).wait(),
@@ -130,7 +123,7 @@ fn should_call_contract() {
let core = tokio::runtime::Runtime::new().unwrap();
let client = Arc::new(substrate_test_runtime_client::new());
let genesis_hash = client.genesis_hash();
let client = new_full(client, Subscriptions::new(Arc::new(core.executor())));
let (client, _child) = new_full(client, Subscriptions::new(Arc::new(core.executor())));
assert_matches!(
client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()).wait(),
@@ -146,7 +139,7 @@ fn should_notify_about_storage_changes() {
{
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
api.subscribe_storage(Default::default(), subscriber, None.into());
@@ -179,7 +172,7 @@ fn should_send_initial_storage_changes_and_notifications() {
{
let mut client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(remote)));
let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
@@ -215,7 +208,7 @@ fn should_send_initial_storage_changes_and_notifications() {
fn should_query_storage() {
fn run_tests(mut client: Arc<TestClient>, has_changes_trie_config: bool) {
let core = tokio::runtime::Runtime::new().unwrap();
let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let mut add_block = |nonce| {
let mut builder = client.new_block(Default::default()).unwrap();
@@ -434,7 +427,7 @@ fn should_return_runtime_version() {
let core = tokio::runtime::Runtime::new().unwrap();
let client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",3],\
@@ -458,7 +451,7 @@ fn should_notify_on_runtime_version_initially() {
{
let client = Arc::new(substrate_test_runtime_client::new());
let api = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
let (api, _child) = new_full(client.clone(), Subscriptions::new(Arc::new(core.executor())));
api.subscribe_runtime_version(Default::default(), subscriber);