sp_storage/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Primitive types for storage related stuff.
19
20#![cfg_attr(not(feature = "std"), no_std)]
21
22extern crate alloc;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26use sp_debug_derive::RuntimeDebug;
27
28use alloc::vec::Vec;
29use codec::{Decode, Encode};
30use core::{
31	fmt::Display,
32	ops::{Deref, DerefMut},
33};
34use ref_cast::RefCast;
35
36/// Storage key.
37#[derive(PartialEq, Eq, RuntimeDebug)]
38#[cfg_attr(
39	feature = "serde",
40	derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode)
41)]
42pub struct StorageKey(
43	#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
44);
45
46impl AsRef<[u8]> for StorageKey {
47	fn as_ref(&self) -> &[u8] {
48		self.0.as_ref()
49	}
50}
51
52/// Storage key with read/write tracking information.
53#[derive(PartialEq, Eq, Ord, PartialOrd, core::hash::Hash, RuntimeDebug, Clone, Encode, Decode)]
54pub struct TrackedStorageKey {
55	pub key: Vec<u8>,
56	pub reads: u32,
57	pub writes: u32,
58	pub whitelisted: bool,
59}
60
61impl TrackedStorageKey {
62	/// Create a default `TrackedStorageKey`
63	pub fn new(key: Vec<u8>) -> Self {
64		Self { key, reads: 0, writes: 0, whitelisted: false }
65	}
66	/// Check if this key has been "read", i.e. it exists in the memory overlay.
67	///
68	/// Can be true if the key has been read, has been written to, or has been
69	/// whitelisted.
70	pub fn has_been_read(&self) -> bool {
71		self.whitelisted || self.reads > 0u32 || self.has_been_written()
72	}
73	/// Check if this key has been "written", i.e. a new value will be committed to the database.
74	///
75	/// Can be true if the key has been written to, or has been whitelisted.
76	pub fn has_been_written(&self) -> bool {
77		self.whitelisted || self.writes > 0u32
78	}
79	/// Add a storage read to this key.
80	pub fn add_read(&mut self) {
81		self.reads += 1;
82	}
83	/// Add a storage write to this key.
84	pub fn add_write(&mut self) {
85		self.writes += 1;
86	}
87	/// Whitelist this key.
88	pub fn whitelist(&mut self) {
89		self.whitelisted = true;
90	}
91}
92
93// Easily convert a key to a `TrackedStorageKey` that has been whitelisted.
94impl From<Vec<u8>> for TrackedStorageKey {
95	fn from(key: Vec<u8>) -> Self {
96		Self { key, reads: 0, writes: 0, whitelisted: true }
97	}
98}
99
100/// Storage key of a child trie, it contains the prefix to the key.
101#[derive(PartialEq, Eq, RuntimeDebug)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))]
103#[repr(transparent)]
104#[derive(RefCast)]
105pub struct PrefixedStorageKey(
106	#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] Vec<u8>,
107);
108
109impl Deref for PrefixedStorageKey {
110	type Target = Vec<u8>;
111
112	fn deref(&self) -> &Vec<u8> {
113		&self.0
114	}
115}
116
117impl DerefMut for PrefixedStorageKey {
118	fn deref_mut(&mut self) -> &mut Vec<u8> {
119		&mut self.0
120	}
121}
122
123impl PrefixedStorageKey {
124	/// Create a prefixed storage key from its byte array representation.
125	pub fn new(inner: Vec<u8>) -> Self {
126		PrefixedStorageKey(inner)
127	}
128
129	/// Create a prefixed storage key reference.
130	pub fn new_ref(inner: &Vec<u8>) -> &Self {
131		PrefixedStorageKey::ref_cast(inner)
132	}
133
134	/// Get inner key, this should only be needed when writing into parent trie to avoid an
135	/// allocation.
136	pub fn into_inner(self) -> Vec<u8> {
137		self.0
138	}
139}
140
141/// Storage data associated to a [`StorageKey`].
142#[derive(PartialEq, Eq, RuntimeDebug)]
143#[cfg_attr(
144	feature = "serde",
145	derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode, Default)
146)]
147pub struct StorageData(
148	#[cfg_attr(feature = "serde", serde(with = "impl_serde::serialize"))] pub Vec<u8>,
149);
150
151/// Map of data to use in a storage, it is a collection of
152/// byte key and values.
153#[cfg(feature = "std")]
154pub type StorageMap = std::collections::BTreeMap<Vec<u8>, Vec<u8>>;
155
156/// Child trie storage data.
157#[cfg(feature = "std")]
158#[derive(Debug, PartialEq, Eq, Clone)]
159pub struct StorageChild {
160	/// Child data for storage.
161	pub data: StorageMap,
162	/// Associated child info for a child
163	/// trie.
164	pub child_info: ChildInfo,
165}
166
167/// Struct containing data needed for a storage.
168#[cfg(feature = "std")]
169#[derive(Default, Debug, Clone)]
170pub struct Storage {
171	/// Top trie storage data.
172	pub top: StorageMap,
173	/// Children trie storage data. Key does not include prefix, only for the `default` trie kind,
174	/// of `ChildType::ParentKeyId` type.
175	pub children_default: std::collections::HashMap<Vec<u8>, StorageChild>,
176}
177
178/// Storage change set
179#[derive(RuntimeDebug)]
180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, PartialEq, Eq, Clone))]
181#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
182pub struct StorageChangeSet<Hash> {
183	/// Block hash
184	pub block: Hash,
185	/// A list of changes
186	pub changes: Vec<(StorageKey, Option<StorageData>)>,
187}
188
189/// List of all well known keys and prefixes in storage.
190pub mod well_known_keys {
191	/// Wasm code of the runtime.
192	///
193	/// Stored as a raw byte vector. Required by substrate.
194	pub const CODE: &[u8] = b":code";
195
196	/// Number of wasm linear memory pages required for execution of the runtime.
197	///
198	/// The type of this value is encoded `u64`.
199	pub const HEAP_PAGES: &[u8] = b":heappages";
200
201	/// Current extrinsic index (u32) is stored under this key.
202	///
203	/// Encodes to `0x3a65787472696e7369635f696e646578`.
204	pub const EXTRINSIC_INDEX: &[u8] = b":extrinsic_index";
205
206	/// Current intra-block entropy (a universally unique `[u8; 32]` value) is stored here.
207	///
208	/// Encodes to `0x3a696e747261626c6f636b5f656e74726f7079`.
209	pub const INTRABLOCK_ENTROPY: &[u8] = b":intrablock_entropy";
210
211	/// Prefix of child storage keys.
212	pub const CHILD_STORAGE_KEY_PREFIX: &[u8] = b":child_storage:";
213
214	/// Prefix of the default child storage keys in the top trie.
215	pub const DEFAULT_CHILD_STORAGE_KEY_PREFIX: &[u8] = b":child_storage:default:";
216
217	/// Whether a key is a default child storage key.
218	///
219	/// This is convenience function which basically checks if the given `key` starts
220	/// with `DEFAULT_CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that.
221	pub fn is_default_child_storage_key(key: &[u8]) -> bool {
222		key.starts_with(DEFAULT_CHILD_STORAGE_KEY_PREFIX)
223	}
224
225	/// Whether a key is a child storage key.
226	///
227	/// This is convenience function which basically checks if the given `key` starts
228	/// with `CHILD_STORAGE_KEY_PREFIX` and doesn't do anything apart from that.
229	pub fn is_child_storage_key(key: &[u8]) -> bool {
230		// Other code might depend on this, so be careful changing this.
231		key.starts_with(CHILD_STORAGE_KEY_PREFIX)
232	}
233
234	/// Returns if the given `key` starts with [`CHILD_STORAGE_KEY_PREFIX`] or collides with it.
235	pub fn starts_with_child_storage_key(key: &[u8]) -> bool {
236		if key.len() > CHILD_STORAGE_KEY_PREFIX.len() {
237			key.starts_with(CHILD_STORAGE_KEY_PREFIX)
238		} else {
239			CHILD_STORAGE_KEY_PREFIX.starts_with(key)
240		}
241	}
242}
243
244/// Threshold size to start using trie value nodes in state.
245pub const TRIE_VALUE_NODE_THRESHOLD: u32 = 33;
246
247/// Information related to a child state.
248#[derive(Debug, Clone)]
249#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))]
250pub enum ChildInfo {
251	/// This is the one used by default.
252	ParentKeyId(ChildTrieParentKeyId),
253}
254
255impl ChildInfo {
256	/// Instantiates child information for a default child trie
257	/// of kind `ChildType::ParentKeyId`, using an unprefixed parent
258	/// storage key.
259	pub fn new_default(storage_key: &[u8]) -> Self {
260		let data = storage_key.to_vec();
261		ChildInfo::ParentKeyId(ChildTrieParentKeyId { data })
262	}
263
264	/// Same as `new_default` but with `Vec<u8>` as input.
265	pub fn new_default_from_vec(storage_key: Vec<u8>) -> Self {
266		ChildInfo::ParentKeyId(ChildTrieParentKeyId { data: storage_key })
267	}
268
269	/// Try to update with another instance, return false if both instance
270	/// are not compatible.
271	pub fn try_update(&mut self, other: &ChildInfo) -> bool {
272		match self {
273			ChildInfo::ParentKeyId(child_trie) => child_trie.try_update(other),
274		}
275	}
276
277	/// Returns byte sequence (keyspace) that can be use by underlying db to isolate keys.
278	/// This is a unique id of the child trie. The collision resistance of this value
279	/// depends on the type of child info use. For `ChildInfo::Default` it is and need to be.
280	#[inline]
281	pub fn keyspace(&self) -> &[u8] {
282		match self {
283			ChildInfo::ParentKeyId(..) => self.storage_key(),
284		}
285	}
286
287	/// Returns a reference to the location in the direct parent of
288	/// this trie but without the common prefix for this kind of
289	/// child trie.
290	pub fn storage_key(&self) -> &[u8] {
291		match self {
292			ChildInfo::ParentKeyId(ChildTrieParentKeyId { data }) => &data[..],
293		}
294	}
295
296	/// Return the full location in the direct parent of
297	/// this trie.
298	pub fn prefixed_storage_key(&self) -> PrefixedStorageKey {
299		match self {
300			ChildInfo::ParentKeyId(ChildTrieParentKeyId { data }) =>
301				ChildType::ParentKeyId.new_prefixed_key(data.as_slice()),
302		}
303	}
304
305	/// Returns the full location in the direct parent of
306	/// this trie.
307	pub fn into_prefixed_storage_key(self) -> PrefixedStorageKey {
308		match self {
309			ChildInfo::ParentKeyId(ChildTrieParentKeyId { mut data }) => {
310				ChildType::ParentKeyId.do_prefix_key(&mut data);
311				PrefixedStorageKey(data)
312			},
313		}
314	}
315
316	/// Returns the type for this child info.
317	pub fn child_type(&self) -> ChildType {
318		match self {
319			ChildInfo::ParentKeyId(..) => ChildType::ParentKeyId,
320		}
321	}
322}
323
324/// Type of child.
325/// It does not strictly define different child type, it can also
326/// be related to technical consideration or api variant.
327#[repr(u32)]
328#[derive(Clone, Copy, PartialEq)]
329#[cfg_attr(feature = "std", derive(Debug))]
330pub enum ChildType {
331	/// If runtime module ensures that the child key is a unique id that will
332	/// only be used once, its parent key is used as a child trie unique id.
333	ParentKeyId = 1,
334}
335
336impl ChildType {
337	/// Try to get a child type from its `u32` representation.
338	pub fn new(repr: u32) -> Option<ChildType> {
339		Some(match repr {
340			r if r == ChildType::ParentKeyId as u32 => ChildType::ParentKeyId,
341			_ => return None,
342		})
343	}
344
345	/// Transform a prefixed key into a tuple of the child type
346	/// and the unprefixed representation of the key.
347	pub fn from_prefixed_key<'a>(storage_key: &'a PrefixedStorageKey) -> Option<(Self, &'a [u8])> {
348		let match_type = |storage_key: &'a [u8], child_type: ChildType| {
349			let prefix = child_type.parent_prefix();
350			if storage_key.starts_with(prefix) {
351				Some((child_type, &storage_key[prefix.len()..]))
352			} else {
353				None
354			}
355		};
356		match_type(storage_key, ChildType::ParentKeyId)
357	}
358
359	/// Produce a prefixed key for a given child type.
360	fn new_prefixed_key(&self, key: &[u8]) -> PrefixedStorageKey {
361		let parent_prefix = self.parent_prefix();
362		let mut result = Vec::with_capacity(parent_prefix.len() + key.len());
363		result.extend_from_slice(parent_prefix);
364		result.extend_from_slice(key);
365		PrefixedStorageKey(result)
366	}
367
368	/// Prefixes a vec with the prefix for this child type.
369	fn do_prefix_key(&self, key: &mut Vec<u8>) {
370		let parent_prefix = self.parent_prefix();
371		let key_len = key.len();
372		if !parent_prefix.is_empty() {
373			key.resize(key_len + parent_prefix.len(), 0);
374			key.copy_within(..key_len, parent_prefix.len());
375			key[..parent_prefix.len()].copy_from_slice(parent_prefix);
376		}
377	}
378
379	/// Returns the location reserved for this child trie in their parent trie if there
380	/// is one.
381	pub fn parent_prefix(&self) -> &'static [u8] {
382		match self {
383			&ChildType::ParentKeyId => well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX,
384		}
385	}
386}
387
388/// A child trie of default type.
389///
390/// It uses the same default implementation as the top trie, top trie being a child trie with no
391/// keyspace and no storage key. Its keyspace is the variable (unprefixed) part of its storage key.
392/// It shares its trie nodes backend storage with every other child trie, so its storage key needs
393/// to be a unique id that will be use only once. Those unique id also required to be long enough to
394/// avoid any unique id to be prefixed by an other unique id.
395#[derive(Debug, Clone)]
396#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Hash, PartialOrd, Ord, Encode, Decode))]
397pub struct ChildTrieParentKeyId {
398	/// Data is the storage key without prefix.
399	data: Vec<u8>,
400}
401
402impl ChildTrieParentKeyId {
403	/// Try to update with another instance, return false if both instance
404	/// are not compatible.
405	fn try_update(&mut self, other: &ChildInfo) -> bool {
406		match other {
407			ChildInfo::ParentKeyId(other) => self.data[..] == other.data[..],
408		}
409	}
410}
411
412/// Different possible state version.
413///
414/// V0 and V1 uses a same trie implementation, but V1 will write external value node in the trie for
415/// value with size at least `TRIE_VALUE_NODE_THRESHOLD`.
416#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
417#[cfg_attr(feature = "std", derive(Encode, Decode))]
418pub enum StateVersion {
419	/// Old state version, no value nodes.
420	V0 = 0,
421	/// New state version can use value nodes.
422	#[default]
423	V1 = 1,
424}
425
426impl Display for StateVersion {
427	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
428		match self {
429			StateVersion::V0 => f.write_str("0"),
430			StateVersion::V1 => f.write_str("1"),
431		}
432	}
433}
434
435impl From<StateVersion> for u8 {
436	fn from(version: StateVersion) -> u8 {
437		version as u8
438	}
439}
440
441impl TryFrom<u8> for StateVersion {
442	type Error = ();
443	fn try_from(val: u8) -> core::result::Result<StateVersion, ()> {
444		match val {
445			0 => Ok(StateVersion::V0),
446			1 => Ok(StateVersion::V1),
447			2 => Ok(StateVersion::V1),
448			_ => Err(()),
449		}
450	}
451}
452
453impl StateVersion {
454	/// If defined, values in state of size bigger or equal
455	/// to this threshold will use a separate trie node.
456	/// Otherwise, value will be inlined in branch or leaf
457	/// node.
458	pub fn state_value_threshold(&self) -> Option<u32> {
459		match self {
460			StateVersion::V0 => None,
461			StateVersion::V1 => Some(TRIE_VALUE_NODE_THRESHOLD),
462		}
463	}
464}
465
466#[cfg(test)]
467mod tests {
468	use super::*;
469
470	#[test]
471	fn test_prefix_default_child_info() {
472		let child_info = ChildInfo::new_default(b"any key");
473		let prefix = child_info.child_type().parent_prefix();
474		assert!(prefix.starts_with(well_known_keys::CHILD_STORAGE_KEY_PREFIX));
475		assert!(prefix.starts_with(well_known_keys::DEFAULT_CHILD_STORAGE_KEY_PREFIX));
476	}
477}