Skip to main content

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