/__w/smoldot/smoldot/repo/lib/src/executor/runtime_call.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Wasm virtual machine, with automatic storage overlay. |
19 | | //! |
20 | | //! The code in this module builds upon the functionalities of the [`host`] module and |
21 | | //! implements some of the host function calls. In other words, it is an easier-to-use version of |
22 | | //! the [`host`] module. |
23 | | //! |
24 | | //! Most of the documentation of the [`host`] module also applies here. |
25 | | //! |
26 | | //! In addition to the functionalities provided by the [`host`] module, the `runtime_call` module: |
27 | | //! |
28 | | //! - Keeps track of the changes to the storage and off-chain storage made by the execution, and |
29 | | //! provides them at the end. Any storage access takes into account the intermediary list of |
30 | | //! changes. |
31 | | //! - Automatically handles some externalities, such as calculating the Merkle root or storage |
32 | | //! transactions. |
33 | | //! |
34 | | //! These additional features considerably reduces the number of externals concepts to plug to |
35 | | //! the virtual machine. |
36 | | |
37 | | // TODO: more docs |
38 | | |
39 | | use crate::{ |
40 | | executor::{self, host, storage_diff, trie_root_calculator, vm}, |
41 | | trie, util, |
42 | | }; |
43 | | |
44 | | use alloc::{ |
45 | | borrow::ToOwned as _, |
46 | | boxed::Box, |
47 | | collections::BTreeMap, |
48 | | format, |
49 | | string::{String, ToString as _}, |
50 | | vec::Vec, |
51 | | }; |
52 | | use core::{fmt, iter, ops}; |
53 | | |
54 | | pub use host::{ |
55 | | Error as ErrorDetail, LogEmitInfo, LogEmitInfoHex, LogEmitInfoStr, StorageProofSizeBehavior, |
56 | | }; |
57 | | pub use trie::{Nibble, TrieEntryVersion}; |
58 | | |
59 | | mod tests; |
60 | | |
61 | | /// Configuration for [`run`]. |
62 | | pub struct Config<'a, TParams> { |
63 | | /// Virtual machine to be run. |
64 | | pub virtual_machine: host::HostVmPrototype, |
65 | | |
66 | | /// Name of the function to be called. |
67 | | pub function_to_call: &'a str, |
68 | | |
69 | | /// Parameter of the call, as an iterator of bytes. The concatenation of bytes forms the |
70 | | /// actual input. |
71 | | pub parameter: TParams, |
72 | | |
73 | | /// Initial state of [`Success::storage_changes`]. The changes made during this |
74 | | /// execution will be pushed over the value in this field. |
75 | | // TODO: consider accepting a different type |
76 | | // TODO: accept also child trie modifications |
77 | | pub storage_main_trie_changes: storage_diff::TrieDiff, |
78 | | |
79 | | /// Behavior if the `ext_storage_proof_size_storage_proof_size_version_1` host function is |
80 | | /// called. |
81 | | /// |
82 | | /// See the documentation of [`StorageProofSizeBehavior`]. |
83 | | pub storage_proof_size_behavior: StorageProofSizeBehavior, |
84 | | |
85 | | /// Maximum log level of the runtime. |
86 | | /// |
87 | | /// > **Note**: This value is opaque from the point of the view of the client, and the runtime |
88 | | /// > is free to interpret it the way it wants. However, usually values are: `0` for |
89 | | /// > "off", `1` for "error", `2` for "warn", `3` for "info", `4` for "debug", |
90 | | /// > and `5` for "trace". |
91 | | pub max_log_level: u32, |
92 | | |
93 | | /// If `true`, then [`StorageChanges::trie_changes_iter_ordered`] will return `Some`. |
94 | | /// Passing `None` requires fewer calculation and fewer storage accesses. |
95 | | pub calculate_trie_changes: bool, |
96 | | } |
97 | | |
98 | | /// Start running the WebAssembly virtual machine. |
99 | 138 | pub fn run( |
100 | 138 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, |
101 | 138 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { |
102 | 138 | let state_trie_version = config |
103 | 138 | .virtual_machine |
104 | 138 | .runtime_version() |
105 | 138 | .decode() |
106 | 138 | .state_version |
107 | 138 | .unwrap_or(TrieEntryVersion::V0); |
108 | 138 | |
109 | 138 | Ok(Inner { |
110 | 138 | vm: config |
111 | 138 | .virtual_machine |
112 | 138 | .run_vectored( |
113 | 138 | config.function_to_call, |
114 | 138 | config.storage_proof_size_behavior, |
115 | 138 | config.parameter, |
116 | 138 | )?0 |
117 | 138 | .into(), |
118 | 138 | pending_storage_changes: PendingStorageChanges { |
119 | 138 | trie_diffs: { |
120 | 138 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); |
121 | 138 | hm.insert(None, config.storage_main_trie_changes); |
122 | 138 | hm |
123 | 138 | }, |
124 | 138 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( |
125 | 138 | 4, |
126 | 138 | Default::default(), |
127 | 138 | ), |
128 | 138 | tries_changes: BTreeMap::new(), |
129 | 138 | offchain_storage_changes: BTreeMap::new(), |
130 | 138 | }, |
131 | 138 | state_trie_version, |
132 | 138 | transactions_stack: Vec::new(), |
133 | 138 | offchain_storage_changes: BTreeMap::new(), |
134 | 138 | root_calculation: None, |
135 | 138 | max_log_level: config.max_log_level, |
136 | 138 | calculate_trie_changes: config.calculate_trie_changes, |
137 | 138 | } |
138 | 138 | .run()) |
139 | 138 | } _RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherIBT_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIBT_B1u_IBT_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1r_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3i_3map3MapIB3e_IB3e_IB3e_INtNtNtB3k_7sources4once4OnceB1n_EB4B_EB4B_EB4B_ENcNtBS_4Left0EIB46_IB3e_IB4C_B2l_EINtNtB3i_7flatten7FlatMapNtNtB6_6header8LogsIterIB46_INtNtNtB3m_5array4iter8IntoIterB2t_Kj2_ENcNtB2l_5Right0ENCNvMs2_B6n_NtB6n_9DigestRef14scale_encoding0EENcNtBS_5Right0EEEB6_ Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIBT_Ahj8_IBT_B1n_B2h_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2G_3map3MapINtNtNtB2I_7sources4once4OnceB1n_ENcNtBS_4Left0EIB3u_INtNtB2G_7flatten7FlatMapINtNtNtB2K_5array4iter8IntoIterTB2h_B2h_EKj1_EIB2C_IB3u_IB3L_B2h_ENcNtB2d_4Left0EIB3u_IB2C_IB3u_B3K_NcNtB2m_4Left0EIB3u_B5U_NcNtB2m_5Right0EENcNtB2d_5Right0EENCINvMs_NtNtB6_6author7runtimeNtB7G_18InherentExtrinsics25inject_raw_inherents_listB2h_B50_E0ENcNtBS_5Right0EEEB6_ Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherRAhj1_IBT_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2d_INtNtB2h_3map3MapINtNtNtB2j_7sources4once4OnceB1n_ENcNtBS_4Left0EIB3a_IB3a_IB3r_B1A_ENcNtB1t_5Right0ENcNtBS_5Right0EEIB3a_IB3a_IB3r_B1x_ENcNtB1t_4Left0EB4M_EEEB6_ Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIBT_B1n_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2Y_INtNtNtB34_7sources4once4OnceBS_EB3U_EINtNtB32_3map3MapINtNtNtB36_5slice4iter4IterNtNtB2_5tests9HexStringENCNvB5g_s_14execute_blockss0_0EEEB6_ Line | Count | Source | 99 | 4 | pub fn run( | 100 | 4 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 4 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 4 | let state_trie_version = config | 103 | 4 | .virtual_machine | 104 | 4 | .runtime_version() | 105 | 4 | .decode() | 106 | 4 | .state_version | 107 | 4 | .unwrap_or(TrieEntryVersion::V0); | 108 | 4 | | 109 | 4 | Ok(Inner { | 110 | 4 | vm: config | 111 | 4 | .virtual_machine | 112 | 4 | .run_vectored( | 113 | 4 | config.function_to_call, | 114 | 4 | config.storage_proof_size_behavior, | 115 | 4 | config.parameter, | 116 | 4 | )?0 | 117 | 4 | .into(), | 118 | 4 | pending_storage_changes: PendingStorageChanges { | 119 | 4 | trie_diffs: { | 120 | 4 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 4 | hm.insert(None, config.storage_main_trie_changes); | 122 | 4 | hm | 123 | 4 | }, | 124 | 4 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 4 | 4, | 126 | 4 | Default::default(), | 127 | 4 | ), | 128 | 4 | tries_changes: BTreeMap::new(), | 129 | 4 | offchain_storage_changes: BTreeMap::new(), | 130 | 4 | }, | 131 | 4 | state_trie_version, | 132 | 4 | transactions_stack: Vec::new(), | 133 | 4 | offchain_storage_changes: BTreeMap::new(), | 134 | 4 | root_calculation: None, | 135 | 4 | max_log_level: config.max_log_level, | 136 | 4 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 4 | } | 138 | 4 | .run()) | 139 | 4 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBS_EEB6_ Line | Count | Source | 99 | 2 | pub fn run( | 100 | 2 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 2 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 2 | let state_trie_version = config | 103 | 2 | .virtual_machine | 104 | 2 | .runtime_version() | 105 | 2 | .decode() | 106 | 2 | .state_version | 107 | 2 | .unwrap_or(TrieEntryVersion::V0); | 108 | 2 | | 109 | 2 | Ok(Inner { | 110 | 2 | vm: config | 111 | 2 | .virtual_machine | 112 | 2 | .run_vectored( | 113 | 2 | config.function_to_call, | 114 | 2 | config.storage_proof_size_behavior, | 115 | 2 | config.parameter, | 116 | 2 | )?0 | 117 | 2 | .into(), | 118 | 2 | pending_storage_changes: PendingStorageChanges { | 119 | 2 | trie_diffs: { | 120 | 2 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 2 | hm.insert(None, config.storage_main_trie_changes); | 122 | 2 | hm | 123 | 2 | }, | 124 | 2 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 2 | 4, | 126 | 2 | Default::default(), | 127 | 2 | ), | 128 | 2 | tries_changes: BTreeMap::new(), | 129 | 2 | offchain_storage_changes: BTreeMap::new(), | 130 | 2 | }, | 131 | 2 | state_trie_version, | 132 | 2 | transactions_stack: Vec::new(), | 133 | 2 | offchain_storage_changes: BTreeMap::new(), | 134 | 2 | root_calculation: None, | 135 | 2 | max_log_level: config.max_log_level, | 136 | 2 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 2 | } | 138 | 2 | .run()) | 139 | 2 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBS_EEB6_ Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call3runRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBS_EEB6_ Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBT_EECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherIBU_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIBU_B1v_IBU_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1s_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3j_3map3MapIB3f_IB3f_IB3f_INtNtNtB3l_7sources4once4OnceB1o_EB4C_EB4C_EB4C_ENcNtBT_4Left0EIB47_IB3f_IB4D_B2m_EINtNtB3j_7flatten7FlatMapNtNtB6_6header8LogsIterIB47_INtNtNtB3n_5array4iter8IntoIterB2u_Kj2_ENcNtB2m_5Right0ENCNvMs2_B6o_NtB6o_9DigestRef14scale_encoding0EENcNtBT_5Right0EEEB6_ Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIBU_Ahj8_IBU_B1o_B2i_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2H_3map3MapINtNtNtB2J_7sources4once4OnceB1o_ENcNtBT_4Left0EIB3v_INtNtB2H_7flatten7FlatMapINtNtNtB2L_5array4iter8IntoIterTB2i_B2i_EKj1_EIB2D_IB3v_IB3M_B2i_ENcNtB2e_4Left0EIB3v_IB2D_IB3v_B3L_NcNtB2n_4Left0EIB3v_B5V_NcNtB2n_5Right0EENcNtB2e_5Right0EENCINvMs_NtNtB6_6author7runtimeNtB7H_18InherentExtrinsics25inject_raw_inherents_listB2i_B51_E0ENcNtBT_5Right0EEEB6_ _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBT_EEB6_ Line | Count | Source | 99 | 126 | pub fn run( | 100 | 126 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 126 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 126 | let state_trie_version = config | 103 | 126 | .virtual_machine | 104 | 126 | .runtime_version() | 105 | 126 | .decode() | 106 | 126 | .state_version | 107 | 126 | .unwrap_or(TrieEntryVersion::V0); | 108 | 126 | | 109 | 126 | Ok(Inner { | 110 | 126 | vm: config | 111 | 126 | .virtual_machine | 112 | 126 | .run_vectored( | 113 | 126 | config.function_to_call, | 114 | 126 | config.storage_proof_size_behavior, | 115 | 126 | config.parameter, | 116 | 126 | )?0 | 117 | 126 | .into(), | 118 | 126 | pending_storage_changes: PendingStorageChanges { | 119 | 126 | trie_diffs: { | 120 | 126 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 126 | hm.insert(None, config.storage_main_trie_changes); | 122 | 126 | hm | 123 | 126 | }, | 124 | 126 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 126 | 4, | 126 | 126 | Default::default(), | 127 | 126 | ), | 128 | 126 | tries_changes: BTreeMap::new(), | 129 | 126 | offchain_storage_changes: BTreeMap::new(), | 130 | 126 | }, | 131 | 126 | state_trie_version, | 132 | 126 | transactions_stack: Vec::new(), | 133 | 126 | offchain_storage_changes: BTreeMap::new(), | 134 | 126 | root_calculation: None, | 135 | 126 | max_log_level: config.max_log_level, | 136 | 126 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 126 | } | 138 | 126 | .run()) | 139 | 126 | } |
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBT_EEB6_ Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBT_EEB6_ Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBT_EECsiLzmwikkc22_14json_rpc_basic _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBT_EECsiUjFBJteJ7x_17smoldot_full_node Line | Count | Source | 99 | 1 | pub fn run( | 100 | 1 | config: Config<impl Iterator<Item = impl AsRef<[u8]>> + Clone>, | 101 | 1 | ) -> Result<RuntimeCall, (host::StartErr, host::HostVmPrototype)> { | 102 | 1 | let state_trie_version = config | 103 | 1 | .virtual_machine | 104 | 1 | .runtime_version() | 105 | 1 | .decode() | 106 | 1 | .state_version | 107 | 1 | .unwrap_or(TrieEntryVersion::V0); | 108 | 1 | | 109 | 1 | Ok(Inner { | 110 | 1 | vm: config | 111 | 1 | .virtual_machine | 112 | 1 | .run_vectored( | 113 | 1 | config.function_to_call, | 114 | 1 | config.storage_proof_size_behavior, | 115 | 1 | config.parameter, | 116 | 1 | )?0 | 117 | 1 | .into(), | 118 | 1 | pending_storage_changes: PendingStorageChanges { | 119 | 1 | trie_diffs: { | 120 | 1 | let mut hm = hashbrown::HashMap::with_capacity_and_hasher(4, Default::default()); | 121 | 1 | hm.insert(None, config.storage_main_trie_changes); | 122 | 1 | hm | 123 | 1 | }, | 124 | 1 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( | 125 | 1 | 4, | 126 | 1 | Default::default(), | 127 | 1 | ), | 128 | 1 | tries_changes: BTreeMap::new(), | 129 | 1 | offchain_storage_changes: BTreeMap::new(), | 130 | 1 | }, | 131 | 1 | state_trie_version, | 132 | 1 | transactions_stack: Vec::new(), | 133 | 1 | offchain_storage_changes: BTreeMap::new(), | 134 | 1 | root_calculation: None, | 135 | 1 | max_log_level: config.max_log_level, | 136 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 137 | 1 | } | 138 | 1 | .run()) | 139 | 1 | } |
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBT_EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call3runRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceBT_EECsibGXYHQB8Ea_25json_rpc_general_requests |
140 | | |
141 | | /// Execution is successful. |
142 | | #[derive(Debug)] |
143 | | pub struct Success { |
144 | | /// Contains the output value of the runtime, and the virtual machine that was passed at |
145 | | /// initialization. |
146 | | pub virtual_machine: SuccessVirtualMachine, |
147 | | /// List of changes to the storage that the block performs. |
148 | | pub storage_changes: StorageChanges, |
149 | | /// State trie version indicated by the runtime. All the storage changes indicated by |
150 | | /// [`Success::storage_changes`] should store this version alongside with them. |
151 | | pub state_trie_version: TrieEntryVersion, |
152 | | } |
153 | | |
154 | | /// See [`Success::storage_changes`]. |
155 | | pub struct StorageChanges { |
156 | | /// The [`PendingStorageChanges`] that was built by the state machine. The changes are no |
157 | | /// longer pending. |
158 | | inner: PendingStorageChanges, |
159 | | |
160 | | /// See [`Config::calculate_trie_changes`]. |
161 | | calculate_trie_changes: bool, |
162 | | } |
163 | | |
164 | | impl StorageChanges { |
165 | | /// Returns an empty [`StorageChanges`], as if the execution didn't modify anything. |
166 | 0 | pub fn empty() -> StorageChanges { |
167 | 0 | StorageChanges { |
168 | 0 | inner: PendingStorageChanges { |
169 | 0 | trie_diffs: hashbrown::HashMap::with_capacity_and_hasher(0, Default::default()), |
170 | 0 | stale_child_tries_root_hashes: hashbrown::HashSet::with_capacity_and_hasher( |
171 | 0 | 4, |
172 | 0 | Default::default(), |
173 | 0 | ), |
174 | 0 | tries_changes: BTreeMap::new(), |
175 | 0 | offchain_storage_changes: BTreeMap::new(), |
176 | 0 | }, |
177 | 0 | calculate_trie_changes: true, |
178 | 0 | } |
179 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges5empty Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges5empty |
180 | | |
181 | | /// Returns the change, if any, at the given key of the main trie. |
182 | | /// |
183 | | /// Returns `None` if the runtime hasn't modified this entry in the main trie, and `Some(None)` |
184 | | /// if the runtime has removed the storage item of this entry. |
185 | 0 | pub fn main_trie_diff_get(&self, key: &[u8]) -> Option<Option<&[u8]>> { |
186 | 0 | self.inner |
187 | 0 | .trie_diffs |
188 | 0 | .get(&None) |
189 | 0 | .and_then(|diff| diff.diff_get(key).map(|(v, _)| v)) Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges18main_trie_diff_get0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges18main_trie_diff_get0B8_ Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges18main_trie_diff_get00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges18main_trie_diff_get00Ba_ |
190 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges18main_trie_diff_get Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges18main_trie_diff_get |
191 | | |
192 | | /// Returns an iterator to all the entries of the main trie that are modified by this runtime |
193 | | /// call. |
194 | | /// |
195 | | /// Each value is either `Some` if the runtime overwrites this value, or `None` if it erases |
196 | | /// the underlying value. |
197 | | /// |
198 | | /// > **Note**: This function is equivalent to |
199 | | /// > [`StorageChanges::storage_changes_iter_unordered`], except that it only returns |
200 | | /// > changes made to the main trie. |
201 | 0 | pub fn main_trie_storage_changes_iter_unordered( |
202 | 0 | &'_ self, |
203 | 0 | ) -> impl Iterator<Item = (&'_ [u8], Option<&'_ [u8]>)> + Clone + '_ { |
204 | 0 | self.inner |
205 | 0 | .trie_diffs |
206 | 0 | .get(&None) |
207 | 0 | .into_iter() |
208 | 0 | .flat_map(|list| list.diff_iter_unordered().map(|(k, v, ())| (k, v))) Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00CsiUjFBJteJ7x_17smoldot_full_node |
209 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges40main_trie_storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges40main_trie_storage_changes_iter_unordered |
210 | | |
211 | | /// Returns the list of all child tries whose content has been modified in some way. |
212 | 0 | pub fn tries_with_storage_changes_unordered(&'_ self) -> impl Iterator<Item = &'_ [u8]> + '_ { |
213 | 0 | self.inner.trie_diffs.keys().filter_map(|k| k.as_deref()) Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges36tries_with_storage_changes_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges36tries_with_storage_changes_unordered0B8_ |
214 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges36tries_with_storage_changes_unordered Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges36tries_with_storage_changes_unordered |
215 | | |
216 | | /// Returns an iterator to all the entries of the given child trie that are modified by this |
217 | | /// runtime call. |
218 | | /// |
219 | | /// Each value is either `Some` if the runtime overwrites this value, or `None` if it erases |
220 | | /// the underlying value. |
221 | | /// |
222 | | /// > **Note**: This function is equivalent to |
223 | | /// > [`StorageChanges::storage_changes_iter_unordered`], except that it only returns |
224 | | /// > changes made to the given child trie. |
225 | 0 | pub fn child_trie_storage_changes_iter_unordered( |
226 | 0 | &'_ self, |
227 | 0 | child_trie: &'_ [u8], |
228 | 0 | ) -> impl Iterator<Item = (&'_ [u8], Option<&'_ [u8]>)> + Clone + '_ { |
229 | 0 | self.inner |
230 | 0 | .trie_diffs |
231 | 0 | .get(&Some(child_trie.to_vec())) // TODO: annoying unnecessary overhead |
232 | 0 | .into_iter() |
233 | 0 | .flat_map(|list| list.diff_iter_unordered().map(|(k, v, ())| (k, v))) Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges41child_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges41child_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges41child_trie_storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges41child_trie_storage_changes_iter_unordered00Ba_ |
234 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges41child_trie_storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges41child_trie_storage_changes_iter_unordered |
235 | | |
236 | | /// Returns an iterator to all the entries that are modified by this runtime call. |
237 | | /// |
238 | | /// Each value is either `Some` if the runtime overwrites this value, or `None` if it erases |
239 | | /// the underlying value. |
240 | 0 | pub fn storage_changes_iter_unordered( |
241 | 0 | &'_ self, |
242 | 0 | ) -> impl Iterator<Item = (Option<&'_ [u8]>, &'_ [u8], Option<&'_ [u8]>)> + Clone + '_ { |
243 | 0 | self.inner.trie_diffs.iter().flat_map(|(trie, list)| { |
244 | 0 | list.diff_iter_unordered() |
245 | 0 | .map(move |(k, v, ())| (trie.as_deref(), k, v)) Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges30storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges30storage_changes_iter_unordered00Ba_ |
246 | 0 | }) Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges30storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges30storage_changes_iter_unordered0B8_ |
247 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges30storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges30storage_changes_iter_unordered |
248 | | |
249 | | /// Returns an iterator over the list of all changes performed to the tries (main trie and |
250 | | /// child tries included). |
251 | | /// |
252 | | /// Returns `Some` if and only if [`Config::calculate_trie_changes`] was `true` or if the |
253 | | /// [`StorageChanges`] was created using [`StorageChanges::empty`]. |
254 | 0 | pub fn trie_changes_iter_ordered( |
255 | 0 | &'_ self, |
256 | 0 | ) -> Option<impl Iterator<Item = (Option<&'_ [u8]>, &'_ [Nibble], TrieChange<'_>)>> { |
257 | 0 | if !self.calculate_trie_changes { |
258 | 0 | return None; |
259 | 0 | } |
260 | 0 |
|
261 | 0 | Some( |
262 | 0 | self.inner |
263 | 0 | .tries_changes |
264 | 0 | .iter() |
265 | 0 | .map(|((child_trie, key), change)| { |
266 | 0 | let change = match change { |
267 | 0 | PendingStorageChangesTrieNode::Removed => TrieChange::Remove, |
268 | | PendingStorageChangesTrieNode::InsertUpdate { |
269 | 0 | new_merkle_value, |
270 | 0 | partial_key, |
271 | 0 | children_merkle_values, |
272 | 0 | } => { |
273 | 0 | debug_assert!(key.ends_with(partial_key)); |
274 | | |
275 | 0 | let new_storage_value = if key.len() % 2 == 0 { |
276 | 0 | let key_bytes = |
277 | 0 | trie::nibbles_to_bytes_truncate(key.iter().copied()) |
278 | 0 | .collect::<Vec<_>>(); |
279 | 0 | match self |
280 | 0 | .inner |
281 | 0 | .trie_diffs |
282 | 0 | .get(child_trie) |
283 | 0 | .and_then(|diff| diff.diff_get(&key_bytes)) Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00CscDgN54JpMGG_6author Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00CsibGXYHQB8Ea_25json_rpc_general_requests |
284 | | { |
285 | 0 | None => TrieChangeStorageValue::Unmodified, |
286 | 0 | Some((new_value, ())) => { |
287 | 0 | TrieChangeStorageValue::Modified { new_value } |
288 | | } |
289 | | } |
290 | | } else { |
291 | 0 | TrieChangeStorageValue::Unmodified |
292 | | }; |
293 | | |
294 | 0 | let children_merkle_values = <Box<[_; 16]>>::try_from( |
295 | 0 | children_merkle_values |
296 | 0 | .iter() |
297 | 0 | .map(|child| child.as_ref().map(|mv| &mv[..])) Unexecuted instantiation: _RNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCNCNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00Bc_ Unexecuted instantiation: _RNCNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00Bc_ Unexecuted instantiation: _RNCNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00CscDgN54JpMGG_6author Unexecuted instantiation: _RNCNCNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00CsibGXYHQB8Ea_25json_rpc_general_requests |
298 | 0 | .collect::<Box<[_]>>(), |
299 | 0 | ) |
300 | 0 | .unwrap(); |
301 | 0 |
|
302 | 0 | TrieChange::InsertUpdate { |
303 | 0 | new_merkle_value, |
304 | 0 | partial_key, |
305 | 0 | children_merkle_values, |
306 | 0 | new_storage_value, |
307 | 0 | } |
308 | | } |
309 | | }; |
310 | | |
311 | 0 | (child_trie.as_deref(), &key[..], change) |
312 | 0 | }), Unexecuted instantiation: _RNCNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0CsibGXYHQB8Ea_25json_rpc_general_requests |
313 | 0 | ) |
314 | 0 | } Unexecuted instantiation: _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges25trie_changes_iter_ordered Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges25trie_changes_iter_ordered |
315 | | |
316 | | /// Returns a diff of the main trie. |
317 | | // TODO: weird API, necessary to turn this object back to a value for Config::storage_changes |
318 | 3 | pub fn into_main_trie_diff(mut self) -> storage_diff::TrieDiff { |
319 | 3 | self.inner |
320 | 3 | .trie_diffs |
321 | 3 | .remove(&None) |
322 | 3 | .unwrap_or(storage_diff::TrieDiff::empty()) |
323 | 3 | } _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB2_14StorageChanges19into_main_trie_diff Line | Count | Source | 318 | 3 | pub fn into_main_trie_diff(mut self) -> storage_diff::TrieDiff { | 319 | 3 | self.inner | 320 | 3 | .trie_diffs | 321 | 3 | .remove(&None) | 322 | 3 | .unwrap_or(storage_diff::TrieDiff::empty()) | 323 | 3 | } |
Unexecuted instantiation: _RNvMNtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB2_14StorageChanges19into_main_trie_diff |
324 | | } |
325 | | |
326 | | impl fmt::Debug for StorageChanges { |
327 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
328 | 0 | if let Some(trie_changes) = self.trie_changes_iter_ordered() { |
329 | 0 | f.debug_map() |
330 | 0 | .entries(trie_changes.map(|(child_trie, key, change)| { |
331 | 0 | let mut key_str = key |
332 | 0 | .iter() |
333 | 0 | .copied() |
334 | 0 | .map(|n| format!("{:x}", n)) Unexecuted instantiation: _RNCNCNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt00Bc_ Unexecuted instantiation: _RNCNCNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt00Bc_ |
335 | 0 | .collect::<String>(); |
336 | 0 | if key_str.is_empty() { |
337 | 0 | key_str = "∅".to_owned(); |
338 | 0 | } |
339 | | |
340 | 0 | let key = match child_trie { |
341 | 0 | Some(ct) => format!( |
342 | 0 | "<{}>:{}", |
343 | 0 | if ct.is_empty() { |
344 | 0 | "∅".to_string() |
345 | | } else { |
346 | 0 | hex::encode(ct) |
347 | | }, |
348 | | key_str |
349 | | ), |
350 | 0 | None => format!("<main>:{}", key_str), |
351 | | }; |
352 | | |
353 | 0 | (key, change) |
354 | 0 | })) Unexecuted instantiation: _RNCNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt0Ba_ Unexecuted instantiation: _RNCNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt0Ba_ |
355 | 0 | .finish() |
356 | | } else { |
357 | 0 | f.debug_map() |
358 | 0 | .entries(self.inner.trie_diffs.iter().flat_map(|(child_trie, diff)| { |
359 | 0 | diff.diff_iter_unordered().map(move |(key, value, _)| { |
360 | 0 | let mut key_str = key |
361 | 0 | .iter() |
362 | 0 | .copied() |
363 | 0 | .map(|n| format!("{:x}", n)) Unexecuted instantiation: _RNCNCNCNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtBa_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_000Be_ Unexecuted instantiation: _RNCNCNCNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_000Be_ |
364 | 0 | .collect::<String>(); |
365 | 0 | if key_str.is_empty() { |
366 | 0 | key_str = "∅".to_owned(); |
367 | 0 | } |
368 | | |
369 | 0 | let key = match child_trie { |
370 | 0 | Some(ct) => format!( |
371 | 0 | "<{}>:{}", |
372 | 0 | if ct.is_empty() { |
373 | 0 | "∅".to_string() |
374 | | } else { |
375 | 0 | hex::encode(ct) |
376 | | }, |
377 | | key_str |
378 | | ), |
379 | 0 | None => format!("<main>:{}", key_str), |
380 | | }; |
381 | | |
382 | 0 | let change = if let Some(value) = value { |
383 | 0 | hex::encode(value) |
384 | | } else { |
385 | 0 | "<deleted>".into() |
386 | | }; |
387 | | |
388 | 0 | (key, change) |
389 | 0 | }) Unexecuted instantiation: _RNCNCNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_00Bc_ Unexecuted instantiation: _RNCNCNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_00Bc_ |
390 | 0 | })) Unexecuted instantiation: _RNCNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_0Ba_ Unexecuted instantiation: _RNCNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_0Ba_ |
391 | 0 | .finish() |
392 | | } |
393 | 0 | } Unexecuted instantiation: _RNvXs_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB4_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB4_14StorageChangesNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
394 | | } |
395 | | |
396 | | #[derive(Clone)] |
397 | | pub enum TrieChange<'a> { |
398 | | /// Trie node is either newly-created, or already existed and has a new Merkle value. |
399 | | InsertUpdate { |
400 | | /// New Merkle value associated to this trie node. Always inferior or equal to 32 bytes. |
401 | | new_merkle_value: &'a [u8], |
402 | | partial_key: &'a [Nibble], |
403 | | children_merkle_values: Box<[Option<&'a [u8]>; 16]>, |
404 | | /// Change to the storage value of that trie node. |
405 | | new_storage_value: TrieChangeStorageValue<'a>, |
406 | | }, |
407 | | /// Trie node is removed. |
408 | | Remove, |
409 | | } |
410 | | |
411 | | impl<'a> fmt::Debug for TrieChange<'a> { |
412 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
413 | 0 | match self { |
414 | 0 | TrieChange::Remove => f.debug_tuple("Remove").finish(), |
415 | | TrieChange::InsertUpdate { |
416 | 0 | new_merkle_value, |
417 | 0 | partial_key, |
418 | 0 | children_merkle_values, |
419 | 0 | new_storage_value, |
420 | 0 | } => f |
421 | 0 | .debug_struct("InsertUpdate") |
422 | 0 | .field("new_merkle_value", &hex::encode(new_merkle_value)) |
423 | 0 | .field( |
424 | 0 | "partial_key", |
425 | 0 | &partial_key |
426 | 0 | .iter() |
427 | 0 | .map(|n| format!("{:x}", n)) Unexecuted instantiation: _RNCNvXs0_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt0Bb_ Unexecuted instantiation: _RNCNvXs0_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt0Bb_ |
428 | 0 | .collect::<String>(), |
429 | 0 | ) |
430 | 0 | .field( |
431 | 0 | "children_merkle_values", |
432 | 0 | &children_merkle_values |
433 | 0 | .iter() |
434 | 0 | .map(|child| match child { |
435 | 0 | Some(child) => hex::encode(child), |
436 | 0 | None => "∅".to_string(), |
437 | 0 | }) Unexecuted instantiation: _RNCNvXs0_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_0Bb_ Unexecuted instantiation: _RNCNvXs0_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmts_0Bb_ |
438 | 0 | .collect::<Vec<_>>() |
439 | 0 | .join(","), |
440 | 0 | ) |
441 | 0 | .field("new_storage_value", new_storage_value) |
442 | 0 | .finish(), |
443 | | } |
444 | 0 | } Unexecuted instantiation: _RNvXs0_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_10TrieChangeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
445 | | } |
446 | | |
447 | | #[derive(Clone)] |
448 | | pub enum TrieChangeStorageValue<'a> { |
449 | | Unmodified, |
450 | | Modified { new_value: Option<&'a [u8]> }, |
451 | | } |
452 | | |
453 | | impl<'a> fmt::Debug for TrieChangeStorageValue<'a> { |
454 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
455 | 0 | match self { |
456 | 0 | TrieChangeStorageValue::Unmodified => f.debug_tuple("Unmodified").finish(), |
457 | | TrieChangeStorageValue::Modified { new_value: None } => { |
458 | 0 | f.debug_tuple("Modified").field(&"<deleted>").finish() |
459 | | } |
460 | | TrieChangeStorageValue::Modified { |
461 | 0 | new_value: Some(new_value), |
462 | 0 | } => f |
463 | 0 | .debug_tuple("Modified") |
464 | 0 | .field(&hex::encode(new_value)) |
465 | 0 | .finish(), |
466 | | } |
467 | 0 | } Unexecuted instantiation: _RNvXs1_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_22TrieChangeStorageValueNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs1_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_22TrieChangeStorageValueNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
468 | | } |
469 | | |
470 | | /// Function execution has succeeded. Contains the return value of the call. |
471 | | pub struct SuccessVirtualMachine(host::Finished); |
472 | | |
473 | | impl SuccessVirtualMachine { |
474 | | /// Returns the value the called function has returned. |
475 | 133 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { |
476 | 133 | self.0.value() |
477 | 133 | } _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachine5value Line | Count | Source | 475 | 6 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { | 476 | 6 | self.0.value() | 477 | 6 | } |
_RNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachine5value Line | Count | Source | 475 | 127 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { | 476 | 127 | self.0.value() | 477 | 127 | } |
|
478 | | |
479 | | /// Turns the virtual machine back into a prototype. |
480 | 132 | pub fn into_prototype(self) -> host::HostVmPrototype { |
481 | 132 | self.0.into_prototype() |
482 | 132 | } _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachine14into_prototype Line | Count | Source | 480 | 6 | pub fn into_prototype(self) -> host::HostVmPrototype { | 481 | 6 | self.0.into_prototype() | 482 | 6 | } |
_RNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachine14into_prototype Line | Count | Source | 480 | 126 | pub fn into_prototype(self) -> host::HostVmPrototype { | 481 | 126 | self.0.into_prototype() | 482 | 126 | } |
|
483 | | } |
484 | | |
485 | | impl fmt::Debug for SuccessVirtualMachine { |
486 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
487 | 0 | f.debug_tuple("SuccessVirtualMachine").finish() |
488 | 0 | } Unexecuted instantiation: _RNvXs3_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachineNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs3_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachineNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
489 | | } |
490 | | |
491 | | /// Error that can happen during the execution. |
492 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXsm_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsm_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
493 | | #[display(fmt = "{detail}")] |
494 | | pub struct Error { |
495 | | /// Exact error that happened. |
496 | | pub detail: ErrorDetail, |
497 | | /// Prototype of the virtual machine that was passed through [`Config::virtual_machine`]. |
498 | | pub prototype: host::HostVmPrototype, |
499 | | } |
500 | | |
501 | | /// Current state of the execution. |
502 | | #[must_use] |
503 | | pub enum RuntimeCall { |
504 | | /// Execution is over. |
505 | | Finished(Result<Success, Error>), |
506 | | /// Loading a storage value is required in order to continue. |
507 | | StorageGet(StorageGet), |
508 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
509 | | /// to continue. |
510 | | ClosestDescendantMerkleValue(ClosestDescendantMerkleValue), |
511 | | /// Fetching the key that follows a given one is required in order to continue. |
512 | | NextKey(NextKey), |
513 | | /// Verifying whether a signature is correct is required in order to continue. |
514 | | SignatureVerification(SignatureVerification), |
515 | | /// Runtime would like to emit some log. |
516 | | LogEmit(LogEmit), |
517 | | /// Setting an offchain storage value is required in order to continue. |
518 | | /// |
519 | | /// Contrary to [`OffchainContext::StorageSet`], this variant is allowed to happen |
520 | | /// outside of offchain workers. |
521 | | OffchainStorageSet(OffchainStorageSet), |
522 | | /// Functions that can only be called within the context of an offchain worker. |
523 | | Offchain(OffchainContext), |
524 | | } |
525 | | |
526 | | impl RuntimeCall { |
527 | | /// Cancels execution of the virtual machine and returns back the prototype. |
528 | 0 | pub fn into_prototype(self) -> host::HostVmPrototype { |
529 | 0 | match self { |
530 | 0 | RuntimeCall::Finished(Ok(inner)) => inner.virtual_machine.into_prototype(), |
531 | 0 | RuntimeCall::Finished(Err(inner)) => inner.prototype, |
532 | 0 | RuntimeCall::StorageGet(inner) => inner.inner.vm.into_prototype(), |
533 | 0 | RuntimeCall::ClosestDescendantMerkleValue(inner) => inner.inner.vm.into_prototype(), |
534 | 0 | RuntimeCall::NextKey(inner) => inner.inner.vm.into_prototype(), |
535 | 0 | RuntimeCall::SignatureVerification(inner) => inner.inner.vm.into_prototype(), |
536 | 0 | RuntimeCall::LogEmit(inner) => inner.inner.vm.into_prototype(), |
537 | 0 | RuntimeCall::OffchainStorageSet(inner) => inner.inner.vm.into_prototype(), |
538 | 0 | RuntimeCall::Offchain(inner) => inner.into_prototype(), |
539 | | } |
540 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_11RuntimeCall14into_prototype Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_11RuntimeCall14into_prototype |
541 | | } |
542 | | |
543 | | pub enum OffchainContext { |
544 | | /// Loading an offchain storage value is required in order to continue. |
545 | | StorageGet(OffchainStorageGet), |
546 | | /// Setting an offchain storage value is required in order to continue. |
547 | | /// |
548 | | /// Contrary to [`RuntimeCall::OffchainStorageSet`], this variant can only happen in offchain |
549 | | /// workers. |
550 | | StorageSet(OffchainStorageCompareSet), |
551 | | /// Timestamp for offchain worker. |
552 | | Timestamp(OffchainTimestamp), |
553 | | /// Random seed for offchain worker. |
554 | | RandomSeed(OffchainRandomSeed), |
555 | | /// Submit transaction from offchain worker. |
556 | | SubmitTransaction(OffchainSubmitTransaction), |
557 | | } |
558 | | |
559 | | impl OffchainContext { |
560 | 0 | pub fn into_prototype(self) -> host::HostVmPrototype { |
561 | 0 | match self { |
562 | 0 | OffchainContext::StorageGet(inner) => inner.inner.vm.into_prototype(), |
563 | 0 | OffchainContext::StorageSet(inner) => inner.inner.vm.into_prototype(), |
564 | 0 | OffchainContext::Timestamp(inner) => inner.inner.vm.into_prototype(), |
565 | 0 | OffchainContext::RandomSeed(inner) => inner.inner.vm.into_prototype(), |
566 | 0 | OffchainContext::SubmitTransaction(inner) => inner.inner.vm.into_prototype(), |
567 | | } |
568 | 0 | } Unexecuted instantiation: _RNvMs5_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_15OffchainContext14into_prototype Unexecuted instantiation: _RNvMs5_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_15OffchainContext14into_prototype |
569 | | } |
570 | | |
571 | | /// Loading a storage value is required in order to continue. |
572 | | #[must_use] |
573 | | pub struct StorageGet { |
574 | | inner: Inner, |
575 | | } |
576 | | |
577 | | impl StorageGet { |
578 | | /// Returns the key whose value must be passed to [`StorageGet::inject_value`]. |
579 | 9.27k | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
580 | 9.27k | enum Three<A, B, C> { |
581 | 9.27k | A(A), |
582 | 9.27k | B(B), |
583 | 9.27k | C(C), |
584 | 9.27k | } |
585 | 9.27k | |
586 | 9.27k | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
587 | 9.27k | fn as_ref(&self) -> &[u8] { |
588 | 9.27k | match self { |
589 | 9.27k | Three::A(a) => a.as_ref()2.22k , |
590 | 9.27k | Three::B(b) => b.as_ref()8 , |
591 | 9.27k | Three::C(c) => c.as_ref()7.05k , |
592 | 9.27k | } |
593 | 9.27k | } _RNvXNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB28_11Interpreter11read_memory12AccessOffsetB1W_EEB1r_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1X_E6as_refBc_ Line | Count | Source | 587 | 9.19k | fn as_ref(&self) -> &[u8] { | 588 | 9.19k | match self { | 589 | 2.13k | Three::A(a) => a.as_ref(), | 590 | 8 | Three::B(b) => b.as_ref(), | 591 | 7.05k | Three::C(c) => c.as_ref(), | 592 | | } | 593 | 9.19k | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refCsDDUKWWCHAU_18smoldot_light_wasm _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refBc_ Line | Count | Source | 587 | 84 | fn as_ref(&self) -> &[u8] { | 588 | 84 | match self { | 589 | 84 | Three::A(a) => a.as_ref(), | 590 | 0 | Three::B(b) => b.as_ref(), | 591 | 0 | Three::C(c) => c.as_ref(), | 592 | | } | 593 | 84 | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refCsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refCsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refCscDgN54JpMGG_6author Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB1Y_E6as_refCsibGXYHQB8Ea_25json_rpc_general_requests |
594 | 9.27k | } |
595 | 9.27k | |
596 | 9.27k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
597 | 2.22k | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), |
598 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), |
599 | 7.05k | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { |
600 | 7.05k | // TODO: optimize? |
601 | 49.3k | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { |
602 | 49.3k | a.extend_from_slice(b.as_ref()); |
603 | 49.3k | a |
604 | 49.3k | }); _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_10StorageGet3key0Bb_ Line | Count | Source | 601 | 49.3k | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 602 | 49.3k | a.extend_from_slice(b.as_ref()); | 603 | 49.3k | a | 604 | 49.3k | }); |
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_10StorageGet3key0Bb_ |
605 | 7.05k | debug_assert_eq!(key_nibbles.len() % 2, 0); |
606 | 7.05k | Three::C( |
607 | 7.05k | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) |
608 | 7.05k | .collect::<Vec<_>>(), |
609 | 7.05k | ) |
610 | | } |
611 | | |
612 | | // We only create a `StorageGet` if the state is one of the above. |
613 | 0 | _ => unreachable!(), |
614 | | } |
615 | 9.27k | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_10StorageGet3key Line | Count | Source | 579 | 9.19k | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 580 | 9.19k | enum Three<A, B, C> { | 581 | 9.19k | A(A), | 582 | 9.19k | B(B), | 583 | 9.19k | C(C), | 584 | 9.19k | } | 585 | 9.19k | | 586 | 9.19k | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 587 | 9.19k | fn as_ref(&self) -> &[u8] { | 588 | 9.19k | match self { | 589 | 9.19k | Three::A(a) => a.as_ref(), | 590 | 9.19k | Three::B(b) => b.as_ref(), | 591 | 9.19k | Three::C(c) => c.as_ref(), | 592 | 9.19k | } | 593 | 9.19k | } | 594 | 9.19k | } | 595 | 9.19k | | 596 | 9.19k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 597 | 2.13k | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), | 598 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), | 599 | 7.05k | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 600 | 7.05k | // TODO: optimize? | 601 | 7.05k | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 602 | | a.extend_from_slice(b.as_ref()); | 603 | | a | 604 | 7.05k | }); | 605 | 7.05k | debug_assert_eq!(key_nibbles.len() % 2, 0); | 606 | 7.05k | Three::C( | 607 | 7.05k | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) | 608 | 7.05k | .collect::<Vec<_>>(), | 609 | 7.05k | ) | 610 | | } | 611 | | | 612 | | // We only create a `StorageGet` if the state is one of the above. | 613 | 0 | _ => unreachable!(), | 614 | | } | 615 | 9.19k | } |
_RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_10StorageGet3key Line | Count | Source | 579 | 84 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 580 | 84 | enum Three<A, B, C> { | 581 | 84 | A(A), | 582 | 84 | B(B), | 583 | 84 | C(C), | 584 | 84 | } | 585 | 84 | | 586 | 84 | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 587 | 84 | fn as_ref(&self) -> &[u8] { | 588 | 84 | match self { | 589 | 84 | Three::A(a) => a.as_ref(), | 590 | 84 | Three::B(b) => b.as_ref(), | 591 | 84 | Three::C(c) => c.as_ref(), | 592 | 84 | } | 593 | 84 | } | 594 | 84 | } | 595 | 84 | | 596 | 84 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 597 | 84 | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), | 598 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), | 599 | 0 | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 600 | 0 | // TODO: optimize? | 601 | 0 | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 602 | | a.extend_from_slice(b.as_ref()); | 603 | | a | 604 | 0 | }); | 605 | 0 | debug_assert_eq!(key_nibbles.len() % 2, 0); | 606 | 0 | Three::C( | 607 | 0 | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) | 608 | 0 | .collect::<Vec<_>>(), | 609 | 0 | ) | 610 | | } | 611 | | | 612 | | // We only create a `StorageGet` if the state is one of the above. | 613 | 0 | _ => unreachable!(), | 614 | | } | 615 | 84 | } |
|
616 | | |
617 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
618 | 449 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
619 | 449 | enum Three<A, B, C> { |
620 | 449 | A(A), |
621 | 449 | B(B), |
622 | 449 | C(C), |
623 | 449 | } |
624 | 449 | |
625 | 449 | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
626 | 449 | fn as_ref(&self) -> &[u8] { |
627 | 11 | match self { |
628 | 449 | Three::A(a) => a.as_ref()6 , |
629 | 449 | Three::B(b) => b.as_ref()0 , |
630 | 449 | Three::C(c) => c.as_ref()5 , |
631 | 449 | } |
632 | 449 | }11 _RNvXNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2g_11Interpreter11read_memory12AccessOffsetB24_EEB24_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB25_E6as_refBc_ Line | Count | Source | 626 | 11 | fn as_ref(&self) -> &[u8] { | 627 | 11 | match self { | 628 | 6 | Three::A(a) => a.as_ref(), | 629 | 0 | Three::B(b) => b.as_ref(), | 630 | 5 | Three::C(c) => c.as_ref(), | 631 | | } | 632 | 11 | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB26_E6as_refCsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNvXININvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBb_10StorageGet10child_trie0pppEINtB5_5ThreepppEINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_refBf_ Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB26_E6as_refCsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB26_E6as_refCsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB26_E6as_refCscDgN54JpMGG_6author Unexecuted instantiation: _RNvXNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsdZExvAaxgia_5alloc3vec3VechEEINtNtCsaYZPK01V26L_4core7convert5AsRefB26_E6as_refCsibGXYHQB8Ea_25json_rpc_general_requests |
633 | 449 | } |
634 | 449 | |
635 | 449 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
636 | 124 | (host::HostVm::ExternalStorageGet(req), None) => req.child_trie().map(Three::A), |
637 | 7 | (host::HostVm::ExternalStorageAppend(req), None) => req.child_trie().map(Three::B), |
638 | 318 | (_, Some((child_trie, trie_root_calculator::InProgress::StorageValue(_)))) => { |
639 | 318 | child_trie.as_ref().map(Three::C) |
640 | | } |
641 | | // We only create a `StorageGet` if the state is one of the above. |
642 | 0 | _ => unreachable!(), |
643 | | } |
644 | 449 | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_10StorageGet10child_trie Line | Count | Source | 618 | 449 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 619 | 449 | enum Three<A, B, C> { | 620 | 449 | A(A), | 621 | 449 | B(B), | 622 | 449 | C(C), | 623 | 449 | } | 624 | 449 | | 625 | 449 | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 626 | 449 | fn as_ref(&self) -> &[u8] { | 627 | 449 | match self { | 628 | 449 | Three::A(a) => a.as_ref(), | 629 | 449 | Three::B(b) => b.as_ref(), | 630 | 449 | Three::C(c) => c.as_ref(), | 631 | 449 | } | 632 | 449 | } | 633 | 449 | } | 634 | 449 | | 635 | 449 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 636 | 124 | (host::HostVm::ExternalStorageGet(req), None) => req.child_trie().map(Three::A), | 637 | 7 | (host::HostVm::ExternalStorageAppend(req), None) => req.child_trie().map(Three::B), | 638 | 318 | (_, Some((child_trie, trie_root_calculator::InProgress::StorageValue(_)))) => { | 639 | 318 | child_trie.as_ref().map(Three::C) | 640 | | } | 641 | | // We only create a `StorageGet` if the state is one of the above. | 642 | 0 | _ => unreachable!(), | 643 | | } | 644 | 449 | } |
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_10StorageGet10child_trie |
645 | | |
646 | | /// Injects the corresponding storage value. |
647 | 697 | pub fn inject_value( |
648 | 697 | mut self, |
649 | 697 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, |
650 | 697 | ) -> RuntimeCall { |
651 | 697 | // TODO: update the implementation to not require the folding here |
652 | 697 | let value = value.map(|(value, version)| { |
653 | 486 | let value = value.fold(Vec::new(), |mut a, b| { |
654 | 486 | a.extend_from_slice(b.as_ref()); |
655 | 486 | a |
656 | 486 | }); _RNCNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EE00Be_ Line | Count | Source | 653 | 402 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | 402 | a.extend_from_slice(b.as_ref()); | 655 | 402 | a | 656 | 402 | }); |
Unexecuted instantiation: _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00CsDDUKWWCHAU_18smoldot_light_wasm _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00Be_ Line | Count | Source | 653 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | 42 | a.extend_from_slice(b.as_ref()); | 655 | 42 | a | 656 | 42 | }); |
_RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00Be_ Line | Count | Source | 653 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | 42 | a.extend_from_slice(b.as_ref()); | 655 | 42 | a | 656 | 42 | }); |
Unexecuted instantiation: _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00CscDgN54JpMGG_6author Unexecuted instantiation: _RNCNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE00CsibGXYHQB8Ea_25json_rpc_general_requests |
657 | 486 | (value, version) |
658 | 697 | }); _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1p_EE0Bc_ Line | Count | Source | 652 | 402 | let value = value.map(|(value, version)| { | 653 | 402 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | 402 | }); | 657 | 402 | (value, version) | 658 | 402 | }); |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0CsDDUKWWCHAU_18smoldot_light_wasm _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0Bc_ Line | Count | Source | 652 | 42 | let value = value.map(|(value, version)| { | 653 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | 42 | }); | 657 | 42 | (value, version) | 658 | 42 | }); |
_RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0Bc_ Line | Count | Source | 652 | 42 | let value = value.map(|(value, version)| { | 653 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | 42 | }); | 657 | 42 | (value, version) | 658 | 42 | }); |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EE0CsibGXYHQB8Ea_25json_rpc_general_requests |
659 | 697 | |
660 | 697 | match (self.inner.vm, self.inner.root_calculation.take()) { |
661 | 251 | (host::HostVm::ExternalStorageGet(req), None) => { |
662 | 251 | // TODO: should actually report the offset and max_size in the API |
663 | 251 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..]177 )); _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1p_EEs_0Bc_ Line | Count | Source | 663 | 93 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0CsDDUKWWCHAU_18smoldot_light_wasm _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0Bc_ Line | Count | Source | 663 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
_RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0Bc_ Line | Count | Source | 663 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs_0CsibGXYHQB8Ea_25json_rpc_general_requests |
664 | 251 | } |
665 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => { |
666 | 8 | // TODO: could be less overhead? |
667 | 8 | let trie = self |
668 | 8 | .inner |
669 | 8 | .pending_storage_changes |
670 | 8 | .trie_diffs |
671 | 8 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec()0 )) Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueppEs0_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueppEs0_0Bc_ |
672 | 8 | .or_insert(storage_diff::TrieDiff::empty()); |
673 | 8 | |
674 | 8 | // TODO: could be less overhead? |
675 | 8 | let mut value = value.map(|(v, _)| v1 ).unwrap_or_default(); _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1p_EEs1_0Bc_ Line | Count | Source | 675 | 1 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs1_0CsibGXYHQB8Ea_25json_rpc_general_requests |
676 | 8 | append_to_storage_value(&mut value, req.value().as_ref()); |
677 | 8 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); |
678 | 8 | |
679 | 8 | self.inner.vm = req.resume(); |
680 | 8 | } |
681 | 438 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { |
682 | 438 | self.inner.vm = vm; |
683 | 438 | self.inner.root_calculation = Some(( |
684 | 438 | trie, |
685 | 438 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers)308 )), _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1p_EEs2_0Bc_ Line | Count | Source | 685 | 308 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), |
Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEs2_0CsibGXYHQB8Ea_25json_rpc_general_requests |
686 | 438 | )); |
687 | 438 | } |
688 | | |
689 | | // We only create a `StorageGet` if the state is one of the above. |
690 | 0 | _ => unreachable!(), |
691 | | }; |
692 | | |
693 | 697 | self.inner.run() |
694 | 697 | } _RINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1n_EEBa_ Line | Count | Source | 647 | 613 | pub fn inject_value( | 648 | 613 | mut self, | 649 | 613 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 650 | 613 | ) -> RuntimeCall { | 651 | 613 | // TODO: update the implementation to not require the folding here | 652 | 613 | let value = value.map(|(value, version)| { | 653 | | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | | }); | 657 | | (value, version) | 658 | 613 | }); | 659 | 613 | | 660 | 613 | match (self.inner.vm, self.inner.root_calculation.take()) { | 661 | 167 | (host::HostVm::ExternalStorageGet(req), None) => { | 662 | 167 | // TODO: should actually report the offset and max_size in the API | 663 | 167 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 664 | 167 | } | 665 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => { | 666 | 8 | // TODO: could be less overhead? | 667 | 8 | let trie = self | 668 | 8 | .inner | 669 | 8 | .pending_storage_changes | 670 | 8 | .trie_diffs | 671 | 8 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 672 | 8 | .or_insert(storage_diff::TrieDiff::empty()); | 673 | 8 | | 674 | 8 | // TODO: could be less overhead? | 675 | 8 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 676 | 8 | append_to_storage_value(&mut value, req.value().as_ref()); | 677 | 8 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 678 | 8 | | 679 | 8 | self.inner.vm = req.resume(); | 680 | 8 | } | 681 | 438 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 682 | 438 | self.inner.vm = vm; | 683 | 438 | self.inner.root_calculation = Some(( | 684 | 438 | trie, | 685 | 438 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 686 | 438 | )); | 687 | 438 | } | 688 | | | 689 | | // We only create a `StorageGet` if the state is one of the above. | 690 | 0 | _ => unreachable!(), | 691 | | }; | 692 | | | 693 | 613 | self.inner.run() | 694 | 613 | } |
Unexecuted instantiation: _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EECsDDUKWWCHAU_18smoldot_light_wasm _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EEBa_ Line | Count | Source | 647 | 42 | pub fn inject_value( | 648 | 42 | mut self, | 649 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 650 | 42 | ) -> RuntimeCall { | 651 | 42 | // TODO: update the implementation to not require the folding here | 652 | 42 | let value = value.map(|(value, version)| { | 653 | | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | | }); | 657 | | (value, version) | 658 | 42 | }); | 659 | 42 | | 660 | 42 | match (self.inner.vm, self.inner.root_calculation.take()) { | 661 | 42 | (host::HostVm::ExternalStorageGet(req), None) => { | 662 | 42 | // TODO: should actually report the offset and max_size in the API | 663 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 664 | 42 | } | 665 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => { | 666 | 0 | // TODO: could be less overhead? | 667 | 0 | let trie = self | 668 | 0 | .inner | 669 | 0 | .pending_storage_changes | 670 | 0 | .trie_diffs | 671 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 672 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 673 | 0 |
| 674 | 0 | // TODO: could be less overhead? | 675 | 0 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 676 | 0 | append_to_storage_value(&mut value, req.value().as_ref()); | 677 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 678 | 0 |
| 679 | 0 | self.inner.vm = req.resume(); | 680 | 0 | } | 681 | 0 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 682 | 0 | self.inner.vm = vm; | 683 | 0 | self.inner.root_calculation = Some(( | 684 | 0 | trie, | 685 | 0 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 686 | 0 | )); | 687 | 0 | } | 688 | | | 689 | | // We only create a `StorageGet` if the state is one of the above. | 690 | 0 | _ => unreachable!(), | 691 | | }; | 692 | | | 693 | 42 | self.inner.run() | 694 | 42 | } |
_RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EEBa_ Line | Count | Source | 647 | 42 | pub fn inject_value( | 648 | 42 | mut self, | 649 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 650 | 42 | ) -> RuntimeCall { | 651 | 42 | // TODO: update the implementation to not require the folding here | 652 | 42 | let value = value.map(|(value, version)| { | 653 | | let value = value.fold(Vec::new(), |mut a, b| { | 654 | | a.extend_from_slice(b.as_ref()); | 655 | | a | 656 | | }); | 657 | | (value, version) | 658 | 42 | }); | 659 | 42 | | 660 | 42 | match (self.inner.vm, self.inner.root_calculation.take()) { | 661 | 42 | (host::HostVm::ExternalStorageGet(req), None) => { | 662 | 42 | // TODO: should actually report the offset and max_size in the API | 663 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 664 | 42 | } | 665 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => { | 666 | 0 | // TODO: could be less overhead? | 667 | 0 | let trie = self | 668 | 0 | .inner | 669 | 0 | .pending_storage_changes | 670 | 0 | .trie_diffs | 671 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 672 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 673 | 0 |
| 674 | 0 | // TODO: could be less overhead? | 675 | 0 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 676 | 0 | append_to_storage_value(&mut value, req.value().as_ref()); | 677 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 678 | 0 |
| 679 | 0 | self.inner.vm = req.resume(); | 680 | 0 | } | 681 | 0 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 682 | 0 | self.inner.vm = vm; | 683 | 0 | self.inner.root_calculation = Some(( | 684 | 0 | trie, | 685 | 0 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 686 | 0 | )); | 687 | 0 | } | 688 | | | 689 | | // We only create a `StorageGet` if the state is one of the above. | 690 | 0 | _ => unreachable!(), | 691 | | }; | 692 | | | 693 | 42 | self.inner.run() | 694 | 42 | } |
Unexecuted instantiation: _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EECsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1o_EECsibGXYHQB8Ea_25json_rpc_general_requests |
695 | | } |
696 | | |
697 | | /// Fetching the key that follows a given one is required in order to continue. |
698 | | #[must_use] |
699 | | pub struct NextKey { |
700 | | inner: Inner, |
701 | | |
702 | | /// If `Some`, ask for the key inside of this field rather than the one of `inner`. |
703 | | key_overwrite: Option<Vec<u8>>, |
704 | | |
705 | | /// Number of keys removed. Used only to implement clearing a prefix, otherwise stays at 0. |
706 | | keys_removed_so_far: u32, |
707 | | } |
708 | | |
709 | | impl NextKey { |
710 | | /// Returns the key whose next key must be passed back. |
711 | 16.4k | pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
712 | 16.4k | if let Some(key_overwrite15 ) = &self.key_overwrite { |
713 | 15 | return either::Left(trie::bytes_to_nibbles(key_overwrite.iter().copied())); |
714 | 16.4k | } |
715 | 16.4k | |
716 | 16.4k | either::Right( |
717 | 16.4k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
718 | 1 | (host::HostVm::ExternalStorageNextKey(req), _) => { |
719 | 1 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.key()))) |
720 | | } |
721 | | |
722 | 16.4k | (_, Some((_, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { |
723 | 16.4k | either::Right(req.key().flat_map(util::as_ref_iter)) |
724 | | } |
725 | | |
726 | | // Note that in the case `ExternalStorageClearPrefix`, `key_overwrite` is |
727 | | // always `Some`. |
728 | 0 | _ => unreachable!(), |
729 | | }, |
730 | | ) |
731 | 16.4k | } _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7NextKey3key Line | Count | Source | 711 | 16.4k | pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ { | 712 | 16.4k | if let Some(key_overwrite15 ) = &self.key_overwrite { | 713 | 15 | return either::Left(trie::bytes_to_nibbles(key_overwrite.iter().copied())); | 714 | 16.4k | } | 715 | 16.4k | | 716 | 16.4k | either::Right( | 717 | 16.4k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 718 | 1 | (host::HostVm::ExternalStorageNextKey(req), _) => { | 719 | 1 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.key()))) | 720 | | } | 721 | | | 722 | 16.4k | (_, Some((_, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { | 723 | 16.4k | either::Right(req.key().flat_map(util::as_ref_iter)) | 724 | | } | 725 | | | 726 | | // Note that in the case `ExternalStorageClearPrefix`, `key_overwrite` is | 727 | | // always `Some`. | 728 | 0 | _ => unreachable!(), | 729 | | }, | 730 | | ) | 731 | 16.4k | } |
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7NextKey3key |
732 | | |
733 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
734 | 12.9k | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
735 | 12.9k | enum Three<A, B, C> { |
736 | 12.9k | A(A), |
737 | 12.9k | B(B), |
738 | 12.9k | C(C), |
739 | 12.9k | } |
740 | 12.9k | |
741 | 12.9k | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
742 | 12.9k | fn as_ref(&self) -> &[u8] { |
743 | 144 | match self { |
744 | 12.9k | Three::A(a) => a.as_ref()0 , |
745 | 12.9k | Three::B(b) => b.as_ref()140 , |
746 | 12.9k | Three::C(c) => c.as_ref()4 , |
747 | 12.9k | } |
748 | 12.9k | }144 _RNvXNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2c_11Interpreter11read_memory12AccessOffsetB20_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1v_EINtNtCsaYZPK01V26L_4core7convert5AsRefB21_E6as_refBc_ Line | Count | Source | 742 | 144 | fn as_ref(&self) -> &[u8] { | 743 | 144 | match self { | 744 | 0 | Three::A(a) => a.as_ref(), | 745 | 140 | Three::B(b) => b.as_ref(), | 746 | 4 | Three::C(c) => c.as_ref(), | 747 | | } | 748 | 144 | } |
Unexecuted instantiation: _RNvXNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1w_EINtNtCsaYZPK01V26L_4core7convert5AsRefB22_E6as_refCsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNvXININvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtBb_7NextKey10child_trie0pppEINtB5_5ThreepppEINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_refBf_ Unexecuted instantiation: _RNvXNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1w_EINtNtCsaYZPK01V26L_4core7convert5AsRefB22_E6as_refCsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1w_EINtNtCsaYZPK01V26L_4core7convert5AsRefB22_E6as_refCsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNvXNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1w_EINtNtCsaYZPK01V26L_4core7convert5AsRefB22_E6as_refCscDgN54JpMGG_6author Unexecuted instantiation: _RNvXNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsdZExvAaxgia_5alloc3vec3VechEB1w_EINtNtCsaYZPK01V26L_4core7convert5AsRefB22_E6as_refCsibGXYHQB8Ea_25json_rpc_general_requests |
749 | 12.9k | } |
750 | 12.9k | |
751 | 12.9k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
752 | 2 | (host::HostVm::ExternalStorageNextKey(req), _) => req.child_trie().map(Three::A), |
753 | 12.9k | (_, Some((child_trie, _))) => child_trie.as_ref().map(Three::B), |
754 | 28 | (host::HostVm::ExternalStorageClearPrefix(req), _) => req.child_trie().map(Three::C), |
755 | 0 | _ => unreachable!(), |
756 | | } |
757 | 12.9k | } _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7NextKey10child_trie Line | Count | Source | 734 | 12.9k | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 735 | 12.9k | enum Three<A, B, C> { | 736 | 12.9k | A(A), | 737 | 12.9k | B(B), | 738 | 12.9k | C(C), | 739 | 12.9k | } | 740 | 12.9k | | 741 | 12.9k | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 742 | 12.9k | fn as_ref(&self) -> &[u8] { | 743 | 12.9k | match self { | 744 | 12.9k | Three::A(a) => a.as_ref(), | 745 | 12.9k | Three::B(b) => b.as_ref(), | 746 | 12.9k | Three::C(c) => c.as_ref(), | 747 | 12.9k | } | 748 | 12.9k | } | 749 | 12.9k | } | 750 | 12.9k | | 751 | 12.9k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 752 | 2 | (host::HostVm::ExternalStorageNextKey(req), _) => req.child_trie().map(Three::A), | 753 | 12.9k | (_, Some((child_trie, _))) => child_trie.as_ref().map(Three::B), | 754 | 28 | (host::HostVm::ExternalStorageClearPrefix(req), _) => req.child_trie().map(Three::C), | 755 | 0 | _ => unreachable!(), | 756 | | } | 757 | 12.9k | } |
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7NextKey10child_trie |
758 | | |
759 | | /// If `true`, then the provided value must the one superior or equal to the requested key. |
760 | | /// If `false`, then the provided value must be strictly superior to the requested key. |
761 | 8.25k | pub fn or_equal(&self) -> bool { |
762 | 8.25k | (matches!8.23k (self.inner.vm, host::HostVm::ExternalStorageClearPrefix(_)) |
763 | 15 | && self.keys_removed_so_far == 0) |
764 | 8.24k | || self.inner.root_calculation.is_some() |
765 | 8.25k | } _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7NextKey8or_equal Line | Count | Source | 761 | 8.25k | pub fn or_equal(&self) -> bool { | 762 | 8.25k | (matches!8.23k (self.inner.vm, host::HostVm::ExternalStorageClearPrefix(_)) | 763 | 15 | && self.keys_removed_so_far == 0) | 764 | 8.24k | || self.inner.root_calculation.is_some() | 765 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7NextKey8or_equal |
766 | | |
767 | | /// If `true`, then the search must include both branch nodes and storage nodes. If `false`, |
768 | | /// the search only covers storage nodes. |
769 | 8.25k | pub fn branch_nodes(&self) -> bool { |
770 | 8.25k | self.inner.root_calculation.is_some() |
771 | 8.25k | } _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7NextKey12branch_nodes Line | Count | Source | 769 | 8.25k | pub fn branch_nodes(&self) -> bool { | 770 | 8.25k | self.inner.root_calculation.is_some() | 771 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7NextKey12branch_nodes |
772 | | |
773 | | /// Returns the prefix the next key must start with. If the next key doesn't start with the |
774 | | /// given prefix, then `None` should be provided. |
775 | 8.25k | pub fn prefix(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
776 | 8.25k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
777 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), _) => { |
778 | 15 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.prefix()))) |
779 | | } |
780 | 8.23k | (_, Some(_)) => either::Right(either::Left(self.key())), |
781 | 1 | _ => either::Right(either::Right(iter::empty())), |
782 | | } |
783 | 8.25k | } _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7NextKey6prefix Line | Count | Source | 775 | 8.25k | pub fn prefix(&'_ self) -> impl Iterator<Item = Nibble> + '_ { | 776 | 8.25k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 777 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), _) => { | 778 | 15 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.prefix()))) | 779 | | } | 780 | 8.23k | (_, Some(_)) => either::Right(either::Left(self.key())), | 781 | 1 | _ => either::Right(either::Right(iter::empty())), | 782 | | } | 783 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7NextKey6prefix |
784 | | |
785 | | /// Injects the key. |
786 | | /// |
787 | | /// # Panic |
788 | | /// |
789 | | /// Panics if the key passed as parameter isn't strictly superior to the requested key. |
790 | | /// Panics if the key passed as parameter doesn't start with the requested prefix. |
791 | | /// |
792 | 8.25k | pub fn inject_key(mut self, key: Option<impl Iterator<Item = Nibble>>) -> RuntimeCall { |
793 | 8.25k | match (self.inner.vm, self.inner.root_calculation.take()) { |
794 | 1 | (host::HostVm::ExternalStorageNextKey(req), None) => { |
795 | 1 | let key = |
796 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); Unexecuted instantiation: _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsdZExvAaxgia_5alloc3vec3VechEEE0Bc_ _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterE0Bc_ Line | Count | Source | 796 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); |
Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEE0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEE0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EE0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsiUjFBJteJ7x_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EE0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEE0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0CsibGXYHQB8Ea_25json_rpc_general_requests |
797 | 1 | |
798 | 1 | let trie = self |
799 | 1 | .inner |
800 | 1 | .pending_storage_changes |
801 | 1 | .trie_diffs |
802 | 1 | .get(&req.child_trie().map(|ct| ct.as_ref().to_owned()0 )); // TODO: overhead Unexecuted instantiation: _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsdZExvAaxgia_5alloc3vec3VechEEEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsiUjFBJteJ7x_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0CsibGXYHQB8Ea_25json_rpc_general_requests |
803 | 1 | |
804 | 1 | let empty = storage_diff::TrieDiff::empty(); // TODO: weird |
805 | 1 | let search = { |
806 | 1 | let req_key = req.key(); |
807 | 1 | let requested_key = if let Some(key_overwrite0 ) = &self.key_overwrite { |
808 | 0 | &key_overwrite[..] |
809 | | } else { |
810 | 1 | req_key.as_ref() |
811 | | }; |
812 | | // TODO: this code is a bit weird |
813 | 1 | trie.unwrap_or(&empty) |
814 | 1 | .storage_next_key(requested_key, key.as_deref(), false) |
815 | 1 | }; |
816 | 1 | |
817 | 1 | match search { |
818 | 1 | storage_diff::StorageNextKey::Found(k) => { |
819 | 1 | self.inner.vm = req.resume(k); |
820 | 1 | } |
821 | 0 | storage_diff::StorageNextKey::NextOf(next) => { |
822 | 0 | let key_overwrite = Some(next.to_owned()); |
823 | 0 | self.inner.vm = host::HostVm::ExternalStorageNextKey(req); |
824 | 0 | return RuntimeCall::NextKey(NextKey { |
825 | 0 | inner: self.inner, |
826 | 0 | key_overwrite, |
827 | 0 | keys_removed_so_far: 0, |
828 | 0 | }); |
829 | | } |
830 | | } |
831 | | } |
832 | | |
833 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), None) => { |
834 | | // TODO: there's some trickiness regarding the behavior w.r.t keys only in the overlay; figure out |
835 | | |
836 | 15 | if let Some(key9 ) = key { |
837 | 9 | let key = trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>(); |
838 | 9 | assert!(key.starts_with(req.prefix().as_ref())); |
839 | | |
840 | | // TODO: /!\ must clear keys from overlay as well |
841 | | |
842 | 9 | if req |
843 | 9 | .max_keys_to_remove() |
844 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) Unexecuted instantiation: _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsdZExvAaxgia_5alloc3vec3VechEEEs0_0Bc_ _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs0_0Bc_ Line | Count | Source | 844 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) |
Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs0_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs0_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs0_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsiUjFBJteJ7x_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs0_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests |
845 | 0 | { |
846 | 0 | self.inner.vm = req.resume(self.keys_removed_so_far, true); |
847 | 0 | } else { |
848 | | // TODO: overhead |
849 | 9 | let trie = self |
850 | 9 | .inner |
851 | 9 | .pending_storage_changes |
852 | 9 | .trie_diffs |
853 | 9 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec()1 )) Unexecuted instantiation: _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsdZExvAaxgia_5alloc3vec3VechEEEs1_0Bc_ _RNCINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs1_0Bc_ Line | Count | Source | 853 | 1 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs1_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs1_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs1_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs1_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsiUjFBJteJ7x_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs1_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs1_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEEs1_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0CsibGXYHQB8Ea_25json_rpc_general_requests |
854 | 9 | .or_insert(storage_diff::TrieDiff::empty()); |
855 | 9 | |
856 | 9 | trie.diff_insert_erase(key.clone(), ()); |
857 | 9 | self.keys_removed_so_far += 1; |
858 | 9 | self.key_overwrite = Some(key); // TODO: might be expensive if lots of keys |
859 | 9 | self.inner.vm = req.into(); |
860 | 9 | |
861 | 9 | return RuntimeCall::NextKey(self); |
862 | | } |
863 | 6 | } else { |
864 | 6 | self.inner.vm = req.resume(self.keys_removed_so_far, false); |
865 | 6 | } |
866 | | } |
867 | | |
868 | 8.23k | (vm, Some((trie, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { |
869 | 8.23k | self.inner.vm = vm; |
870 | 8.23k | self.inner.root_calculation = Some((trie, req.inject(key))); |
871 | 8.23k | } |
872 | | |
873 | | // We only create a `NextKey` if the state is one of the above. |
874 | 0 | _ => unreachable!(), |
875 | | }; |
876 | | |
877 | 8.24k | self.inner.run() |
878 | 8.25k | } Unexecuted instantiation: _RINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtCsdZExvAaxgia_5alloc3vec3VechEEEBa_ _RINvMs7_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyNtNtNtBa_4trie13branch_search21BranchTrieNodeKeyIterEBa_ Line | Count | Source | 792 | 8.25k | pub fn inject_key(mut self, key: Option<impl Iterator<Item = Nibble>>) -> RuntimeCall { | 793 | 8.25k | match (self.inner.vm, self.inner.root_calculation.take()) { | 794 | 1 | (host::HostVm::ExternalStorageNextKey(req), None) => { | 795 | 1 | let key = | 796 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); | 797 | 1 | | 798 | 1 | let trie = self | 799 | 1 | .inner | 800 | 1 | .pending_storage_changes | 801 | 1 | .trie_diffs | 802 | 1 | .get(&req.child_trie().map(|ct| ct.as_ref().to_owned())); // TODO: overhead | 803 | 1 | | 804 | 1 | let empty = storage_diff::TrieDiff::empty(); // TODO: weird | 805 | 1 | let search = { | 806 | 1 | let req_key = req.key(); | 807 | 1 | let requested_key = if let Some(key_overwrite0 ) = &self.key_overwrite { | 808 | 0 | &key_overwrite[..] | 809 | | } else { | 810 | 1 | req_key.as_ref() | 811 | | }; | 812 | | // TODO: this code is a bit weird | 813 | 1 | trie.unwrap_or(&empty) | 814 | 1 | .storage_next_key(requested_key, key.as_deref(), false) | 815 | 1 | }; | 816 | 1 | | 817 | 1 | match search { | 818 | 1 | storage_diff::StorageNextKey::Found(k) => { | 819 | 1 | self.inner.vm = req.resume(k); | 820 | 1 | } | 821 | 0 | storage_diff::StorageNextKey::NextOf(next) => { | 822 | 0 | let key_overwrite = Some(next.to_owned()); | 823 | 0 | self.inner.vm = host::HostVm::ExternalStorageNextKey(req); | 824 | 0 | return RuntimeCall::NextKey(NextKey { | 825 | 0 | inner: self.inner, | 826 | 0 | key_overwrite, | 827 | 0 | keys_removed_so_far: 0, | 828 | 0 | }); | 829 | | } | 830 | | } | 831 | | } | 832 | | | 833 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), None) => { | 834 | | // TODO: there's some trickiness regarding the behavior w.r.t keys only in the overlay; figure out | 835 | | | 836 | 15 | if let Some(key9 ) = key { | 837 | 9 | let key = trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>(); | 838 | 9 | assert!(key.starts_with(req.prefix().as_ref())); | 839 | | | 840 | | // TODO: /!\ must clear keys from overlay as well | 841 | | | 842 | 9 | if req | 843 | 9 | .max_keys_to_remove() | 844 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) | 845 | 0 | { | 846 | 0 | self.inner.vm = req.resume(self.keys_removed_so_far, true); | 847 | 0 | } else { | 848 | | // TODO: overhead | 849 | 9 | let trie = self | 850 | 9 | .inner | 851 | 9 | .pending_storage_changes | 852 | 9 | .trie_diffs | 853 | 9 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 854 | 9 | .or_insert(storage_diff::TrieDiff::empty()); | 855 | 9 | | 856 | 9 | trie.diff_insert_erase(key.clone(), ()); | 857 | 9 | self.keys_removed_so_far += 1; | 858 | 9 | self.key_overwrite = Some(key); // TODO: might be expensive if lots of keys | 859 | 9 | self.inner.vm = req.into(); | 860 | 9 | | 861 | 9 | return RuntimeCall::NextKey(self); | 862 | | } | 863 | 6 | } else { | 864 | 6 | self.inner.vm = req.resume(self.keys_removed_so_far, false); | 865 | 6 | } | 866 | | } | 867 | | | 868 | 8.23k | (vm, Some((trie, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { | 869 | 8.23k | self.inner.vm = vm; | 870 | 8.23k | self.inner.root_calculation = Some((trie, req.inject(key))); | 871 | 8.23k | } | 872 | | | 873 | | // We only create a `NextKey` if the state is one of the above. | 874 | 0 | _ => unreachable!(), | 875 | | }; | 876 | | | 877 | 8.24k | self.inner.run() | 878 | 8.25k | } |
Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterRShEECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBa_8database11full_sqliteNtB33_18SqliteFullDatabase20to_chain_informations_00EEBa_ Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsiUjFBJteJ7x_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEB38_ Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RINvMs7_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsiUjFBJteJ7x_17smoldot_full_node17consensus_service12runtime_call0s7_00EECsibGXYHQB8Ea_25json_rpc_general_requests |
879 | | } |
880 | | |
881 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order to |
882 | | /// continue. |
883 | | #[must_use] |
884 | | pub struct ClosestDescendantMerkleValue { |
885 | | inner: Inner, |
886 | | } |
887 | | |
888 | | impl ClosestDescendantMerkleValue { |
889 | | /// Returns the key whose closest descendant Merkle value must be passed to |
890 | | /// [`ClosestDescendantMerkleValue::inject_merkle_value`]. |
891 | 0 | pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
892 | 0 | let (_, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
893 | 0 | self.inner.root_calculation.as_ref().unwrap() |
894 | | else { |
895 | 0 | unreachable!() |
896 | | }; |
897 | 0 | request.key().flat_map(util::as_ref_iter) |
898 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue3key Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue3key |
899 | | |
900 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
901 | 0 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
902 | 0 | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(_)) = |
903 | 0 | self.inner.root_calculation.as_ref().unwrap() |
904 | | else { |
905 | 0 | unreachable!() |
906 | | }; |
907 | 0 | trie.as_ref() |
908 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue10child_trie Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue10child_trie |
909 | | |
910 | | /// Indicate that the value is unknown and resume the calculation. |
911 | | /// |
912 | | /// This function be used if you are unaware of the Merkle value. The algorithm will perform |
913 | | /// the calculation of this Merkle value manually, which takes more time. |
914 | 6.77k | pub fn resume_unknown(mut self) -> RuntimeCall { |
915 | 6.77k | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
916 | 6.77k | self.inner.root_calculation.take().unwrap() |
917 | | else { |
918 | 0 | unreachable!() |
919 | | }; |
920 | | |
921 | 6.77k | self.inner.root_calculation = Some((trie, request.resume_unknown())); |
922 | 6.77k | self.inner.run() |
923 | 6.77k | } _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue14resume_unknown Line | Count | Source | 914 | 6.77k | pub fn resume_unknown(mut self) -> RuntimeCall { | 915 | 6.77k | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = | 916 | 6.77k | self.inner.root_calculation.take().unwrap() | 917 | | else { | 918 | 0 | unreachable!() | 919 | | }; | 920 | | | 921 | 6.77k | self.inner.root_calculation = Some((trie, request.resume_unknown())); | 922 | 6.77k | self.inner.run() | 923 | 6.77k | } |
Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue14resume_unknown |
924 | | |
925 | | /// Injects the corresponding Merkle value. |
926 | | /// |
927 | | /// `None` can be passed if there is no descendant or, in the case of a child trie read, in |
928 | | /// order to indicate that the child trie does not exist. |
929 | 0 | pub fn inject_merkle_value(mut self, merkle_value: Option<&[u8]>) -> RuntimeCall { |
930 | 0 | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
931 | 0 | self.inner.root_calculation.take().unwrap() |
932 | | else { |
933 | 0 | unreachable!() |
934 | | }; |
935 | | |
936 | 0 | self.inner.root_calculation = Some(( |
937 | 0 | trie, |
938 | 0 | match merkle_value { |
939 | 0 | Some(merkle_value) => request.inject_merkle_value(merkle_value), |
940 | | None => { |
941 | | // We don't properly handle the situation where there's no descendant or no child |
942 | | // trie. |
943 | 0 | request.resume_unknown() |
944 | | } |
945 | | }, |
946 | | )); |
947 | 0 | self.inner.run() |
948 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue19inject_merkle_value Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue19inject_merkle_value |
949 | | } |
950 | | |
951 | | /// Verifying whether a signature is correct is required in order to continue. |
952 | | #[must_use] |
953 | | pub struct SignatureVerification { |
954 | | inner: Inner, |
955 | | } |
956 | | |
957 | | impl SignatureVerification { |
958 | | /// Returns the message that the signature is expected to sign. |
959 | 0 | pub fn message(&'_ self) -> impl AsRef<[u8]> + '_ { |
960 | 0 | match self.inner.vm { |
961 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.message(), |
962 | 0 | _ => unreachable!(), |
963 | | } |
964 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification7message Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification7message |
965 | | |
966 | | /// Returns the signature. |
967 | | /// |
968 | | /// > **Note**: Be aware that this signature is untrusted input and might not be part of the |
969 | | /// > set of valid signatures. |
970 | 0 | pub fn signature(&'_ self) -> impl AsRef<[u8]> + '_ { |
971 | 0 | match self.inner.vm { |
972 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.signature(), |
973 | 0 | _ => unreachable!(), |
974 | | } |
975 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification9signature Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification9signature |
976 | | |
977 | | /// Returns the public key the signature is against. |
978 | | /// |
979 | | /// > **Note**: Be aware that this public key is untrusted input and might not be part of the |
980 | | /// > set of valid public keys. |
981 | 0 | pub fn public_key(&'_ self) -> impl AsRef<[u8]> + '_ { |
982 | 0 | match self.inner.vm { |
983 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.public_key(), |
984 | 0 | _ => unreachable!(), |
985 | | } |
986 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification10public_key Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification10public_key |
987 | | |
988 | | /// Verify the signature. Returns `true` if it is valid. |
989 | 0 | pub fn is_valid(&self) -> bool { |
990 | 0 | match self.inner.vm { |
991 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.is_valid(), |
992 | 0 | _ => unreachable!(), |
993 | | } |
994 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification8is_valid Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification8is_valid |
995 | | |
996 | | /// Verify the signature and resume execution. |
997 | 6 | pub fn verify_and_resume(mut self) -> RuntimeCall { |
998 | 6 | match self.inner.vm { |
999 | 6 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.verify_and_resume(), |
1000 | 0 | _ => unreachable!(), |
1001 | | } |
1002 | | |
1003 | 6 | self.inner.run() |
1004 | 6 | } _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification17verify_and_resume Line | Count | Source | 997 | 6 | pub fn verify_and_resume(mut self) -> RuntimeCall { | 998 | 6 | match self.inner.vm { | 999 | 6 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.verify_and_resume(), | 1000 | 0 | _ => unreachable!(), | 1001 | | } | 1002 | | | 1003 | 6 | self.inner.run() | 1004 | 6 | } |
Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification17verify_and_resume |
1005 | | |
1006 | | /// Resume the execution assuming that the signature is valid. |
1007 | | /// |
1008 | | /// > **Note**: You are strongly encouraged to call |
1009 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
1010 | | /// > used only in debugging situations. |
1011 | 0 | pub fn resume_success(mut self) -> RuntimeCall { |
1012 | 0 | match self.inner.vm { |
1013 | 0 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.resume_success(), |
1014 | 0 | _ => unreachable!(), |
1015 | | } |
1016 | | |
1017 | 0 | self.inner.run() |
1018 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification14resume_success Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification14resume_success |
1019 | | |
1020 | | /// Resume the execution assuming that the signature is invalid. |
1021 | | /// |
1022 | | /// > **Note**: You are strongly encouraged to call |
1023 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
1024 | | /// > used only in debugging situations. |
1025 | 0 | pub fn resume_failed(mut self) -> RuntimeCall { |
1026 | 0 | match self.inner.vm { |
1027 | 0 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.resume_failed(), |
1028 | 0 | _ => unreachable!(), |
1029 | | } |
1030 | | |
1031 | 0 | self.inner.run() |
1032 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_21SignatureVerification13resume_failed Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_21SignatureVerification13resume_failed |
1033 | | } |
1034 | | |
1035 | | /// Loading an offchain storage value is required in order to continue. |
1036 | | #[must_use] |
1037 | | pub struct OffchainStorageGet { |
1038 | | inner: Inner, |
1039 | | } |
1040 | | |
1041 | | impl OffchainStorageGet { |
1042 | | /// Returns the key whose value must be passed to [`OffchainStorageGet::inject_value`]. |
1043 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
1044 | 0 | match &self.inner.vm { |
1045 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => req.key(), |
1046 | | // We only create a `OffchainStorageGet` if the state is one of the above. |
1047 | 0 | _ => unreachable!(), |
1048 | | } |
1049 | 0 | } Unexecuted instantiation: _RNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_18OffchainStorageGet3key Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_18OffchainStorageGet3key |
1050 | | |
1051 | | /// Injects the corresponding storage value. |
1052 | 0 | pub fn inject_value(mut self, value: Option<impl AsRef<[u8]>>) -> RuntimeCall { |
1053 | 0 | match self.inner.vm { |
1054 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { |
1055 | 0 | self.inner.vm = req.resume(value.as_ref().map(|v| v.as_ref())); Unexecuted instantiation: _RNCINvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB8_18OffchainStorageGet12inject_valuepE0Bc_ Unexecuted instantiation: _RNCINvMsa_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB8_18OffchainStorageGet12inject_valuepE0Bc_ |
1056 | 0 | } |
1057 | | // We only create a `OffchainStorageGet` if the state is one of the above. |
1058 | 0 | _ => unreachable!(), |
1059 | | }; |
1060 | | |
1061 | 0 | self.inner.run() |
1062 | 0 | } Unexecuted instantiation: _RINvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB6_18OffchainStorageGet12inject_valuepEBa_ Unexecuted instantiation: _RINvMsa_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB6_18OffchainStorageGet12inject_valuepEBa_ |
1063 | | } |
1064 | | |
1065 | | /// Setting the value of an offchain storage value is required. |
1066 | | #[must_use] |
1067 | | pub struct OffchainStorageSet { |
1068 | | inner: Inner, |
1069 | | } |
1070 | | |
1071 | | impl OffchainStorageSet { |
1072 | | /// Returns the key whose value must be set. |
1073 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
1074 | 0 | match &self.inner.vm { |
1075 | | host::HostVm::Finished(_) => { |
1076 | 0 | self.inner |
1077 | 0 | .offchain_storage_changes |
1078 | 0 | .first_key_value() |
1079 | 0 | .unwrap() |
1080 | 0 | .0 |
1081 | | } |
1082 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1083 | 0 | _ => unreachable!(), |
1084 | | } |
1085 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet3key Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet3key |
1086 | | |
1087 | | /// Returns the value to set. |
1088 | | /// |
1089 | | /// If `None` is returned, the key should be removed from the storage entirely. |
1090 | 0 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
1091 | 0 | match &self.inner.vm { |
1092 | 0 | host::HostVm::Finished(_) => self |
1093 | 0 | .inner |
1094 | 0 | .offchain_storage_changes |
1095 | 0 | .first_key_value() |
1096 | 0 | .unwrap() |
1097 | 0 | .1 |
1098 | 0 | .as_ref(), |
1099 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1100 | 0 | _ => unreachable!(), |
1101 | | } |
1102 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet5value Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet5value |
1103 | | |
1104 | | /// Resumes execution after having set the value. |
1105 | 0 | pub fn resume(mut self) -> RuntimeCall { |
1106 | 0 | match self.inner.vm { |
1107 | 0 | host::HostVm::Finished(_) => { |
1108 | 0 | self.inner.offchain_storage_changes.pop_first(); |
1109 | 0 | } |
1110 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1111 | 0 | _ => unreachable!(), |
1112 | | }; |
1113 | | |
1114 | 0 | self.inner.run() |
1115 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet6resume Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet6resume |
1116 | | } |
1117 | | |
1118 | | /// Setting the value of an offchain storage value is required. |
1119 | | #[must_use] |
1120 | | pub struct OffchainStorageCompareSet { |
1121 | | inner: Inner, |
1122 | | } |
1123 | | |
1124 | | impl OffchainStorageCompareSet { |
1125 | | /// Returns the key whose value must be set. |
1126 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
1127 | 0 | match &self.inner.vm { |
1128 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => either::Left(req.key()), |
1129 | 0 | host::HostVm::Finished(_) => either::Right( |
1130 | 0 | self.inner |
1131 | 0 | .offchain_storage_changes |
1132 | 0 | .first_key_value() |
1133 | 0 | .unwrap() |
1134 | 0 | .0, |
1135 | 0 | ), |
1136 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1137 | 0 | _ => unreachable!(), |
1138 | | } |
1139 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet3key Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet3key |
1140 | | |
1141 | | /// Returns the value to set. |
1142 | | /// |
1143 | | /// If `None` is returned, the key should be removed from the storage entirely. |
1144 | 0 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
1145 | 0 | match &self.inner.vm { |
1146 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => req.value().map(either::Left), |
1147 | 0 | host::HostVm::Finished(_) => self |
1148 | 0 | .inner |
1149 | 0 | .offchain_storage_changes |
1150 | 0 | .first_key_value() |
1151 | 0 | .unwrap() |
1152 | 0 | .1 |
1153 | 0 | .as_ref() |
1154 | 0 | .map(either::Right), |
1155 | | |
1156 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1157 | 0 | _ => unreachable!(), |
1158 | | } |
1159 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet5value Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet5value |
1160 | | |
1161 | | /// Returns the value the current value should be compared against. The operation is a no-op if they don't compare equal. |
1162 | 0 | pub fn old_value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
1163 | 0 | match &self.inner.vm { |
1164 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => req.old_value(), |
1165 | 0 | host::HostVm::Finished(_) => None, |
1166 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1167 | 0 | _ => unreachable!(), |
1168 | | } |
1169 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet9old_value Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet9old_value |
1170 | | |
1171 | | /// Resumes execution after having set the value. Must indicate whether a value was written. |
1172 | 0 | pub fn resume(mut self, replaced: bool) -> RuntimeCall { |
1173 | 0 | match self.inner.vm { |
1174 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { |
1175 | 0 | self.inner.vm = req.resume(replaced); |
1176 | 0 | } |
1177 | 0 | host::HostVm::Finished(_) => { |
1178 | 0 | self.inner.offchain_storage_changes.pop_first(); |
1179 | 0 | } |
1180 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1181 | 0 | _ => unreachable!(), |
1182 | | }; |
1183 | | |
1184 | 0 | self.inner.run() |
1185 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet6resume Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet6resume |
1186 | | } |
1187 | | |
1188 | | /// Providing the current UNIX timestamp is required in order to continue. |
1189 | | #[must_use] |
1190 | | pub struct OffchainTimestamp { |
1191 | | inner: Inner, |
1192 | | } |
1193 | | |
1194 | | impl OffchainTimestamp { |
1195 | | /// Resume execution by providing the current UNIX timestamp. |
1196 | 0 | pub fn inject_timestamp(mut self, value: u64) -> RuntimeCall { |
1197 | 0 | match self.inner.vm { |
1198 | 0 | host::HostVm::OffchainTimestamp(req) => { |
1199 | 0 | self.inner.vm = req.resume(value); |
1200 | 0 | } |
1201 | | // We only create a `OffchainTimestamp` if the state is one of the above. |
1202 | 0 | _ => unreachable!(), |
1203 | | }; |
1204 | | |
1205 | 0 | self.inner.run() |
1206 | 0 | } Unexecuted instantiation: _RNvMsd_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_17OffchainTimestamp16inject_timestamp Unexecuted instantiation: _RNvMsd_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_17OffchainTimestamp16inject_timestamp |
1207 | | } |
1208 | | |
1209 | | /// Providing a random number is required in order to continue. |
1210 | | #[must_use] |
1211 | | pub struct OffchainRandomSeed { |
1212 | | inner: Inner, |
1213 | | } |
1214 | | |
1215 | | impl OffchainRandomSeed { |
1216 | | /// Resume execution by providing a random number. |
1217 | 0 | pub fn inject_random_seed(mut self, value: [u8; 32]) -> RuntimeCall { |
1218 | 0 | match self.inner.vm { |
1219 | 0 | host::HostVm::OffchainRandomSeed(req) => { |
1220 | 0 | self.inner.vm = req.resume(value); |
1221 | 0 | } |
1222 | | // We only create a `OffchainRandomSeed` if the state is one of the above. |
1223 | 0 | _ => unreachable!(), |
1224 | | }; |
1225 | | |
1226 | 0 | self.inner.run() |
1227 | 0 | } Unexecuted instantiation: _RNvMse_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_18OffchainRandomSeed18inject_random_seed Unexecuted instantiation: _RNvMse_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_18OffchainRandomSeed18inject_random_seed |
1228 | | } |
1229 | | |
1230 | | /// The runtime requests submitting a transaction. |
1231 | | #[must_use] |
1232 | | pub struct OffchainSubmitTransaction { |
1233 | | inner: Inner, |
1234 | | } |
1235 | | |
1236 | | impl OffchainSubmitTransaction { |
1237 | | /// Returns the SCALE-encoded transaction that must be submitted. |
1238 | 0 | pub fn transaction(&'_ self) -> impl AsRef<[u8]> + '_ { |
1239 | 0 | match &self.inner.vm { |
1240 | 0 | host::HostVm::OffchainSubmitTransaction(req) => req.transaction(), |
1241 | | // We only create a `OffchainSubmitTransaction` if the state is one of the above. |
1242 | 0 | _ => unreachable!(), |
1243 | | } |
1244 | 0 | } Unexecuted instantiation: _RNvMsf_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction11transaction Unexecuted instantiation: _RNvMsf_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction11transaction |
1245 | | |
1246 | | /// Resume execution. Must indicate whether the transaction has been successfully submitted. |
1247 | 0 | pub fn resume(mut self, success: bool) -> RuntimeCall { |
1248 | 0 | match self.inner.vm { |
1249 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { |
1250 | 0 | self.inner.vm = req.resume(success); |
1251 | 0 | } |
1252 | | // We only create a `OffchainSubmitTransaction` if the state is one of the above. |
1253 | 0 | _ => unreachable!(), |
1254 | | }; |
1255 | | |
1256 | 0 | self.inner.run() |
1257 | 0 | } Unexecuted instantiation: _RNvMsf_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction6resume Unexecuted instantiation: _RNvMsf_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction6resume |
1258 | | } |
1259 | | |
1260 | | /// Report about a log entry being emitted. |
1261 | | /// |
1262 | | /// Use [`LogEmit::info`] to obtain what must be printed. |
1263 | | #[must_use] |
1264 | | pub struct LogEmit { |
1265 | | inner: Inner, |
1266 | | } |
1267 | | |
1268 | | impl LogEmit { |
1269 | | /// Returns the data that the runtime would like to print. |
1270 | 0 | pub fn info(&self) -> LogEmitInfo { |
1271 | 0 | match &self.inner.vm { |
1272 | 0 | host::HostVm::LogEmit(req) => req.info(), |
1273 | | // We only create a `LogEmit` if the inner state is `LogEmit`. |
1274 | 0 | _ => unreachable!(), |
1275 | | } |
1276 | 0 | } Unexecuted instantiation: _RNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7LogEmit4info Unexecuted instantiation: _RNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7LogEmit4info |
1277 | | |
1278 | | /// Resume execution. |
1279 | 0 | pub fn resume(mut self) -> RuntimeCall { |
1280 | 0 | match self.inner.vm { |
1281 | 0 | host::HostVm::LogEmit(req) => { |
1282 | 0 | self.inner.vm = req.resume(); |
1283 | 0 | } |
1284 | | // We only create a `LogEmit` if the inner state is `LogEmit`. |
1285 | 0 | _ => unreachable!(), |
1286 | | }; |
1287 | | |
1288 | 0 | self.inner.run() |
1289 | 0 | } Unexecuted instantiation: _RNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_7LogEmit6resume Unexecuted instantiation: _RNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_7LogEmit6resume |
1290 | | } |
1291 | | |
1292 | | /// Implementation detail of the execution. Shared by all the variants of [`RuntimeCall`] |
1293 | | /// other than [`RuntimeCall::Finished`]. |
1294 | | struct Inner { |
1295 | | /// Virtual machine running the call. |
1296 | | vm: host::HostVm, |
1297 | | |
1298 | | /// Pending changes to the storage that this execution performs. |
1299 | | pending_storage_changes: PendingStorageChanges, |
1300 | | |
1301 | | /// Contains a copy of [`Inner::pending_storage_changes`] at the time when the transaction |
1302 | | /// started. When the storage transaction ends, either the entry is silently discarded (to |
1303 | | /// commit), or is written over [`Inner::pending_storage_changes`] (to rollback). |
1304 | | /// |
1305 | | /// Contains a `Vec` in case transactions are stacked. |
1306 | | transactions_stack: Vec<PendingStorageChanges>, |
1307 | | |
1308 | | /// State trie version indicated by the runtime. All the storage changes that are performed |
1309 | | /// use this version. |
1310 | | state_trie_version: TrieEntryVersion, |
1311 | | |
1312 | | /// Pending changes to the off-chain storage that this execution performs. |
1313 | | offchain_storage_changes: BTreeMap<Vec<u8>, Option<Vec<u8>>>, |
1314 | | |
1315 | | /// Trie root calculation in progress. Contains the trie whose root is being calculated |
1316 | | /// (`Some` for a child trie or `None` for the main trie) and the calculation state machine. |
1317 | | root_calculation: Option<(Option<Vec<u8>>, trie_root_calculator::InProgress)>, |
1318 | | |
1319 | | /// Value provided by [`Config::max_log_level`]. |
1320 | | max_log_level: u32, |
1321 | | |
1322 | | /// See [`Config::calculate_trie_changes`]. |
1323 | | calculate_trie_changes: bool, |
1324 | | } |
1325 | | |
1326 | | /// See [`Inner::pending_storage_changes`]. |
1327 | | #[derive(Clone)] |
1328 | | struct PendingStorageChanges { |
1329 | | /// For each trie, the values that have been written to it. |
1330 | | trie_diffs: hashbrown::HashMap<Option<Vec<u8>>, storage_diff::TrieDiff, fnv::FnvBuildHasher>, |
1331 | | |
1332 | | /// List of tries (`None` for the main trie and `Some` for child tries) whose root hash must |
1333 | | /// be recalculated (and for child tries stored into the main trie). |
1334 | | /// This is necessary in order to populate [`PendingStorageChanges::tries_changes`]. |
1335 | | stale_child_tries_root_hashes: hashbrown::HashSet<Option<Vec<u8>>, fnv::FnvBuildHasher>, |
1336 | | |
1337 | | /// Changes to the trie nodes of all the tries. |
1338 | | tries_changes: BTreeMap<(Option<Vec<u8>>, Vec<Nibble>), PendingStorageChangesTrieNode>, |
1339 | | |
1340 | | /// Changes to the off-chain storage committed by on-chain transactions. |
1341 | | offchain_storage_changes: BTreeMap<Vec<u8>, Option<Vec<u8>>>, |
1342 | | } |
1343 | | |
1344 | | /// See [`PendingStorageChanges::tries_changes`]. |
1345 | | #[derive(Clone)] |
1346 | | enum PendingStorageChangesTrieNode { |
1347 | | Removed, |
1348 | | InsertUpdate { |
1349 | | new_merkle_value: Vec<u8>, |
1350 | | partial_key: Vec<Nibble>, |
1351 | | children_merkle_values: Box<[Option<Vec<u8>>; 16]>, |
1352 | | }, |
1353 | | } |
1354 | | |
1355 | | /// Writing and reading keys the main trie under this prefix obeys special rules. |
1356 | | const CHILD_STORAGE_SPECIAL_PREFIX: &[u8] = b":child_storage:"; |
1357 | | /// Writing and reading keys the main trie under this prefix obeys special rules. |
1358 | | const DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX: &[u8] = b":child_storage:default:"; |
1359 | | |
1360 | | impl Inner { |
1361 | | /// Continues the execution. |
1362 | 15.8k | fn run(mut self) -> RuntimeCall { |
1363 | | loop { |
1364 | 18.9k | match self.root_calculation.take() { |
1365 | 2.90k | None => {} |
1366 | 8.23k | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { |
1367 | 8.23k | self.root_calculation = Some(( |
1368 | 8.23k | trie, |
1369 | 8.23k | trie_root_calculator::InProgress::ClosestDescendant(calc_req), |
1370 | 8.23k | )); |
1371 | 8.23k | return RuntimeCall::NextKey(NextKey { |
1372 | 8.23k | inner: self, |
1373 | 8.23k | key_overwrite: None, |
1374 | 8.23k | keys_removed_so_far: 0, |
1375 | 8.23k | }); |
1376 | | } |
1377 | 514 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { |
1378 | 514 | if calc_req |
1379 | 514 | .key() |
1380 | 3.56k | .fold(0, |count, slice| count + slice.as_ref().len()) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3run0Bb_ Line | Count | Source | 1380 | 3.56k | .fold(0, |count, slice| count + slice.as_ref().len()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3run0Bb_ |
1381 | 514 | % 2 |
1382 | 514 | == 0 |
1383 | | { |
1384 | 438 | self.root_calculation = Some(( |
1385 | 438 | trie, |
1386 | 438 | trie_root_calculator::InProgress::StorageValue(calc_req), |
1387 | 438 | )); |
1388 | 438 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1389 | | } else { |
1390 | | // If the number of nibbles in the key is uneven, we are sure that |
1391 | | // there exists no storage value. |
1392 | 76 | self.root_calculation = Some((trie, calc_req.inject_value(None))); |
1393 | 76 | continue; |
1394 | | } |
1395 | | } |
1396 | | Some(( |
1397 | 6.77k | trie, |
1398 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), |
1399 | 6.77k | )) => { |
1400 | 6.77k | self.root_calculation = Some(( |
1401 | 6.77k | trie, |
1402 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), |
1403 | 6.77k | )); |
1404 | 6.77k | return RuntimeCall::ClosestDescendantMerkleValue( |
1405 | 6.77k | ClosestDescendantMerkleValue { inner: self }, |
1406 | 6.77k | ); |
1407 | | } |
1408 | 500 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { |
1409 | 500 | self.pending_storage_changes.tries_changes.insert( |
1410 | 500 | (trie.clone(), ev.key_as_vec()), |
1411 | 500 | PendingStorageChangesTrieNode::InsertUpdate { |
1412 | 500 | new_merkle_value: ev.merkle_value().to_owned(), |
1413 | 500 | partial_key: ev.partial_key().to_owned(), |
1414 | 500 | children_merkle_values: TryFrom::try_from( |
1415 | 500 | ev.children_merkle_values() |
1416 | 8.00k | .map(|mv| mv.map(|mv| mv.to_owned()489 )) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs_0Bb_ Line | Count | Source | 1416 | 8.00k | .map(|mv| mv.map(|mv| mv.to_owned())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs_0Bb_ _RNCNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB9_5Inner3runs_00Bd_ Line | Count | Source | 1416 | 489 | .map(|mv| mv.map(|mv| mv.to_owned())) |
Unexecuted instantiation: _RNCNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB9_5Inner3runs_00Bd_ |
1417 | 500 | .collect::<Vec<_>>() |
1418 | 500 | .into_boxed_slice(), |
1419 | 500 | ) |
1420 | 500 | .unwrap(), |
1421 | 500 | }, |
1422 | 500 | ); |
1423 | 500 | |
1424 | 500 | self.root_calculation = Some((trie, ev.resume())); |
1425 | 500 | continue; |
1426 | | } |
1427 | 13 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { |
1428 | 13 | self.pending_storage_changes.tries_changes.insert( |
1429 | 13 | (trie.clone(), ev.key_as_vec()), |
1430 | 13 | PendingStorageChangesTrieNode::Removed, |
1431 | 13 | ); |
1432 | 13 | |
1433 | 13 | self.root_calculation = Some((trie, ev.resume())); |
1434 | 13 | continue; |
1435 | | } |
1436 | 10 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { |
1437 | 10 | self.pending_storage_changes |
1438 | 10 | .stale_child_tries_root_hashes |
1439 | 10 | .remove(&trie); |
1440 | | |
1441 | | // If we've finished calculating a child trie, update its entry in the |
1442 | | // main trie. |
1443 | 10 | if let Some(child_trie5 ) = &trie { |
1444 | 5 | let mut main_trie_key = Vec::with_capacity( |
1445 | 5 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), |
1446 | 5 | ); |
1447 | 5 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); |
1448 | 5 | main_trie_key.extend_from_slice(child_trie); |
1449 | 5 | |
1450 | 5 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { |
1451 | 4 | self.pending_storage_changes |
1452 | 4 | .trie_diffs |
1453 | 4 | .entry(None) |
1454 | 4 | .or_default() |
1455 | 4 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); |
1456 | 4 | } else { |
1457 | 1 | self.pending_storage_changes |
1458 | 1 | .trie_diffs |
1459 | 1 | .entry(None) |
1460 | 1 | .or_default() |
1461 | 1 | .diff_insert_erase(main_trie_key, ()); |
1462 | 1 | } |
1463 | | |
1464 | 5 | self.pending_storage_changes |
1465 | 5 | .stale_child_tries_root_hashes |
1466 | 5 | .insert(None); |
1467 | 5 | } |
1468 | | |
1469 | | // Resume the VM execution only if the calculated trie is the one that was |
1470 | | // requested by the runtime. |
1471 | 10 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { |
1472 | | // Code below is a bit convoluted due to borrow checker issues. |
1473 | 10 | let trie_match = match (req.child_trie(), trie) { |
1474 | 5 | (None, None) => true, |
1475 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, |
1476 | 5 | _ => false, |
1477 | | }; |
1478 | 10 | if trie_match { |
1479 | 5 | self.vm = req.resume(&trie_root_hash); |
1480 | 5 | } else { |
1481 | 5 | self.vm = host::HostVm::ExternalStorageRoot(req); |
1482 | 5 | } |
1483 | 0 | } |
1484 | | |
1485 | 10 | continue; |
1486 | | } |
1487 | | } |
1488 | | |
1489 | | // If the the runtime requests the trie root hash of the main trie, we must first |
1490 | | // recalculate the trie root hash of every single child trie that has been modified |
1491 | | // since the previous trie root hash calculation. |
1492 | | // This is also done if execution is finished, in order for the diff provided as |
1493 | | // output to be accurate. |
1494 | | { |
1495 | 2.90k | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { |
1496 | | host::HostVm::Finished(_) => { |
1497 | 138 | if let Some(child_trie0 ) = self |
1498 | 138 | .pending_storage_changes |
1499 | 138 | .stale_child_tries_root_hashes |
1500 | 138 | .iter() |
1501 | 138 | .find_map(|ct| ct.as_ref()3 ) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs0_0Bb_ Line | Count | Source | 1501 | 3 | .find_map(|ct| ct.as_ref()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs0_0Bb_ |
1502 | | { |
1503 | 0 | Some(Some(either::Right(child_trie))) |
1504 | 138 | } else if self |
1505 | 138 | .pending_storage_changes |
1506 | 138 | .stale_child_tries_root_hashes |
1507 | 138 | .contains(&None) |
1508 | 3 | && self.calculate_trie_changes |
1509 | | { |
1510 | 0 | Some(None) |
1511 | | } else { |
1512 | 138 | None |
1513 | | } |
1514 | | } |
1515 | 10 | host::HostVm::ExternalStorageRoot(req) => { |
1516 | 10 | if let Some(child_trie0 ) = req.child_trie() { |
1517 | 0 | Some(Some(either::Left(child_trie))) |
1518 | | } else { |
1519 | | // Find any child trie in `pending_storage_changes`. If `None` is |
1520 | | // found, calculate the main trie. |
1521 | | // It is important to calculate the child tries before the main tries. |
1522 | 10 | Some( |
1523 | 10 | self.pending_storage_changes |
1524 | 10 | .stale_child_tries_root_hashes |
1525 | 10 | .iter() |
1526 | 12 | .find_map(|ct| ct.as_ref()) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs1_0Bb_ Line | Count | Source | 1526 | 12 | .find_map(|ct| ct.as_ref()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs1_0Bb_ |
1527 | 10 | .map(|t| either::Right(&t[..])5 ), _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs2_0Bb_ Line | Count | Source | 1527 | 5 | .map(|t| either::Right(&t[..])), |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs2_0Bb_ |
1528 | 10 | ) |
1529 | | } |
1530 | | } |
1531 | 2.75k | _ => None, |
1532 | | }; |
1533 | | |
1534 | 2.90k | if let Some(trie_to_flush10 ) = trie_to_flush { |
1535 | | // Remove from `tries_changes` all the changes concerning this trie. |
1536 | | // TODO: O(n) and generally not optimized |
1537 | | { |
1538 | 10 | let to_remove = self |
1539 | 10 | .pending_storage_changes |
1540 | 10 | .tries_changes |
1541 | 10 | .range(( |
1542 | 10 | ops::Bound::Included(( |
1543 | 10 | trie_to_flush |
1544 | 10 | .as_ref() |
1545 | 10 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()5 ), _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs3_0Bb_ Line | Count | Source | 1545 | 5 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs3_0Bb_ |
1546 | 10 | Vec::new(), |
1547 | 10 | )), |
1548 | 10 | ops::Bound::Unbounded, |
1549 | 10 | )) |
1550 | 10 | .take_while(|((ct, _), _)| { |
1551 | 4 | ct.as_ref().map(|ct| &ct[..]) _RNCNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB9_5Inner3runs4_00Bd_ Line | Count | Source | 1551 | 4 | ct.as_ref().map(|ct| &ct[..]) |
Unexecuted instantiation: _RNCNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB9_5Inner3runs4_00Bd_ |
1552 | 4 | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) |
1553 | 10 | }) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs4_0Bb_ Line | Count | Source | 1550 | 4 | .take_while(|((ct, _), _)| { | 1551 | 4 | ct.as_ref().map(|ct| &ct[..]) | 1552 | 4 | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1553 | 4 | }) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs4_0Bb_ |
1554 | 10 | .map(|(k, _)| k.clone()0 ) Unexecuted instantiation: _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs5_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs5_0Bb_ |
1555 | 10 | .collect::<Vec<_>>(); |
1556 | 10 | for to_remove0 in to_remove { |
1557 | 0 | self.pending_storage_changes |
1558 | 0 | .tries_changes |
1559 | 0 | .remove(&to_remove); |
1560 | 0 | } |
1561 | | } |
1562 | | |
1563 | | // TODO: don't clone? |
1564 | 10 | let diff = match self |
1565 | 10 | .pending_storage_changes |
1566 | 10 | .trie_diffs |
1567 | 10 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()5 )) // TODO: overhead _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs6_0Bb_ Line | Count | Source | 1567 | 5 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs6_0Bb_ |
1568 | | { |
1569 | 0 | None => storage_diff::TrieDiff::empty(), |
1570 | 10 | Some(diff) => diff.clone(), |
1571 | | }; |
1572 | | |
1573 | 10 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. |
1574 | 10 | self.root_calculation = Some(( |
1575 | 10 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()5 ), _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs7_0Bb_ Line | Count | Source | 1575 | 5 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs7_0Bb_ |
1576 | 10 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { |
1577 | 10 | diff, |
1578 | 10 | diff_trie_entries_version: self.state_trie_version, |
1579 | 10 | max_trie_recalculation_depth_hint: 16, // TODO: ?! |
1580 | 10 | }), |
1581 | 10 | )); |
1582 | 10 | continue; |
1583 | 2.89k | } |
1584 | | } |
1585 | | |
1586 | 2.89k | if matches!2.75k (self.vm, host::HostVm::Finished(_)) |
1587 | 138 | && !self.offchain_storage_changes.is_empty() |
1588 | | { |
1589 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); |
1590 | 2.89k | } |
1591 | 2.89k | |
1592 | 2.89k | match self.vm { |
1593 | 1.44k | host::HostVm::ReadyToRun(r) => self.vm = r.run(), |
1594 | | |
1595 | 0 | host::HostVm::Error { error, prototype } => { |
1596 | 0 | return RuntimeCall::Finished(Err(Error { |
1597 | 0 | detail: error, |
1598 | 0 | prototype, |
1599 | 0 | })); |
1600 | | } |
1601 | | |
1602 | 138 | host::HostVm::Finished(finished) => { |
1603 | 138 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. |
1604 | 138 | debug_assert!( |
1605 | 138 | self.pending_storage_changes |
1606 | 138 | .stale_child_tries_root_hashes |
1607 | 138 | .is_empty() |
1608 | 3 | || (!self.calculate_trie_changes |
1609 | 3 | && self |
1610 | 3 | .pending_storage_changes |
1611 | 3 | .stale_child_tries_root_hashes |
1612 | 3 | .len() |
1613 | 3 | == 1 |
1614 | 3 | && self |
1615 | 3 | .pending_storage_changes |
1616 | 3 | .stale_child_tries_root_hashes |
1617 | 3 | .contains(&None)) |
1618 | | ); |
1619 | 138 | debug_assert!(self.offchain_storage_changes.is_empty()); |
1620 | | |
1621 | 138 | return RuntimeCall::Finished(Ok(Success { |
1622 | 138 | virtual_machine: SuccessVirtualMachine(finished), |
1623 | 138 | storage_changes: StorageChanges { |
1624 | 138 | inner: self.pending_storage_changes, |
1625 | 138 | calculate_trie_changes: self.calculate_trie_changes, |
1626 | 138 | }, |
1627 | 138 | state_trie_version: self.state_trie_version, |
1628 | 138 | })); |
1629 | | } |
1630 | | |
1631 | 687 | host::HostVm::ExternalStorageGet(req) => { |
1632 | 687 | let diff_search = self |
1633 | 687 | .pending_storage_changes |
1634 | 687 | .trie_diffs |
1635 | 687 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec()6 )) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs8_0Bb_ Line | Count | Source | 1635 | 6 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs8_0Bb_ |
1636 | 687 | .and_then(|diff| diff.diff_get(req.key().as_ref())681 ); _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runs9_0Bb_ Line | Count | Source | 1636 | 597 | .and_then(|diff| diff.diff_get(req.key().as_ref())); |
_RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runs9_0Bb_ Line | Count | Source | 1636 | 84 | .and_then(|diff| diff.diff_get(req.key().as_ref())); |
|
1637 | | |
1638 | 687 | if let Some((value_in_diff436 , _)) = diff_search { |
1639 | 436 | self.vm = req.resume_full_value(value_in_diff); |
1640 | 436 | } else { |
1641 | 251 | self.vm = req.into(); |
1642 | 251 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1643 | | } |
1644 | | } |
1645 | | |
1646 | 375 | host::HostVm::ExternalStorageSet(req) => { |
1647 | 375 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` |
1648 | 375 | // is silently ignored, as per spec. |
1649 | 375 | if req.child_trie().is_none() |
1650 | 371 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) |
1651 | | { |
1652 | 0 | self.vm = req.resume(); |
1653 | 0 | continue; |
1654 | 375 | } |
1655 | 375 | |
1656 | 375 | // TOOD: to_owned overhead |
1657 | 375 | self.pending_storage_changes |
1658 | 375 | .stale_child_tries_root_hashes |
1659 | 375 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned()4 )); _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsa_0Bb_ Line | Count | Source | 1659 | 4 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsa_0Bb_ |
1660 | 375 | |
1661 | 375 | let trie = self |
1662 | 375 | .pending_storage_changes |
1663 | 375 | .trie_diffs |
1664 | 375 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec()4 )) _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsb_0Bb_ Line | Count | Source | 1664 | 4 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsb_0Bb_ |
1665 | 375 | .or_insert(storage_diff::TrieDiff::empty()); |
1666 | | |
1667 | 375 | if let Some(value304 ) = req.value() { |
1668 | 304 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); |
1669 | 304 | } else { |
1670 | 71 | trie.diff_insert_erase(req.key().as_ref(), ()); |
1671 | 71 | } |
1672 | | |
1673 | 375 | self.vm = req.resume() |
1674 | | } |
1675 | | |
1676 | 71 | host::HostVm::ExternalStorageAppend(req) => { |
1677 | 71 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` |
1678 | 71 | // is silently ignored, as per spec. |
1679 | 71 | if req.child_trie().is_none() |
1680 | 71 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) |
1681 | | { |
1682 | 0 | self.vm = req.resume(); |
1683 | 0 | continue; |
1684 | 71 | } |
1685 | 71 | |
1686 | 71 | // TOOD: to_owned overhead |
1687 | 71 | self.pending_storage_changes |
1688 | 71 | .stale_child_tries_root_hashes |
1689 | 71 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned()0 )); Unexecuted instantiation: _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsc_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsc_0Bb_ |
1690 | 71 | |
1691 | 71 | let trie = self |
1692 | 71 | .pending_storage_changes |
1693 | 71 | .trie_diffs |
1694 | 71 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec()0 )) Unexecuted instantiation: _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsd_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsd_0Bb_ |
1695 | 71 | .or_insert(storage_diff::TrieDiff::empty()); |
1696 | 71 | |
1697 | 71 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v63 ); _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runse_0Bb_ Line | Count | Source | 1697 | 63 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runse_0Bb_ |
1698 | | |
1699 | 71 | if let Some(current_value63 ) = current_value { |
1700 | 63 | let mut current_value = current_value.unwrap_or_default().to_vec(); |
1701 | 63 | append_to_storage_value(&mut current_value, req.value().as_ref()); |
1702 | 63 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); |
1703 | 63 | self.vm = req.resume(); |
1704 | 63 | } else { |
1705 | 8 | self.vm = req.into(); |
1706 | 8 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1707 | | } |
1708 | | } |
1709 | | |
1710 | 6 | host::HostVm::ExternalStorageClearPrefix(req) => { |
1711 | 6 | // Any attempt at clear a prefix that "intersects" (see code) with |
1712 | 6 | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. |
1713 | 6 | if req.child_trie().is_none() |
1714 | 5 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) |
1715 | | { |
1716 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? |
1717 | 0 | continue; |
1718 | 6 | } |
1719 | 6 | |
1720 | 6 | // TODO: consider doing this only if at least one key was actually removed |
1721 | 6 | // TOOD: to_owned overhead |
1722 | 6 | self.pending_storage_changes |
1723 | 6 | .stale_child_tries_root_hashes |
1724 | 6 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned()1 )); _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsf_0Bb_ Line | Count | Source | 1724 | 1 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); |
Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsf_0Bb_ |
1725 | 6 | |
1726 | 6 | let prefix = req.prefix().as_ref().to_owned(); |
1727 | 6 | self.vm = req.into(); |
1728 | 6 | return RuntimeCall::NextKey(NextKey { |
1729 | 6 | inner: self, |
1730 | 6 | key_overwrite: Some(prefix), |
1731 | 6 | keys_removed_so_far: 0, |
1732 | 6 | }); |
1733 | | } |
1734 | | |
1735 | | host::HostVm::ExternalStorageRoot(_) => { |
1736 | | // Handled above. |
1737 | 0 | unreachable!() |
1738 | | } |
1739 | | |
1740 | 1 | host::HostVm::ExternalStorageNextKey(req) => { |
1741 | 1 | self.vm = req.into(); |
1742 | 1 | return RuntimeCall::NextKey(NextKey { |
1743 | 1 | inner: self, |
1744 | 1 | key_overwrite: None, |
1745 | 1 | keys_removed_so_far: 0, |
1746 | 1 | }); |
1747 | | } |
1748 | | |
1749 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { |
1750 | 0 | self.pending_storage_changes |
1751 | 0 | .offchain_storage_changes |
1752 | 0 | .insert( |
1753 | 0 | req.key().as_ref().to_vec(), |
1754 | 0 | req.value().map(|v| v.as_ref().to_vec()), Unexecuted instantiation: _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsg_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsg_0Bb_ |
1755 | 0 | ); |
1756 | 0 |
|
1757 | 0 | self.vm = req.resume(); |
1758 | 0 | } |
1759 | | |
1760 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { |
1761 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); |
1762 | 0 | match current_value { |
1763 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), Unexecuted instantiation: _RNCNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB7_5Inner3runsh_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB7_5Inner3runsh_0Bb_ |
1764 | | None => { |
1765 | 0 | self.vm = req.into(); |
1766 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( |
1767 | 0 | OffchainStorageGet { inner: self }, |
1768 | 0 | )); |
1769 | | } |
1770 | | } |
1771 | | } |
1772 | | |
1773 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { |
1774 | 0 | self.vm = req.into(); |
1775 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( |
1776 | 0 | OffchainStorageCompareSet { inner: self }, |
1777 | 0 | )); |
1778 | | } |
1779 | | |
1780 | 6 | host::HostVm::SignatureVerification(req) => { |
1781 | 6 | self.vm = req.into(); |
1782 | 6 | return RuntimeCall::SignatureVerification(SignatureVerification { |
1783 | 6 | inner: self, |
1784 | 6 | }); |
1785 | | } |
1786 | | |
1787 | 0 | host::HostVm::CallRuntimeVersion(req) => { |
1788 | 0 | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 |
1789 | 0 | // The code below compiles the provided WebAssembly runtime code, which is a |
1790 | 0 | // relatively expensive operation (in the order of milliseconds). |
1791 | 0 | // While it could be tempting to use a system cache, this function is expected |
1792 | 0 | // to be called only right before runtime upgrades. Considering that runtime |
1793 | 0 | // upgrades are quite uncommon and that a caching system is rather non-trivial |
1794 | 0 | // to set up, the approach of recompiling every single time is preferred here. |
1795 | 0 | // TODO: number of heap pages?! we use the default here, but not sure whether that's correct or if we have to take the current heap pages |
1796 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { |
1797 | 0 | module: req.wasm_code(), |
1798 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, |
1799 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, |
1800 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? |
1801 | 0 | }) { |
1802 | 0 | Ok(w) => w, |
1803 | | Err(_) => { |
1804 | 0 | self.vm = req.resume(Err(())); |
1805 | 0 | continue; |
1806 | | } |
1807 | | }; |
1808 | | |
1809 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); |
1810 | | } |
1811 | | |
1812 | 14 | host::HostVm::StartStorageTransaction(tx) => { |
1813 | 14 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated |
1814 | 14 | self.transactions_stack |
1815 | 14 | .push(self.pending_storage_changes.clone()); |
1816 | 14 | self.vm = tx.resume(); |
1817 | 14 | } |
1818 | | |
1819 | 14 | host::HostVm::EndStorageTransaction { resume, rollback } => { |
1820 | 14 | // The inner implementation guarantees that a storage transaction can only |
1821 | 14 | // end if it has earlier been started. |
1822 | 14 | debug_assert!(!self.transactions_stack.is_empty()); |
1823 | 14 | let rollback_diff = self.transactions_stack.pop().unwrap(); |
1824 | 14 | |
1825 | 14 | if rollback { |
1826 | 0 | self.pending_storage_changes = rollback_diff; |
1827 | 14 | } |
1828 | | |
1829 | 14 | self.vm = resume.resume(); |
1830 | | } |
1831 | | |
1832 | 132 | host::HostVm::GetMaxLogLevel(resume) => { |
1833 | 132 | self.vm = resume.resume(self.max_log_level); |
1834 | 132 | } |
1835 | | |
1836 | 0 | host::HostVm::LogEmit(req) => { |
1837 | 0 | self.vm = req.into(); |
1838 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); |
1839 | | } |
1840 | 0 | host::HostVm::OffchainTimestamp(req) => { |
1841 | 0 | self.vm = req.into(); |
1842 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { |
1843 | 0 | inner: self, |
1844 | 0 | })); |
1845 | | } |
1846 | 0 | host::HostVm::OffchainRandomSeed(req) => { |
1847 | 0 | self.vm = req.into(); |
1848 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( |
1849 | 0 | OffchainRandomSeed { inner: self }, |
1850 | 0 | )); |
1851 | | } |
1852 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { |
1853 | 0 | self.vm = req.into(); |
1854 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( |
1855 | 0 | OffchainSubmitTransaction { inner: self }, |
1856 | 0 | )); |
1857 | | } |
1858 | | } |
1859 | | } |
1860 | 15.8k | } _RNvMsh_NtNtCsN16ciHI6Qf_7smoldot8executor12runtime_callNtB5_5Inner3run Line | Count | Source | 1362 | 15.6k | fn run(mut self) -> RuntimeCall { | 1363 | | loop { | 1364 | 18.2k | match self.root_calculation.take() { | 1365 | 2.22k | None => {} | 1366 | 8.23k | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { | 1367 | 8.23k | self.root_calculation = Some(( | 1368 | 8.23k | trie, | 1369 | 8.23k | trie_root_calculator::InProgress::ClosestDescendant(calc_req), | 1370 | 8.23k | )); | 1371 | 8.23k | return RuntimeCall::NextKey(NextKey { | 1372 | 8.23k | inner: self, | 1373 | 8.23k | key_overwrite: None, | 1374 | 8.23k | keys_removed_so_far: 0, | 1375 | 8.23k | }); | 1376 | | } | 1377 | 514 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { | 1378 | 514 | if calc_req | 1379 | 514 | .key() | 1380 | 514 | .fold(0, |count, slice| count + slice.as_ref().len()) | 1381 | 514 | % 2 | 1382 | 514 | == 0 | 1383 | | { | 1384 | 438 | self.root_calculation = Some(( | 1385 | 438 | trie, | 1386 | 438 | trie_root_calculator::InProgress::StorageValue(calc_req), | 1387 | 438 | )); | 1388 | 438 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1389 | | } else { | 1390 | | // If the number of nibbles in the key is uneven, we are sure that | 1391 | | // there exists no storage value. | 1392 | 76 | self.root_calculation = Some((trie, calc_req.inject_value(None))); | 1393 | 76 | continue; | 1394 | | } | 1395 | | } | 1396 | | Some(( | 1397 | 6.77k | trie, | 1398 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1399 | 6.77k | )) => { | 1400 | 6.77k | self.root_calculation = Some(( | 1401 | 6.77k | trie, | 1402 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1403 | 6.77k | )); | 1404 | 6.77k | return RuntimeCall::ClosestDescendantMerkleValue( | 1405 | 6.77k | ClosestDescendantMerkleValue { inner: self }, | 1406 | 6.77k | ); | 1407 | | } | 1408 | 500 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { | 1409 | 500 | self.pending_storage_changes.tries_changes.insert( | 1410 | 500 | (trie.clone(), ev.key_as_vec()), | 1411 | 500 | PendingStorageChangesTrieNode::InsertUpdate { | 1412 | 500 | new_merkle_value: ev.merkle_value().to_owned(), | 1413 | 500 | partial_key: ev.partial_key().to_owned(), | 1414 | 500 | children_merkle_values: TryFrom::try_from( | 1415 | 500 | ev.children_merkle_values() | 1416 | 500 | .map(|mv| mv.map(|mv| mv.to_owned())) | 1417 | 500 | .collect::<Vec<_>>() | 1418 | 500 | .into_boxed_slice(), | 1419 | 500 | ) | 1420 | 500 | .unwrap(), | 1421 | 500 | }, | 1422 | 500 | ); | 1423 | 500 | | 1424 | 500 | self.root_calculation = Some((trie, ev.resume())); | 1425 | 500 | continue; | 1426 | | } | 1427 | 13 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { | 1428 | 13 | self.pending_storage_changes.tries_changes.insert( | 1429 | 13 | (trie.clone(), ev.key_as_vec()), | 1430 | 13 | PendingStorageChangesTrieNode::Removed, | 1431 | 13 | ); | 1432 | 13 | | 1433 | 13 | self.root_calculation = Some((trie, ev.resume())); | 1434 | 13 | continue; | 1435 | | } | 1436 | 10 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { | 1437 | 10 | self.pending_storage_changes | 1438 | 10 | .stale_child_tries_root_hashes | 1439 | 10 | .remove(&trie); | 1440 | | | 1441 | | // If we've finished calculating a child trie, update its entry in the | 1442 | | // main trie. | 1443 | 10 | if let Some(child_trie5 ) = &trie { | 1444 | 5 | let mut main_trie_key = Vec::with_capacity( | 1445 | 5 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), | 1446 | 5 | ); | 1447 | 5 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); | 1448 | 5 | main_trie_key.extend_from_slice(child_trie); | 1449 | 5 | | 1450 | 5 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { | 1451 | 4 | self.pending_storage_changes | 1452 | 4 | .trie_diffs | 1453 | 4 | .entry(None) | 1454 | 4 | .or_default() | 1455 | 4 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); | 1456 | 4 | } else { | 1457 | 1 | self.pending_storage_changes | 1458 | 1 | .trie_diffs | 1459 | 1 | .entry(None) | 1460 | 1 | .or_default() | 1461 | 1 | .diff_insert_erase(main_trie_key, ()); | 1462 | 1 | } | 1463 | | | 1464 | 5 | self.pending_storage_changes | 1465 | 5 | .stale_child_tries_root_hashes | 1466 | 5 | .insert(None); | 1467 | 5 | } | 1468 | | | 1469 | | // Resume the VM execution only if the calculated trie is the one that was | 1470 | | // requested by the runtime. | 1471 | 10 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { | 1472 | | // Code below is a bit convoluted due to borrow checker issues. | 1473 | 10 | let trie_match = match (req.child_trie(), trie) { | 1474 | 5 | (None, None) => true, | 1475 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, | 1476 | 5 | _ => false, | 1477 | | }; | 1478 | 10 | if trie_match { | 1479 | 5 | self.vm = req.resume(&trie_root_hash); | 1480 | 5 | } else { | 1481 | 5 | self.vm = host::HostVm::ExternalStorageRoot(req); | 1482 | 5 | } | 1483 | 0 | } | 1484 | | | 1485 | 10 | continue; | 1486 | | } | 1487 | | } | 1488 | | | 1489 | | // If the the runtime requests the trie root hash of the main trie, we must first | 1490 | | // recalculate the trie root hash of every single child trie that has been modified | 1491 | | // since the previous trie root hash calculation. | 1492 | | // This is also done if execution is finished, in order for the diff provided as | 1493 | | // output to be accurate. | 1494 | | { | 1495 | 2.22k | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { | 1496 | | host::HostVm::Finished(_) => { | 1497 | 11 | if let Some(child_trie0 ) = self | 1498 | 11 | .pending_storage_changes | 1499 | 11 | .stale_child_tries_root_hashes | 1500 | 11 | .iter() | 1501 | 11 | .find_map(|ct| ct.as_ref()) | 1502 | | { | 1503 | 0 | Some(Some(either::Right(child_trie))) | 1504 | 11 | } else if self | 1505 | 11 | .pending_storage_changes | 1506 | 11 | .stale_child_tries_root_hashes | 1507 | 11 | .contains(&None) | 1508 | 3 | && self.calculate_trie_changes | 1509 | | { | 1510 | 0 | Some(None) | 1511 | | } else { | 1512 | 11 | None | 1513 | | } | 1514 | | } | 1515 | 10 | host::HostVm::ExternalStorageRoot(req) => { | 1516 | 10 | if let Some(child_trie0 ) = req.child_trie() { | 1517 | 0 | Some(Some(either::Left(child_trie))) | 1518 | | } else { | 1519 | | // Find any child trie in `pending_storage_changes`. If `None` is | 1520 | | // found, calculate the main trie. | 1521 | | // It is important to calculate the child tries before the main tries. | 1522 | 10 | Some( | 1523 | 10 | self.pending_storage_changes | 1524 | 10 | .stale_child_tries_root_hashes | 1525 | 10 | .iter() | 1526 | 10 | .find_map(|ct| ct.as_ref()) | 1527 | 10 | .map(|t| either::Right(&t[..])), | 1528 | 10 | ) | 1529 | | } | 1530 | | } | 1531 | 2.20k | _ => None, | 1532 | | }; | 1533 | | | 1534 | 2.22k | if let Some(trie_to_flush10 ) = trie_to_flush { | 1535 | | // Remove from `tries_changes` all the changes concerning this trie. | 1536 | | // TODO: O(n) and generally not optimized | 1537 | | { | 1538 | 10 | let to_remove = self | 1539 | 10 | .pending_storage_changes | 1540 | 10 | .tries_changes | 1541 | 10 | .range(( | 1542 | 10 | ops::Bound::Included(( | 1543 | 10 | trie_to_flush | 1544 | 10 | .as_ref() | 1545 | 10 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), | 1546 | 10 | Vec::new(), | 1547 | 10 | )), | 1548 | 10 | ops::Bound::Unbounded, | 1549 | 10 | )) | 1550 | 10 | .take_while(|((ct, _), _)| { | 1551 | | ct.as_ref().map(|ct| &ct[..]) | 1552 | | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1553 | 10 | }) | 1554 | 10 | .map(|(k, _)| k.clone()) | 1555 | 10 | .collect::<Vec<_>>(); | 1556 | 10 | for to_remove0 in to_remove { | 1557 | 0 | self.pending_storage_changes | 1558 | 0 | .tries_changes | 1559 | 0 | .remove(&to_remove); | 1560 | 0 | } | 1561 | | } | 1562 | | | 1563 | | // TODO: don't clone? | 1564 | 10 | let diff = match self | 1565 | 10 | .pending_storage_changes | 1566 | 10 | .trie_diffs | 1567 | 10 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead | 1568 | | { | 1569 | 0 | None => storage_diff::TrieDiff::empty(), | 1570 | 10 | Some(diff) => diff.clone(), | 1571 | | }; | 1572 | | | 1573 | 10 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. | 1574 | 10 | self.root_calculation = Some(( | 1575 | 10 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), | 1576 | 10 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { | 1577 | 10 | diff, | 1578 | 10 | diff_trie_entries_version: self.state_trie_version, | 1579 | 10 | max_trie_recalculation_depth_hint: 16, // TODO: ?! | 1580 | 10 | }), | 1581 | 10 | )); | 1582 | 10 | continue; | 1583 | 2.21k | } | 1584 | | } | 1585 | | | 1586 | 2.21k | if matches!2.20k (self.vm, host::HostVm::Finished(_)) | 1587 | 11 | && !self.offchain_storage_changes.is_empty() | 1588 | | { | 1589 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); | 1590 | 2.21k | } | 1591 | 2.21k | | 1592 | 2.21k | match self.vm { | 1593 | 1.11k | host::HostVm::ReadyToRun(r) => self.vm = r.run(), | 1594 | | | 1595 | 0 | host::HostVm::Error { error, prototype } => { | 1596 | 0 | return RuntimeCall::Finished(Err(Error { | 1597 | 0 | detail: error, | 1598 | 0 | prototype, | 1599 | 0 | })); | 1600 | | } | 1601 | | | 1602 | 11 | host::HostVm::Finished(finished) => { | 1603 | 11 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. | 1604 | 11 | debug_assert!( | 1605 | 11 | self.pending_storage_changes | 1606 | 11 | .stale_child_tries_root_hashes | 1607 | 11 | .is_empty() | 1608 | 3 | || (!self.calculate_trie_changes | 1609 | 3 | && self | 1610 | 3 | .pending_storage_changes | 1611 | 3 | .stale_child_tries_root_hashes | 1612 | 3 | .len() | 1613 | 3 | == 1 | 1614 | 3 | && self | 1615 | 3 | .pending_storage_changes | 1616 | 3 | .stale_child_tries_root_hashes | 1617 | 3 | .contains(&None)) | 1618 | | ); | 1619 | 11 | debug_assert!(self.offchain_storage_changes.is_empty()); | 1620 | | | 1621 | 11 | return RuntimeCall::Finished(Ok(Success { | 1622 | 11 | virtual_machine: SuccessVirtualMachine(finished), | 1623 | 11 | storage_changes: StorageChanges { | 1624 | 11 | inner: self.pending_storage_changes, | 1625 | 11 | calculate_trie_changes: self.calculate_trie_changes, | 1626 | 11 | }, | 1627 | 11 | state_trie_version: self.state_trie_version, | 1628 | 11 | })); | 1629 | | } | 1630 | | | 1631 | 603 | host::HostVm::ExternalStorageGet(req) => { | 1632 | 603 | let diff_search = self | 1633 | 603 | .pending_storage_changes | 1634 | 603 | .trie_diffs | 1635 | 603 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1636 | 603 | .and_then(|diff| diff.diff_get(req.key().as_ref())); | 1637 | | | 1638 | 603 | if let Some((value_in_diff436 , _)) = diff_search { | 1639 | 436 | self.vm = req.resume_full_value(value_in_diff); | 1640 | 436 | } else { | 1641 | 167 | self.vm = req.into(); | 1642 | 167 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1643 | | } | 1644 | | } | 1645 | | | 1646 | 375 | host::HostVm::ExternalStorageSet(req) => { | 1647 | 375 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1648 | 375 | // is silently ignored, as per spec. | 1649 | 375 | if req.child_trie().is_none() | 1650 | 371 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1651 | | { | 1652 | 0 | self.vm = req.resume(); | 1653 | 0 | continue; | 1654 | 375 | } | 1655 | 375 | | 1656 | 375 | // TOOD: to_owned overhead | 1657 | 375 | self.pending_storage_changes | 1658 | 375 | .stale_child_tries_root_hashes | 1659 | 375 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1660 | 375 | | 1661 | 375 | let trie = self | 1662 | 375 | .pending_storage_changes | 1663 | 375 | .trie_diffs | 1664 | 375 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1665 | 375 | .or_insert(storage_diff::TrieDiff::empty()); | 1666 | | | 1667 | 375 | if let Some(value304 ) = req.value() { | 1668 | 304 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); | 1669 | 304 | } else { | 1670 | 71 | trie.diff_insert_erase(req.key().as_ref(), ()); | 1671 | 71 | } | 1672 | | | 1673 | 375 | self.vm = req.resume() | 1674 | | } | 1675 | | | 1676 | 71 | host::HostVm::ExternalStorageAppend(req) => { | 1677 | 71 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1678 | 71 | // is silently ignored, as per spec. | 1679 | 71 | if req.child_trie().is_none() | 1680 | 71 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1681 | | { | 1682 | 0 | self.vm = req.resume(); | 1683 | 0 | continue; | 1684 | 71 | } | 1685 | 71 | | 1686 | 71 | // TOOD: to_owned overhead | 1687 | 71 | self.pending_storage_changes | 1688 | 71 | .stale_child_tries_root_hashes | 1689 | 71 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1690 | 71 | | 1691 | 71 | let trie = self | 1692 | 71 | .pending_storage_changes | 1693 | 71 | .trie_diffs | 1694 | 71 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1695 | 71 | .or_insert(storage_diff::TrieDiff::empty()); | 1696 | 71 | | 1697 | 71 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); | 1698 | | | 1699 | 71 | if let Some(current_value63 ) = current_value { | 1700 | 63 | let mut current_value = current_value.unwrap_or_default().to_vec(); | 1701 | 63 | append_to_storage_value(&mut current_value, req.value().as_ref()); | 1702 | 63 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); | 1703 | 63 | self.vm = req.resume(); | 1704 | 63 | } else { | 1705 | 8 | self.vm = req.into(); | 1706 | 8 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1707 | | } | 1708 | | } | 1709 | | | 1710 | 6 | host::HostVm::ExternalStorageClearPrefix(req) => { | 1711 | 6 | // Any attempt at clear a prefix that "intersects" (see code) with | 1712 | 6 | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. | 1713 | 6 | if req.child_trie().is_none() | 1714 | 5 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) | 1715 | | { | 1716 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? | 1717 | 0 | continue; | 1718 | 6 | } | 1719 | 6 | | 1720 | 6 | // TODO: consider doing this only if at least one key was actually removed | 1721 | 6 | // TOOD: to_owned overhead | 1722 | 6 | self.pending_storage_changes | 1723 | 6 | .stale_child_tries_root_hashes | 1724 | 6 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1725 | 6 | | 1726 | 6 | let prefix = req.prefix().as_ref().to_owned(); | 1727 | 6 | self.vm = req.into(); | 1728 | 6 | return RuntimeCall::NextKey(NextKey { | 1729 | 6 | inner: self, | 1730 | 6 | key_overwrite: Some(prefix), | 1731 | 6 | keys_removed_so_far: 0, | 1732 | 6 | }); | 1733 | | } | 1734 | | | 1735 | | host::HostVm::ExternalStorageRoot(_) => { | 1736 | | // Handled above. | 1737 | 0 | unreachable!() | 1738 | | } | 1739 | | | 1740 | 1 | host::HostVm::ExternalStorageNextKey(req) => { | 1741 | 1 | self.vm = req.into(); | 1742 | 1 | return RuntimeCall::NextKey(NextKey { | 1743 | 1 | inner: self, | 1744 | 1 | key_overwrite: None, | 1745 | 1 | keys_removed_so_far: 0, | 1746 | 1 | }); | 1747 | | } | 1748 | | | 1749 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { | 1750 | 0 | self.pending_storage_changes | 1751 | 0 | .offchain_storage_changes | 1752 | 0 | .insert( | 1753 | 0 | req.key().as_ref().to_vec(), | 1754 | 0 | req.value().map(|v| v.as_ref().to_vec()), | 1755 | 0 | ); | 1756 | 0 |
| 1757 | 0 | self.vm = req.resume(); | 1758 | 0 | } | 1759 | | | 1760 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { | 1761 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); | 1762 | 0 | match current_value { | 1763 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), | 1764 | | None => { | 1765 | 0 | self.vm = req.into(); | 1766 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( | 1767 | 0 | OffchainStorageGet { inner: self }, | 1768 | 0 | )); | 1769 | | } | 1770 | | } | 1771 | | } | 1772 | | | 1773 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { | 1774 | 0 | self.vm = req.into(); | 1775 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( | 1776 | 0 | OffchainStorageCompareSet { inner: self }, | 1777 | 0 | )); | 1778 | | } | 1779 | | | 1780 | 6 | host::HostVm::SignatureVerification(req) => { | 1781 | 6 | self.vm = req.into(); | 1782 | 6 | return RuntimeCall::SignatureVerification(SignatureVerification { | 1783 | 6 | inner: self, | 1784 | 6 | }); | 1785 | | } | 1786 | | | 1787 | 0 | host::HostVm::CallRuntimeVersion(req) => { | 1788 | 0 | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 | 1789 | 0 | // The code below compiles the provided WebAssembly runtime code, which is a | 1790 | 0 | // relatively expensive operation (in the order of milliseconds). | 1791 | 0 | // While it could be tempting to use a system cache, this function is expected | 1792 | 0 | // to be called only right before runtime upgrades. Considering that runtime | 1793 | 0 | // upgrades are quite uncommon and that a caching system is rather non-trivial | 1794 | 0 | // to set up, the approach of recompiling every single time is preferred here. | 1795 | 0 | // TODO: number of heap pages?! we use the default here, but not sure whether that's correct or if we have to take the current heap pages | 1796 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { | 1797 | 0 | module: req.wasm_code(), | 1798 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, | 1799 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, | 1800 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? | 1801 | 0 | }) { | 1802 | 0 | Ok(w) => w, | 1803 | | Err(_) => { | 1804 | 0 | self.vm = req.resume(Err(())); | 1805 | 0 | continue; | 1806 | | } | 1807 | | }; | 1808 | | | 1809 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); | 1810 | | } | 1811 | | | 1812 | 14 | host::HostVm::StartStorageTransaction(tx) => { | 1813 | 14 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated | 1814 | 14 | self.transactions_stack | 1815 | 14 | .push(self.pending_storage_changes.clone()); | 1816 | 14 | self.vm = tx.resume(); | 1817 | 14 | } | 1818 | | | 1819 | 14 | host::HostVm::EndStorageTransaction { resume, rollback } => { | 1820 | 14 | // The inner implementation guarantees that a storage transaction can only | 1821 | 14 | // end if it has earlier been started. | 1822 | 14 | debug_assert!(!self.transactions_stack.is_empty()); | 1823 | 14 | let rollback_diff = self.transactions_stack.pop().unwrap(); | 1824 | 14 | | 1825 | 14 | if rollback { | 1826 | 0 | self.pending_storage_changes = rollback_diff; | 1827 | 14 | } | 1828 | | | 1829 | 14 | self.vm = resume.resume(); | 1830 | | } | 1831 | | | 1832 | 5 | host::HostVm::GetMaxLogLevel(resume) => { | 1833 | 5 | self.vm = resume.resume(self.max_log_level); | 1834 | 5 | } | 1835 | | | 1836 | 0 | host::HostVm::LogEmit(req) => { | 1837 | 0 | self.vm = req.into(); | 1838 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); | 1839 | | } | 1840 | 0 | host::HostVm::OffchainTimestamp(req) => { | 1841 | 0 | self.vm = req.into(); | 1842 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { | 1843 | 0 | inner: self, | 1844 | 0 | })); | 1845 | | } | 1846 | 0 | host::HostVm::OffchainRandomSeed(req) => { | 1847 | 0 | self.vm = req.into(); | 1848 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( | 1849 | 0 | OffchainRandomSeed { inner: self }, | 1850 | 0 | )); | 1851 | | } | 1852 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { | 1853 | 0 | self.vm = req.into(); | 1854 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( | 1855 | 0 | OffchainSubmitTransaction { inner: self }, | 1856 | 0 | )); | 1857 | | } | 1858 | | } | 1859 | | } | 1860 | 15.6k | } |
_RNvMsh_NtNtCseuYC0Zibziv_7smoldot8executor12runtime_callNtB5_5Inner3run Line | Count | Source | 1362 | 211 | fn run(mut self) -> RuntimeCall { | 1363 | | loop { | 1364 | 676 | match self.root_calculation.take() { | 1365 | 676 | None => {} | 1366 | 0 | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { | 1367 | 0 | self.root_calculation = Some(( | 1368 | 0 | trie, | 1369 | 0 | trie_root_calculator::InProgress::ClosestDescendant(calc_req), | 1370 | 0 | )); | 1371 | 0 | return RuntimeCall::NextKey(NextKey { | 1372 | 0 | inner: self, | 1373 | 0 | key_overwrite: None, | 1374 | 0 | keys_removed_so_far: 0, | 1375 | 0 | }); | 1376 | | } | 1377 | 0 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { | 1378 | 0 | if calc_req | 1379 | 0 | .key() | 1380 | 0 | .fold(0, |count, slice| count + slice.as_ref().len()) | 1381 | 0 | % 2 | 1382 | 0 | == 0 | 1383 | | { | 1384 | 0 | self.root_calculation = Some(( | 1385 | 0 | trie, | 1386 | 0 | trie_root_calculator::InProgress::StorageValue(calc_req), | 1387 | 0 | )); | 1388 | 0 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1389 | | } else { | 1390 | | // If the number of nibbles in the key is uneven, we are sure that | 1391 | | // there exists no storage value. | 1392 | 0 | self.root_calculation = Some((trie, calc_req.inject_value(None))); | 1393 | 0 | continue; | 1394 | | } | 1395 | | } | 1396 | | Some(( | 1397 | 0 | trie, | 1398 | 0 | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1399 | 0 | )) => { | 1400 | 0 | self.root_calculation = Some(( | 1401 | 0 | trie, | 1402 | 0 | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1403 | 0 | )); | 1404 | 0 | return RuntimeCall::ClosestDescendantMerkleValue( | 1405 | 0 | ClosestDescendantMerkleValue { inner: self }, | 1406 | 0 | ); | 1407 | | } | 1408 | 0 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { | 1409 | 0 | self.pending_storage_changes.tries_changes.insert( | 1410 | 0 | (trie.clone(), ev.key_as_vec()), | 1411 | 0 | PendingStorageChangesTrieNode::InsertUpdate { | 1412 | 0 | new_merkle_value: ev.merkle_value().to_owned(), | 1413 | 0 | partial_key: ev.partial_key().to_owned(), | 1414 | 0 | children_merkle_values: TryFrom::try_from( | 1415 | 0 | ev.children_merkle_values() | 1416 | 0 | .map(|mv| mv.map(|mv| mv.to_owned())) | 1417 | 0 | .collect::<Vec<_>>() | 1418 | 0 | .into_boxed_slice(), | 1419 | 0 | ) | 1420 | 0 | .unwrap(), | 1421 | 0 | }, | 1422 | 0 | ); | 1423 | 0 |
| 1424 | 0 | self.root_calculation = Some((trie, ev.resume())); | 1425 | 0 | continue; | 1426 | | } | 1427 | 0 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { | 1428 | 0 | self.pending_storage_changes.tries_changes.insert( | 1429 | 0 | (trie.clone(), ev.key_as_vec()), | 1430 | 0 | PendingStorageChangesTrieNode::Removed, | 1431 | 0 | ); | 1432 | 0 |
| 1433 | 0 | self.root_calculation = Some((trie, ev.resume())); | 1434 | 0 | continue; | 1435 | | } | 1436 | 0 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { | 1437 | 0 | self.pending_storage_changes | 1438 | 0 | .stale_child_tries_root_hashes | 1439 | 0 | .remove(&trie); | 1440 | | | 1441 | | // If we've finished calculating a child trie, update its entry in the | 1442 | | // main trie. | 1443 | 0 | if let Some(child_trie) = &trie { | 1444 | 0 | let mut main_trie_key = Vec::with_capacity( | 1445 | 0 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), | 1446 | 0 | ); | 1447 | 0 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); | 1448 | 0 | main_trie_key.extend_from_slice(child_trie); | 1449 | 0 |
| 1450 | 0 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { | 1451 | 0 | self.pending_storage_changes | 1452 | 0 | .trie_diffs | 1453 | 0 | .entry(None) | 1454 | 0 | .or_default() | 1455 | 0 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); | 1456 | 0 | } else { | 1457 | 0 | self.pending_storage_changes | 1458 | 0 | .trie_diffs | 1459 | 0 | .entry(None) | 1460 | 0 | .or_default() | 1461 | 0 | .diff_insert_erase(main_trie_key, ()); | 1462 | 0 | } | 1463 | | | 1464 | 0 | self.pending_storage_changes | 1465 | 0 | .stale_child_tries_root_hashes | 1466 | 0 | .insert(None); | 1467 | 0 | } | 1468 | | | 1469 | | // Resume the VM execution only if the calculated trie is the one that was | 1470 | | // requested by the runtime. | 1471 | 0 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { | 1472 | | // Code below is a bit convoluted due to borrow checker issues. | 1473 | 0 | let trie_match = match (req.child_trie(), trie) { | 1474 | 0 | (None, None) => true, | 1475 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, | 1476 | 0 | _ => false, | 1477 | | }; | 1478 | 0 | if trie_match { | 1479 | 0 | self.vm = req.resume(&trie_root_hash); | 1480 | 0 | } else { | 1481 | 0 | self.vm = host::HostVm::ExternalStorageRoot(req); | 1482 | 0 | } | 1483 | 0 | } | 1484 | | | 1485 | 0 | continue; | 1486 | | } | 1487 | | } | 1488 | | | 1489 | | // If the the runtime requests the trie root hash of the main trie, we must first | 1490 | | // recalculate the trie root hash of every single child trie that has been modified | 1491 | | // since the previous trie root hash calculation. | 1492 | | // This is also done if execution is finished, in order for the diff provided as | 1493 | | // output to be accurate. | 1494 | | { | 1495 | 676 | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { | 1496 | | host::HostVm::Finished(_) => { | 1497 | 127 | if let Some(child_trie0 ) = self | 1498 | 127 | .pending_storage_changes | 1499 | 127 | .stale_child_tries_root_hashes | 1500 | 127 | .iter() | 1501 | 127 | .find_map(|ct| ct.as_ref()) | 1502 | | { | 1503 | 0 | Some(Some(either::Right(child_trie))) | 1504 | 127 | } else if self | 1505 | 127 | .pending_storage_changes | 1506 | 127 | .stale_child_tries_root_hashes | 1507 | 127 | .contains(&None) | 1508 | 0 | && self.calculate_trie_changes | 1509 | | { | 1510 | 0 | Some(None) | 1511 | | } else { | 1512 | 127 | None | 1513 | | } | 1514 | | } | 1515 | 0 | host::HostVm::ExternalStorageRoot(req) => { | 1516 | 0 | if let Some(child_trie) = req.child_trie() { | 1517 | 0 | Some(Some(either::Left(child_trie))) | 1518 | | } else { | 1519 | | // Find any child trie in `pending_storage_changes`. If `None` is | 1520 | | // found, calculate the main trie. | 1521 | | // It is important to calculate the child tries before the main tries. | 1522 | 0 | Some( | 1523 | 0 | self.pending_storage_changes | 1524 | 0 | .stale_child_tries_root_hashes | 1525 | 0 | .iter() | 1526 | 0 | .find_map(|ct| ct.as_ref()) | 1527 | 0 | .map(|t| either::Right(&t[..])), | 1528 | 0 | ) | 1529 | | } | 1530 | | } | 1531 | 549 | _ => None, | 1532 | | }; | 1533 | | | 1534 | 676 | if let Some(trie_to_flush0 ) = trie_to_flush { | 1535 | | // Remove from `tries_changes` all the changes concerning this trie. | 1536 | | // TODO: O(n) and generally not optimized | 1537 | | { | 1538 | 0 | let to_remove = self | 1539 | 0 | .pending_storage_changes | 1540 | 0 | .tries_changes | 1541 | 0 | .range(( | 1542 | 0 | ops::Bound::Included(( | 1543 | 0 | trie_to_flush | 1544 | 0 | .as_ref() | 1545 | 0 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), | 1546 | 0 | Vec::new(), | 1547 | 0 | )), | 1548 | 0 | ops::Bound::Unbounded, | 1549 | 0 | )) | 1550 | 0 | .take_while(|((ct, _), _)| { | 1551 | | ct.as_ref().map(|ct| &ct[..]) | 1552 | | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1553 | 0 | }) | 1554 | 0 | .map(|(k, _)| k.clone()) | 1555 | 0 | .collect::<Vec<_>>(); | 1556 | 0 | for to_remove in to_remove { | 1557 | 0 | self.pending_storage_changes | 1558 | 0 | .tries_changes | 1559 | 0 | .remove(&to_remove); | 1560 | 0 | } | 1561 | | } | 1562 | | | 1563 | | // TODO: don't clone? | 1564 | 0 | let diff = match self | 1565 | 0 | .pending_storage_changes | 1566 | 0 | .trie_diffs | 1567 | 0 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead | 1568 | | { | 1569 | 0 | None => storage_diff::TrieDiff::empty(), | 1570 | 0 | Some(diff) => diff.clone(), | 1571 | | }; | 1572 | | | 1573 | 0 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. | 1574 | 0 | self.root_calculation = Some(( | 1575 | 0 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), | 1576 | 0 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { | 1577 | 0 | diff, | 1578 | 0 | diff_trie_entries_version: self.state_trie_version, | 1579 | 0 | max_trie_recalculation_depth_hint: 16, // TODO: ?! | 1580 | 0 | }), | 1581 | 0 | )); | 1582 | 0 | continue; | 1583 | 676 | } | 1584 | | } | 1585 | | | 1586 | 676 | if matches!549 (self.vm, host::HostVm::Finished(_)) | 1587 | 127 | && !self.offchain_storage_changes.is_empty() | 1588 | | { | 1589 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); | 1590 | 676 | } | 1591 | 676 | | 1592 | 676 | match self.vm { | 1593 | 338 | host::HostVm::ReadyToRun(r) => self.vm = r.run(), | 1594 | | | 1595 | 0 | host::HostVm::Error { error, prototype } => { | 1596 | 0 | return RuntimeCall::Finished(Err(Error { | 1597 | 0 | detail: error, | 1598 | 0 | prototype, | 1599 | 0 | })); | 1600 | | } | 1601 | | | 1602 | 127 | host::HostVm::Finished(finished) => { | 1603 | 127 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. | 1604 | 127 | debug_assert!( | 1605 | 127 | self.pending_storage_changes | 1606 | 127 | .stale_child_tries_root_hashes | 1607 | 127 | .is_empty() | 1608 | 0 | || (!self.calculate_trie_changes | 1609 | 0 | && self | 1610 | 0 | .pending_storage_changes | 1611 | 0 | .stale_child_tries_root_hashes | 1612 | 0 | .len() | 1613 | 0 | == 1 | 1614 | 0 | && self | 1615 | 0 | .pending_storage_changes | 1616 | 0 | .stale_child_tries_root_hashes | 1617 | 0 | .contains(&None)) | 1618 | | ); | 1619 | 127 | debug_assert!(self.offchain_storage_changes.is_empty()); | 1620 | | | 1621 | 127 | return RuntimeCall::Finished(Ok(Success { | 1622 | 127 | virtual_machine: SuccessVirtualMachine(finished), | 1623 | 127 | storage_changes: StorageChanges { | 1624 | 127 | inner: self.pending_storage_changes, | 1625 | 127 | calculate_trie_changes: self.calculate_trie_changes, | 1626 | 127 | }, | 1627 | 127 | state_trie_version: self.state_trie_version, | 1628 | 127 | })); | 1629 | | } | 1630 | | | 1631 | 84 | host::HostVm::ExternalStorageGet(req) => { | 1632 | 84 | let diff_search = self | 1633 | 84 | .pending_storage_changes | 1634 | 84 | .trie_diffs | 1635 | 84 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1636 | 84 | .and_then(|diff| diff.diff_get(req.key().as_ref())); | 1637 | | | 1638 | 84 | if let Some((value_in_diff0 , _)) = diff_search { | 1639 | 0 | self.vm = req.resume_full_value(value_in_diff); | 1640 | 0 | } else { | 1641 | 84 | self.vm = req.into(); | 1642 | 84 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1643 | | } | 1644 | | } | 1645 | | | 1646 | 0 | host::HostVm::ExternalStorageSet(req) => { | 1647 | 0 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1648 | 0 | // is silently ignored, as per spec. | 1649 | 0 | if req.child_trie().is_none() | 1650 | 0 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1651 | | { | 1652 | 0 | self.vm = req.resume(); | 1653 | 0 | continue; | 1654 | 0 | } | 1655 | 0 |
| 1656 | 0 | // TOOD: to_owned overhead | 1657 | 0 | self.pending_storage_changes | 1658 | 0 | .stale_child_tries_root_hashes | 1659 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1660 | 0 |
| 1661 | 0 | let trie = self | 1662 | 0 | .pending_storage_changes | 1663 | 0 | .trie_diffs | 1664 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1665 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 1666 | | | 1667 | 0 | if let Some(value) = req.value() { | 1668 | 0 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); | 1669 | 0 | } else { | 1670 | 0 | trie.diff_insert_erase(req.key().as_ref(), ()); | 1671 | 0 | } | 1672 | | | 1673 | 0 | self.vm = req.resume() | 1674 | | } | 1675 | | | 1676 | 0 | host::HostVm::ExternalStorageAppend(req) => { | 1677 | 0 | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1678 | 0 | // is silently ignored, as per spec. | 1679 | 0 | if req.child_trie().is_none() | 1680 | 0 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1681 | | { | 1682 | 0 | self.vm = req.resume(); | 1683 | 0 | continue; | 1684 | 0 | } | 1685 | 0 |
| 1686 | 0 | // TOOD: to_owned overhead | 1687 | 0 | self.pending_storage_changes | 1688 | 0 | .stale_child_tries_root_hashes | 1689 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1690 | 0 |
| 1691 | 0 | let trie = self | 1692 | 0 | .pending_storage_changes | 1693 | 0 | .trie_diffs | 1694 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1695 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 1696 | 0 |
| 1697 | 0 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); | 1698 | | | 1699 | 0 | if let Some(current_value) = current_value { | 1700 | 0 | let mut current_value = current_value.unwrap_or_default().to_vec(); | 1701 | 0 | append_to_storage_value(&mut current_value, req.value().as_ref()); | 1702 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); | 1703 | 0 | self.vm = req.resume(); | 1704 | 0 | } else { | 1705 | 0 | self.vm = req.into(); | 1706 | 0 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1707 | | } | 1708 | | } | 1709 | | | 1710 | 0 | host::HostVm::ExternalStorageClearPrefix(req) => { | 1711 | 0 | // Any attempt at clear a prefix that "intersects" (see code) with | 1712 | 0 | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. | 1713 | 0 | if req.child_trie().is_none() | 1714 | 0 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) | 1715 | | { | 1716 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? | 1717 | 0 | continue; | 1718 | 0 | } | 1719 | 0 |
| 1720 | 0 | // TODO: consider doing this only if at least one key was actually removed | 1721 | 0 | // TOOD: to_owned overhead | 1722 | 0 | self.pending_storage_changes | 1723 | 0 | .stale_child_tries_root_hashes | 1724 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1725 | 0 |
| 1726 | 0 | let prefix = req.prefix().as_ref().to_owned(); | 1727 | 0 | self.vm = req.into(); | 1728 | 0 | return RuntimeCall::NextKey(NextKey { | 1729 | 0 | inner: self, | 1730 | 0 | key_overwrite: Some(prefix), | 1731 | 0 | keys_removed_so_far: 0, | 1732 | 0 | }); | 1733 | | } | 1734 | | | 1735 | | host::HostVm::ExternalStorageRoot(_) => { | 1736 | | // Handled above. | 1737 | 0 | unreachable!() | 1738 | | } | 1739 | | | 1740 | 0 | host::HostVm::ExternalStorageNextKey(req) => { | 1741 | 0 | self.vm = req.into(); | 1742 | 0 | return RuntimeCall::NextKey(NextKey { | 1743 | 0 | inner: self, | 1744 | 0 | key_overwrite: None, | 1745 | 0 | keys_removed_so_far: 0, | 1746 | 0 | }); | 1747 | | } | 1748 | | | 1749 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { | 1750 | 0 | self.pending_storage_changes | 1751 | 0 | .offchain_storage_changes | 1752 | 0 | .insert( | 1753 | 0 | req.key().as_ref().to_vec(), | 1754 | 0 | req.value().map(|v| v.as_ref().to_vec()), | 1755 | 0 | ); | 1756 | 0 |
| 1757 | 0 | self.vm = req.resume(); | 1758 | 0 | } | 1759 | | | 1760 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { | 1761 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); | 1762 | 0 | match current_value { | 1763 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), | 1764 | | None => { | 1765 | 0 | self.vm = req.into(); | 1766 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( | 1767 | 0 | OffchainStorageGet { inner: self }, | 1768 | 0 | )); | 1769 | | } | 1770 | | } | 1771 | | } | 1772 | | | 1773 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { | 1774 | 0 | self.vm = req.into(); | 1775 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( | 1776 | 0 | OffchainStorageCompareSet { inner: self }, | 1777 | 0 | )); | 1778 | | } | 1779 | | | 1780 | 0 | host::HostVm::SignatureVerification(req) => { | 1781 | 0 | self.vm = req.into(); | 1782 | 0 | return RuntimeCall::SignatureVerification(SignatureVerification { | 1783 | 0 | inner: self, | 1784 | 0 | }); | 1785 | | } | 1786 | | | 1787 | 0 | host::HostVm::CallRuntimeVersion(req) => { | 1788 | 0 | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 | 1789 | 0 | // The code below compiles the provided WebAssembly runtime code, which is a | 1790 | 0 | // relatively expensive operation (in the order of milliseconds). | 1791 | 0 | // While it could be tempting to use a system cache, this function is expected | 1792 | 0 | // to be called only right before runtime upgrades. Considering that runtime | 1793 | 0 | // upgrades are quite uncommon and that a caching system is rather non-trivial | 1794 | 0 | // to set up, the approach of recompiling every single time is preferred here. | 1795 | 0 | // TODO: number of heap pages?! we use the default here, but not sure whether that's correct or if we have to take the current heap pages | 1796 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { | 1797 | 0 | module: req.wasm_code(), | 1798 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, | 1799 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, | 1800 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? | 1801 | 0 | }) { | 1802 | 0 | Ok(w) => w, | 1803 | | Err(_) => { | 1804 | 0 | self.vm = req.resume(Err(())); | 1805 | 0 | continue; | 1806 | | } | 1807 | | }; | 1808 | | | 1809 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); | 1810 | | } | 1811 | | | 1812 | 0 | host::HostVm::StartStorageTransaction(tx) => { | 1813 | 0 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated | 1814 | 0 | self.transactions_stack | 1815 | 0 | .push(self.pending_storage_changes.clone()); | 1816 | 0 | self.vm = tx.resume(); | 1817 | 0 | } | 1818 | | | 1819 | 0 | host::HostVm::EndStorageTransaction { resume, rollback } => { | 1820 | 0 | // The inner implementation guarantees that a storage transaction can only | 1821 | 0 | // end if it has earlier been started. | 1822 | 0 | debug_assert!(!self.transactions_stack.is_empty()); | 1823 | 0 | let rollback_diff = self.transactions_stack.pop().unwrap(); | 1824 | 0 |
| 1825 | 0 | if rollback { | 1826 | 0 | self.pending_storage_changes = rollback_diff; | 1827 | 0 | } | 1828 | | | 1829 | 0 | self.vm = resume.resume(); | 1830 | | } | 1831 | | | 1832 | 127 | host::HostVm::GetMaxLogLevel(resume) => { | 1833 | 127 | self.vm = resume.resume(self.max_log_level); | 1834 | 127 | } | 1835 | | | 1836 | 0 | host::HostVm::LogEmit(req) => { | 1837 | 0 | self.vm = req.into(); | 1838 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); | 1839 | | } | 1840 | 0 | host::HostVm::OffchainTimestamp(req) => { | 1841 | 0 | self.vm = req.into(); | 1842 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { | 1843 | 0 | inner: self, | 1844 | 0 | })); | 1845 | | } | 1846 | 0 | host::HostVm::OffchainRandomSeed(req) => { | 1847 | 0 | self.vm = req.into(); | 1848 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( | 1849 | 0 | OffchainRandomSeed { inner: self }, | 1850 | 0 | )); | 1851 | | } | 1852 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { | 1853 | 0 | self.vm = req.into(); | 1854 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( | 1855 | 0 | OffchainSubmitTransaction { inner: self }, | 1856 | 0 | )); | 1857 | | } | 1858 | | } | 1859 | | } | 1860 | 211 | } |
|
1861 | | } |
1862 | | |
1863 | | /// Performs the action described by [`host::HostVm::ExternalStorageAppend`] on an |
1864 | | /// encoded storage value. |
1865 | 71 | fn append_to_storage_value(value: &mut Vec<u8>, to_add: &[u8]) { |
1866 | 55 | let (curr_len, curr_len_encoded_size) = |
1867 | 71 | match util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(value) { |
1868 | 55 | Ok((rest, l)) => (l, value.len() - rest.len()), |
1869 | | Err(_) => { |
1870 | 16 | value.clear(); |
1871 | 16 | value.reserve(to_add.len() + 1); |
1872 | 16 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); |
1873 | 16 | value.extend_from_slice(to_add); |
1874 | 16 | return; |
1875 | | } |
1876 | | }; |
1877 | | |
1878 | | // Note: we use `checked_add`, as it is possible that the storage entry erroneously starts |
1879 | | // with `u64::MAX`. |
1880 | 55 | let new_len = match curr_len.checked_add(1) { |
1881 | 55 | Some(l) => l, |
1882 | | None => { |
1883 | 0 | value.clear(); |
1884 | 0 | value.reserve(to_add.len() + 1); |
1885 | 0 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); |
1886 | 0 | value.extend_from_slice(to_add); |
1887 | 0 | return; |
1888 | | } |
1889 | | }; |
1890 | | |
1891 | 55 | let new_len_encoded = util::encode_scale_compact_usize(new_len); |
1892 | 55 | |
1893 | 55 | let new_len_encoded_size = new_len_encoded.as_ref().len(); |
1894 | 55 | debug_assert!( |
1895 | 55 | new_len_encoded_size == curr_len_encoded_size |
1896 | 0 | || new_len_encoded_size == curr_len_encoded_size + 1 |
1897 | | ); |
1898 | | |
1899 | 55 | value.reserve(to_add.len() + (new_len_encoded_size - curr_len_encoded_size)); |
1900 | 55 | |
1901 | 55 | // Since `new_len_encoded_size` is either equal to `curr_len_encoded_size` or equal to |
1902 | 55 | // `curr_len_encoded_size + 1`, we simply use `insert(0, _)` in the latter case. |
1903 | 55 | if new_len_encoded_size != curr_len_encoded_size { |
1904 | 0 | value.insert(0, 0); |
1905 | 55 | } |
1906 | | |
1907 | 55 | value[..new_len_encoded_size].copy_from_slice(new_len_encoded.as_ref()); |
1908 | 55 | value.extend_from_slice(to_add); |
1909 | 71 | } _RNvNtNtCsN16ciHI6Qf_7smoldot8executor12runtime_call23append_to_storage_value Line | Count | Source | 1865 | 71 | fn append_to_storage_value(value: &mut Vec<u8>, to_add: &[u8]) { | 1866 | 55 | let (curr_len, curr_len_encoded_size) = | 1867 | 71 | match util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(value) { | 1868 | 55 | Ok((rest, l)) => (l, value.len() - rest.len()), | 1869 | | Err(_) => { | 1870 | 16 | value.clear(); | 1871 | 16 | value.reserve(to_add.len() + 1); | 1872 | 16 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); | 1873 | 16 | value.extend_from_slice(to_add); | 1874 | 16 | return; | 1875 | | } | 1876 | | }; | 1877 | | | 1878 | | // Note: we use `checked_add`, as it is possible that the storage entry erroneously starts | 1879 | | // with `u64::MAX`. | 1880 | 55 | let new_len = match curr_len.checked_add(1) { | 1881 | 55 | Some(l) => l, | 1882 | | None => { | 1883 | 0 | value.clear(); | 1884 | 0 | value.reserve(to_add.len() + 1); | 1885 | 0 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); | 1886 | 0 | value.extend_from_slice(to_add); | 1887 | 0 | return; | 1888 | | } | 1889 | | }; | 1890 | | | 1891 | 55 | let new_len_encoded = util::encode_scale_compact_usize(new_len); | 1892 | 55 | | 1893 | 55 | let new_len_encoded_size = new_len_encoded.as_ref().len(); | 1894 | 55 | debug_assert!( | 1895 | 55 | new_len_encoded_size == curr_len_encoded_size | 1896 | 0 | || new_len_encoded_size == curr_len_encoded_size + 1 | 1897 | | ); | 1898 | | | 1899 | 55 | value.reserve(to_add.len() + (new_len_encoded_size - curr_len_encoded_size)); | 1900 | 55 | | 1901 | 55 | // Since `new_len_encoded_size` is either equal to `curr_len_encoded_size` or equal to | 1902 | 55 | // `curr_len_encoded_size + 1`, we simply use `insert(0, _)` in the latter case. | 1903 | 55 | if new_len_encoded_size != curr_len_encoded_size { | 1904 | 0 | value.insert(0, 0); | 1905 | 55 | } | 1906 | | | 1907 | 55 | value[..new_len_encoded_size].copy_from_slice(new_len_encoded.as_ref()); | 1908 | 55 | value.extend_from_slice(to_add); | 1909 | 71 | } |
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot8executor12runtime_call23append_to_storage_value |