#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use sp_debug_derive::RuntimeDebug;
use alloc::vec::Vec;
use codec::{Decode, Encode};
use core::{
fmt::Display,
ops::{Deref, DerefMut},
};
use ref_cast::RefCast;
#[derive(PartialEq, Eq, RuntimeDebug)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode)
)]
pub struct StorageKey(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
impl AsRef<[u8]> for StorageKey {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
#[derive(PartialEq, Eq, Ord, PartialOrd, core::hash::Hash, RuntimeDebug, Clone, Encode, Decode)]
pub struct TrackedStorageKey {
pub key: Vec<u8>,
pub reads: u32,
pub writes: u32,
pub whitelisted: bool,
}
impl TrackedStorageKey {
pub fn new(key: Vec<u8>) -> Self {
Self { key, reads: 0, writes: 0, whitelisted: false }
}
pub fn has_been_read(&self) -> bool {
self.whitelisted || self.reads > 0u32 || self.has_been_written()
}
pub fn has_been_written(&self) -> bool {
self.whitelisted || self.writes > 0u32
}
pub fn add_read(&mut self) {
self.reads += 1;
}
pub fn add_write(&mut self) {
self.writes += 1;
}
pub fn whitelist(&mut self) {
self.whitelisted = true;
}
}
impl From<Vec<u8>> for TrackedStorageKey {
fn from(key: Vec<u8>) -> Self {
Self { key, reads: 0, writes: 0, whitelisted: true }
}
}
#[derive(PartialEq, Eq, RuntimeDebug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))]
#[repr(transparent)]
#[derive(RefCast)]
pub struct PrefixedStorageKey(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] Vec<u8>,
);
impl Deref for PrefixedStorageKey {
type Target = Vec<u8>;
fn deref(&self) -> &Vec<u8> {
&self.0
}
}
impl DerefMut for PrefixedStorageKey {
fn deref_mut(&mut self) -> &mut Vec<u8> {
&mut self.0
}
}
impl PrefixedStorageKey {
pub fn new(inner: Vec<u8>) -> Self {
PrefixedStorageKey(inner)
}
pub fn new_ref(inner: &Vec<u8>) -> &Self {
PrefixedStorageKey::ref_cast(inner)
}
pub fn into_inner(self) -> Vec<u8> {
self.0
}
}
#[derive(PartialEq, Eq, RuntimeDebug)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode, Default)
)]
pub struct StorageData(
#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
);
#[cfg(feature = "std")]
pub type StorageMap = std::collections::BTreeMap<Vec<u8>, Vec<u8>>;
#[cfg(feature = "std")]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct StorageChild {
pub data: StorageMap,
pub child_info: ChildInfo,
}
#[cfg(feature = "std")]
#[derive(Default, Debug, Clone)]
pub struct Storage {
pub top: StorageMap,
pub children_default: std::collections::HashMap<Vec<u8>, StorageChild>,
}
#[derive(RuntimeDebug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, PartialEq, Eq, Clone))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct StorageChangeSet<Hash> {
pub block: Hash,
pub changes: Vec<(StorageKey, Option<StorageData>)>,
}
pub mod well_known_keys {
pub const CODE: &[u8] = b":code";
pub const HEAP_PAGES: &[u8] = b":heappages";
pub const EXTRINSIC_INDEX: &[u8] = b":extrinsic_index";
pub const INTRABLOCK_ENTROPY: &[u8] = b":intrablock_entropy";
pub const CHILD_STORAGE_KEY_PREFIX: &[u8] = b":child_storage:";
pub const DEFAULT_CHILD_STORAGE_KEY_PREFIX: &[u8] = b":child_storage:default:";
pub fn is_default_child_storage_key(key: &[u8]) -> bool {
key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX)
}
pub fn is_child_storage_key(key: &[u8]) -> bool {
key.starts_with(CHILD_STORAGE_KEY_PREFIX)
}
pub fn starts_with_child_storage_key(key: &[u8]) -> bool {
if key.len() > CHILD_STORAGE_KEY_PREFIX.len() {
key.starts_with(CHILD_STORAGE_KEY_PREFIX)
} else {
CHILD_STORAGE_KEY_PREFIX.starts_with(key)
}
}
}
pub const TRIE_VALUE_NODE_THRESHOLD: u32 = 33;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))]
pub enum ChildInfo {
ParentKeyId(ChildTrieParentKeyId),
}
impl ChildInfo {
pub fn new_default(storage_key: &[u8]) -> Self {
let data = storage_key.to_vec();
ChildInfo::ParentKeyId(ChildTrieParentKeyId { data })
}
pub fn new_default_from_vec(storage_key: Vec<u8>) -> Self {
ChildInfo::ParentKeyId(ChildTrieParentKeyId { data: storage_key })
}
pub fn try_update(&mut self, other: &ChildInfo) -> bool {
match self {
ChildInfo::ParentKeyId(child_trie) => child_trie.try_update(other),
}
}
#[inline]
pub fn keyspace(&self) -> &[u8] {
match self {
ChildInfo::ParentKeyId(..) => self.storage_key(),
}
}
pub fn storage_key(&self) -> &[u8] {
match self {
ChildInfo::ParentKeyId(ChildTrieParentKeyId { data }) => &data[..],
}
}
pub fn prefixed_storage_key(&self) -> PrefixedStorageKey {
match self {
ChildInfo::ParentKeyId(ChildTrieParentKeyId { data }) =>
ChildType::ParentKeyId.new_prefixed_key(data.as_slice()),
}
}
pub fn into_prefixed_storage_key(self) -> PrefixedStorageKey {
match self {
ChildInfo::ParentKeyId(ChildTrieParentKeyId { mut data }) => {
ChildType::ParentKeyId.do_prefix_key(&mut data);
PrefixedStorageKey(data)
},
}
}
pub fn child_type(&self) -> ChildType {
match self {
ChildInfo::ParentKeyId(..) => ChildType::ParentKeyId,
}
}
}
#[repr(u32)]
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ChildType {
ParentKeyId = 1,
}
impl ChildType {
pub fn new(repr: u32) -> Option<ChildType> {
Some(match repr {
r if r == ChildType::ParentKeyId as u32 => ChildType::ParentKeyId,
_ => return None,
})
}
pub fn from_prefixed_key<'a>(storage_key: &'a PrefixedStorageKey) -> Option<(Self, &'a [u8])> {
let match_type = |storage_key: &'a [u8], child_type: ChildType| {
let prefix = child_type.parent_prefix();
if storage_key.starts_with(prefix) {
Some((child_type, &storage_key[prefix.len()..]))
} else {
None
}
};
match_type(storage_key, ChildType::ParentKeyId)
}
fn new_prefixed_key(&self, key: &[u8]) -> PrefixedStorageKey {
let parent_prefix = self.parent_prefix();
let mut result = Vec::with_capacity(parent_prefix.len() + key.len());
result.extend_from_slice(parent_prefix);
result.extend_from_slice(key);
PrefixedStorageKey(result)
}
fn do_prefix_key(&self, key: &mut Vec<u8>) {
let parent_prefix = self.parent_prefix();
let key_len = key.len();
if !parent_prefix.is_empty() {
key.resize(key_len + parent_prefix.len(), 0);
key.copy_within(..key_len, parent_prefix.len());
key[..parent_prefix.len()].copy_from_slice(parent_prefix);
}
}
pub fn parent_prefix(&self) -> &'static [u8] {
match self {
&ChildType::ParentKeyId => well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))]
pub struct ChildTrieParentKeyId {
data: Vec<u8>,
}
impl ChildTrieParentKeyId {
fn try_update(&mut self, other: &ChildInfo) -> bool {
match other {
ChildInfo::ParentKeyId(other) => self.data[..] == other.data[..],
}
}
}
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(Encode, Decode))]
pub enum StateVersion {
V0 = 0,
#[default]
V1 = 1,
}
impl Display for StateVersion {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
StateVersion::V0 => f.write_str("0"),
StateVersion::V1 => f.write_str("1"),
}
}
}
impl From<StateVersion> for u8 {
fn from(version: StateVersion) -> u8 {
version as u8
}
}
impl TryFrom<u8> for StateVersion {
type Error = ();
fn try_from(val: u8) -> core::result::Result<StateVersion, ()> {
match val {
0 => Ok(StateVersion::V0),
1 => Ok(StateVersion::V1),
_ => Err(()),
}
}
}
impl StateVersion {
pub fn state_value_threshold(&self) -> Option<u32> {
match self {
StateVersion::V0 => None,
StateVersion::V1 => Some(TRIE_VALUE_NODE_THRESHOLD),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prefix_default_child_info() {
let child_info = ChildInfo::new_default(b"any key");
let prefix = child_info.child_type().parent_prefix();
assert!(prefix.starts_with(well_known_keys::CHILD_STORAGE_KEY_PREFIX));
assert!(prefix.starts_with(well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX));
}
}