Skip to main content

sp_state_machine/overlayed_changes/
mod.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//! The overlayed changes to state.
19
20mod changeset;
21mod offchain;
22
23use self::changeset::OverlayedChangeSet;
24use crate::{backend::Backend, stats::StateMachineStats, BackendTransaction, DefaultError};
25use alloc::{collections::btree_set::BTreeSet, vec::Vec};
26use codec::{Decode, Encode};
27use hash_db::Hasher;
28pub use offchain::OffchainOverlayedChanges;
29use sp_core::{
30	offchain::OffchainOverlayedChange,
31	storage::{well_known_keys::EXTRINSIC_INDEX, ChildInfo, StateVersion},
32};
33#[cfg(feature = "std")]
34use sp_externalities::{Extension, Extensions, TransactionType};
35use sp_trie::{empty_child_trie_root, LayoutV1};
36
37#[cfg(not(feature = "std"))]
38use alloc::collections::btree_map::BTreeMap as Map;
39#[cfg(feature = "std")]
40use std::collections::{hash_map::Entry as MapEntry, HashMap as Map};
41
42#[cfg(feature = "std")]
43use std::{
44	any::{Any, TypeId},
45	boxed::Box,
46};
47
48pub use self::changeset::{AlreadyInRuntime, NoOpenTransaction, NotInRuntime, OverlayedValue};
49
50/// Changes that are made outside of extrinsics are marked with this index;
51pub const NO_EXTRINSIC_INDEX: u32 = 0xffffffff;
52
53/// Storage key.
54pub type StorageKey = Vec<u8>;
55
56/// Storage value.
57pub type StorageValue = Vec<u8>;
58
59/// In memory array of storage values.
60pub type StorageCollection = Vec<(StorageKey, Option<StorageValue>)>;
61
62/// In memory arrays of storage values for multiple child tries.
63pub type ChildStorageCollection = Vec<(StorageKey, StorageCollection)>;
64
65/// In memory array of storage values.
66pub type OffchainChangesCollection = Vec<((Vec<u8>, Vec<u8>), OffchainOverlayedChange)>;
67
68/// Keep trace of extrinsics index for a modified value.
69#[derive(Debug, Default, Eq, PartialEq, Clone)]
70pub struct Extrinsics(Vec<u32>);
71
72impl Extrinsics {
73	/// Extracts extrinsics into a `BTreeSets`.
74	fn copy_extrinsics_into(&self, dest: &mut BTreeSet<u32>) {
75		dest.extend(self.0.iter())
76	}
77
78	/// Add an extrinsics.
79	fn insert(&mut self, ext: u32) {
80		if Some(&ext) != self.0.last() {
81			self.0.push(ext);
82		}
83	}
84
85	/// Extend `self` with `other`.
86	fn extend(&mut self, other: Self) {
87		self.0.extend(other.0.into_iter());
88	}
89}
90
91/// The set of changes that are overlaid onto the backend.
92///
93/// It allows changes to be modified using nestable transactions.
94pub struct OverlayedChanges<H: Hasher> {
95	/// Top level storage changes.
96	top: OverlayedChangeSet,
97	/// Child storage changes. The map key is the child storage key without the common prefix.
98	children: Map<StorageKey, (OverlayedChangeSet, ChildInfo)>,
99	/// Offchain related changes.
100	offchain: OffchainOverlayedChanges,
101	/// Transaction index changes,
102	transaction_index_ops: Vec<IndexOperation>,
103	/// True if extrinsics stats must be collected.
104	collect_extrinsics: bool,
105	/// Collect statistic on this execution.
106	stats: StateMachineStats,
107	/// Caches the "storage transaction" that is created while calling `storage_root`.
108	///
109	/// This transaction can be applied to the backend to persist the state changes.
110	storage_transaction_cache: Option<StorageTransactionCache<H>>,
111}
112
113impl<H: Hasher> Default for OverlayedChanges<H> {
114	fn default() -> Self {
115		Self {
116			top: Default::default(),
117			children: Default::default(),
118			offchain: Default::default(),
119			transaction_index_ops: Default::default(),
120			collect_extrinsics: Default::default(),
121			stats: Default::default(),
122			storage_transaction_cache: None,
123		}
124	}
125}
126
127impl<H: Hasher> Clone for OverlayedChanges<H> {
128	fn clone(&self) -> Self {
129		Self {
130			top: self.top.clone(),
131			children: self.children.clone(),
132			offchain: self.offchain.clone(),
133			transaction_index_ops: self.transaction_index_ops.clone(),
134			collect_extrinsics: self.collect_extrinsics,
135			stats: self.stats.clone(),
136			storage_transaction_cache: self.storage_transaction_cache.clone(),
137		}
138	}
139}
140
141impl<H: Hasher> core::fmt::Debug for OverlayedChanges<H> {
142	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143		f.debug_struct("OverlayedChanges")
144			.field("top", &self.top)
145			.field("children", &self.children)
146			.field("offchain", &self.offchain)
147			.field("transaction_index_ops", &self.transaction_index_ops)
148			.field("collect_extrinsics", &self.collect_extrinsics)
149			.field("stats", &self.stats)
150			.field("storage_transaction_cache", &self.storage_transaction_cache)
151			.finish()
152	}
153}
154
155/// Transaction index operation.
156#[derive(Debug, Clone)]
157pub enum IndexOperation {
158	/// Insert transaction into index.
159	Insert {
160		/// Extrinsic index in the current block.
161		extrinsic: u32,
162		/// Data content hash.
163		hash: Vec<u8>,
164		/// Indexed data size.
165		size: u32,
166	},
167	/// Renew existing transaction storage.
168	Renew {
169		/// Extrinsic index in the current block.
170		extrinsic: u32,
171		/// Referenced index hash.
172		hash: Vec<u8>,
173	},
174}
175
176/// A storage changes structure that can be generated by the data collected in [`OverlayedChanges`].
177///
178/// This contains all the changes to the storage and transactions to apply theses changes to the
179/// backend.
180pub struct StorageChanges<H: Hasher> {
181	/// All changes to the main storage.
182	///
183	/// A value of `None` means that it was deleted.
184	pub main_storage_changes: StorageCollection,
185	/// All changes to the child storages.
186	pub child_storage_changes: ChildStorageCollection,
187	/// Offchain state changes to write to the offchain database.
188	pub offchain_storage_changes: OffchainChangesCollection,
189	/// A transaction for the backend that contains all changes from
190	/// [`main_storage_changes`](StorageChanges::main_storage_changes) and from
191	/// [`child_storage_changes`](StorageChanges::child_storage_changes).
192	/// [`offchain_storage_changes`](StorageChanges::offchain_storage_changes).
193	pub transaction: BackendTransaction<H>,
194	/// The storage root after applying the transaction.
195	pub transaction_storage_root: H::Out,
196	/// Changes to the transaction index,
197	#[cfg(feature = "std")]
198	pub transaction_index_changes: Vec<IndexOperation>,
199}
200
201#[cfg(feature = "std")]
202impl<H: Hasher> StorageChanges<H> {
203	/// Deconstruct into the inner values
204	pub fn into_inner(
205		self,
206	) -> (
207		StorageCollection,
208		ChildStorageCollection,
209		OffchainChangesCollection,
210		BackendTransaction<H>,
211		H::Out,
212		Vec<IndexOperation>,
213	) {
214		(
215			self.main_storage_changes,
216			self.child_storage_changes,
217			self.offchain_storage_changes,
218			self.transaction,
219			self.transaction_storage_root,
220			self.transaction_index_changes,
221		)
222	}
223}
224
225impl<H: Hasher> Default for StorageChanges<H> {
226	fn default() -> Self {
227		Self {
228			main_storage_changes: Default::default(),
229			child_storage_changes: Default::default(),
230			offchain_storage_changes: Default::default(),
231			transaction: BackendTransaction::with_hasher(Default::default()),
232			transaction_storage_root: Default::default(),
233			#[cfg(feature = "std")]
234			transaction_index_changes: Default::default(),
235		}
236	}
237}
238
239/// Storage transactions are calculated as part of the `storage_root`.
240/// These transactions can be reused for importing the block into the
241/// storage. So, we cache them to not require a recomputation of those transactions.
242struct StorageTransactionCache<H: Hasher> {
243	/// Contains the changes for the main and the child storages as one transaction.
244	transaction: BackendTransaction<H>,
245	/// The storage root after applying the transaction.
246	transaction_storage_root: H::Out,
247	/// The state version that was used to compute the transaction and the root.
248	state_version: StateVersion,
249}
250
251impl<H: Hasher> StorageTransactionCache<H> {
252	fn into_inner(self) -> (BackendTransaction<H>, H::Out) {
253		(self.transaction, self.transaction_storage_root)
254	}
255}
256
257impl<H: Hasher> Clone for StorageTransactionCache<H> {
258	fn clone(&self) -> Self {
259		Self {
260			transaction: self.transaction.clone(),
261			transaction_storage_root: self.transaction_storage_root,
262			state_version: self.state_version,
263		}
264	}
265}
266
267impl<H: Hasher> core::fmt::Debug for StorageTransactionCache<H> {
268	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
269		let mut debug = f.debug_struct("StorageTransactionCache");
270
271		#[cfg(feature = "std")]
272		debug.field("transaction_storage_root", &self.transaction_storage_root);
273
274		#[cfg(not(feature = "std"))]
275		debug.field("transaction_storage_root", &self.transaction_storage_root.as_ref());
276
277		debug.finish()
278	}
279}
280
281impl<H: Hasher> OverlayedChanges<H> {
282	/// Whether no changes are contained in the top nor in any of the child changes.
283	pub fn is_empty(&self) -> bool {
284		self.top.is_empty() && self.children.is_empty()
285	}
286
287	/// Ask to collect/not to collect extrinsics indices where key(s) has been changed.
288	pub fn set_collect_extrinsics(&mut self, collect_extrinsics: bool) {
289		self.collect_extrinsics = collect_extrinsics;
290	}
291
292	/// Returns a double-Option: None if the key is unknown (i.e. and the query should be referred
293	/// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose
294	/// value has been set.
295	pub fn storage(&mut self, key: &[u8]) -> Option<Option<&[u8]>> {
296		self.top.get(key).map(|x| {
297			let value = x.value();
298			let size_read = value.map(|x| x.len() as u64).unwrap_or(0);
299			self.stats.tally_read_modified(size_read);
300			value.map(AsRef::as_ref)
301		})
302	}
303
304	/// Should be called when there are changes that require to reset the
305	/// `storage_transaction_cache`.
306	fn mark_dirty(&mut self) {
307		self.storage_transaction_cache = None;
308	}
309
310	/// Returns a double-Option: None if the key is unknown (i.e. and the query should be referred
311	/// to the backend); Some(None) if the key has been deleted. Some(Some(...)) for a key whose
312	/// value has been set.
313	pub fn child_storage(&mut self, child_info: &ChildInfo, key: &[u8]) -> Option<Option<&[u8]>> {
314		let map = self.children.get_mut(child_info.storage_key())?;
315		let value = map.0.get(key)?.value();
316		let size_read = value.map(|x| x.len() as u64).unwrap_or(0);
317		self.stats.tally_read_modified(size_read);
318		Some(value.map(AsRef::as_ref))
319	}
320
321	/// Set a new value for the specified key.
322	///
323	/// Can be rolled back or committed when called inside a transaction.
324	pub fn set_storage(&mut self, key: StorageKey, val: Option<StorageValue>) {
325		self.mark_dirty();
326
327		let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
328		self.stats.tally_write_overlay(size_write);
329		let extrinsic_index = self.extrinsic_index();
330		self.top.set(key, val, extrinsic_index);
331	}
332
333	/// Append a element to storage, init with existing value if first write.
334	pub fn append_storage(
335		&mut self,
336		key: StorageKey,
337		element: StorageValue,
338		init: impl Fn() -> StorageValue,
339	) {
340		let extrinsic_index = self.extrinsic_index();
341		let size_write = element.len() as u64;
342		self.stats.tally_write_overlay(size_write);
343		self.top.append_storage(key, element, init, extrinsic_index);
344	}
345
346	/// Set a new value for the specified key and child.
347	///
348	/// `None` can be used to delete a value specified by the given key.
349	///
350	/// Can be rolled back or committed when called inside a transaction.
351	pub fn set_child_storage(
352		&mut self,
353		child_info: &ChildInfo,
354		key: StorageKey,
355		val: Option<StorageValue>,
356	) {
357		self.mark_dirty();
358
359		let extrinsic_index = self.extrinsic_index();
360		let size_write = val.as_ref().map(|x| x.len() as u64).unwrap_or(0);
361		self.stats.tally_write_overlay(size_write);
362		let storage_key = child_info.storage_key().to_vec();
363		let top = &self.top;
364		let (changeset, info) = self
365			.children
366			.entry(storage_key)
367			.or_insert_with(|| (top.spawn_child(), child_info.clone()));
368		let updatable = info.try_update(child_info);
369		debug_assert!(updatable);
370		changeset.set(key, val, extrinsic_index);
371	}
372
373	/// Clear child storage of given storage key.
374	///
375	/// Can be rolled back or committed when called inside a transaction.
376	pub fn clear_child_storage(&mut self, child_info: &ChildInfo) -> u32 {
377		self.mark_dirty();
378
379		let extrinsic_index = self.extrinsic_index();
380		let storage_key = child_info.storage_key().to_vec();
381		let top = &self.top;
382		let (changeset, info) = self
383			.children
384			.entry(storage_key)
385			.or_insert_with(|| (top.spawn_child(), child_info.clone()));
386		let updatable = info.try_update(child_info);
387		debug_assert!(updatable);
388		changeset.clear_where(|_, _| true, extrinsic_index)
389	}
390
391	/// Removes all key-value pairs which keys share the given prefix.
392	///
393	/// Can be rolled back or committed when called inside a transaction.
394	pub fn clear_prefix(&mut self, prefix: &[u8]) -> u32 {
395		self.mark_dirty();
396
397		let extrinsic_index = self.extrinsic_index();
398		self.top.clear_where(|key, _| key.starts_with(prefix), extrinsic_index)
399	}
400
401	/// Removes all key-value pairs which keys share the given prefix.
402	///
403	/// Can be rolled back or committed when called inside a transaction
404	pub fn clear_child_prefix(&mut self, child_info: &ChildInfo, prefix: &[u8]) -> u32 {
405		self.mark_dirty();
406
407		let extrinsic_index = self.extrinsic_index();
408		let storage_key = child_info.storage_key().to_vec();
409		let top = &self.top;
410		let (changeset, info) = self
411			.children
412			.entry(storage_key)
413			.or_insert_with(|| (top.spawn_child(), child_info.clone()));
414		let updatable = info.try_update(child_info);
415		debug_assert!(updatable);
416		changeset.clear_where(|key, _| key.starts_with(prefix), extrinsic_index)
417	}
418
419	/// Returns the current nesting depth of the transaction stack.
420	///
421	/// A value of zero means that no transaction is open and changes are committed on write.
422	pub fn transaction_depth(&self) -> usize {
423		// The top changeset and all child changesets transact in lockstep and are
424		// therefore always at the same transaction depth.
425		self.top.transaction_depth()
426	}
427
428	/// Start a new nested transaction.
429	///
430	/// This allows to either commit or roll back all changes that where made while this
431	/// transaction was open. Any transaction must be closed by either `rollback_transaction` or
432	/// `commit_transaction` before this overlay can be converted into storage changes.
433	///
434	/// Changes made without any open transaction are committed immediately.
435	pub fn start_transaction(&mut self) {
436		self.top.start_transaction();
437		for (_, (changeset, _)) in self.children.iter_mut() {
438			changeset.start_transaction();
439		}
440		self.offchain.overlay_mut().start_transaction();
441	}
442
443	/// Rollback the last transaction started by `start_transaction`.
444	///
445	/// Any changes made during that transaction are discarded. Returns an error if
446	/// there is no open transaction that can be rolled back.
447	pub fn rollback_transaction(&mut self) -> Result<(), NoOpenTransaction> {
448		self.mark_dirty();
449
450		self.top.rollback_transaction()?;
451		retain_map(&mut self.children, |_, (changeset, _)| {
452			changeset
453				.rollback_transaction()
454				.expect("Top and children changesets are started in lockstep; qed");
455			!changeset.is_empty()
456		});
457		self.offchain
458			.overlay_mut()
459			.rollback_transaction_offchain()
460			.expect("Top and offchain changesets are started in lockstep; qed");
461		Ok(())
462	}
463
464	/// Commit the last transaction started by `start_transaction`.
465	///
466	/// Any changes made during that transaction are committed. Returns an error if there
467	/// is no open transaction that can be committed.
468	pub fn commit_transaction(&mut self) -> Result<(), NoOpenTransaction> {
469		self.top.commit_transaction()?;
470		for (_, (changeset, _)) in self.children.iter_mut() {
471			changeset
472				.commit_transaction()
473				.expect("Top and children changesets are started in lockstep; qed");
474		}
475		self.offchain
476			.overlay_mut()
477			.commit_transaction_offchain()
478			.expect("Top and offchain changesets are started in lockstep; qed");
479		Ok(())
480	}
481
482	/// Call this before transferring control to the runtime.
483	///
484	/// This protects all existing transactions from being removed by the runtime.
485	/// Calling this while already inside the runtime will return an error.
486	pub fn enter_runtime(&mut self) -> Result<(), AlreadyInRuntime> {
487		self.top.enter_runtime()?;
488		for (_, (changeset, _)) in self.children.iter_mut() {
489			changeset
490				.enter_runtime()
491				.expect("Top and children changesets are entering runtime in lockstep; qed")
492		}
493		self.offchain
494			.overlay_mut()
495			.enter_runtime()
496			.expect("Top and offchain changesets are started in lockstep; qed");
497		Ok(())
498	}
499
500	/// Call this when control returns from the runtime.
501	///
502	/// This rollbacks all dangling transaction left open by the runtime.
503	/// Calling this while outside the runtime will return an error.
504	pub fn exit_runtime(&mut self) -> Result<(), NotInRuntime> {
505		self.top.exit_runtime()?;
506		for (_, (changeset, _)) in self.children.iter_mut() {
507			changeset
508				.exit_runtime()
509				.expect("Top and children changesets are entering runtime in lockstep; qed");
510		}
511		self.offchain
512			.overlay_mut()
513			.exit_runtime_offchain()
514			.expect("Top and offchain changesets are started in lockstep; qed");
515		Ok(())
516	}
517
518	/// Consume all changes (top + children) and return them.
519	///
520	/// After calling this function no more changes are contained in this changeset.
521	///
522	/// Panics:
523	/// Panics if `transaction_depth() > 0`
524	pub fn offchain_drain_committed(
525		&mut self,
526	) -> impl Iterator<Item = ((StorageKey, StorageKey), OffchainOverlayedChange)> {
527		self.offchain.drain()
528	}
529
530	/// Get an iterator over all child changes as seen by the current transaction.
531	pub fn children(
532		&self,
533	) -> impl Iterator<Item = (impl Iterator<Item = (&StorageKey, &OverlayedValue)>, &ChildInfo)> {
534		self.children.values().map(|v| (v.0.changes(), &v.1))
535	}
536
537	/// Get an iterator over all child changes as seen by the current transaction.
538	pub fn children_mut(
539		&mut self,
540	) -> impl Iterator<Item = (impl Iterator<Item = (&StorageKey, &mut OverlayedValue)>, &ChildInfo)>
541	{
542		self.children.values_mut().map(|v| (v.0.changes_mut(), &v.1))
543	}
544
545	/// Get an iterator over all top changes as been by the current transaction.
546	pub fn changes(&self) -> impl Iterator<Item = (&StorageKey, &OverlayedValue)> {
547		self.top.changes()
548	}
549
550	/// Get an iterator over all top changes as been by the current transaction.
551	pub fn changes_mut(&mut self) -> impl Iterator<Item = (&StorageKey, &mut OverlayedValue)> {
552		self.top.changes_mut()
553	}
554
555	/// Get an optional iterator over all child changes stored under the supplied key.
556	pub fn child_changes(
557		&self,
558		key: &[u8],
559	) -> Option<(impl Iterator<Item = (&StorageKey, &OverlayedValue)>, &ChildInfo)> {
560		self.children.get(key).map(|(overlay, info)| (overlay.changes(), info))
561	}
562
563	/// Get an optional iterator over all child changes stored under the supplied key.
564	pub fn child_changes_mut(
565		&mut self,
566		key: &[u8],
567	) -> Option<(impl Iterator<Item = (&StorageKey, &mut OverlayedValue)>, &ChildInfo)> {
568		self.children
569			.get_mut(key)
570			.map(|(overlay, info)| (overlay.changes_mut(), &*info))
571	}
572
573	/// Get an list of all index operations.
574	pub fn transaction_index_ops(&self) -> &[IndexOperation] {
575		&self.transaction_index_ops
576	}
577
578	/// Drain all changes into a [`StorageChanges`] instance. Leave empty overlay in place.
579	pub fn drain_storage_changes<B: Backend<H>>(
580		&mut self,
581		backend: &B,
582		state_version: StateVersion,
583	) -> Result<StorageChanges<H>, DefaultError>
584	where
585		H::Out: Ord + Encode + 'static,
586	{
587		let (transaction, transaction_storage_root) = match self.storage_transaction_cache.take() {
588			Some(cache) => cache.into_inner(),
589			// If the transaction does not exist, we generate it.
590			None => {
591				self.storage_root(backend, state_version);
592				self.storage_transaction_cache
593					.take()
594					.expect("`storage_transaction_cache` was just initialized; qed")
595					.into_inner()
596			},
597		};
598
599		use core::mem::take;
600		let main_storage_changes =
601			take(&mut self.top).drain_committed().map(|(k, v)| (k, v.to_option()));
602		let child_storage_changes =
603			take(&mut self.children).into_iter().map(|(key, (val, info))| {
604				(key, (val.drain_committed().map(|(k, v)| (k, v.to_option())), info))
605			});
606		let offchain_storage_changes = self.offchain_drain_committed().collect();
607
608		#[cfg(feature = "std")]
609		let transaction_index_changes = std::mem::take(&mut self.transaction_index_ops);
610
611		Ok(StorageChanges {
612			main_storage_changes: main_storage_changes.collect(),
613			child_storage_changes: child_storage_changes
614				.map(|(sk, it)| (sk, it.0.collect()))
615				.collect(),
616			offchain_storage_changes,
617			transaction,
618			transaction_storage_root,
619			#[cfg(feature = "std")]
620			transaction_index_changes,
621		})
622	}
623
624	/// Inserts storage entry responsible for current extrinsic index.
625	#[cfg(test)]
626	pub(crate) fn set_extrinsic_index(&mut self, extrinsic_index: u32) {
627		self.top.set(EXTRINSIC_INDEX.to_vec(), Some(extrinsic_index.encode()), None);
628	}
629
630	/// Returns current extrinsic index to use in changes trie construction.
631	/// None is returned if it is not set or changes trie config is not set.
632	/// Persistent value (from the backend) can be ignored because runtime must
633	/// set this index before first and unset after last extrinsic is executed.
634	/// Changes that are made outside of extrinsics, are marked with
635	/// `NO_EXTRINSIC_INDEX` index.
636	fn extrinsic_index(&mut self) -> Option<u32> {
637		self.collect_extrinsics.then(|| {
638			self.storage(EXTRINSIC_INDEX)
639				.and_then(|idx| idx.and_then(|idx| Decode::decode(&mut &*idx).ok()))
640				.unwrap_or(NO_EXTRINSIC_INDEX)
641		})
642	}
643
644	/// Generate the storage root using `backend` and all changes
645	/// as seen by the current transaction.
646	///
647	/// Returns the storage root and whether it was already cached.
648	pub fn storage_root<B: Backend<H>>(
649		&mut self,
650		backend: &B,
651		state_version: StateVersion,
652	) -> (H::Out, bool)
653	where
654		H::Out: Ord + Encode,
655	{
656		if let Some(cache) = &self.storage_transaction_cache {
657			if cache.state_version == state_version {
658				return (cache.transaction_storage_root, true);
659			}
660		}
661
662		let delta = self.top.changes_mut().map(|(k, v)| (&k[..], v.value().map(|v| &v[..])));
663
664		let child_delta = self
665			.children
666			.values_mut()
667			.map(|v| (&v.1, v.0.changes_mut().map(|(k, v)| (&k[..], v.value().map(|v| &v[..])))));
668
669		let (root, transaction) = backend.full_storage_root(delta, child_delta, state_version);
670
671		self.storage_transaction_cache = Some(StorageTransactionCache {
672			transaction,
673			transaction_storage_root: root,
674			state_version,
675		});
676
677		(root, false)
678	}
679
680	/// Generate the child storage root using `backend` and all child changes
681	/// as seen by the current transaction.
682	///
683	/// Returns the child storage root and whether it was already cached.
684	pub fn child_storage_root<B: Backend<H>>(
685		&mut self,
686		child_info: &ChildInfo,
687		backend: &B,
688		state_version: StateVersion,
689	) -> Result<(H::Out, bool), B::Error>
690	where
691		H::Out: Ord + Encode + Decode,
692	{
693		let storage_key = child_info.storage_key();
694		let prefixed_storage_key = child_info.prefixed_storage_key();
695
696		if self.storage_transaction_cache.is_some() {
697			let root = self
698				.storage(prefixed_storage_key.as_slice())
699				.map(|v| Ok(v.map(|v| v.to_vec())))
700				.or_else(|| backend.storage(prefixed_storage_key.as_slice()).map(Some).transpose())
701				.transpose()?
702				.flatten()
703				.and_then(|k| Decode::decode(&mut &k[..]).ok())
704				// V1 is equivalent to V0 on empty root.
705				.unwrap_or_else(empty_child_trie_root::<LayoutV1<H>>);
706
707			return Ok((root, true));
708		}
709
710		let root = if let Some((changes, info)) = self.child_changes_mut(storage_key) {
711			let delta = changes.map(|(k, v)| (k.as_ref(), v.value().map(AsRef::as_ref)));
712			Some(backend.child_storage_root(info, delta, state_version))
713		} else {
714			None
715		};
716
717		let root = if let Some((root, is_empty, _)) = root {
718			// We store update in the overlay in order to be able to use
719			// 'self.storage_transaction' cache. This is brittle as it rely on Ext only querying
720			// the trie backend for storage root.
721			// A better design would be to manage 'child_storage_transaction' in a
722			// similar way as 'storage_transaction' but for each child trie.
723			self.set_storage(prefixed_storage_key.into_inner(), (!is_empty).then(|| root.encode()));
724
725			self.mark_dirty();
726
727			root
728		} else {
729			// empty overlay
730			let root = backend
731				.storage(prefixed_storage_key.as_slice())?
732				.and_then(|k| Decode::decode(&mut &k[..]).ok())
733				// V1 is equivalent to V0 on empty root.
734				.unwrap_or_else(empty_child_trie_root::<LayoutV1<H>>);
735
736			root
737		};
738
739		Ok((root, false))
740	}
741
742	/// Returns an iterator over the keys (in lexicographic order) following `key` (excluding `key`)
743	/// alongside its value.
744	pub fn iter_after(&mut self, key: &[u8]) -> impl Iterator<Item = (&[u8], &mut OverlayedValue)> {
745		self.top.changes_after(key)
746	}
747
748	/// Returns an iterator over the keys (in lexicographic order) following `key` (excluding `key`)
749	/// alongside its value for the given `storage_key` child.
750	pub fn child_iter_after(
751		&mut self,
752		storage_key: &[u8],
753		key: &[u8],
754	) -> impl Iterator<Item = (&[u8], &mut OverlayedValue)> {
755		self.children
756			.get_mut(storage_key)
757			.map(|(overlay, _)| overlay.changes_after(key))
758			.into_iter()
759			.flatten()
760	}
761
762	/// Read only access ot offchain overlay.
763	pub fn offchain(&self) -> &OffchainOverlayedChanges {
764		&self.offchain
765	}
766
767	/// Write a key value pair to the offchain storage overlay.
768	pub fn set_offchain_storage(&mut self, key: &[u8], value: Option<&[u8]>) {
769		use sp_core::offchain::STORAGE_PREFIX;
770		match value {
771			Some(value) => self.offchain.set(STORAGE_PREFIX, key, value),
772			None => self.offchain.remove(STORAGE_PREFIX, key),
773		}
774	}
775
776	/// Add transaction index operation.
777	pub fn add_transaction_index(&mut self, op: IndexOperation) {
778		self.transaction_index_ops.push(op)
779	}
780}
781
782#[cfg(not(substrate_runtime))]
783impl<H: Hasher> From<sp_core::storage::Storage> for OverlayedChanges<H> {
784	fn from(storage: sp_core::storage::Storage) -> Self {
785		Self {
786			top: storage.top.into(),
787			children: storage
788				.children_default
789				.into_iter()
790				.map(|(k, v)| (k, (v.data.into(), v.child_info)))
791				.collect(),
792			..Default::default()
793		}
794	}
795}
796
797#[cfg(feature = "std")]
798fn retain_map<K, V, F>(map: &mut Map<K, V>, f: F)
799where
800	K: std::cmp::Eq + std::hash::Hash,
801	F: FnMut(&K, &mut V) -> bool,
802{
803	map.retain(f);
804}
805
806#[cfg(not(feature = "std"))]
807fn retain_map<K, V, F>(map: &mut Map<K, V>, mut f: F)
808where
809	K: Ord,
810	F: FnMut(&K, &mut V) -> bool,
811{
812	let old = core::mem::replace(map, Map::default());
813	for (k, mut v) in old.into_iter() {
814		if f(&k, &mut v) {
815			map.insert(k, v);
816		}
817	}
818}
819
820/// An overlayed extension is either a mutable reference
821/// or an owned extension.
822#[cfg(feature = "std")]
823pub enum OverlayedExtension<'a> {
824	MutRef(&'a mut Box<dyn Extension>),
825	Owned(Box<dyn Extension>),
826}
827
828#[cfg(feature = "std")]
829impl OverlayedExtension<'_> {
830	fn extension(&mut self) -> &mut dyn Extension {
831		match self {
832			Self::MutRef(ext) => *ext,
833			Self::Owned(ext) => &mut *ext,
834		}
835	}
836}
837
838/// Overlayed extensions which are sourced from [`Extensions`].
839///
840/// The sourced extensions will be stored as mutable references,
841/// while extensions that are registered while execution are stored
842/// as owned references. After the execution of a runtime function, we
843/// can safely drop this object while not having modified the original
844/// list.
845#[cfg(feature = "std")]
846pub struct OverlayedExtensions<'a> {
847	extensions: Map<TypeId, OverlayedExtension<'a>>,
848}
849
850#[cfg(feature = "std")]
851impl<'a> OverlayedExtensions<'a> {
852	/// Create a new instance of overlaid extensions from the given extensions.
853	pub fn new(extensions: &'a mut Extensions) -> Self {
854		Self {
855			extensions: extensions
856				.iter_mut()
857				.map(|(k, v)| (*k, OverlayedExtension::MutRef(v)))
858				.collect(),
859		}
860	}
861
862	/// Return a mutable reference to the requested extension.
863	pub fn get_mut(&mut self, ext_type_id: TypeId) -> Option<&mut dyn Any> {
864		self.extensions.get_mut(&ext_type_id).map(|ext| match ext {
865			OverlayedExtension::MutRef(ext) => ext.as_mut_any(),
866			OverlayedExtension::Owned(ext) => ext.as_mut_any(),
867		})
868	}
869
870	/// Register extension `extension` with the given `type_id`.
871	pub fn register(
872		&mut self,
873		type_id: TypeId,
874		extension: Box<dyn Extension>,
875	) -> Result<(), sp_externalities::Error> {
876		match self.extensions.entry(type_id) {
877			MapEntry::Vacant(vacant) => {
878				vacant.insert(OverlayedExtension::Owned(extension));
879				Ok(())
880			},
881			MapEntry::Occupied(_) => Err(sp_externalities::Error::ExtensionAlreadyRegistered),
882		}
883	}
884
885	/// Deregister extension with the given `type_id`.
886	///
887	/// Returns `true` when there was an extension registered for the given `type_id`.
888	pub fn deregister(&mut self, type_id: TypeId) -> bool {
889		self.extensions.remove(&type_id).is_some()
890	}
891
892	/// Start a transaction.
893	///
894	/// The `ty` declares the type of transaction.
895	pub fn start_transaction(&mut self, ty: TransactionType) {
896		self.extensions.values_mut().for_each(|e| e.extension().start_transaction(ty));
897	}
898
899	/// Commit a transaction.
900	///
901	/// The `ty` declares the type of transaction.
902	pub fn commit_transaction(&mut self, ty: TransactionType) {
903		self.extensions.values_mut().for_each(|e| e.extension().commit_transaction(ty));
904	}
905
906	/// Rollback a transaction.
907	///
908	/// The `ty` declares the type of transaction.
909	pub fn rollback_transaction(&mut self, ty: TransactionType) {
910		self.extensions
911			.values_mut()
912			.for_each(|e| e.extension().rollback_transaction(ty));
913	}
914}
915
916#[cfg(test)]
917mod tests {
918	use super::*;
919	use crate::{ext::Ext, new_in_mem, InMemoryBackend};
920	use array_bytes::bytes2hex;
921	use sp_core::{traits::Externalities, Blake2Hasher};
922	use std::collections::BTreeMap;
923
924	fn assert_extrinsics(
925		overlay: &mut OverlayedChangeSet,
926		key: impl AsRef<[u8]>,
927		expected: Vec<u32>,
928	) {
929		assert_eq!(
930			overlay.get(key.as_ref()).unwrap().extrinsics().into_iter().collect::<Vec<_>>(),
931			expected
932		)
933	}
934
935	#[test]
936	fn overlayed_storage_works() {
937		let mut overlayed = OverlayedChanges::<Blake2Hasher>::default();
938
939		let key = vec![42, 69, 169, 142];
940
941		assert!(overlayed.storage(&key).is_none());
942
943		overlayed.start_transaction();
944
945		overlayed.set_storage(key.clone(), Some(vec![1, 2, 3]));
946		assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
947
948		overlayed.commit_transaction().unwrap();
949
950		assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
951
952		overlayed.start_transaction();
953
954		overlayed.set_storage(key.clone(), Some(vec![]));
955		assert_eq!(overlayed.storage(&key).unwrap(), Some(&[][..]));
956
957		overlayed.set_storage(key.clone(), None);
958		assert!(overlayed.storage(&key).unwrap().is_none());
959
960		overlayed.rollback_transaction().unwrap();
961
962		assert_eq!(overlayed.storage(&key).unwrap(), Some(&[1, 2, 3][..]));
963
964		overlayed.set_storage(key.clone(), None);
965		assert!(overlayed.storage(&key).unwrap().is_none());
966	}
967
968	#[test]
969	fn offchain_overlayed_storage_transactions_works() {
970		use sp_core::offchain::STORAGE_PREFIX;
971		fn check_offchain_content(
972			state: &OverlayedChanges<Blake2Hasher>,
973			nb_commit: usize,
974			expected: Vec<(Vec<u8>, Option<Vec<u8>>)>,
975		) {
976			let mut state = state.clone();
977			for _ in 0..nb_commit {
978				state.commit_transaction().unwrap();
979			}
980			let offchain_data: Vec<_> = state.offchain_drain_committed().collect();
981			let expected: Vec<_> = expected
982				.into_iter()
983				.map(|(key, value)| {
984					let change = match value {
985						Some(value) => OffchainOverlayedChange::SetValue(value),
986						None => OffchainOverlayedChange::Remove,
987					};
988					((STORAGE_PREFIX.to_vec(), key), change)
989				})
990				.collect();
991			assert_eq!(offchain_data, expected);
992		}
993
994		let mut overlayed = OverlayedChanges::default();
995
996		let key = vec![42, 69, 169, 142];
997
998		check_offchain_content(&overlayed, 0, vec![]);
999
1000		overlayed.start_transaction();
1001
1002		overlayed.set_offchain_storage(key.as_slice(), Some(&[1, 2, 3][..]));
1003		check_offchain_content(&overlayed, 1, vec![(key.clone(), Some(vec![1, 2, 3]))]);
1004
1005		overlayed.commit_transaction().unwrap();
1006
1007		check_offchain_content(&overlayed, 0, vec![(key.clone(), Some(vec![1, 2, 3]))]);
1008
1009		overlayed.start_transaction();
1010
1011		overlayed.set_offchain_storage(key.as_slice(), Some(&[][..]));
1012		check_offchain_content(&overlayed, 1, vec![(key.clone(), Some(vec![]))]);
1013
1014		overlayed.set_offchain_storage(key.as_slice(), None);
1015		check_offchain_content(&overlayed, 1, vec![(key.clone(), None)]);
1016
1017		overlayed.rollback_transaction().unwrap();
1018
1019		check_offchain_content(&overlayed, 0, vec![(key.clone(), Some(vec![1, 2, 3]))]);
1020
1021		overlayed.set_offchain_storage(key.as_slice(), None);
1022		check_offchain_content(&overlayed, 0, vec![(key.clone(), None)]);
1023	}
1024
1025	#[test]
1026	fn overlayed_storage_root_works() {
1027		let state_version = StateVersion::default();
1028		let initial: BTreeMap<_, _> = vec![
1029			(b"doe".to_vec(), b"reindeer".to_vec()),
1030			(b"dog".to_vec(), b"puppyXXX".to_vec()),
1031			(b"dogglesworth".to_vec(), b"catXXX".to_vec()),
1032			(b"doug".to_vec(), b"notadog".to_vec()),
1033		]
1034		.into_iter()
1035		.collect();
1036		let backend = InMemoryBackend::<Blake2Hasher>::from((initial, state_version));
1037		let mut overlay = OverlayedChanges::default();
1038
1039		overlay.start_transaction();
1040		overlay.set_storage(b"dog".to_vec(), Some(b"puppy".to_vec()));
1041		overlay.set_storage(b"dogglesworth".to_vec(), Some(b"catYYY".to_vec()));
1042		overlay.set_storage(b"doug".to_vec(), Some(vec![]));
1043		overlay.commit_transaction().unwrap();
1044
1045		overlay.start_transaction();
1046		overlay.set_storage(b"dogglesworth".to_vec(), Some(b"cat".to_vec()));
1047		overlay.set_storage(b"doug".to_vec(), None);
1048
1049		{
1050			let mut ext = Ext::new(&mut overlay, &backend, None);
1051			let root = "39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa";
1052
1053			assert_eq!(bytes2hex("", &ext.storage_root(state_version)), root);
1054			// Calling a second time should use it from the cache
1055			assert_eq!(bytes2hex("", &ext.storage_root(state_version)), root);
1056		}
1057
1058		// Check that the storage root is recalculated
1059		overlay.set_storage(b"doug2".to_vec(), Some(b"yes".to_vec()));
1060
1061		let mut ext = Ext::new(&mut overlay, &backend, None);
1062		let root = "5c0a4e35cb967de785e1cb8743e6f24b6ff6d45155317f2078f6eb3fc4ff3e3d";
1063		assert_eq!(bytes2hex("", &ext.storage_root(state_version)), root);
1064	}
1065
1066	#[test]
1067	fn storage_root_cache_invalidates_on_state_version_change() {
1068		// `TRIE_VALUE_NODE_THRESHOLD` is 33, so a value of 64 bytes is inlined under V0
1069		// but stored as a separate hashed node under V1, producing distinct roots.
1070		let backend = InMemoryBackend::<Blake2Hasher>::default();
1071		let mut overlay = OverlayedChanges::<Blake2Hasher>::default();
1072		overlay.start_transaction();
1073		overlay.set_storage(b"key".to_vec(), Some(vec![0x42; 64]));
1074		overlay.commit_transaction().unwrap();
1075
1076		let (root_v0_first, cached) = overlay.storage_root(&backend, StateVersion::V0);
1077		assert!(!cached);
1078		let (root_v0_second, cached) = overlay.storage_root(&backend, StateVersion::V0);
1079		assert!(cached);
1080		assert_eq!(root_v0_first, root_v0_second);
1081
1082		// A request for a different state version must NOT return the cached V0 root.
1083		let (root_v1, cached) = overlay.storage_root(&backend, StateVersion::V1);
1084		assert!(!cached, "cache must be invalidated when state version changes");
1085		assert_ne!(
1086			root_v0_first, root_v1,
1087			"V0 and V1 roots must differ for values exceeding the inline threshold",
1088		);
1089
1090		// And switching back to V0 must again recompute, not reuse the V1 cache.
1091		let (root_v0_third, cached) = overlay.storage_root(&backend, StateVersion::V0);
1092		assert!(!cached);
1093		assert_eq!(root_v0_first, root_v0_third);
1094	}
1095
1096	#[test]
1097	fn overlayed_child_storage_root_works() {
1098		let state_version = StateVersion::default();
1099		let child_info = ChildInfo::new_default(b"Child1");
1100		let child_info = &child_info;
1101		let backend = new_in_mem::<Blake2Hasher>();
1102		let mut overlay = OverlayedChanges::<Blake2Hasher>::default();
1103		overlay.start_transaction();
1104		overlay.set_child_storage(child_info, vec![20], Some(vec![20]));
1105		overlay.set_child_storage(child_info, vec![30], Some(vec![30]));
1106		overlay.set_child_storage(child_info, vec![40], Some(vec![40]));
1107		overlay.commit_transaction().unwrap();
1108		overlay.set_child_storage(child_info, vec![10], Some(vec![10]));
1109		overlay.set_child_storage(child_info, vec![30], None);
1110
1111		{
1112			let mut ext = Ext::new(&mut overlay, &backend, None);
1113			let child_root = "c02965e1df4dc5baf6977390ce67dab1d7a9b27a87c1afe27b50d29cc990e0f5";
1114			let root = "eafb765909c3ed5afd92a0c564acf4620d0234b31702e8e8e9b48da72a748838";
1115
1116			assert_eq!(
1117				bytes2hex("", &ext.child_storage_root(child_info, state_version)),
1118				child_root,
1119			);
1120
1121			assert_eq!(bytes2hex("", &ext.storage_root(state_version)), root);
1122
1123			// Calling a second time should use it from the cache
1124			assert_eq!(
1125				bytes2hex("", &ext.child_storage_root(child_info, state_version)),
1126				child_root,
1127			);
1128		}
1129	}
1130
1131	#[test]
1132	fn extrinsic_changes_are_collected() {
1133		let mut overlay = OverlayedChanges::<Blake2Hasher>::default();
1134		overlay.set_collect_extrinsics(true);
1135
1136		overlay.start_transaction();
1137
1138		overlay.set_storage(vec![100], Some(vec![101]));
1139
1140		overlay.set_extrinsic_index(0);
1141		overlay.set_storage(vec![1], Some(vec![2]));
1142
1143		overlay.set_extrinsic_index(1);
1144		overlay.set_storage(vec![3], Some(vec![4]));
1145
1146		overlay.set_extrinsic_index(2);
1147		overlay.set_storage(vec![1], Some(vec![6]));
1148
1149		assert_extrinsics(&mut overlay.top, vec![1], vec![0, 2]);
1150		assert_extrinsics(&mut overlay.top, vec![3], vec![1]);
1151		assert_extrinsics(&mut overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
1152
1153		overlay.start_transaction();
1154
1155		overlay.set_extrinsic_index(3);
1156		overlay.set_storage(vec![3], Some(vec![7]));
1157
1158		overlay.set_extrinsic_index(4);
1159		overlay.set_storage(vec![1], Some(vec![8]));
1160
1161		assert_extrinsics(&mut overlay.top, vec![1], vec![0, 2, 4]);
1162		assert_extrinsics(&mut overlay.top, vec![3], vec![1, 3]);
1163		assert_extrinsics(&mut overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
1164
1165		overlay.rollback_transaction().unwrap();
1166
1167		assert_extrinsics(&mut overlay.top, vec![1], vec![0, 2]);
1168		assert_extrinsics(&mut overlay.top, vec![3], vec![1]);
1169		assert_extrinsics(&mut overlay.top, vec![100], vec![NO_EXTRINSIC_INDEX]);
1170	}
1171
1172	#[test]
1173	fn next_storage_key_change_works() {
1174		let mut overlay = OverlayedChanges::<Blake2Hasher>::default();
1175		overlay.start_transaction();
1176		overlay.set_storage(vec![20], Some(vec![20]));
1177		overlay.set_storage(vec![30], Some(vec![30]));
1178		overlay.set_storage(vec![40], Some(vec![40]));
1179		overlay.commit_transaction().unwrap();
1180		overlay.set_storage(vec![10], Some(vec![10]));
1181		overlay.set_storage(vec![30], None);
1182
1183		// next_prospective < next_committed
1184		let next_to_5 = overlay.iter_after(&[5]).next().unwrap();
1185		assert_eq!(next_to_5.0.to_vec(), vec![10]);
1186		assert_eq!(next_to_5.1.value(), Some(&vec![10]));
1187
1188		// next_committed < next_prospective
1189		let next_to_10 = overlay.iter_after(&[10]).next().unwrap();
1190		assert_eq!(next_to_10.0.to_vec(), vec![20]);
1191		assert_eq!(next_to_10.1.value(), Some(&vec![20]));
1192
1193		// next_committed == next_prospective
1194		let next_to_20 = overlay.iter_after(&[20]).next().unwrap();
1195		assert_eq!(next_to_20.0.to_vec(), vec![30]);
1196		assert_eq!(next_to_20.1.value(), None);
1197
1198		// next_committed, no next_prospective
1199		let next_to_30 = overlay.iter_after(&[30]).next().unwrap();
1200		assert_eq!(next_to_30.0.to_vec(), vec![40]);
1201		assert_eq!(next_to_30.1.value(), Some(&vec![40]));
1202
1203		overlay.set_storage(vec![50], Some(vec![50]));
1204		// next_prospective, no next_committed
1205		let next_to_40 = overlay.iter_after(&[40]).next().unwrap();
1206		assert_eq!(next_to_40.0.to_vec(), vec![50]);
1207		assert_eq!(next_to_40.1.value(), Some(&vec![50]));
1208	}
1209
1210	#[test]
1211	fn next_child_storage_key_change_works() {
1212		let child_info = ChildInfo::new_default(b"Child1");
1213		let child_info = &child_info;
1214		let child = child_info.storage_key();
1215		let mut overlay = OverlayedChanges::<Blake2Hasher>::default();
1216		overlay.start_transaction();
1217		overlay.set_child_storage(child_info, vec![20], Some(vec![20]));
1218		overlay.set_child_storage(child_info, vec![30], Some(vec![30]));
1219		overlay.set_child_storage(child_info, vec![40], Some(vec![40]));
1220		overlay.commit_transaction().unwrap();
1221		overlay.set_child_storage(child_info, vec![10], Some(vec![10]));
1222		overlay.set_child_storage(child_info, vec![30], None);
1223
1224		// next_prospective < next_committed
1225		let next_to_5 = overlay.child_iter_after(child, &[5]).next().unwrap();
1226		assert_eq!(next_to_5.0.to_vec(), vec![10]);
1227		assert_eq!(next_to_5.1.value(), Some(&vec![10]));
1228
1229		// next_committed < next_prospective
1230		let next_to_10 = overlay.child_iter_after(child, &[10]).next().unwrap();
1231		assert_eq!(next_to_10.0.to_vec(), vec![20]);
1232		assert_eq!(next_to_10.1.value(), Some(&vec![20]));
1233
1234		// next_committed == next_prospective
1235		let next_to_20 = overlay.child_iter_after(child, &[20]).next().unwrap();
1236		assert_eq!(next_to_20.0.to_vec(), vec![30]);
1237		assert_eq!(next_to_20.1.value(), None);
1238
1239		// next_committed, no next_prospective
1240		let next_to_30 = overlay.child_iter_after(child, &[30]).next().unwrap();
1241		assert_eq!(next_to_30.0.to_vec(), vec![40]);
1242		assert_eq!(next_to_30.1.value(), Some(&vec![40]));
1243
1244		overlay.set_child_storage(child_info, vec![50], Some(vec![50]));
1245		// next_prospective, no next_committed
1246		let next_to_40 = overlay.child_iter_after(child, &[40]).next().unwrap();
1247		assert_eq!(next_to_40.0.to_vec(), vec![50]);
1248		assert_eq!(next_to_40.1.value(), Some(&vec![50]));
1249	}
1250}