Struct sp_state_machine::TrieBackend
source · pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher, C = LocalTrieCache<H>> { /* private fields */ }
Expand description
Patricia trie-based backend. Transaction type is an overlay of changes to commit.
Implementations§
source§impl<H: Hasher, KF> TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H: Hasher, KF> TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
sourcepub fn update<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&self,
changes: T,
state_version: StateVersion
) -> Self
pub fn update<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&self,
changes: T,
state_version: StateVersion
) -> Self
Copy the state, with applied updates
Examples found in repository?
src/testing.rs (line 173)
161 162 163 164 165 166 167 168 169 170 171 172 173 174
pub fn as_backend(&self) -> InMemoryBackend<H> {
let top: Vec<_> =
self.overlay.changes().map(|(k, v)| (k.clone(), v.value().cloned())).collect();
let mut transaction = vec![(None, top)];
for (child_changes, child_info) in self.overlay.children() {
transaction.push((
Some(child_info.clone()),
child_changes.map(|(k, v)| (k.clone(), v.value().cloned())).collect(),
))
}
self.backend.update(transaction, self.state_version)
}
sourcepub fn insert<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&mut self,
changes: T,
state_version: StateVersion
)
pub fn insert<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&mut self,
changes: T,
state_version: StateVersion
)
Insert values into backend trie.
Examples found in repository?
More examples
src/in_memory_backend.rs (line 65)
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
pub fn update<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&self,
changes: T,
state_version: StateVersion,
) -> Self {
let mut clone = self.clone();
clone.insert(changes, state_version);
clone
}
/// Insert values into backend trie.
pub fn insert<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&mut self,
changes: T,
state_version: StateVersion,
) {
let (top, child) = changes.into_iter().partition::<Vec<_>, _>(|v| v.0.is_none());
let (root, transaction) = self.full_storage_root(
top.iter().flat_map(|(_, v)| v).map(|(k, v)| (&k[..], v.as_deref())),
child.iter().filter_map(|v| {
v.0.as_ref().map(|c| (c, v.1.iter().map(|(k, v)| (&k[..], v.as_deref()))))
}),
state_version,
);
self.apply_transaction(root, transaction);
}
/// Merge trie nodes into this backend.
pub fn update_backend(&self, root: H::Out, changes: GenericMemoryDB<H, KF>) -> Self {
let mut clone = self.backend_storage().clone();
clone.consolidate(changes);
TrieBackendBuilder::new(clone, root).build()
}
/// Apply the given transaction to this backend and set the root to the given value.
pub fn apply_transaction(&mut self, root: H::Out, transaction: GenericMemoryDB<H, KF>) {
let mut storage = sp_std::mem::take(self).into_storage();
storage.consolidate(transaction);
*self = TrieBackendBuilder::new(storage, root).build();
}
/// Compare with another in-memory backend.
pub fn eq(&self, other: &Self) -> bool {
self.root() == other.root()
}
}
impl<H: Hasher, KF> Clone for TrieBackend<GenericMemoryDB<H, KF>, H>
where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
{
fn clone(&self) -> Self {
TrieBackendBuilder::new(self.backend_storage().clone(), *self.root()).build()
}
}
impl<H, KF> Default for TrieBackend<GenericMemoryDB<H, KF>, H>
where
H: Hasher,
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
{
fn default() -> Self {
new_in_mem()
}
}
impl<H: Hasher, KF>
From<(HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>, StateVersion)>
for TrieBackend<GenericMemoryDB<H, KF>, H>
where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
{
fn from(
(inner, state_version): (
HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>,
StateVersion,
),
) -> Self {
let mut backend = new_in_mem();
backend.insert(
inner
.into_iter()
.map(|(k, m)| (k, m.into_iter().map(|(k, v)| (k, Some(v))).collect())),
state_version,
);
backend
}
sourcepub fn update_backend(
&self,
root: H::Out,
changes: GenericMemoryDB<H, KF>
) -> Self
pub fn update_backend(
&self,
root: H::Out,
changes: GenericMemoryDB<H, KF>
) -> Self
Merge trie nodes into this backend.
sourcepub fn apply_transaction(
&mut self,
root: H::Out,
transaction: GenericMemoryDB<H, KF>
)
pub fn apply_transaction(
&mut self,
root: H::Out,
transaction: GenericMemoryDB<H, KF>
)
Apply the given transaction to this backend and set the root to the given value.
Examples found in repository?
More examples
src/in_memory_backend.rs (line 84)
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
pub fn insert<T: IntoIterator<Item = (Option<ChildInfo>, StorageCollection)>>(
&mut self,
changes: T,
state_version: StateVersion,
) {
let (top, child) = changes.into_iter().partition::<Vec<_>, _>(|v| v.0.is_none());
let (root, transaction) = self.full_storage_root(
top.iter().flat_map(|(_, v)| v).map(|(k, v)| (&k[..], v.as_deref())),
child.iter().filter_map(|v| {
v.0.as_ref().map(|c| (c, v.1.iter().map(|(k, v)| (&k[..], v.as_deref()))))
}),
state_version,
);
self.apply_transaction(root, transaction);
}
source§impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> TrieBackend<S, H, C>where
H::Out: Codec,
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> TrieBackend<S, H, C>where
H::Out: Codec,
sourcepub fn backend_storage(&self) -> &S
pub fn backend_storage(&self) -> &S
Get backend storage reference.
Examples found in repository?
src/in_memory_backend.rs (line 89)
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
pub fn update_backend(&self, root: H::Out, changes: GenericMemoryDB<H, KF>) -> Self {
let mut clone = self.backend_storage().clone();
clone.consolidate(changes);
TrieBackendBuilder::new(clone, root).build()
}
/// Apply the given transaction to this backend and set the root to the given value.
pub fn apply_transaction(&mut self, root: H::Out, transaction: GenericMemoryDB<H, KF>) {
let mut storage = sp_std::mem::take(self).into_storage();
storage.consolidate(transaction);
*self = TrieBackendBuilder::new(storage, root).build();
}
/// Compare with another in-memory backend.
pub fn eq(&self, other: &Self) -> bool {
self.root() == other.root()
}
}
impl<H: Hasher, KF> Clone for TrieBackend<GenericMemoryDB<H, KF>, H>
where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
{
fn clone(&self) -> Self {
TrieBackendBuilder::new(self.backend_storage().clone(), *self.root()).build()
}
sourcepub fn root(&self) -> &H::Out
pub fn root(&self) -> &H::Out
Get trie root.
Examples found in repository?
src/in_memory_backend.rs (line 103)
102 103 104 105 106 107 108 109 110 111 112 113 114
pub fn eq(&self, other: &Self) -> bool {
self.root() == other.root()
}
}
impl<H: Hasher, KF> Clone for TrieBackend<GenericMemoryDB<H, KF>, H>
where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
{
fn clone(&self) -> Self {
TrieBackendBuilder::new(self.backend_storage().clone(), *self.root()).build()
}
sourcepub fn into_storage(self) -> S
pub fn into_storage(self) -> S
Consumes self and returns underlying storage.
sourcepub fn extract_proof(self) -> Option<StorageProof>
pub fn extract_proof(self) -> Option<StorageProof>
Extract the StorageProof
.
This only returns Some
when there was a recorder set.
Examples found in repository?
src/testing.rs (line 218)
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
pub fn execute_and_prove<R>(&mut self, execute: impl FnOnce() -> R) -> (R, StorageProof) {
let proving_backend = TrieBackendBuilder::wrap(&self.backend)
.with_recorder(Default::default())
.build();
let mut proving_ext = Ext::new(
&mut self.overlay,
&mut self.storage_transaction_cache,
&proving_backend,
Some(&mut self.extensions),
);
let outcome = sp_externalities::set_and_run_with_externalities(&mut proving_ext, execute);
let proof = proving_backend.extract_proof().expect("Failed to extract storage proof");
(outcome, proof)
}
More examples
src/lib.rs (line 581)
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
pub fn prove_execution_on_trie_backend<S, H, Exec, Spawn>(
trie_backend: &TrieBackend<S, H>,
overlay: &mut OverlayedChanges,
exec: &Exec,
spawn_handle: Spawn,
method: &str,
call_data: &[u8],
runtime_code: &RuntimeCode,
extensions: Extensions,
) -> Result<(Vec<u8>, StorageProof), Box<dyn Error>>
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord + 'static + codec::Codec,
Exec: CodeExecutor + 'static + Clone,
Spawn: SpawnNamed + Send + 'static,
{
let proving_backend =
TrieBackendBuilder::wrap(trie_backend).with_recorder(Default::default()).build();
let result = StateMachine::<_, H, Exec>::new(
&proving_backend,
overlay,
exec,
method,
call_data,
extensions,
runtime_code,
spawn_handle,
)
.execute_using_consensus_failure_handler::<_>(always_wasm())?;
let proof = proving_backend
.extract_proof()
.expect("A recorder was set and thus, a storage proof can be extracted; qed");
Ok((result, proof))
}
/// Check execution proof, generated by `prove_execution` call.
pub fn execution_proof_check<H, Exec, Spawn>(
root: H::Out,
proof: StorageProof,
overlay: &mut OverlayedChanges,
exec: &Exec,
spawn_handle: Spawn,
method: &str,
call_data: &[u8],
runtime_code: &RuntimeCode,
) -> Result<Vec<u8>, Box<dyn Error>>
where
H: Hasher + 'static,
Exec: CodeExecutor + Clone + 'static,
H::Out: Ord + 'static + codec::Codec,
Spawn: SpawnNamed + Send + 'static,
{
let trie_backend = create_proof_check_backend::<H>(root, proof)?;
execution_proof_check_on_trie_backend::<_, _, _>(
&trie_backend,
overlay,
exec,
spawn_handle,
method,
call_data,
runtime_code,
)
}
/// Check execution proof on proving backend, generated by `prove_execution` call.
pub fn execution_proof_check_on_trie_backend<H, Exec, Spawn>(
trie_backend: &TrieBackend<MemoryDB<H>, H>,
overlay: &mut OverlayedChanges,
exec: &Exec,
spawn_handle: Spawn,
method: &str,
call_data: &[u8],
runtime_code: &RuntimeCode,
) -> Result<Vec<u8>, Box<dyn Error>>
where
H: Hasher,
H::Out: Ord + 'static + codec::Codec,
Exec: CodeExecutor + Clone + 'static,
Spawn: SpawnNamed + Send + 'static,
{
StateMachine::<_, H, Exec>::new(
trie_backend,
overlay,
exec,
method,
call_data,
Extensions::default(),
runtime_code,
spawn_handle,
)
.execute_using_consensus_failure_handler(always_untrusted_wasm())
}
/// Generate storage read proof.
pub fn prove_read<B, H, I>(backend: B, keys: I) -> Result<StorageProof, Box<dyn Error>>
where
B: AsTrieBackend<H>,
H: Hasher,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let trie_backend = backend.as_trie_backend();
prove_read_on_trie_backend(trie_backend, keys)
}
/// State machine only allows a single level
/// of child trie.
pub const MAX_NESTED_TRIE_DEPTH: usize = 2;
/// Multiple key value state.
/// States are ordered by root storage key.
#[derive(PartialEq, Eq, Clone)]
pub struct KeyValueStates(pub Vec<KeyValueStorageLevel>);
/// A key value state at any storage level.
#[derive(PartialEq, Eq, Clone)]
pub struct KeyValueStorageLevel {
/// State root of the level, for
/// top trie it is as an empty byte array.
pub state_root: Vec<u8>,
/// Storage of parents, empty for top root or
/// when exporting (building proof).
pub parent_storage_keys: Vec<Vec<u8>>,
/// Pair of key and values from this state.
pub key_values: Vec<(Vec<u8>, Vec<u8>)>,
}
impl<I> From<I> for KeyValueStates
where
I: IntoIterator<Item = (Vec<u8>, (Vec<(Vec<u8>, Vec<u8>)>, Vec<Vec<u8>>))>,
{
fn from(b: I) -> Self {
let mut result = Vec::new();
for (state_root, (key_values, storage_paths)) in b.into_iter() {
result.push(KeyValueStorageLevel {
state_root,
key_values,
parent_storage_keys: storage_paths,
})
}
KeyValueStates(result)
}
}
impl KeyValueStates {
/// Return total number of key values in states.
pub fn len(&self) -> usize {
self.0.iter().fold(0, |nb, state| nb + state.key_values.len())
}
/// Update last keys accessed from this state.
pub fn update_last_key(
&self,
stopped_at: usize,
last: &mut SmallVec<[Vec<u8>; 2]>,
) -> bool {
if stopped_at == 0 || stopped_at > MAX_NESTED_TRIE_DEPTH {
return false
}
match stopped_at {
1 => {
let top_last =
self.0.get(0).and_then(|s| s.key_values.last().map(|kv| kv.0.clone()));
if let Some(top_last) = top_last {
match last.len() {
0 => {
last.push(top_last);
return true
},
2 => {
last.pop();
},
_ => (),
}
// update top trie access.
last[0] = top_last;
return true
} else {
// No change in top trie accesses.
// Indicates end of reading of a child trie.
last.truncate(1);
return true
}
},
2 => {
let top_last =
self.0.get(0).and_then(|s| s.key_values.last().map(|kv| kv.0.clone()));
let child_last =
self.0.last().and_then(|s| s.key_values.last().map(|kv| kv.0.clone()));
if let Some(child_last) = child_last {
if last.is_empty() {
if let Some(top_last) = top_last {
last.push(top_last)
} else {
return false
}
} else if let Some(top_last) = top_last {
last[0] = top_last;
}
if last.len() == 2 {
last.pop();
}
last.push(child_last);
return true
} else {
// stopped at level 2 so child last is define.
return false
}
},
_ => (),
}
false
}
}
/// Generate range storage read proof, with child tries
/// content.
/// A size limit is applied to the proof with the
/// exception that `start_at` and its following element
/// are always part of the proof.
/// If a key different than `start_at` is a child trie root,
/// the child trie content will be included in the proof.
pub fn prove_range_read_with_child_with_size<B, H>(
backend: B,
size_limit: usize,
start_at: &[Vec<u8>],
) -> Result<(StorageProof, u32), Box<dyn Error>>
where
B: AsTrieBackend<H>,
H: Hasher,
H::Out: Ord + Codec,
{
let trie_backend = backend.as_trie_backend();
prove_range_read_with_child_with_size_on_trie_backend(trie_backend, size_limit, start_at)
}
/// Generate range storage read proof, with child tries
/// content.
/// See `prove_range_read_with_child_with_size`.
pub fn prove_range_read_with_child_with_size_on_trie_backend<S, H>(
trie_backend: &TrieBackend<S, H>,
size_limit: usize,
start_at: &[Vec<u8>],
) -> Result<(StorageProof, u32), Box<dyn Error>>
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord + Codec,
{
if start_at.len() > MAX_NESTED_TRIE_DEPTH {
return Err(Box::new("Invalid start of range."))
}
let recorder = sp_trie::recorder::Recorder::default();
let proving_backend =
TrieBackendBuilder::wrap(trie_backend).with_recorder(recorder.clone()).build();
let mut count = 0;
let mut child_roots = HashSet::new();
let (mut child_key, mut start_at) = if start_at.len() == 2 {
let storage_key = start_at.get(0).expect("Checked length.").clone();
if let Some(state_root) = proving_backend
.storage(&storage_key)
.map_err(|e| Box::new(e) as Box<dyn Error>)?
{
child_roots.insert(state_root);
} else {
return Err(Box::new("Invalid range start child trie key."))
}
(Some(storage_key), start_at.get(1).cloned())
} else {
(None, start_at.get(0).cloned())
};
loop {
let (child_info, depth) = if let Some(storage_key) = child_key.as_ref() {
let storage_key = PrefixedStorageKey::new_ref(storage_key);
(
Some(match ChildType::from_prefixed_key(storage_key) {
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(Box::new("Invalid range start child trie key.")),
}),
2,
)
} else {
(None, 1)
};
let start_at_ref = start_at.as_ref().map(AsRef::as_ref);
let mut switch_child_key = None;
let mut first = start_at.is_some();
let completed = proving_backend
.apply_to_key_values_while(
child_info.as_ref(),
None,
start_at_ref,
|key, value| {
if first &&
start_at_ref
.as_ref()
.map(|start| &key.as_slice() > start)
.unwrap_or(true)
{
first = false;
}
if first {
true
} else if depth < MAX_NESTED_TRIE_DEPTH &&
sp_core::storage::well_known_keys::is_child_storage_key(
key.as_slice(),
) {
count += 1;
if !child_roots.contains(value.as_slice()) {
child_roots.insert(value);
switch_child_key = Some(key);
false
} else {
// do not add two child trie with same root
true
}
} else if recorder.estimate_encoded_size() <= size_limit {
count += 1;
true
} else {
false
}
},
false,
)
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
if switch_child_key.is_none() {
if depth == 1 {
break
} else if completed {
start_at = child_key.take();
} else {
break
}
} else {
child_key = switch_child_key;
start_at = None;
}
}
let proof = proving_backend
.extract_proof()
.expect("A recorder was set and thus, a storage proof can be extracted; qed");
Ok((proof, count))
}
/// Generate range storage read proof.
pub fn prove_range_read_with_size<B, H>(
backend: B,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
size_limit: usize,
start_at: Option<&[u8]>,
) -> Result<(StorageProof, u32), Box<dyn Error>>
where
B: AsTrieBackend<H>,
H: Hasher,
H::Out: Ord + Codec,
{
let trie_backend = backend.as_trie_backend();
prove_range_read_with_size_on_trie_backend(
trie_backend,
child_info,
prefix,
size_limit,
start_at,
)
}
/// Generate range storage read proof on an existing trie backend.
pub fn prove_range_read_with_size_on_trie_backend<S, H>(
trie_backend: &TrieBackend<S, H>,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
size_limit: usize,
start_at: Option<&[u8]>,
) -> Result<(StorageProof, u32), Box<dyn Error>>
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord + Codec,
{
let recorder = sp_trie::recorder::Recorder::default();
let proving_backend =
TrieBackendBuilder::wrap(trie_backend).with_recorder(recorder.clone()).build();
let mut count = 0;
proving_backend
.apply_to_key_values_while(
child_info,
prefix,
start_at,
|_key, _value| {
if count == 0 || recorder.estimate_encoded_size() <= size_limit {
count += 1;
true
} else {
false
}
},
false,
)
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
let proof = proving_backend
.extract_proof()
.expect("A recorder was set and thus, a storage proof can be extracted; qed");
Ok((proof, count))
}
/// Generate child storage read proof.
pub fn prove_child_read<B, H, I>(
backend: B,
child_info: &ChildInfo,
keys: I,
) -> Result<StorageProof, Box<dyn Error>>
where
B: AsTrieBackend<H>,
H: Hasher,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let trie_backend = backend.as_trie_backend();
prove_child_read_on_trie_backend(trie_backend, child_info, keys)
}
/// Generate storage read proof on pre-created trie backend.
pub fn prove_read_on_trie_backend<S, H, I>(
trie_backend: &TrieBackend<S, H>,
keys: I,
) -> Result<StorageProof, Box<dyn Error>>
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let proving_backend =
TrieBackendBuilder::wrap(trie_backend).with_recorder(Default::default()).build();
for key in keys.into_iter() {
proving_backend
.storage(key.as_ref())
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
}
Ok(proving_backend
.extract_proof()
.expect("A recorder was set and thus, a storage proof can be extracted; qed"))
}
/// Generate storage read proof on pre-created trie backend.
pub fn prove_child_read_on_trie_backend<S, H, I>(
trie_backend: &TrieBackend<S, H>,
child_info: &ChildInfo,
keys: I,
) -> Result<StorageProof, Box<dyn Error>>
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
let proving_backend =
TrieBackendBuilder::wrap(trie_backend).with_recorder(Default::default()).build();
for key in keys.into_iter() {
proving_backend
.child_storage(child_info, key.as_ref())
.map_err(|e| Box::new(e) as Box<dyn Error>)?;
}
Ok(proving_backend
.extract_proof()
.expect("A recorder was set and thus, a storage proof can be extracted; qed"))
}
Trait Implementations§
source§impl<S: TrieBackendStorage<H>, H: Hasher, C> AsTrieBackend<H, C> for TrieBackend<S, H, C>
impl<S: TrieBackendStorage<H>, H: Hasher, C> AsTrieBackend<H, C> for TrieBackend<S, H, C>
§type TrieBackendStorage = S
type TrieBackendStorage = S
Type of trie backend storage.
source§fn as_trie_backend(&self) -> &TrieBackend<S, H, C>
fn as_trie_backend(&self) -> &TrieBackend<S, H, C>
Return the type as
TrieBackend
.source§impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> Backend<H> for TrieBackend<S, H, C>where
H::Out: Ord + Codec,
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H> + Send + Sync> Backend<H> for TrieBackend<S, H, C>where
H::Out: Ord + Codec,
§type Transaction = <S as TrieBackendStorage<H>>::Overlay
type Transaction = <S as TrieBackendStorage<H>>::Overlay
Storage changes to be applied if committing
§type TrieBackendStorage = S
type TrieBackendStorage = S
Type of trie backend storage.
source§fn storage_hash(&self, key: &[u8]) -> Result<Option<H::Out>, Self::Error>
fn storage_hash(&self, key: &[u8]) -> Result<Option<H::Out>, Self::Error>
Get keyed storage value hash or None if there is nothing associated.
source§fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>, Self::Error>
fn storage(&self, key: &[u8]) -> Result<Option<StorageValue>, Self::Error>
Get keyed storage or None if there is nothing associated.
source§fn child_storage_hash(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<H::Out>, Self::Error>
fn child_storage_hash(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<H::Out>, Self::Error>
Get child keyed storage value hash or None if there is nothing associated.
source§fn child_storage(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<StorageValue>, Self::Error>
fn child_storage(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<StorageValue>, Self::Error>
Get keyed child storage or None if there is nothing associated.
source§fn next_storage_key(&self, key: &[u8]) -> Result<Option<StorageKey>, Self::Error>
fn next_storage_key(&self, key: &[u8]) -> Result<Option<StorageKey>, Self::Error>
Return the next key in storage in lexicographic order or
None
if there is no value.source§fn next_child_storage_key(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<StorageKey>, Self::Error>
fn next_child_storage_key(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<Option<StorageKey>, Self::Error>
Return the next key in child storage in lexicographic order or
None
if there is no value.source§fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F)
fn for_keys_with_prefix<F: FnMut(&[u8])>(&self, prefix: &[u8], f: F)
Retrieve all entries keys which start with the given prefix and
call
f
for each of those keys.source§fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F)
fn for_key_values_with_prefix<F: FnMut(&[u8], &[u8])>(&self, prefix: &[u8], f: F)
Retrieve all entries keys and values of which start with the given prefix and
call
f
for each of those keys.source§fn apply_to_key_values_while<F: FnMut(Vec<u8>, Vec<u8>) -> bool>(
&self,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
start_at: Option<&[u8]>,
f: F,
allow_missing: bool
) -> Result<bool, Self::Error>
fn apply_to_key_values_while<F: FnMut(Vec<u8>, Vec<u8>) -> bool>(
&self,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
start_at: Option<&[u8]>,
f: F,
allow_missing: bool
) -> Result<bool, Self::Error>
Iterate over storage starting at key, for a given prefix and child trie.
Aborts as soon as
f
returns false.
Warning, this fails at first error when usual iteration skips errors.
If allow_missing
is true, iteration stops when it reaches a missing trie node.
Otherwise an error is produced. Read moresource§fn apply_to_keys_while<F: FnMut(&[u8]) -> bool>(
&self,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
start_at: Option<&[u8]>,
f: F
)
fn apply_to_keys_while<F: FnMut(&[u8]) -> bool>(
&self,
child_info: Option<&ChildInfo>,
prefix: Option<&[u8]>,
start_at: Option<&[u8]>,
f: F
)
Retrieve all entries keys of storage and call
f
for each of those keys.
Aborts as soon as f
returns false.source§fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
&self,
child_info: &ChildInfo,
prefix: &[u8],
f: F
)
fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
&self,
child_info: &ChildInfo,
prefix: &[u8],
f: F
)
Retrieve all child entries keys which start with the given prefix and
call
f
for each of those keys.source§fn pairs(&self) -> Vec<(StorageKey, StorageValue)> ⓘ
fn pairs(&self) -> Vec<(StorageKey, StorageValue)> ⓘ
Get all key/value pairs into a Vec.
source§fn storage_root<'a>(
&self,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
state_version: StateVersion
) -> (H::Out, Self::Transaction)where
H::Out: Ord,
fn storage_root<'a>(
&self,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
state_version: StateVersion
) -> (H::Out, Self::Transaction)where
H::Out: Ord,
Calculate the storage root, with given delta over what is already stored in
the backend, and produce a “transaction” that can be used to commit.
Does not include child storage updates.
source§fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
state_version: StateVersion
) -> (H::Out, bool, Self::Transaction)where
H::Out: Ord,
fn child_storage_root<'a>(
&self,
child_info: &ChildInfo,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
state_version: StateVersion
) -> (H::Out, bool, Self::Transaction)where
H::Out: Ord,
Calculate the child storage root, with given delta over what is already stored in
the backend, and produce a “transaction” that can be used to commit. The second argument
is true if child storage root equals default storage root.
source§fn register_overlay_stats(&self, _stats: &StateMachineStats)
fn register_overlay_stats(&self, _stats: &StateMachineStats)
Register stats from overlay of state machine. Read more
source§fn usage_info(&self) -> UsageInfo
fn usage_info(&self) -> UsageInfo
Query backend usage statistics (i/o, memory) Read more
source§fn exists_storage(&self, key: &[u8]) -> Result<bool, Self::Error>
fn exists_storage(&self, key: &[u8]) -> Result<bool, Self::Error>
true if a key exists in storage.
source§fn exists_child_storage(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<bool, Self::Error>
fn exists_child_storage(
&self,
child_info: &ChildInfo,
key: &[u8]
) -> Result<bool, Self::Error>
true if a key exists in child storage.
source§fn child_keys(&self, child_info: &ChildInfo, prefix: &[u8]) -> Vec<StorageKey> ⓘ
fn child_keys(&self, child_info: &ChildInfo, prefix: &[u8]) -> Vec<StorageKey> ⓘ
Get all keys of child storage with given prefix
source§fn full_storage_root<'a>(
&self,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
child_deltas: impl Iterator<Item = (&'a ChildInfo, impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>)>,
state_version: StateVersion
) -> (H::Out, Self::Transaction)where
H::Out: Ord + Encode,
fn full_storage_root<'a>(
&self,
delta: impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>,
child_deltas: impl Iterator<Item = (&'a ChildInfo, impl Iterator<Item = (&'a [u8], Option<&'a [u8]>)>)>,
state_version: StateVersion
) -> (H::Out, Self::Transaction)where
H::Out: Ord + Encode,
Calculate the storage root, with given delta over what is already stored
in the backend, and produce a “transaction” that can be used to commit.
Does include child storage updates.
source§fn commit(
&self,
_: H::Out,
_: Self::Transaction,
_: StorageCollection,
_: ChildStorageCollection
) -> Result<(), Self::Error>
fn commit(
&self,
_: H::Out,
_: Self::Transaction,
_: StorageCollection,
_: ChildStorageCollection
) -> Result<(), Self::Error>
Commit given transaction to storage.
source§fn reset_read_write_count(&self)
fn reset_read_write_count(&self)
Get the read/write count of the db
source§fn get_whitelist(&self) -> Vec<TrackedStorageKey> ⓘ
fn get_whitelist(&self) -> Vec<TrackedStorageKey> ⓘ
Get the whitelist for tracking db reads/writes
source§fn set_whitelist(&self, _: Vec<TrackedStorageKey>)
fn set_whitelist(&self, _: Vec<TrackedStorageKey>)
Update the whitelist for tracking db reads/writes
source§fn proof_size(&self) -> Option<u32>
fn proof_size(&self) -> Option<u32>
Estimate proof size
source§impl<H: Hasher, KF> Clone for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H: Hasher, KF> Clone for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
source§impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> Debug for TrieBackend<S, H, C>
impl<S: TrieBackendStorage<H>, H: Hasher, C: AsLocalTrieCache<H>> Debug for TrieBackend<S, H, C>
source§impl<H, KF> Default for TrieBackend<GenericMemoryDB<H, KF>, H>where
H: Hasher,
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H, KF> Default for TrieBackend<GenericMemoryDB<H, KF>, H>where
H: Hasher,
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
source§impl<H: Hasher, KF> From<(BTreeMap<Vec<u8, Global>, Vec<u8, Global>, Global>, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H: Hasher, KF> From<(BTreeMap<Vec<u8, Global>, Vec<u8, Global>, Global>, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
source§fn from(
(inner, state_version): (BTreeMap<StorageKey, StorageValue>, StateVersion)
) -> Self
fn from(
(inner, state_version): (BTreeMap<StorageKey, StorageValue>, StateVersion)
) -> Self
Converts to this type from the input type.
source§impl<H: Hasher, KF> From<(HashMap<Option<ChildInfo>, BTreeMap<Vec<u8, Global>, Vec<u8, Global>, Global>, RandomState>, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H: Hasher, KF> From<(HashMap<Option<ChildInfo>, BTreeMap<Vec<u8, Global>, Vec<u8, Global>, Global>, RandomState>, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
source§fn from(
(inner, state_version): (HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>, StateVersion)
) -> Self
fn from(
(inner, state_version): (HashMap<Option<ChildInfo>, BTreeMap<StorageKey, StorageValue>>, StateVersion)
) -> Self
Converts to this type from the input type.
source§impl<H: Hasher, KF> From<(Storage, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
impl<H: Hasher, KF> From<(Storage, StateVersion)> for TrieBackend<GenericMemoryDB<H, KF>, H>where
H::Out: Codec + Ord,
KF: KeyFunction<H> + Send + Sync,
Auto Trait Implementations§
impl<S, H, C = LocalTrieCache<H>> !RefUnwindSafe for TrieBackend<S, H, C>
impl<S, H, C> Send for TrieBackend<S, H, C>where
C: Send,
impl<S, H, C> Sync for TrieBackend<S, H, C>where
C: Sync,
impl<S, H, C> Unpin for TrieBackend<S, H, C>where
C: Unpin,
S: Unpin,
<H as Hasher>::Out: Unpin,
impl<S, H, C = LocalTrieCache<H>> !UnwindSafe for TrieBackend<S, H, C>
Blanket Implementations§
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
Convert
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Convert
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
Convert
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
Convert
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T, Outer> IsWrappedBy<Outer> for Twhere
Outer: AsRef<T> + AsMut<T> + From<T>,
T: From<Outer>,
impl<T, Outer> IsWrappedBy<Outer> for Twhere
Outer: AsRef<T> + AsMut<T> + From<T>,
T: From<Outer>,
source§impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
impl<S, T> UncheckedInto<T> for Swhere
T: UncheckedFrom<S>,
source§fn unchecked_into(self) -> T
fn unchecked_into(self) -> T
The counterpart to
unchecked_from
.