-
Notifications
You must be signed in to change notification settings - Fork 2.6k
state_machine no_std witness externalities #6934
Changes from 6 commits
ea03567
c0e25ae
2cb6378
b0e04a4
a9aa27c
2747339
cac2280
11305d1
4f05206
d4ce6dd
147ef68
d067b0c
0e6b642
4c454cc
d32e3fd
753a8d7
2d63cf7
1fadc14
9b3146d
bdbaefc
d1b10c8
14e40b6
e459698
bef5997
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,11 @@ | |
//! | ||
//! It is required that each extension implements the [`Extension`] trait. | ||
|
||
use std::{collections::HashMap, collections::hash_map::Entry, any::{Any, TypeId}, ops::DerefMut}; | ||
#[cfg(feature = "std")] | ||
use std::{collections::HashMap as Map, collections::hash_map::Entry}; | ||
#[cfg(not(feature = "std"))] | ||
use sp_std::collections::btree_map::{BTreeMap as Map, Entry}; | ||
use sp_std::{any::{Any, TypeId}, ops::DerefMut, boxed::Box}; | ||
use crate::Error; | ||
|
||
/// Marker trait for types that should be registered as [`Externalities`](crate::Externalities) extension. | ||
|
@@ -104,9 +108,10 @@ pub trait ExtensionStore { | |
/// Stores extensions that should be made available through the externalities. | ||
#[derive(Default)] | ||
pub struct Extensions { | ||
extensions: HashMap<TypeId, Box<dyn Extension>>, | ||
extensions: Map<TypeId, Box<dyn Extension>>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just use |
||
} | ||
|
||
#[cfg(feature = "std")] | ||
impl std::fmt::Debug for Extensions { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "Extensions: ({})", self.extensions.len()) | ||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -15,6 +15,8 @@ | |||||||||
// See the License for the specific language governing permissions and | ||||||||||
// limitations under the License. | ||||||||||
|
||||||||||
#![cfg_attr(not(feature = "std"), no_std)] | ||||||||||
|
||||||||||
//! Substrate externalities abstraction | ||||||||||
//! | ||||||||||
//! The externalities mainly provide access to storage and to registered extensions. Extensions | ||||||||||
|
@@ -23,14 +25,18 @@ | |||||||||
//! | ||||||||||
//! This crate exposes the main [`Externalities`] trait. | ||||||||||
|
||||||||||
use std::any::{Any, TypeId}; | ||||||||||
use sp_std::any::{Any, TypeId}; | ||||||||||
use sp_std::vec::Vec; | ||||||||||
use sp_std::boxed::Box; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
||||||||||
use sp_storage::{ChildInfo, TrackedStorageKey}; | ||||||||||
|
||||||||||
#[cfg(feature = "std")] | ||||||||||
pub use scope_limited::{set_and_run_with_externalities, with_externalities}; | ||||||||||
pub use extensions::{Extension, Extensions, ExtensionStore}; | ||||||||||
|
||||||||||
mod extensions; | ||||||||||
#[cfg(feature = "std")] | ||||||||||
mod scope_limited; | ||||||||||
|
||||||||||
/// Externalities error. | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ use num_traits::One; | |
use crate::{ | ||
StorageKey, | ||
backend::Backend, | ||
overlayed_changes::{OverlayedChanges, OverlayedValue}, | ||
overlayed_changes::{OverlayedChanges, OverlayedValue, ChangeTrieOverlay}, | ||
trie_backend_essence::TrieBackendEssence, | ||
changes_trie::{ | ||
AnchorBlockId, ConfigurationRange, Storage, BlockNumber, | ||
|
@@ -39,11 +39,11 @@ use sp_core::storage::{ChildInfo, PrefixedStorageKey}; | |
/// | ||
/// Returns Err if storage error has occurred OR if storage haven't returned | ||
/// required data. | ||
pub(crate) fn prepare_input<'a, B, H, Number>( | ||
pub(crate) fn prepare_input<'a, B, H, Number, CT>( | ||
backend: &'a B, | ||
storage: &'a dyn Storage<H, Number>, | ||
config: ConfigurationRange<'a, Number>, | ||
overlay: &'a OverlayedChanges, | ||
overlay: &'a OverlayedChanges<CT>, | ||
parent: &'a AnchorBlockId<H::Out, Number>, | ||
) -> Result<( | ||
impl Iterator<Item=InputPair<Number>> + 'a, | ||
|
@@ -55,6 +55,7 @@ pub(crate) fn prepare_input<'a, B, H, Number>( | |
H: Hasher + 'a, | ||
H::Out: Encode, | ||
Number: BlockNumber, | ||
CT: ChangeTrieOverlay, | ||
{ | ||
let number = parent.number.clone() + One::one(); | ||
let (extrinsics_input, children_extrinsics_input) = prepare_extrinsics_input( | ||
|
@@ -93,10 +94,10 @@ pub(crate) fn prepare_input<'a, B, H, Number>( | |
)) | ||
} | ||
/// Prepare ExtrinsicIndex input pairs. | ||
fn prepare_extrinsics_input<'a, B, H, Number>( | ||
fn prepare_extrinsics_input<'a, B, H, Number, CT>( | ||
backend: &'a B, | ||
block: &Number, | ||
overlay: &'a OverlayedChanges, | ||
overlay: &'a OverlayedChanges<CT>, | ||
) -> Result<( | ||
impl Iterator<Item=InputPair<Number>> + 'a, | ||
BTreeMap<ChildIndex<Number>, impl Iterator<Item=InputPair<Number>> + 'a>, | ||
|
@@ -105,6 +106,7 @@ fn prepare_extrinsics_input<'a, B, H, Number>( | |
B: Backend<H>, | ||
H: Hasher + 'a, | ||
Number: BlockNumber, | ||
CT: ChangeTrieOverlay, | ||
{ | ||
let mut children_result = BTreeMap::new(); | ||
|
||
|
@@ -127,55 +129,58 @@ fn prepare_extrinsics_input<'a, B, H, Number>( | |
Ok((top, children_result)) | ||
} | ||
|
||
fn prepare_extrinsics_input_inner<'a, B, H, Number>( | ||
fn prepare_extrinsics_input_inner<'a, B, H, Number, CT>( | ||
backend: &'a B, | ||
block: &Number, | ||
overlay: &'a OverlayedChanges, | ||
overlay: &'a OverlayedChanges<CT>, | ||
child_info: Option<ChildInfo>, | ||
changes: impl Iterator<Item=(&'a StorageKey, &'a OverlayedValue)> | ||
mut changes: impl Iterator<Item=(&'a StorageKey, &'a OverlayedValue<CT>)> | ||
) -> Result<impl Iterator<Item=InputPair<Number>> + 'a, String> | ||
where | ||
B: Backend<H>, | ||
H: Hasher, | ||
Number: BlockNumber, | ||
CT: ChangeTrieOverlay, | ||
{ | ||
changes | ||
.filter(|( _, v)| v.extrinsics().next().is_some()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change this code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did modify the 'extrinsics' prototype to stop returning an iterator (before it was fusing iterator with itertools unique but I am do not like the implementation a lot (internal hashmap), so I simply return a btreeset instead, changing the code here calling 'extrinsics' multiple times, so avoid fusing the iterator multiple time). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you change this to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well it avoid a tab, will change (easier to review, even if I like it better without the filter map, I am really waiting for rustc "Tracking issue for methods converting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I remember, 'extrinsics' function is not a getter, it have an associated cost, that is the main reason (even if optimized by the compilator, this way of putting it makes it clear that we don't want to call the function multiple times, but I can write it with combinator too). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see the problem. However the old implementation was also an |
||
.try_fold(BTreeMap::new(), |mut map: BTreeMap<&[u8], (ExtrinsicIndex<Number>, Vec<u32>)>, (k, v)| { | ||
match map.entry(k) { | ||
Entry::Vacant(entry) => { | ||
// ignore temporary values (values that have null value at the end of operation | ||
// AND are not in storage at the beginning of operation | ||
if let Some(child_info) = child_info.as_ref() { | ||
if !overlay.child_storage(child_info, k).map(|v| v.is_some()).unwrap_or_default() { | ||
if !backend.exists_child_storage(&child_info, k) | ||
.map_err(|e| format!("{}", e))? { | ||
return Ok(map); | ||
let extrinsics = v.extrinsics(); | ||
if !extrinsics.is_empty() { | ||
match map.entry(k) { | ||
Entry::Vacant(entry) => { | ||
// ignore temporary values (values that have null value at the end of operation | ||
// AND are not in storage at the beginning of operation | ||
if let Some(child_info) = child_info.as_ref() { | ||
if !overlay.child_storage(child_info, k).map(|v| v.is_some()).unwrap_or_default() { | ||
if !backend.exists_child_storage(&child_info, k) | ||
.map_err(|e| format!("{}", e))? { | ||
return Ok(map); | ||
} | ||
} | ||
} | ||
} else { | ||
if !overlay.storage(k).map(|v| v.is_some()).unwrap_or_default() { | ||
if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { | ||
return Ok(map); | ||
} else { | ||
if !overlay.storage(k).map(|v| v.is_some()).unwrap_or_default() { | ||
if !backend.exists_storage(k).map_err(|e| format!("{}", e))? { | ||
return Ok(map); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
let extrinsics = v.extrinsics().cloned().collect(); | ||
entry.insert((ExtrinsicIndex { | ||
block: block.clone(), | ||
key: k.to_vec(), | ||
}, extrinsics)); | ||
}, | ||
Entry::Occupied(mut entry) => { | ||
// we do not need to check for temporary values here, because entry is Occupied | ||
// AND we are checking it before insertion | ||
let extrinsics = &mut entry.get_mut().1; | ||
extrinsics.extend( | ||
v.extrinsics().cloned() | ||
); | ||
extrinsics.sort(); | ||
}, | ||
}; | ||
|
||
let extrinsics = extrinsics.into_iter().collect(); | ||
entry.insert((ExtrinsicIndex { | ||
block: block.clone(), | ||
key: k.to_vec(), | ||
}, extrinsics)); | ||
}, | ||
Entry::Occupied(mut entry) => { | ||
// we do not need to check for temporary values here, because entry is Occupied | ||
// AND we are checking it before insertion | ||
let entry_extrinsics = &mut entry.get_mut().1; | ||
entry_extrinsics.extend( | ||
extrinsics.into_iter() | ||
); | ||
entry_extrinsics.sort(); | ||
}, | ||
} | ||
} | ||
|
||
Ok(map) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vec
comes fromprelude