tp_state_machine/
lib.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2017-2021 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//! Tetcore state machine implementation.
19
20#![warn(missing_docs)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23pub mod backend;
24#[cfg(feature = "std")]
25mod in_memory_backend;
26#[cfg(feature = "std")]
27mod changes_trie;
28mod error;
29mod ext;
30#[cfg(feature = "std")]
31mod testing;
32#[cfg(feature = "std")]
33mod basic;
34pub(crate) mod overlayed_changes;
35#[cfg(feature = "std")]
36mod proving_backend;
37mod trie_backend;
38mod trie_backend_essence;
39mod stats;
40#[cfg(feature = "std")]
41mod read_only;
42
43#[cfg(feature = "std")]
44pub use std_reexport::*;
45
46#[cfg(feature = "std")]
47pub use execution::*;
48#[cfg(feature = "std")]
49pub use log::{debug, warn, trace, error as log_error};
50
51/// In no_std we skip logs for state_machine, this macro
52/// is a noops.
53#[cfg(not(feature = "std"))]
54#[macro_export]
55macro_rules! warn {
56	(target: $target:expr, $($arg:tt)+) => (
57		()
58	);
59	($($arg:tt)+) => (
60		()
61	);
62}
63
64/// In no_std we skip logs for state_machine, this macro
65/// is a noops.
66#[cfg(not(feature = "std"))]
67#[macro_export]
68macro_rules! debug {
69	(target: $target:expr, $($arg:tt)+) => (
70		()
71	);
72	($($arg:tt)+) => (
73		()
74	);
75}
76
77/// In no_std we skip logs for state_machine, this macro
78/// is a noops.
79#[cfg(not(feature = "std"))]
80#[macro_export]
81macro_rules! trace {
82	(target: $target:expr, $($arg:tt)+) => (
83		()
84	);
85	($($arg:tt)+) => (
86		()
87	);
88}
89
90/// In no_std we skip logs for state_machine, this macro
91/// is a noops.
92#[cfg(not(feature = "std"))]
93#[macro_export]
94macro_rules! log_error {
95	(target: $target:expr, $($arg:tt)+) => (
96		()
97	);
98	($($arg:tt)+) => (
99		()
100	);
101}
102
103/// Default error type to use with state machine trie backend.
104#[cfg(feature = "std")]
105pub type DefaultError = String;
106/// Error type to use with state machine trie backend.
107#[cfg(not(feature = "std"))]
108#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
109pub struct DefaultError;
110
111#[cfg(not(feature = "std"))]
112impl tetcore_std::fmt::Display for DefaultError {
113	fn fmt(&self, f: &mut tetcore_std::fmt::Formatter) -> tetcore_std::fmt::Result {
114		write!(f, "DefaultError")
115	}
116}
117
118pub use crate::overlayed_changes::{
119	OverlayedChanges, StorageKey, StorageValue,
120	StorageCollection, ChildStorageCollection,
121	StorageChanges, StorageTransactionCache,
122	OffchainChangesCollection,
123	OffchainOverlayedChanges,
124};
125pub use crate::backend::Backend;
126pub use crate::trie_backend_essence::{TrieBackendStorage, Storage};
127pub use crate::trie_backend::TrieBackend;
128pub use crate::stats::{UsageInfo, UsageUnit, StateMachineStats};
129pub use error::{Error, ExecutionError};
130pub use crate::ext::Ext;
131
132#[cfg(not(feature = "std"))]
133mod changes_trie {
134	/// Stub for change trie block number until
135	/// change trie move to no_std.
136	pub trait BlockNumber {}
137
138	impl<N> BlockNumber for N {}
139}
140
141#[cfg(feature = "std")]
142mod std_reexport {
143	pub use tp_trie::{trie_types::{Layout, TrieDBMut}, StorageProof, TrieMut, DBValue, MemoryDB};
144	pub use crate::testing::TestExternalities;
145	pub use crate::basic::BasicExternalities;
146	pub use crate::read_only::{ReadOnlyExternalities, InspectState};
147	pub use crate::changes_trie::{
148		AnchorBlockId as ChangesTrieAnchorBlockId,
149		State as ChangesTrieState,
150		Storage as ChangesTrieStorage,
151		RootsStorage as ChangesTrieRootsStorage,
152		InMemoryStorage as InMemoryChangesTrieStorage,
153		BuildCache as ChangesTrieBuildCache,
154		CacheAction as ChangesTrieCacheAction,
155		ConfigurationRange as ChangesTrieConfigurationRange,
156		key_changes, key_changes_proof,
157		key_changes_proof_check, key_changes_proof_check_with_db,
158		prune as prune_changes_tries,
159		disabled_state as disabled_changes_trie_state,
160		BlockNumber as ChangesTrieBlockNumber,
161	};
162	pub use crate::proving_backend::{
163		create_proof_check_backend, ProofRecorder, ProvingBackend, ProvingBackendRecorder,
164	};
165	pub use crate::error::{Error, ExecutionError};
166	pub use crate::in_memory_backend::new_in_mem;
167}
168
169#[cfg(feature = "std")]
170mod execution {
171	use super::*;
172	use std::{fmt, result, collections::HashMap, panic::UnwindSafe};
173	use log::{warn, trace};
174	use tetsy_hash_db::Hasher;
175	use codec::{Decode, Encode, Codec};
176	use tet_core::{
177		storage::ChildInfo, NativeOrEncoded, NeverNativeValue, hexdisplay::HexDisplay,
178		traits::{CodeExecutor, CallInWasmExt, RuntimeCode, SpawnNamed},
179	};
180	use externalities::Extensions;
181
182
183	const PROOF_CLOSE_TRANSACTION: &str = "\
184		Closing a transaction that was started in this function. Client initiated transactions
185		are protected from being closed by the runtime. qed";
186
187	pub(crate) type CallResult<R, E> = Result<NativeOrEncoded<R>, E>;
188
189	/// Default handler of the execution manager.
190	pub type DefaultHandler<R, E> = fn(CallResult<R, E>, CallResult<R, E>) -> CallResult<R, E>;
191
192	/// Type of changes trie transaction.
193	pub type ChangesTrieTransaction<H, N> = (
194		MemoryDB<H>,
195		ChangesTrieCacheAction<<H as Hasher>::Out, N>,
196	);
197
198	/// Trie backend with in-memory storage.
199	pub type InMemoryBackend<H> = TrieBackend<MemoryDB<H>, H>;
200
201	/// Strategy for executing a call into the runtime.
202	#[derive(Copy, Clone, Eq, PartialEq, Debug)]
203	pub enum ExecutionStrategy {
204		/// Execute with the native equivalent if it is compatible with the given wasm module;
205		/// otherwise fall back to the wasm.
206		NativeWhenPossible,
207		/// Use the given wasm module.
208		AlwaysWasm,
209		/// Run with both the wasm and the native variant (if compatible). Report any discrepancy as an error.
210		Both,
211		/// First native, then if that fails or is not possible, wasm.
212		NativeElseWasm,
213	}
214
215	/// Storage backend trust level.
216	#[derive(Debug, Clone)]
217	pub enum BackendTrustLevel {
218		/// Panics from trusted backends are considered justified, and never caught.
219		Trusted,
220		/// Panics from untrusted backend are caught and interpreted as runtime error.
221		/// Untrusted backend may be missing some parts of the trie, so panics are not considered
222		/// fatal.
223		Untrusted,
224	}
225
226	/// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure.
227	#[derive(Clone)]
228	pub enum ExecutionManager<F> {
229		/// Execute with the native equivalent if it is compatible with the given wasm module;
230		/// otherwise fall back to the wasm.
231		NativeWhenPossible,
232		/// Use the given wasm module. The backend on which code is executed code could be
233		/// trusted to provide all storage or not (i.e. the light client cannot be trusted to provide
234		/// for all storage queries since the storage entries it has come from an external node).
235		AlwaysWasm(BackendTrustLevel),
236		/// Run with both the wasm and the native variant (if compatible). Call `F` in the case of any discrepancy.
237		Both(F),
238		/// First native, then if that fails or is not possible, wasm.
239		NativeElseWasm,
240	}
241
242	impl<'a, F> From<&'a ExecutionManager<F>> for ExecutionStrategy {
243		fn from(s: &'a ExecutionManager<F>) -> Self {
244			match *s {
245				ExecutionManager::NativeWhenPossible => ExecutionStrategy::NativeWhenPossible,
246				ExecutionManager::AlwaysWasm(_) => ExecutionStrategy::AlwaysWasm,
247				ExecutionManager::NativeElseWasm => ExecutionStrategy::NativeElseWasm,
248				ExecutionManager::Both(_) => ExecutionStrategy::Both,
249			}
250		}
251	}
252
253	impl ExecutionStrategy {
254		/// Gets the corresponding manager for the execution strategy.
255		pub fn get_manager<E: fmt::Debug, R: Decode + Encode>(
256			self,
257		) -> ExecutionManager<DefaultHandler<R, E>> {
258			match self {
259				ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted),
260				ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible,
261				ExecutionStrategy::NativeElseWasm => ExecutionManager::NativeElseWasm,
262				ExecutionStrategy::Both => ExecutionManager::Both(|wasm_result, native_result| {
263					warn!(
264						"Consensus error between wasm {:?} and native {:?}. Using wasm.",
265						wasm_result,
266						native_result,
267					);
268					warn!("   Native result {:?}", native_result);
269					warn!("   Wasm result {:?}", wasm_result);
270					wasm_result
271				}),
272			}
273		}
274	}
275
276	/// Evaluate to ExecutionManager::NativeElseWasm, without having to figure out the type.
277	pub fn native_else_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>> {
278		ExecutionManager::NativeElseWasm
279	}
280
281	/// Evaluate to ExecutionManager::AlwaysWasm with trusted backend, without having to figure out the type.
282	fn always_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>> {
283		ExecutionManager::AlwaysWasm(BackendTrustLevel::Trusted)
284	}
285
286	/// Evaluate ExecutionManager::AlwaysWasm with untrusted backend, without having to figure out the type.
287	fn always_untrusted_wasm<E, R: Decode>() -> ExecutionManager<DefaultHandler<R, E>> {
288		ExecutionManager::AlwaysWasm(BackendTrustLevel::Untrusted)
289	}
290
291	/// The tetcore state machine.
292	pub struct StateMachine<'a, B, H, N, Exec>
293		where
294			H: Hasher,
295			B: Backend<H>,
296			N: ChangesTrieBlockNumber,
297	{
298		backend: &'a B,
299		exec: &'a Exec,
300		method: &'a str,
301		call_data: &'a [u8],
302		overlay: &'a mut OverlayedChanges,
303		extensions: Extensions,
304		changes_trie_state: Option<ChangesTrieState<'a, H, N>>,
305		storage_transaction_cache: Option<&'a mut StorageTransactionCache<B::Transaction, H, N>>,
306		runtime_code: &'a RuntimeCode<'a>,
307		stats: StateMachineStats,
308	}
309
310	impl<'a, B, H, N, Exec> Drop for StateMachine<'a, B, H, N, Exec> where
311		H: Hasher,
312		B: Backend<H>,
313		N: ChangesTrieBlockNumber,
314	{
315		fn drop(&mut self) {
316			self.backend.register_overlay_stats(&self.stats);
317		}
318	}
319
320	impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where
321		H: Hasher,
322		H::Out: Ord + 'static + codec::Codec,
323		Exec: CodeExecutor + Clone + 'static,
324		B: Backend<H>,
325		N: crate::changes_trie::BlockNumber,
326	{
327		/// Creates new tetcore state machine.
328		pub fn new(
329			backend: &'a B,
330			changes_trie_state: Option<ChangesTrieState<'a, H, N>>,
331			overlay: &'a mut OverlayedChanges,
332			exec: &'a Exec,
333			method: &'a str,
334			call_data: &'a [u8],
335			mut extensions: Extensions,
336			runtime_code: &'a RuntimeCode,
337			spawn_handle: impl SpawnNamed + Send + 'static,
338		) -> Self {
339			extensions.register(CallInWasmExt::new(exec.clone()));
340			extensions.register(tet_core::traits::TaskExecutorExt::new(spawn_handle));
341
342			Self {
343				backend,
344				exec,
345				method,
346				call_data,
347				extensions,
348				overlay,
349				changes_trie_state,
350				storage_transaction_cache: None,
351				runtime_code,
352				stats: StateMachineStats::default(),
353			}
354		}
355
356		/// Use given `cache` as storage transaction cache.
357		///
358		/// The cache will be used to cache storage transactions that can be build while executing a
359		/// function in the runtime. For example, when calculating the storage root a transaction is
360		/// build that will be cached.
361		pub fn with_storage_transaction_cache(
362			mut self,
363			cache: Option<&'a mut StorageTransactionCache<B::Transaction, H, N>>,
364		) -> Self {
365			self.storage_transaction_cache = cache;
366			self
367		}
368
369		/// Execute a call using the given state backend, overlayed changes, and call executor.
370		///
371		/// On an error, no prospective changes are written to the overlay.
372		///
373		/// Note: changes to code will be in place if this call is made again. For running partial
374		/// blocks (e.g. a transaction at a time), ensure a different method is used.
375		///
376		/// Returns the SCALE encoded result of the executed function.
377		pub fn execute(&mut self, strategy: ExecutionStrategy) -> Result<Vec<u8>, Box<dyn Error>> {
378			// We are not giving a native call and thus we are sure that the result can never be a native
379			// value.
380			self.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
381				strategy.get_manager(),
382				None,
383			).map(NativeOrEncoded::into_encoded)
384		}
385
386		fn execute_aux<R, NC>(
387			&mut self,
388			use_native: bool,
389			native_call: Option<NC>,
390		) -> (
391			CallResult<R, Exec::Error>,
392			bool,
393		) where
394			R: Decode + Encode + PartialEq,
395			NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
396		{
397			let mut cache = StorageTransactionCache::default();
398
399			let cache = match self.storage_transaction_cache.as_mut() {
400				Some(cache) => cache,
401				None => &mut cache,
402			};
403
404			self.overlay.enter_runtime().expect("StateMachine is never called from the runtime; qed");
405
406			let mut ext = Ext::new(
407				self.overlay,
408				cache,
409				self.backend,
410				self.changes_trie_state.clone(),
411				Some(&mut self.extensions),
412			);
413
414			let id = ext.id;
415			trace!(
416				target: "state", "{:04x}: Call {} at {:?}. Input={:?}",
417				id,
418				self.method,
419				self.backend,
420				HexDisplay::from(&self.call_data),
421			);
422
423			let (result, was_native) = self.exec.call(
424				&mut ext,
425				self.runtime_code,
426				self.method,
427				self.call_data,
428				use_native,
429				native_call,
430			);
431
432			self.overlay.exit_runtime()
433				.expect("Runtime is not able to call this function in the overlay; qed");
434
435			trace!(
436				target: "state", "{:04x}: Return. Native={:?}, Result={:?}",
437				id,
438				was_native,
439				result,
440			);
441
442			(result, was_native)
443		}
444
445		fn execute_call_with_both_strategy<Handler, R, NC>(
446			&mut self,
447			mut native_call: Option<NC>,
448			on_consensus_failure: Handler,
449		) -> CallResult<R, Exec::Error>
450			where
451				R: Decode + Encode + PartialEq,
452				NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
453				Handler: FnOnce(
454					CallResult<R, Exec::Error>,
455					CallResult<R, Exec::Error>,
456				) -> CallResult<R, Exec::Error>
457		{
458			self.overlay.start_transaction();
459			let (result, was_native) = self.execute_aux(true, native_call.take());
460
461			if was_native {
462				self.overlay.rollback_transaction().expect(PROOF_CLOSE_TRANSACTION);
463				let (wasm_result, _) = self.execute_aux(
464					false,
465					native_call,
466				);
467
468				if (result.is_ok() && wasm_result.is_ok()
469					&& result.as_ref().ok() == wasm_result.as_ref().ok())
470					|| result.is_err() && wasm_result.is_err()
471				{
472					result
473				} else {
474					on_consensus_failure(wasm_result, result)
475				}
476			} else {
477				self.overlay.commit_transaction().expect(PROOF_CLOSE_TRANSACTION);
478				result
479			}
480		}
481
482		fn execute_call_with_native_else_wasm_strategy<R, NC>(
483			&mut self,
484			mut native_call: Option<NC>,
485		) -> CallResult<R, Exec::Error>
486			where
487				R: Decode + Encode + PartialEq,
488				NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
489		{
490			self.overlay.start_transaction();
491			let (result, was_native) = self.execute_aux(
492				true,
493				native_call.take(),
494			);
495
496			if !was_native || result.is_ok() {
497				self.overlay.commit_transaction().expect(PROOF_CLOSE_TRANSACTION);
498				result
499			} else {
500				self.overlay.rollback_transaction().expect(PROOF_CLOSE_TRANSACTION);
501				let (wasm_result, _) = self.execute_aux(
502					false,
503					native_call,
504				);
505				wasm_result
506			}
507		}
508
509		/// Execute a call using the given state backend, overlayed changes, and call executor.
510		///
511		/// On an error, no prospective changes are written to the overlay.
512		///
513		/// Note: changes to code will be in place if this call is made again. For running partial
514		/// blocks (e.g. a transaction at a time), ensure a different method is used.
515		///
516		/// Returns the result of the executed function either in native representation `R` or
517		/// in SCALE encoded representation.
518		pub fn execute_using_consensus_failure_handler<Handler, R, NC>(
519			&mut self,
520			manager: ExecutionManager<Handler>,
521			mut native_call: Option<NC>,
522		) -> Result<NativeOrEncoded<R>, Box<dyn Error>>
523			where
524				R: Decode + Encode + PartialEq,
525				NC: FnOnce() -> result::Result<R, String> + UnwindSafe,
526				Handler: FnOnce(
527					CallResult<R, Exec::Error>,
528					CallResult<R, Exec::Error>,
529				) -> CallResult<R, Exec::Error>
530		{
531			let changes_tries_enabled = self.changes_trie_state.is_some();
532			self.overlay.set_collect_extrinsics(changes_tries_enabled);
533
534			let result = {
535				match manager {
536					ExecutionManager::Both(on_consensus_failure) => {
537						self.execute_call_with_both_strategy(
538							native_call.take(),
539							on_consensus_failure,
540						)
541					},
542					ExecutionManager::NativeElseWasm => {
543						self.execute_call_with_native_else_wasm_strategy(
544							native_call.take(),
545						)
546					},
547					ExecutionManager::AlwaysWasm(trust_level) => {
548						let _abort_guard = match trust_level {
549							BackendTrustLevel::Trusted => None,
550							BackendTrustLevel::Untrusted => Some(panic_handler::AbortGuard::never_abort()),
551						};
552						self.execute_aux(false, native_call).0
553					},
554					ExecutionManager::NativeWhenPossible => {
555						self.execute_aux(true, native_call).0
556					},
557				}
558			};
559
560			result.map_err(|e| Box::new(e) as _)
561		}
562	}
563
564	/// Prove execution using the given state backend, overlayed changes, and call executor.
565	pub fn prove_execution<B, H, N, Exec, Spawn>(
566		mut backend: B,
567		overlay: &mut OverlayedChanges,
568		exec: &Exec,
569		spawn_handle: Spawn,
570		method: &str,
571		call_data: &[u8],
572		runtime_code: &RuntimeCode,
573	) -> Result<(Vec<u8>, StorageProof), Box<dyn Error>>
574	where
575		B: Backend<H>,
576		H: Hasher,
577		H::Out: Ord + 'static + codec::Codec,
578		Exec: CodeExecutor + Clone + 'static,
579		N: crate::changes_trie::BlockNumber,
580		Spawn: SpawnNamed + Send + 'static,
581	{
582		let trie_backend = backend.as_trie_backend()
583			.ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box<dyn Error>)?;
584		prove_execution_on_trie_backend::<_, _, N, _, _>(
585			trie_backend,
586			overlay,
587			exec,
588			spawn_handle,
589			method,
590			call_data,
591			runtime_code,
592		)
593	}
594
595	/// Prove execution using the given trie backend, overlayed changes, and call executor.
596	/// Produces a state-backend-specific "transaction" which can be used to apply the changes
597	/// to the backing store, such as the disk.
598	/// Execution proof is the set of all 'touched' storage DBValues from the backend.
599	///
600	/// On an error, no prospective changes are written to the overlay.
601	///
602	/// Note: changes to code will be in place if this call is made again. For running partial
603	/// blocks (e.g. a transaction at a time), ensure a different method is used.
604	pub fn prove_execution_on_trie_backend<S, H, N, Exec, Spawn>(
605		trie_backend: &TrieBackend<S, H>,
606		overlay: &mut OverlayedChanges,
607		exec: &Exec,
608		spawn_handle: Spawn,
609		method: &str,
610		call_data: &[u8],
611		runtime_code: &RuntimeCode,
612	) -> Result<(Vec<u8>, StorageProof), Box<dyn Error>>
613	where
614		S: trie_backend_essence::TrieBackendStorage<H>,
615		H: Hasher,
616		H::Out: Ord + 'static + codec::Codec,
617		Exec: CodeExecutor + 'static + Clone,
618		N: crate::changes_trie::BlockNumber,
619		Spawn: SpawnNamed + Send + 'static,
620	{
621		let proving_backend = proving_backend::ProvingBackend::new(trie_backend);
622		let mut sm = StateMachine::<_, H, N, Exec>::new(
623			&proving_backend,
624			None,
625			overlay,
626			exec,
627			method,
628			call_data,
629			Extensions::default(),
630			runtime_code,
631			spawn_handle,
632		);
633
634		let result = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
635			always_wasm(),
636			None,
637		)?;
638		let proof = sm.backend.extract_proof();
639		Ok((result.into_encoded(), proof))
640	}
641
642	/// Check execution proof, generated by `prove_execution` call.
643	pub fn execution_proof_check<H, N, Exec, Spawn>(
644		root: H::Out,
645		proof: StorageProof,
646		overlay: &mut OverlayedChanges,
647		exec: &Exec,
648		spawn_handle: Spawn,
649		method: &str,
650		call_data: &[u8],
651		runtime_code: &RuntimeCode,
652	) -> Result<Vec<u8>, Box<dyn Error>>
653	where
654		H: Hasher,
655		Exec: CodeExecutor + Clone + 'static,
656		H::Out: Ord + 'static + codec::Codec,
657		N: crate::changes_trie::BlockNumber,
658		Spawn: SpawnNamed + Send + 'static,
659	{
660		let trie_backend = create_proof_check_backend::<H>(root.into(), proof)?;
661		execution_proof_check_on_trie_backend::<_, N, _, _>(
662			&trie_backend,
663			overlay,
664			exec,
665			spawn_handle,
666			method,
667			call_data,
668			runtime_code,
669		)
670	}
671
672	/// Check execution proof on proving backend, generated by `prove_execution` call.
673	pub fn execution_proof_check_on_trie_backend<H, N, Exec, Spawn>(
674		trie_backend: &TrieBackend<MemoryDB<H>, H>,
675		overlay: &mut OverlayedChanges,
676		exec: &Exec,
677		spawn_handle: Spawn,
678		method: &str,
679		call_data: &[u8],
680		runtime_code: &RuntimeCode,
681	) -> Result<Vec<u8>, Box<dyn Error>>
682	where
683		H: Hasher,
684		H::Out: Ord + 'static + codec::Codec,
685		Exec: CodeExecutor + Clone + 'static,
686		N: crate::changes_trie::BlockNumber,
687		Spawn: SpawnNamed + Send + 'static,
688	{
689		let mut sm = StateMachine::<_, H, N, Exec>::new(
690			trie_backend,
691			None,
692			overlay,
693			exec,
694			method,
695			call_data,
696			Extensions::default(),
697			runtime_code,
698			spawn_handle,
699		);
700
701		sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
702			always_untrusted_wasm(),
703			None,
704		).map(NativeOrEncoded::into_encoded)
705	}
706
707	/// Generate storage read proof.
708	pub fn prove_read<B, H, I>(
709		mut backend: B,
710		keys: I,
711	) -> Result<StorageProof, Box<dyn Error>>
712	where
713		B: Backend<H>,
714		H: Hasher,
715		H::Out: Ord + Codec,
716		I: IntoIterator,
717		I::Item: AsRef<[u8]>,
718	{
719		let trie_backend = backend.as_trie_backend()
720			.ok_or_else(
721				|| Box::new(ExecutionError::UnableToGenerateProof) as Box<dyn Error>
722			)?;
723		prove_read_on_trie_backend(trie_backend, keys)
724	}
725
726	/// Generate child storage read proof.
727	pub fn prove_child_read<B, H, I>(
728		mut backend: B,
729		child_info: &ChildInfo,
730		keys: I,
731	) -> Result<StorageProof, Box<dyn Error>>
732	where
733		B: Backend<H>,
734		H: Hasher,
735		H::Out: Ord + Codec,
736		I: IntoIterator,
737		I::Item: AsRef<[u8]>,
738	{
739		let trie_backend = backend.as_trie_backend()
740			.ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box<dyn Error>)?;
741		prove_child_read_on_trie_backend(trie_backend, child_info, keys)
742	}
743
744	/// Generate storage read proof on pre-created trie backend.
745	pub fn prove_read_on_trie_backend<S, H, I>(
746		trie_backend: &TrieBackend<S, H>,
747		keys: I,
748	) -> Result<StorageProof, Box<dyn Error>>
749	where
750		S: trie_backend_essence::TrieBackendStorage<H>,
751		H: Hasher,
752		H::Out: Ord + Codec,
753		I: IntoIterator,
754		I::Item: AsRef<[u8]>,
755	{
756		let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend);
757		for key in keys.into_iter() {
758			proving_backend
759				.storage(key.as_ref())
760				.map_err(|e| Box::new(e) as Box<dyn Error>)?;
761		}
762		Ok(proving_backend.extract_proof())
763	}
764
765	/// Generate storage read proof on pre-created trie backend.
766	pub fn prove_child_read_on_trie_backend<S, H, I>(
767		trie_backend: &TrieBackend<S, H>,
768		child_info: &ChildInfo,
769		keys: I,
770	) -> Result<StorageProof, Box<dyn Error>>
771	where
772		S: trie_backend_essence::TrieBackendStorage<H>,
773		H: Hasher,
774		H::Out: Ord + Codec,
775		I: IntoIterator,
776		I::Item: AsRef<[u8]>,
777	{
778		let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend);
779		for key in keys.into_iter() {
780			proving_backend
781				.child_storage(child_info, key.as_ref())
782				.map_err(|e| Box::new(e) as Box<dyn Error>)?;
783		}
784		Ok(proving_backend.extract_proof())
785	}
786
787	/// Check storage read proof, generated by `prove_read` call.
788	pub fn read_proof_check<H, I>(
789		root: H::Out,
790		proof: StorageProof,
791		keys: I,
792	) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
793	where
794		H: Hasher,
795		H::Out: Ord + Codec,
796		I: IntoIterator,
797		I::Item: AsRef<[u8]>,
798	{
799		let proving_backend = create_proof_check_backend::<H>(root, proof)?;
800		let mut result = HashMap::new();
801		for key in keys.into_iter() {
802			let value = read_proof_check_on_proving_backend(&proving_backend, key.as_ref())?;
803			result.insert(key.as_ref().to_vec(), value);
804		}
805		Ok(result)
806	}
807
808	/// Check child storage read proof, generated by `prove_child_read` call.
809	pub fn read_child_proof_check<H, I>(
810		root: H::Out,
811		proof: StorageProof,
812		child_info: &ChildInfo,
813		keys: I,
814	) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
815	where
816		H: Hasher,
817		H::Out: Ord + Codec,
818		I: IntoIterator,
819		I::Item: AsRef<[u8]>,
820	{
821		let proving_backend = create_proof_check_backend::<H>(root, proof)?;
822		let mut result = HashMap::new();
823		for key in keys.into_iter() {
824			let value = read_child_proof_check_on_proving_backend(
825				&proving_backend,
826				child_info,
827				key.as_ref(),
828			)?;
829			result.insert(key.as_ref().to_vec(), value);
830		}
831		Ok(result)
832	}
833
834	/// Check storage read proof on pre-created proving backend.
835	pub fn read_proof_check_on_proving_backend<H>(
836		proving_backend: &TrieBackend<MemoryDB<H>, H>,
837		key: &[u8],
838	) -> Result<Option<Vec<u8>>, Box<dyn Error>>
839	where
840		H: Hasher,
841		H::Out: Ord + Codec,
842	{
843		proving_backend.storage(key).map_err(|e| Box::new(e) as Box<dyn Error>)
844	}
845
846	/// Check child storage read proof on pre-created proving backend.
847	pub fn read_child_proof_check_on_proving_backend<H>(
848		proving_backend: &TrieBackend<MemoryDB<H>, H>,
849		child_info: &ChildInfo,
850		key: &[u8],
851	) -> Result<Option<Vec<u8>>, Box<dyn Error>>
852	where
853		H: Hasher,
854		H::Out: Ord + Codec,
855	{
856		proving_backend.child_storage(child_info, key)
857			.map_err(|e| Box::new(e) as Box<dyn Error>)
858	}
859}
860
861#[cfg(test)]
862mod tests {
863	use std::collections::BTreeMap;
864	use codec::Encode;
865	use super::*;
866	use super::ext::Ext;
867	use super::changes_trie::Configuration as ChangesTrieConfig;
868	use tet_core::{
869		map, traits::{Externalities, RuntimeCode}, testing::TaskExecutor,
870	};
871	use tp_runtime::traits::BlakeTwo256;
872	use std::{result, collections::HashMap};
873	use codec::Decode;
874	use tet_core::{
875		storage::ChildInfo, NativeOrEncoded, NeverNativeValue,
876		traits::CodeExecutor,
877	};
878	use crate::execution::CallResult;
879
880
881	#[derive(Clone)]
882	struct DummyCodeExecutor {
883		change_changes_trie_config: bool,
884		native_available: bool,
885		native_succeeds: bool,
886		fallback_succeeds: bool,
887	}
888
889	impl CodeExecutor for DummyCodeExecutor {
890		type Error = u8;
891
892		fn call<
893			R: Encode + Decode + PartialEq,
894			NC: FnOnce() -> result::Result<R, String>,
895		>(
896			&self,
897			ext: &mut dyn Externalities,
898			_: &RuntimeCode,
899			_method: &str,
900			_data: &[u8],
901			use_native: bool,
902			native_call: Option<NC>,
903		) -> (CallResult<R, Self::Error>, bool) {
904			if self.change_changes_trie_config {
905				ext.place_storage(
906					tet_core::storage::well_known_keys::CHANGES_TRIE_CONFIG.to_vec(),
907					Some(
908						ChangesTrieConfig {
909							digest_interval: 777,
910							digest_levels: 333,
911						}.encode()
912					)
913				);
914			}
915
916			let using_native = use_native && self.native_available;
917			match (using_native, self.native_succeeds, self.fallback_succeeds, native_call) {
918				(true, true, _, Some(call)) => {
919					let res = externalities::set_and_run_with_externalities(ext, || call());
920					(
921						res.map(NativeOrEncoded::Native).map_err(|_| 0),
922						true
923					)
924				},
925				(true, true, _, None) | (false, _, true, None) => {
926					(
927						Ok(
928							NativeOrEncoded::Encoded(
929								vec![
930									ext.storage(b"value1").unwrap()[0] +
931									ext.storage(b"value2").unwrap()[0]
932								]
933							)
934						),
935						using_native
936					)
937				},
938				_ => (Err(0), using_native),
939			}
940		}
941	}
942
943	impl tet_core::traits::CallInWasm for DummyCodeExecutor {
944		fn call_in_wasm(
945			&self,
946			_: &[u8],
947			_: Option<Vec<u8>>,
948			_: &str,
949			_: &[u8],
950			_: &mut dyn Externalities,
951			_: tet_core::traits::MissingHostFunctions,
952		) -> std::result::Result<Vec<u8>, String> {
953			unimplemented!("Not required in tests.")
954		}
955	}
956
957	#[test]
958	fn execute_works() {
959		let backend = trie_backend::tests::test_trie();
960		let mut overlayed_changes = Default::default();
961		let wasm_code = RuntimeCode::empty();
962
963		let mut state_machine = StateMachine::new(
964			&backend,
965			changes_trie::disabled_state::<_, u64>(),
966			&mut overlayed_changes,
967			&DummyCodeExecutor {
968				change_changes_trie_config: false,
969				native_available: true,
970				native_succeeds: true,
971				fallback_succeeds: true,
972			},
973			"test",
974			&[],
975			Default::default(),
976			&wasm_code,
977			TaskExecutor::new(),
978		);
979
980		assert_eq!(
981			state_machine.execute(ExecutionStrategy::NativeWhenPossible).unwrap(),
982			vec![66],
983		);
984	}
985
986
987	#[test]
988	fn execute_works_with_native_else_wasm() {
989		let backend = trie_backend::tests::test_trie();
990		let mut overlayed_changes = Default::default();
991		let wasm_code = RuntimeCode::empty();
992
993		let mut state_machine = StateMachine::new(
994			&backend,
995			changes_trie::disabled_state::<_, u64>(),
996			&mut overlayed_changes,
997			&DummyCodeExecutor {
998				change_changes_trie_config: false,
999				native_available: true,
1000				native_succeeds: true,
1001				fallback_succeeds: true,
1002			},
1003			"test",
1004			&[],
1005			Default::default(),
1006			&wasm_code,
1007			TaskExecutor::new(),
1008		);
1009
1010		assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]);
1011	}
1012
1013	#[test]
1014	fn dual_execution_strategy_detects_consensus_failure() {
1015		let mut consensus_failed = false;
1016		let backend = trie_backend::tests::test_trie();
1017		let mut overlayed_changes = Default::default();
1018		let wasm_code = RuntimeCode::empty();
1019
1020		let mut state_machine = StateMachine::new(
1021			&backend,
1022			changes_trie::disabled_state::<_, u64>(),
1023			&mut overlayed_changes,
1024			&DummyCodeExecutor {
1025				change_changes_trie_config: false,
1026				native_available: true,
1027				native_succeeds: true,
1028				fallback_succeeds: false,
1029			},
1030			"test",
1031			&[],
1032			Default::default(),
1033			&wasm_code,
1034			TaskExecutor::new(),
1035		);
1036
1037		assert!(
1038			state_machine.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
1039				ExecutionManager::Both(|we, _ne| {
1040					consensus_failed = true;
1041					we
1042				}),
1043				None,
1044			).is_err()
1045		);
1046		assert!(consensus_failed);
1047	}
1048
1049	#[test]
1050	fn prove_execution_and_proof_check_works() {
1051		let executor = DummyCodeExecutor {
1052			change_changes_trie_config: false,
1053			native_available: true,
1054			native_succeeds: true,
1055			fallback_succeeds: true,
1056		};
1057
1058		// fetch execution proof from 'remote' full node
1059		let remote_backend = trie_backend::tests::test_trie();
1060		let remote_root = remote_backend.storage_root(std::iter::empty()).0;
1061		let (remote_result, remote_proof) = prove_execution::<_, _, u64, _, _>(
1062			remote_backend,
1063			&mut Default::default(),
1064			&executor,
1065			TaskExecutor::new(),
1066			"test",
1067			&[],
1068			&RuntimeCode::empty(),
1069		).unwrap();
1070
1071		// check proof locally
1072		let local_result = execution_proof_check::<BlakeTwo256, u64, _, _>(
1073			remote_root,
1074			remote_proof,
1075			&mut Default::default(),
1076			&executor,
1077			TaskExecutor::new(),
1078			"test",
1079			&[],
1080			&RuntimeCode::empty(),
1081		).unwrap();
1082
1083		// check that both results are correct
1084		assert_eq!(remote_result, vec![66]);
1085		assert_eq!(remote_result, local_result);
1086	}
1087
1088	#[test]
1089	fn clear_prefix_in_ext_works() {
1090		let initial: BTreeMap<_, _> = map![
1091			b"aaa".to_vec() => b"0".to_vec(),
1092			b"abb".to_vec() => b"1".to_vec(),
1093			b"abc".to_vec() => b"2".to_vec(),
1094			b"bbb".to_vec() => b"3".to_vec()
1095		];
1096		let mut state = InMemoryBackend::<BlakeTwo256>::from(initial);
1097		let backend = state.as_trie_backend().unwrap();
1098
1099		let mut overlay = OverlayedChanges::default();
1100		overlay.set_storage(b"aba".to_vec(), Some(b"1312".to_vec()));
1101		overlay.set_storage(b"bab".to_vec(), Some(b"228".to_vec()));
1102		overlay.start_transaction();
1103		overlay.set_storage(b"abd".to_vec(), Some(b"69".to_vec()));
1104		overlay.set_storage(b"bbd".to_vec(), Some(b"42".to_vec()));
1105
1106		{
1107			let mut cache = StorageTransactionCache::default();
1108			let mut ext = Ext::new(
1109				&mut overlay,
1110				&mut cache,
1111				backend,
1112				changes_trie::disabled_state::<_, u64>(),
1113				None,
1114			);
1115			ext.clear_prefix(b"ab");
1116		}
1117		overlay.commit_transaction().unwrap();
1118
1119		assert_eq!(
1120			overlay.changes().map(|(k, v)| (k.clone(), v.value().cloned()))
1121				.collect::<HashMap<_, _>>(),
1122			map![
1123				b"abc".to_vec() => None.into(),
1124				b"abb".to_vec() => None.into(),
1125				b"aba".to_vec() => None.into(),
1126				b"abd".to_vec() => None.into(),
1127
1128				b"bab".to_vec() => Some(b"228".to_vec()).into(),
1129				b"bbd".to_vec() => Some(b"42".to_vec()).into()
1130			],
1131		);
1132	}
1133
1134	#[test]
1135	fn limited_child_kill_works() {
1136		let child_info = ChildInfo::new_default(b"sub1");
1137		let initial: HashMap<_, BTreeMap<_, _>> = map![
1138			Some(child_info.clone()) => map![
1139				b"a".to_vec() => b"0".to_vec(),
1140				b"b".to_vec() => b"1".to_vec(),
1141				b"c".to_vec() => b"2".to_vec(),
1142				b"d".to_vec() => b"3".to_vec()
1143			],
1144		];
1145		let backend = InMemoryBackend::<BlakeTwo256>::from(initial);
1146
1147		let mut overlay = OverlayedChanges::default();
1148		overlay.set_child_storage(&child_info, b"1".to_vec(), Some(b"1312".to_vec()));
1149		overlay.set_child_storage(&child_info, b"2".to_vec(), Some(b"1312".to_vec()));
1150		overlay.set_child_storage(&child_info, b"3".to_vec(), Some(b"1312".to_vec()));
1151		overlay.set_child_storage(&child_info, b"4".to_vec(), Some(b"1312".to_vec()));
1152
1153		{
1154			let mut cache = StorageTransactionCache::default();
1155			let mut ext = Ext::new(
1156				&mut overlay,
1157				&mut cache,
1158				&backend,
1159				changes_trie::disabled_state::<_, u64>(),
1160				None,
1161			);
1162			assert_eq!(ext.kill_child_storage(&child_info, Some(2)), false);
1163		}
1164
1165		assert_eq!(
1166			overlay.children()
1167				.flat_map(|(iter, _child_info)| iter)
1168				.map(|(k, v)| (k.clone(), v.value().clone()))
1169				.collect::<BTreeMap<_, _>>(),
1170			map![
1171				b"1".to_vec() => None.into(),
1172				b"2".to_vec() => None.into(),
1173				b"3".to_vec() => None.into(),
1174				b"4".to_vec() => None.into(),
1175				b"a".to_vec() => None.into(),
1176				b"b".to_vec() => None.into(),
1177			],
1178		);
1179	}
1180
1181	#[test]
1182	fn limited_child_kill_off_by_one_works() {
1183		let child_info = ChildInfo::new_default(b"sub1");
1184		let initial: HashMap<_, BTreeMap<_, _>> = map![
1185			Some(child_info.clone()) => map![
1186				b"a".to_vec() => b"0".to_vec(),
1187				b"b".to_vec() => b"1".to_vec(),
1188				b"c".to_vec() => b"2".to_vec(),
1189				b"d".to_vec() => b"3".to_vec()
1190			],
1191		];
1192		let backend = InMemoryBackend::<BlakeTwo256>::from(initial);
1193		let mut overlay = OverlayedChanges::default();
1194		let mut cache = StorageTransactionCache::default();
1195		let mut ext = Ext::new(
1196			&mut overlay,
1197			&mut cache,
1198			&backend,
1199			changes_trie::disabled_state::<_, u64>(),
1200			None,
1201		);
1202		assert_eq!(ext.kill_child_storage(&child_info, Some(0)), false);
1203		assert_eq!(ext.kill_child_storage(&child_info, Some(1)), false);
1204		assert_eq!(ext.kill_child_storage(&child_info, Some(2)), false);
1205		assert_eq!(ext.kill_child_storage(&child_info, Some(3)), false);
1206		assert_eq!(ext.kill_child_storage(&child_info, Some(4)), true);
1207		assert_eq!(ext.kill_child_storage(&child_info, Some(5)), true);
1208	}
1209
1210	#[test]
1211	fn set_child_storage_works() {
1212		let child_info = ChildInfo::new_default(b"sub1");
1213		let child_info = &child_info;
1214		let mut state = new_in_mem::<BlakeTwo256>();
1215		let backend = state.as_trie_backend().unwrap();
1216		let mut overlay = OverlayedChanges::default();
1217		let mut cache = StorageTransactionCache::default();
1218		let mut ext = Ext::new(
1219			&mut overlay,
1220			&mut cache,
1221			backend,
1222			changes_trie::disabled_state::<_, u64>(),
1223			None,
1224		);
1225
1226		ext.set_child_storage(
1227			child_info,
1228			b"abc".to_vec(),
1229			b"def".to_vec()
1230		);
1231		assert_eq!(
1232			ext.child_storage(
1233				child_info,
1234				b"abc"
1235			),
1236			Some(b"def".to_vec())
1237		);
1238		ext.kill_child_storage(
1239			child_info,
1240			None,
1241		);
1242		assert_eq!(
1243			ext.child_storage(
1244				child_info,
1245				b"abc"
1246			),
1247			None
1248		);
1249	}
1250
1251	#[test]
1252	fn append_storage_works() {
1253		let reference_data = vec![
1254			b"data1".to_vec(),
1255			b"2".to_vec(),
1256			b"D3".to_vec(),
1257			b"d4".to_vec(),
1258		];
1259		let key = b"key".to_vec();
1260		let mut state = new_in_mem::<BlakeTwo256>();
1261		let backend = state.as_trie_backend().unwrap();
1262		let mut overlay = OverlayedChanges::default();
1263		let mut cache = StorageTransactionCache::default();
1264		{
1265			let mut ext = Ext::new(
1266				&mut overlay,
1267				&mut cache,
1268				backend,
1269				changes_trie::disabled_state::<_, u64>(),
1270				None,
1271			);
1272
1273			ext.storage_append(key.clone(), reference_data[0].encode());
1274			assert_eq!(
1275				ext.storage(key.as_slice()),
1276				Some(vec![reference_data[0].clone()].encode()),
1277			);
1278		}
1279		overlay.start_transaction();
1280		{
1281			let mut ext = Ext::new(
1282				&mut overlay,
1283				&mut cache,
1284				backend,
1285				changes_trie::disabled_state::<_, u64>(),
1286				None,
1287			);
1288
1289			for i in reference_data.iter().skip(1) {
1290				ext.storage_append(key.clone(), i.encode());
1291			}
1292			assert_eq!(
1293				ext.storage(key.as_slice()),
1294				Some(reference_data.encode()),
1295			);
1296		}
1297		overlay.rollback_transaction().unwrap();
1298		{
1299			let ext = Ext::new(
1300				&mut overlay,
1301				&mut cache,
1302				backend,
1303				changes_trie::disabled_state::<_, u64>(),
1304				None,
1305			);
1306			assert_eq!(
1307				ext.storage(key.as_slice()),
1308				Some(vec![reference_data[0].clone()].encode()),
1309			);
1310		}
1311	}
1312
1313	#[test]
1314	fn remove_with_append_then_rollback_appended_then_append_again() {
1315
1316		#[derive(codec::Encode, codec::Decode)]
1317		enum Item { InitializationItem, DiscardedItem, CommitedItem }
1318
1319		let key = b"events".to_vec();
1320		let mut cache = StorageTransactionCache::default();
1321		let mut state = new_in_mem::<BlakeTwo256>();
1322		let backend = state.as_trie_backend().unwrap();
1323		let mut overlay = OverlayedChanges::default();
1324
1325		// For example, block initialization with event.
1326		{
1327			let mut ext = Ext::new(
1328				&mut overlay,
1329				&mut cache,
1330				backend,
1331				changes_trie::disabled_state::<_, u64>(),
1332				None,
1333			);
1334			ext.clear_storage(key.as_slice());
1335			ext.storage_append(key.clone(), Item::InitializationItem.encode());
1336		}
1337		overlay.start_transaction();
1338
1339		// For example, first transaction resulted in panic during block building
1340		{
1341			let mut ext = Ext::new(
1342				&mut overlay,
1343				&mut cache,
1344				backend,
1345				changes_trie::disabled_state::<_, u64>(),
1346				None,
1347			);
1348
1349			assert_eq!(
1350				ext.storage(key.as_slice()),
1351				Some(vec![Item::InitializationItem].encode()),
1352			);
1353
1354			ext.storage_append(key.clone(), Item::DiscardedItem.encode());
1355
1356			assert_eq!(
1357				ext.storage(key.as_slice()),
1358				Some(vec![Item::InitializationItem, Item::DiscardedItem].encode()),
1359			);
1360		}
1361		overlay.rollback_transaction().unwrap();
1362
1363		// Then we apply next transaction which is valid this time.
1364		{
1365			let mut ext = Ext::new(
1366				&mut overlay,
1367				&mut cache,
1368				backend,
1369				changes_trie::disabled_state::<_, u64>(),
1370				None,
1371			);
1372
1373			assert_eq!(
1374				ext.storage(key.as_slice()),
1375				Some(vec![Item::InitializationItem].encode()),
1376			);
1377
1378			ext.storage_append(key.clone(), Item::CommitedItem.encode());
1379
1380			assert_eq!(
1381				ext.storage(key.as_slice()),
1382				Some(vec![Item::InitializationItem, Item::CommitedItem].encode()),
1383			);
1384
1385		}
1386		overlay.start_transaction();
1387
1388		// Then only initlaization item and second (commited) item should persist.
1389		{
1390			let ext = Ext::new(
1391				&mut overlay,
1392				&mut cache,
1393				backend,
1394				changes_trie::disabled_state::<_, u64>(),
1395				None,
1396			);
1397			assert_eq!(
1398				ext.storage(key.as_slice()),
1399				Some(vec![Item::InitializationItem, Item::CommitedItem].encode()),
1400			);
1401		}
1402	}
1403
1404	#[test]
1405	fn prove_read_and_proof_check_works() {
1406		let child_info = ChildInfo::new_default(b"sub1");
1407		let child_info = &child_info;
1408		// fetch read proof from 'remote' full node
1409		let remote_backend = trie_backend::tests::test_trie();
1410		let remote_root = remote_backend.storage_root(::std::iter::empty()).0;
1411		let remote_proof = prove_read(remote_backend, &[b"value2"]).unwrap();
1412 		// check proof locally
1413		let local_result1 = read_proof_check::<BlakeTwo256, _>(
1414			remote_root,
1415			remote_proof.clone(),
1416			&[b"value2"],
1417		).unwrap();
1418		let local_result2 = read_proof_check::<BlakeTwo256, _>(
1419			remote_root,
1420			remote_proof.clone(),
1421			&[&[0xff]],
1422		).is_ok();
1423 		// check that results are correct
1424		assert_eq!(
1425			local_result1.into_iter().collect::<Vec<_>>(),
1426			vec![(b"value2".to_vec(), Some(vec![24]))],
1427		);
1428		assert_eq!(local_result2, false);
1429		// on child trie
1430		let remote_backend = trie_backend::tests::test_trie();
1431		let remote_root = remote_backend.storage_root(::std::iter::empty()).0;
1432		let remote_proof = prove_child_read(
1433			remote_backend,
1434			child_info,
1435			&[b"value3"],
1436		).unwrap();
1437		let local_result1 = read_child_proof_check::<BlakeTwo256, _>(
1438			remote_root,
1439			remote_proof.clone(),
1440			child_info,
1441			&[b"value3"],
1442		).unwrap();
1443		let local_result2 = read_child_proof_check::<BlakeTwo256, _>(
1444			remote_root,
1445			remote_proof.clone(),
1446			child_info,
1447			&[b"value2"],
1448		).unwrap();
1449		assert_eq!(
1450			local_result1.into_iter().collect::<Vec<_>>(),
1451			vec![(b"value3".to_vec(), Some(vec![142]))],
1452		);
1453		assert_eq!(
1454			local_result2.into_iter().collect::<Vec<_>>(),
1455			vec![(b"value2".to_vec(), None)],
1456		);
1457	}
1458
1459	#[test]
1460	fn child_storage_uuid() {
1461
1462		let child_info_1 = ChildInfo::new_default(b"sub_test1");
1463		let child_info_2 = ChildInfo::new_default(b"sub_test2");
1464
1465		use crate::trie_backend::tests::test_trie;
1466		let mut overlay = OverlayedChanges::default();
1467
1468		let mut transaction = {
1469			let backend = test_trie();
1470			let mut cache = StorageTransactionCache::default();
1471			let mut ext = Ext::new(
1472				&mut overlay,
1473				&mut cache,
1474				&backend,
1475				changes_trie::disabled_state::<_, u64>(),
1476				None,
1477			);
1478			ext.set_child_storage(&child_info_1, b"abc".to_vec(), b"def".to_vec());
1479			ext.set_child_storage(&child_info_2, b"abc".to_vec(), b"def".to_vec());
1480			ext.storage_root();
1481			cache.transaction.unwrap()
1482		};
1483		let mut duplicate = false;
1484		for (k, (value, rc)) in transaction.drain().iter() {
1485			// look for a key inserted twice: transaction rc is 2
1486			if *rc == 2 {
1487				duplicate = true;
1488				println!("test duplicate for {:?} {:?}", k, value);
1489			}
1490		}
1491		assert!(!duplicate);
1492	}
1493
1494	#[test]
1495	fn set_storage_empty_allowed() {
1496		let initial: BTreeMap<_, _> = map![
1497			b"aaa".to_vec() => b"0".to_vec(),
1498			b"bbb".to_vec() => b"".to_vec()
1499		];
1500		let mut state = InMemoryBackend::<BlakeTwo256>::from(initial);
1501		let backend = state.as_trie_backend().unwrap();
1502
1503		let mut overlay = OverlayedChanges::default();
1504		overlay.start_transaction();
1505		overlay.set_storage(b"ccc".to_vec(), Some(b"".to_vec()));
1506		assert_eq!(overlay.storage(b"ccc"), Some(Some(&[][..])));
1507		overlay.commit_transaction().unwrap();
1508		overlay.start_transaction();
1509		assert_eq!(overlay.storage(b"ccc"), Some(Some(&[][..])));
1510		assert_eq!(overlay.storage(b"bbb"), None);
1511
1512		{
1513			let mut cache = StorageTransactionCache::default();
1514			let mut ext = Ext::new(
1515				&mut overlay,
1516				&mut cache,
1517				backend,
1518				changes_trie::disabled_state::<_, u64>(),
1519				None,
1520			);
1521			assert_eq!(ext.storage(b"bbb"), Some(vec![]));
1522			assert_eq!(ext.storage(b"ccc"), Some(vec![]));
1523			ext.clear_storage(b"ccc");
1524			assert_eq!(ext.storage(b"ccc"), None);
1525		}
1526		overlay.commit_transaction().unwrap();
1527		assert_eq!(overlay.storage(b"ccc"), Some(None));
1528	}
1529
1530	#[test]
1531	fn runtime_registered_extensions_are_removed_after_execution() {
1532		use externalities::ExternalitiesExt;
1533		externalities::decl_extension! {
1534			struct DummyExt(u32);
1535		}
1536
1537		let backend = trie_backend::tests::test_trie();
1538		let mut overlayed_changes = Default::default();
1539		let wasm_code = RuntimeCode::empty();
1540
1541		let mut state_machine = StateMachine::new(
1542			&backend,
1543			changes_trie::disabled_state::<_, u64>(),
1544			&mut overlayed_changes,
1545			&DummyCodeExecutor {
1546				change_changes_trie_config: false,
1547				native_available: true,
1548				native_succeeds: true,
1549				fallback_succeeds: false,
1550			},
1551			"test",
1552			&[],
1553			Default::default(),
1554			&wasm_code,
1555			TaskExecutor::new(),
1556		);
1557
1558		let run_state_machine = |state_machine: &mut StateMachine<_, _, _, _>| {
1559			state_machine.execute_using_consensus_failure_handler::<fn(_, _) -> _, _, _>(
1560				ExecutionManager::NativeWhenPossible,
1561				Some(|| {
1562					externalities::with_externalities(|mut ext| {
1563						ext.register_extension(DummyExt(2)).unwrap();
1564					}).unwrap();
1565
1566					Ok(())
1567				}),
1568			).unwrap();
1569		};
1570
1571		run_state_machine(&mut state_machine);
1572		run_state_machine(&mut state_machine);
1573	}
1574}