referrerpolicy=no-referrer-when-downgrade

sp_state_machine/
backend.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//! State machine backends. These manage the code and storage of contracts.
19
20#[cfg(feature = "std")]
21use crate::trie_backend::TrieBackend;
22use crate::{
23	trie_backend_essence::TrieBackendStorage, ChildStorageCollection, StorageCollection,
24	StorageKey, StorageValue, UsageInfo,
25};
26use alloc::vec::Vec;
27use codec::Encode;
28use core::marker::PhantomData;
29use hash_db::Hasher;
30use sp_core::storage::{ChildInfo, StateVersion, TrackedStorageKey};
31#[cfg(feature = "std")]
32use sp_core::traits::RuntimeCode;
33use sp_trie::{MerkleValue, PrefixedMemoryDB, RandomState};
34
35/// A struct containing arguments for iterating over the storage.
36#[derive(Default)]
37#[non_exhaustive]
38pub struct IterArgs<'a> {
39	/// The prefix of the keys over which to iterate.
40	pub prefix: Option<&'a [u8]>,
41
42	/// The prefix from which to start the iteration from.
43	///
44	/// This is inclusive and the iteration will include the key which is specified here.
45	pub start_at: Option<&'a [u8]>,
46
47	/// If this is `true` then the iteration will *not* include
48	/// the key specified in `start_at`, if there is such a key.
49	pub start_at_exclusive: bool,
50
51	/// The info of the child trie over which to iterate over.
52	pub child_info: Option<ChildInfo>,
53
54	/// Whether to stop iteration when a missing trie node is reached.
55	///
56	/// When a missing trie node is reached the iterator will:
57	///   - return an error if this is set to `false` (default)
58	///   - return `None` if this is set to `true`
59	pub stop_on_incomplete_database: bool,
60}
61
62/// A trait for a raw storage iterator.
63pub trait StorageIterator<H>
64where
65	H: Hasher,
66{
67	/// The state backend over which the iterator is iterating.
68	type Backend;
69
70	/// The error type.
71	type Error;
72
73	/// Fetches the next key from the storage.
74	fn next_key(
75		&mut self,
76		backend: &Self::Backend,
77	) -> Option<core::result::Result<StorageKey, Self::Error>>;
78
79	/// Fetches the next key and value from the storage.
80	fn next_pair(
81		&mut self,
82		backend: &Self::Backend,
83	) -> Option<core::result::Result<(StorageKey, StorageValue), Self::Error>>;
84
85	/// Returns whether the end of iteration was reached without an error.
86	fn was_complete(&self) -> bool;
87}
88
89/// An iterator over storage keys and values.
90pub struct PairsIter<'a, H, I>
91where
92	H: Hasher,
93	I: StorageIterator<H>,
94{
95	backend: Option<&'a I::Backend>,
96	raw_iter: I,
97	_phantom: PhantomData<H>,
98}
99
100impl<'a, H, I> Iterator for PairsIter<'a, H, I>
101where
102	H: Hasher,
103	I: StorageIterator<H>,
104{
105	type Item = Result<(Vec<u8>, Vec<u8>), <I as StorageIterator<H>>::Error>;
106	fn next(&mut self) -> Option<Self::Item> {
107		self.raw_iter.next_pair(self.backend.as_ref()?)
108	}
109}
110
111impl<'a, H, I> Default for PairsIter<'a, H, I>
112where
113	H: Hasher,
114	I: StorageIterator<H> + Default,
115{
116	fn default() -> Self {
117		Self {
118			backend: Default::default(),
119			raw_iter: Default::default(),
120			_phantom: Default::default(),
121		}
122	}
123}
124
125impl<'a, H, I> PairsIter<'a, H, I>
126where
127	H: Hasher,
128	I: StorageIterator<H> + Default,
129{
130	#[cfg(feature = "std")]
131	pub(crate) fn was_complete(&self) -> bool {
132		self.raw_iter.was_complete()
133	}
134}
135
136/// An iterator over storage keys.
137pub struct KeysIter<'a, H, I>
138where
139	H: Hasher,
140	I: StorageIterator<H>,
141{
142	backend: Option<&'a I::Backend>,
143	raw_iter: I,
144	_phantom: PhantomData<H>,
145}
146
147impl<'a, H, I> Iterator for KeysIter<'a, H, I>
148where
149	H: Hasher,
150	I: StorageIterator<H>,
151{
152	type Item = Result<Vec<u8>, <I as StorageIterator<H>>::Error>;
153	fn next(&mut self) -> Option<Self::Item> {
154		self.raw_iter.next_key(self.backend.as_ref()?)
155	}
156}
157
158impl<'a, H, I> Default for KeysIter<'a, H, I>
159where
160	H: Hasher,
161	I: StorageIterator<H> + Default,
162{
163	fn default() -> Self {
164		Self {
165			backend: Default::default(),
166			raw_iter: Default::default(),
167			_phantom: Default::default(),
168		}
169	}
170}
171
172/// The transaction type used by [`Backend`].
173///
174/// This transaction contains all the changes that need to be applied to the backend to create the
175/// state for a new block.
176pub type BackendTransaction<H> = PrefixedMemoryDB<H>;
177
178/// A state backend is used to read state data and can have changes committed
179/// to it.
180///
181/// The clone operation (if implemented) should be cheap.
182pub trait Backend<H: Hasher>: core::fmt::Debug {
183	/// An error type when fetching data is not possible.
184	type Error: super::Error;
185
186	/// Type of trie backend storage.
187	type TrieBackendStorage: TrieBackendStorage<H>;
188
189	/// Type of the raw storage iterator.
190	type RawIter: StorageIterator<H, Backend = Self, Error = Self::Error>;
191
192	/// Get keyed storage or None if there is nothing associated.
193	fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>, Self::Error>;
194
195	/// Get keyed storage value hash or None if there is nothing associated.
196	fn storage_hash(&self, key: &[u8]) -> Result<Option<H::Out>, Self::Error>;
197
198	/// Get the merkle value or None if there is nothing associated.
199	fn closest_merkle_value(&self, key: &[u8]) -> Result<Option<MerkleValue<H::Out>>, Self::Error>;
200
201	/// Get the child merkle value or None if there is nothing associated.
202	fn child_closest_merkle_value(
203		&self,
204		child_info: &ChildInfo,
205		key: &[u8],
206	) -> Result<Option<MerkleValue<H::Out>>, Self::Error>;
207
208	/// Get child keyed child storage or None if there is nothing associated.
209	fn child_storage(
210		&self,
211		child_info: &ChildInfo,
212		key: &[u8],
213	) -> Result<Option<StorageValue>, Self::Error>;
214
215	/// Get child keyed storage value hash or None if there is nothing associated.
216	fn child_storage_hash(
217		&self,
218		child_info: &ChildInfo,
219		key: &[u8],
220	) -> Result<Option<H::Out>, Self::Error>;
221
222	/// true if a key exists in storage.
223	fn exists_storage(&self, key: &[u8]) -> Result<bool, Self::Error> {
224		Ok(self.storage_hash(key)?.is_some())
225	}
226
227	/// true if a key exists in child storage.
228	fn exists_child_storage(
229		&self,
230		child_info: &ChildInfo,
231		key: &[u8],
232	) -> Result<bool, Self::Error> {
233		Ok(self.child_storage_hash(child_info, key)?.is_some())
234	}
235
236	/// Return the next key in storage in lexicographic order or `None` if there is no value.
237	fn next_storage_key(&self, key: &[u8]) -> Result<Option<StorageKey>, Self::Error>;
238
239	/// Return the next key in child storage in lexicographic order or `None` if there is no value.
240	fn next_child_storage_key(
241		&self,
242		child_info: &ChildInfo,
243		key: &[u8],
244	) -> Result<Option<StorageKey>, Self::Error>;
245
246	/// Calculate the storage root, with given delta over what is already stored in
247	/// the backend, and produce a "transaction" that can be used to commit.
248	/// Does not include child storage updates.
249	fn storage_root<'a>(
250		&self,
251		delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
252		state_version: StateVersion,
253	) -> (H::Out, BackendTransaction<H>)
254	where
255		H::Out: Ord;
256
257	/// Calculate the child storage root, with given delta over what is already stored in
258	/// the backend, and produce a "transaction" that can be used to commit. The second argument
259	/// is true if child storage root equals default storage root.
260	fn child_storage_root<'a>(
261		&self,
262		child_info: &ChildInfo,
263		delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
264		state_version: StateVersion,
265	) -> (H::Out, bool, BackendTransaction<H>)
266	where
267		H::Out: Ord;
268
269	/// Returns a lifetimeless raw storage iterator.
270	fn raw_iter(&self, args: IterArgs) -> Result<Self::RawIter, Self::Error>;
271
272	/// Get an iterator over key/value pairs.
273	fn pairs<'a>(&'a self, args: IterArgs) -> Result<PairsIter<'a, H, Self::RawIter>, Self::Error> {
274		Ok(PairsIter {
275			backend: Some(self),
276			raw_iter: self.raw_iter(args)?,
277			_phantom: Default::default(),
278		})
279	}
280
281	/// Get an iterator over keys.
282	fn keys<'a>(&'a self, args: IterArgs) -> Result<KeysIter<'a, H, Self::RawIter>, Self::Error> {
283		Ok(KeysIter {
284			backend: Some(self),
285			raw_iter: self.raw_iter(args)?,
286			_phantom: Default::default(),
287		})
288	}
289
290	/// Calculate the storage root, with given delta over what is already stored
291	/// in the backend, and produce a "transaction" that can be used to commit.
292	/// Does include child storage updates.
293	fn full_storage_root<'a>(
294		&self,
295		delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
296		child_deltas: impl Iterator<
297			Item = (&'a ChildInfo, impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>),
298		>,
299		state_version: StateVersion,
300	) -> (H::Out, BackendTransaction<H>)
301	where
302		H::Out: Ord + Encode,
303	{
304		let mut txs = BackendTransaction::with_hasher(RandomState::default());
305		let mut child_roots: Vec<_> = Default::default();
306		// child first
307		for (child_info, child_delta) in child_deltas {
308			let (child_root, empty, child_txs) =
309				self.child_storage_root(child_info, child_delta, state_version);
310			let prefixed_storage_key = child_info.prefixed_storage_key();
311			txs.consolidate(child_txs);
312			if empty {
313				child_roots.push((prefixed_storage_key.into_inner(), None));
314			} else {
315				child_roots.push((prefixed_storage_key.into_inner(), Some(child_root.encode())));
316			}
317		}
318		let (root, parent_txs) = self.storage_root(
319			delta
320				.map(|(k, v)| (k, v.as_ref().map(|v| &v[..])))
321				.chain(child_roots.iter().map(|(k, v)| (&k[..], v.as_ref().map(|v| &v[..])))),
322			state_version,
323		);
324		txs.consolidate(parent_txs);
325
326		(root, txs)
327	}
328
329	/// Register stats from overlay of state machine.
330	///
331	/// By default nothing is registered.
332	fn register_overlay_stats(&self, _stats: &crate::stats::StateMachineStats);
333
334	/// Query backend usage statistics (i/o, memory)
335	///
336	/// Not all implementations are expected to be able to do this. In the
337	/// case when they don't, empty statistics is returned.
338	fn usage_info(&self) -> UsageInfo;
339
340	/// Wipe the state database.
341	fn wipe(&self) -> Result<(), Self::Error> {
342		unimplemented!()
343	}
344
345	/// Commit given transaction to storage.
346	fn commit(
347		&self,
348		_: H::Out,
349		_: BackendTransaction<H>,
350		_: StorageCollection,
351		_: ChildStorageCollection,
352	) -> Result<(), Self::Error> {
353		unimplemented!()
354	}
355
356	/// Get the read/write count of the db
357	fn read_write_count(&self) -> (u32, u32, u32, u32) {
358		unimplemented!()
359	}
360
361	/// Get the read/write count of the db
362	fn reset_read_write_count(&self) {
363		unimplemented!()
364	}
365
366	/// Get the whitelist for tracking db reads/writes
367	fn get_whitelist(&self) -> Vec<TrackedStorageKey> {
368		Default::default()
369	}
370
371	/// Update the whitelist for tracking db reads/writes
372	fn set_whitelist(&self, _: Vec<TrackedStorageKey>) {}
373
374	/// Estimate proof size
375	fn proof_size(&self) -> Option<u32> {
376		unimplemented!()
377	}
378
379	/// Extend storage info for benchmarking db
380	fn get_read_and_written_keys(&self) -> Vec<(Vec<u8>, u32, u32, bool)> {
381		unimplemented!()
382	}
383}
384
385/// Something that can be converted into a [`TrieBackend`].
386#[cfg(feature = "std")]
387pub trait AsTrieBackend<H: Hasher, C = sp_trie::cache::LocalTrieCache<H>> {
388	/// Type of trie backend storage.
389	type TrieBackendStorage: TrieBackendStorage<H>;
390
391	/// Return the type as [`TrieBackend`].
392	fn as_trie_backend(&self) -> &TrieBackend<Self::TrieBackendStorage, H, C>;
393}
394
395/// Wrapper to create a [`RuntimeCode`] from a type that implements [`Backend`].
396#[cfg(feature = "std")]
397pub struct BackendRuntimeCode<'a, B, H> {
398	backend: &'a B,
399	_marker: PhantomData<H>,
400}
401
402#[cfg(feature = "std")]
403impl<'a, B: Backend<H>, H: Hasher> sp_core::traits::FetchRuntimeCode
404	for BackendRuntimeCode<'a, B, H>
405{
406	fn fetch_runtime_code(&self) -> Option<std::borrow::Cow<[u8]>> {
407		self.backend
408			.storage(sp_core::storage::well_known_keys::CODE)
409			.ok()
410			.flatten()
411			.map(Into::into)
412	}
413}
414
415#[cfg(feature = "std")]
416impl<'a, B: Backend<H>, H: Hasher> BackendRuntimeCode<'a, B, H>
417where
418	H::Out: Encode,
419{
420	/// Create a new instance.
421	pub fn new(backend: &'a B) -> Self {
422		Self { backend, _marker: PhantomData }
423	}
424
425	/// Return the [`RuntimeCode`] build from the wrapped `backend`.
426	pub fn runtime_code(&self) -> Result<RuntimeCode, &'static str> {
427		let hash = self
428			.backend
429			.storage_hash(sp_core::storage::well_known_keys::CODE)
430			.ok()
431			.flatten()
432			.ok_or("`:code` hash not found")?
433			.encode();
434		let heap_pages = self
435			.backend
436			.storage(sp_core::storage::well_known_keys::HEAP_PAGES)
437			.ok()
438			.flatten()
439			.and_then(|d| codec::Decode::decode(&mut &d[..]).ok());
440
441		Ok(RuntimeCode { code_fetcher: self, hash, heap_pages })
442	}
443}