mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 13:07:56 +00:00
Child trie api changes BREAKING (#4857)
Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
+132
-175
@@ -37,7 +37,7 @@ use sp_core::{
|
||||
traits::{KeystoreExt, CallInWasmExt, TaskExecutorExt},
|
||||
offchain::{OffchainExt, TransactionPoolExt},
|
||||
hexdisplay::HexDisplay,
|
||||
storage::{ChildStorageKey, ChildInfo},
|
||||
storage::ChildInfo,
|
||||
};
|
||||
|
||||
use sp_core::{
|
||||
@@ -74,19 +74,6 @@ pub enum EcdsaVerifyError {
|
||||
BadSignature,
|
||||
}
|
||||
|
||||
/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage
|
||||
/// key or panics otherwise.
|
||||
///
|
||||
/// Panicking here is aligned with what the `without_std` environment would do
|
||||
/// in the case of an invalid child storage key.
|
||||
#[cfg(feature = "std")]
|
||||
fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey {
|
||||
match ChildStorageKey::from_slice(storage_key) {
|
||||
Some(storage_key) => storage_key,
|
||||
None => panic!("child storage key is invalid"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Interface for accessing the storage from within the runtime.
|
||||
#[runtime_interface]
|
||||
pub trait Storage {
|
||||
@@ -95,30 +82,6 @@ pub trait Storage {
|
||||
self.storage(key).map(|s| s.to_vec())
|
||||
}
|
||||
|
||||
/// All Child api uses :
|
||||
/// - A `child_storage_key` to define the anchor point for the child proof
|
||||
/// (commonly the location where the child root is stored in its parent trie).
|
||||
/// - A `child_storage_types` to identify the kind of the child type and how its
|
||||
/// `child definition` parameter is encoded.
|
||||
/// - A `child_definition_parameter` which is the additional information required
|
||||
/// to use the child trie. For instance defaults child tries requires this to
|
||||
/// contain a collision free unique id.
|
||||
///
|
||||
/// This function specifically returns the data for `key` in the child storage or `None`
|
||||
/// if the key can not be found.
|
||||
fn child_get(
|
||||
&self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.child_storage(storage_key, child_info, key).map(|s| s.to_vec())
|
||||
}
|
||||
|
||||
/// Get `key` from storage, placing the value into `value_out` and return the number of
|
||||
/// bytes that the entry in storage has beyond the offset or `None` if the storage entry
|
||||
/// doesn't exist at all.
|
||||
@@ -134,135 +97,26 @@ pub trait Storage {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get `key` from child storage, placing the value into `value_out` and return the number
|
||||
/// of bytes that the entry in storage has beyond the offset or `None` if the storage entry
|
||||
/// doesn't exist at all.
|
||||
/// If `value_out` length is smaller than the returned length, only `value_out` length bytes
|
||||
/// are copied into `value_out`.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_read(
|
||||
&self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
key: &[u8],
|
||||
value_out: &mut [u8],
|
||||
value_offset: u32,
|
||||
) -> Option<u32> {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.child_storage(storage_key, child_info, key)
|
||||
.map(|value| {
|
||||
let value_offset = value_offset as usize;
|
||||
let data = &value[value_offset.min(value.len())..];
|
||||
let written = std::cmp::min(data.len(), value_out.len());
|
||||
value_out[..written].copy_from_slice(&data[..written]);
|
||||
value.len() as u32
|
||||
})
|
||||
}
|
||||
|
||||
/// Set `key` to `value` in the storage.
|
||||
fn set(&mut self, key: &[u8], value: &[u8]) {
|
||||
self.set_storage(key.to_vec(), value.to_vec());
|
||||
}
|
||||
|
||||
/// Set `key` to `value` in the child storage denoted by `child_storage_key`.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_set(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
key: &[u8],
|
||||
value: &[u8],
|
||||
) {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec());
|
||||
}
|
||||
|
||||
/// Clear the storage of the given `key` and its value.
|
||||
fn clear(&mut self, key: &[u8]) {
|
||||
self.clear_storage(key)
|
||||
}
|
||||
|
||||
/// Clear the given child storage of the given `key` and its value.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_clear(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
key: &[u8],
|
||||
) {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.clear_child_storage(storage_key, child_info, key);
|
||||
}
|
||||
|
||||
/// Clear an entire child storage.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_storage_kill(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
) {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.kill_child_storage(storage_key, child_info);
|
||||
}
|
||||
|
||||
/// Check whether the given `key` exists in storage.
|
||||
fn exists(&self, key: &[u8]) -> bool {
|
||||
self.exists_storage(key)
|
||||
}
|
||||
|
||||
/// Check whether the given `key` exists in storage.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_exists(
|
||||
&self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
key: &[u8],
|
||||
) -> bool {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.exists_child_storage(storage_key, child_info, key)
|
||||
}
|
||||
|
||||
/// Clear the storage of each key-value pair where the key starts with the given `prefix`.
|
||||
fn clear_prefix(&mut self, prefix: &[u8]) {
|
||||
Externalities::clear_prefix(*self, prefix)
|
||||
}
|
||||
|
||||
/// Clear the child storage of each key-value pair where the key starts with the given `prefix`.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_clear_prefix(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
prefix: &[u8],
|
||||
) {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.clear_child_prefix(storage_key, child_info, prefix);
|
||||
}
|
||||
|
||||
/// "Commit" all existing operations and compute the resulting storage root.
|
||||
///
|
||||
/// The hashing algorithm is defined by the `Block`.
|
||||
@@ -272,21 +126,6 @@ pub trait Storage {
|
||||
self.storage_root()
|
||||
}
|
||||
|
||||
/// "Commit" all existing operations and compute the resulting child storage root.
|
||||
///
|
||||
/// The hashing algorithm is defined by the `Block`.
|
||||
///
|
||||
/// Returns the SCALE encoded hash.
|
||||
///
|
||||
/// See `child_get` for common child api parameters.
|
||||
fn child_root(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
) -> Vec<u8> {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
self.child_storage_root(storage_key)
|
||||
}
|
||||
|
||||
/// "Commit" all existing operations and get the resulting storage change root.
|
||||
/// `parent_hash` is a SCALE encoded hash.
|
||||
///
|
||||
@@ -303,19 +142,136 @@ pub trait Storage {
|
||||
fn next_key(&mut self, key: &[u8]) -> Option<Vec<u8>> {
|
||||
self.next_storage_key(&key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the next key in storage after the given one in lexicographic order in child storage.
|
||||
fn child_next_key(
|
||||
&mut self,
|
||||
child_storage_key: &[u8],
|
||||
child_definition: &[u8],
|
||||
child_type: u32,
|
||||
/// Interface for accessing the child storage for default child trie,
|
||||
/// from within the runtime.
|
||||
#[runtime_interface]
|
||||
pub trait DefaultChildStorage {
|
||||
|
||||
/// Get a default child storage value for a given key.
|
||||
///
|
||||
/// Parameter `storage_key` is the unprefixed location of the root of the child trie in the parent trie.
|
||||
/// Result is `None` if the value for `key` in the child storage can not be found.
|
||||
fn get(
|
||||
&self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
let storage_key = child_storage_key_or_panic(child_storage_key);
|
||||
let child_info = ChildInfo::resolve_child_info(child_type, child_definition)
|
||||
.expect("Invalid child definition");
|
||||
self.next_child_storage_key(storage_key, child_info, key)
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.child_storage(&child_info, key).map(|s| s.to_vec())
|
||||
}
|
||||
|
||||
/// Allocation efficient variant of `get`.
|
||||
///
|
||||
/// Get `key` from child storage, placing the value into `value_out` and return the number
|
||||
/// of bytes that the entry in storage has beyond the offset or `None` if the storage entry
|
||||
/// doesn't exist at all.
|
||||
/// If `value_out` length is smaller than the returned length, only `value_out` length bytes
|
||||
/// are copied into `value_out`.
|
||||
fn read(
|
||||
&self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
value_out: &mut [u8],
|
||||
value_offset: u32,
|
||||
) -> Option<u32> {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.child_storage(&child_info, key)
|
||||
.map(|value| {
|
||||
let value_offset = value_offset as usize;
|
||||
let data = &value[value_offset.min(value.len())..];
|
||||
let written = std::cmp::min(data.len(), value_out.len());
|
||||
value_out[..written].copy_from_slice(&data[..written]);
|
||||
value.len() as u32
|
||||
})
|
||||
}
|
||||
|
||||
/// Set a child storage value.
|
||||
///
|
||||
/// Set `key` to `value` in the child storage denoted by `storage_key`.
|
||||
fn set(
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
value: &[u8],
|
||||
) {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.set_child_storage(&child_info, key.to_vec(), value.to_vec());
|
||||
}
|
||||
|
||||
/// Clear a child storage key.
|
||||
///
|
||||
/// For the default child storage at `storage_key`, clear value at `key`.
|
||||
fn clear (
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
) {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.clear_child_storage(&child_info, key);
|
||||
}
|
||||
|
||||
/// Clear an entire child storage.
|
||||
///
|
||||
/// If it exists, the child storage for `storage_key`
|
||||
/// is removed.
|
||||
fn storage_kill(
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
) {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.kill_child_storage(&child_info);
|
||||
}
|
||||
|
||||
/// Check a child storage key.
|
||||
///
|
||||
/// Check whether the given `key` exists in default child defined at `storage_key`.
|
||||
fn exists(
|
||||
&self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
) -> bool {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.exists_child_storage(&child_info, key)
|
||||
}
|
||||
|
||||
/// Clear child default key by prefix.
|
||||
///
|
||||
/// Clear the child storage of each key-value pair where the key starts with the given `prefix`.
|
||||
fn clear_prefix(
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
prefix: &[u8],
|
||||
) {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.clear_child_prefix(&child_info, prefix);
|
||||
}
|
||||
|
||||
/// Default child root calculation.
|
||||
///
|
||||
/// "Commit" all existing operations and compute the resulting child storage root.
|
||||
/// The hashing algorithm is defined by the `Block`.
|
||||
///
|
||||
/// Returns the SCALE encoded hash.
|
||||
fn root(
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
) -> Vec<u8> {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.child_storage_root(&child_info)
|
||||
}
|
||||
|
||||
/// Child storage key iteration.
|
||||
///
|
||||
/// Get the next key in storage after the given one in lexicographic order in child storage.
|
||||
fn next_key(
|
||||
&mut self,
|
||||
storage_key: &[u8],
|
||||
key: &[u8],
|
||||
) -> Option<Vec<u8>> {
|
||||
let child_info = ChildInfo::new_default(storage_key);
|
||||
self.next_child_storage_key(&child_info, key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,6 +975,7 @@ pub type TestExternalities = sp_state_machine::TestExternalities<sp_core::Blake2
|
||||
#[cfg(feature = "std")]
|
||||
pub type SubstrateHostFunctions = (
|
||||
storage::HostFunctions,
|
||||
default_child_storage::HostFunctions,
|
||||
misc::HostFunctions,
|
||||
offchain::HostFunctions,
|
||||
crypto::HostFunctions,
|
||||
@@ -1050,7 +1007,7 @@ mod tests {
|
||||
|
||||
t = BasicExternalities::new(Storage {
|
||||
top: map![b"foo".to_vec() => b"bar".to_vec()],
|
||||
children: map![],
|
||||
children_default: map![],
|
||||
});
|
||||
|
||||
t.execute_with(|| {
|
||||
@@ -1063,7 +1020,7 @@ mod tests {
|
||||
fn read_storage_works() {
|
||||
let mut t = BasicExternalities::new(Storage {
|
||||
top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()],
|
||||
children: map![],
|
||||
children_default: map![],
|
||||
});
|
||||
|
||||
t.execute_with(|| {
|
||||
@@ -1085,7 +1042,7 @@ mod tests {
|
||||
b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(),
|
||||
b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec()
|
||||
],
|
||||
children: map![],
|
||||
children_default: map![],
|
||||
});
|
||||
|
||||
t.execute_with(|| {
|
||||
|
||||
Reference in New Issue
Block a user