Access child storage over RPC. (#2586)

* Access child storage over RPC.

* Address review grumbles.

* Test happy case in child_storage rpc.

* Remove stray printlns

* Fix line widths.

* Bump runtime again.

* Fix genesis storage root calculation for light clients.

* Don't pass values to full_storage_root child_delta.
This commit is contained in:
Tomasz Drwięga
2019-05-19 19:02:09 +02:00
committed by DemiMarie-parity
parent a827869dfb
commit 98de97e1d9
11 changed files with 248 additions and 24 deletions
+29 -2
View File
@@ -337,19 +337,46 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
self.import_lock.clone()
}
/// Return storage entry keys in state in a block of given hash with given prefix.
/// Given a `BlockId` and a key prefix, return the matching child storage keys in that block.
pub fn storage_keys(&self, id: &BlockId<Block>, key_prefix: &StorageKey) -> error::Result<Vec<StorageKey>> {
let keys = self.state_at(id)?.keys(&key_prefix.0).into_iter().map(StorageKey).collect();
Ok(keys)
}
/// Return single storage entry of contract under given address in state in a block of given hash.
/// Given a `BlockId` and a key, return the value under the key in that block.
pub fn storage(&self, id: &BlockId<Block>, key: &StorageKey) -> error::Result<Option<StorageData>> {
Ok(self.state_at(id)?
.storage(&key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
.map(StorageData))
}
/// Given a `BlockId`, a key prefix, and a child storage key, return the matching child storage keys.
pub fn child_storage_keys(
&self,
id: &BlockId<Block>,
child_storage_key: &StorageKey,
key_prefix: &StorageKey
) -> error::Result<Vec<StorageKey>> {
let keys = self.state_at(id)?
.child_keys(&child_storage_key.0, &key_prefix.0)
.into_iter()
.map(StorageKey)
.collect();
Ok(keys)
}
/// Given a `BlockId`, a key and a child storage key, return the value under the key in that block.
pub fn child_storage(
&self,
id: &BlockId<Block>,
child_storage_key: &StorageKey,
key: &StorageKey
) -> error::Result<Option<StorageData>> {
Ok(self.state_at(id)?
.child_storage(&child_storage_key.0, &key.0).map_err(|e| error::Error::from_state(Box::new(e)))?
.map(StorageData))
}
/// Get the code at a given block.
pub fn code_at(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))?
+12 -3
View File
@@ -278,11 +278,20 @@ where
// this is only called when genesis block is imported => shouldn't be performance bottleneck
let mut storage: HashMap<Option<Vec<u8>>, StorageOverlay> = HashMap::new();
storage.insert(None, top);
// create a list of children keys to re-compute roots for
let child_delta = children.keys()
.cloned()
.map(|storage_key| (storage_key, None))
.collect::<Vec<_>>();
// make sure to persist the child storage
for (child_key, child_storage) in children {
storage.insert(Some(child_key), child_storage);
}
let storage_update: InMemoryState<H> = storage.into();
let (storage_root, _) = storage_update.storage_root(::std::iter::empty());
let (storage_root, _) = storage_update.full_storage_root(::std::iter::empty(), child_delta);
self.storage_update = Some(storage_update);
Ok(storage_root)
@@ -373,7 +382,7 @@ where
Vec::new()
}
fn keys(&self, _prefix: &Vec<u8>) -> Vec<Vec<u8>> {
fn keys(&self, _prefix: &[u8]) -> Vec<Vec<u8>> {
// whole state is not available on light node
Vec::new()
}
@@ -465,7 +474,7 @@ where
}
}
fn keys(&self, prefix: &Vec<u8>) -> Vec<Vec<u8>> {
fn keys(&self, prefix: &[u8]) -> Vec<Vec<u8>> {
match *self {
OnDemandOrGenesisState::OnDemand(ref state) =>
StateBackend::<H>::keys(state, prefix),