/__w/smoldot/smoldot/repo/lib/src/executor/runtime_call.rs
Line | Count | Source |
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 | | |
109 | | 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 | 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 | .run()) |
139 | 138 | } _RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherIBU_RShINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EEIBU_B1v_IBU_INtNtCsaFPxhswmqCN_5alloc3vec3VechEB1s_EEEINtNtNtNtCs1p5UDGgVI4d_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_ 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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EIBU_Ahj8_IBU_B1o_B2i_EEEINtNtNtNtCs1p5UDGgVI4d_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_ 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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherRAhj1_IBU_RShRINtNtCsaFPxhswmqCN_5alloc3vec3VechEEEINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters5chain5ChainIB2e_INtNtB2i_3map3MapINtNtNtB2k_7sources4once4OnceB1o_ENcNtBT_4Left0EIB3b_IB3b_IB3s_B1B_ENcNtB1u_5Right0ENcNtBT_5Right0EEIB3b_IB3b_IB3s_B1y_ENcNtB1u_4Left0EB4N_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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherRINtNtCsaFPxhswmqCN_5alloc3vec3VechEIBU_B1o_INtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters5chain5ChainIB2Z_INtNtNtB35_7sources4once4OnceBT_EB3V_EINtNtB33_3map3MapINtNtNtB37_5slice4iter4IterNtNtB2_5tests9HexStringENCNvB5h_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 | | | 109 | | 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 | 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 | | } | 138 | 4 | .run()) | 139 | 4 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources5empty5EmptyBT_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 | | | 109 | | 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 | 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 | | } | 138 | 2 | .run()) | 139 | 2 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
_RINvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call3runRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources5empty5EmptyBT_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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_EECscoAnRPySggw_6author _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources5empty5EmptyBT_EECsfFWJyR6nd6r_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 | | | 109 | | 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 | 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 | | } | 138 | 1 | .run()) | 139 | 1 | } |
Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherIBU_RShINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EEIBU_B1v_IBU_INtNtCsaFPxhswmqCN_5alloc3vec3VechEB1s_EEEINtNtNtNtCs1p5UDGgVI4d_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: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runINtCsfDbbEgL1j7J_6either6EitherINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EIBU_Ahj8_IBU_B1o_B2i_EEEINtNtNtNtCs1p5UDGgVI4d_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_ _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_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 | | | 109 | | 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 | 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 | | } | 138 | 126 | .run()) | 139 | 126 | } |
Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_EEB6_ Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources5empty5EmptyBT_EEB6_ Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_EECs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call3runRRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceBT_EECs4VrkfB1pvQ3_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: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges5empty Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges18main_trie_diff_get0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges18main_trie_diff_get0B8_ |
190 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges18main_trie_diff_get Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0CsfFWJyR6nd6r_17smoldot_full_node Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges40main_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00CsfFWJyR6nd6r_17smoldot_full_node Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges40main_trie_storage_changes_iter_unordered00Ba_ |
209 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges40main_trie_storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges36tries_with_storage_changes_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges36tries_with_storage_changes_unordered0B8_ |
214 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges36tries_with_storage_changes_unordered Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges41child_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges41child_trie_storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChanges41child_trie_storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges41child_trie_storage_changes_iter_unordered00Ba_ |
234 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges41child_trie_storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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: _RNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChanges30storage_changes_iter_unordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges30storage_changes_iter_unordered00Ba_ |
246 | 0 | }) Unexecuted instantiation: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges30storage_changes_iter_unordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges30storage_changes_iter_unordered0B8_ |
247 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges30storage_changes_iter_unordered Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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 | | |
261 | | 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 | | } => { |
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: _RNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00CscoAnRPySggw_6author Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered00Cs4VrkfB1pvQ3_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: _RNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0Ba_ Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChanges25trie_changes_iter_ordered0s_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCNCNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00Bc_ Unexecuted instantiation: _RNCNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00CscoAnRPySggw_6author Unexecuted instantiation: _RNCNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00Bc_ Unexecuted instantiation: _RNCNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCNCNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChanges25trie_changes_iter_ordered0s_00Cs4VrkfB1pvQ3_25json_rpc_general_requests |
298 | 0 | .collect::<Box<[_]>>(), |
299 | | ) |
300 | 0 | .unwrap(); |
301 | | |
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: _RNCNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0CscoAnRPySggw_6author Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0B8_ Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCNvMNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChanges25trie_changes_iter_ordered0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
313 | | ) |
314 | 0 | } Unexecuted instantiation: _RNvMNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB2_14StorageChanges25trie_changes_iter_ordered Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_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 | } _RNvMNtNtCsjlkOsLH0Zfj_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: _RNvMNtNtCsc1ywvx6YAnK_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt00Bc_ Unexecuted instantiation: _RNCNCNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt0Ba_ Unexecuted instantiation: _RNCNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtBa_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_000Be_ Unexecuted instantiation: _RNCNCNCNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_14StorageChangesNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_00Bc_ Unexecuted instantiation: _RNCNCNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_00Bc_ |
390 | 0 | })) Unexecuted instantiation: _RNCNvXs_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_0Ba_ Unexecuted instantiation: _RNCNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_0Ba_ |
391 | 0 | .finish() |
392 | | } |
393 | 0 | } Unexecuted instantiation: _RNvXs_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB4_14StorageChangesNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB4_14StorageChangesNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt0Bb_ Unexecuted instantiation: _RNCNvXs0_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt0Bb_ |
428 | 0 | .collect::<String>(), |
429 | | ) |
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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_0Bb_ Unexecuted instantiation: _RNCNvXs0_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_10TrieChangeNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmts_0Bb_ |
438 | 0 | .collect::<Vec<_>>() |
439 | 0 | .join(","), |
440 | | ) |
441 | 0 | .field("new_storage_value", new_storage_value) |
442 | 0 | .finish(), |
443 | | } |
444 | 0 | } Unexecuted instantiation: _RNvXs0_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_10TrieChangeNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs0_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_10TrieChangeNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_22TrieChangeStorageValueNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs1_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_22TrieChangeStorageValueNtNtCs1p5UDGgVI4d_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachine5value Line | Count | Source | 475 | 6 | pub fn value(&self) -> impl AsRef<[u8]> { | 476 | 6 | self.0.value() | 477 | 6 | } |
_RNvMs2_NtNtCsc1ywvx6YAnK_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_NtNtCsjlkOsLH0Zfj_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_NtNtCsc1ywvx6YAnK_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_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachineNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs3_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SuccessVirtualMachineNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt |
489 | | } |
490 | | |
491 | | /// Error that can happen during the execution. |
492 | | #[derive(Debug, derive_more::Display, derive_more::Error)] |
493 | | #[display("{detail}")] |
494 | | pub struct Error { |
495 | | /// Exact error that happened. |
496 | | #[error(source)] |
497 | | pub detail: ErrorDetail, |
498 | | /// Prototype of the virtual machine that was passed through [`Config::virtual_machine`]. |
499 | | pub prototype: host::HostVmPrototype, |
500 | | } |
501 | | |
502 | | /// Current state of the execution. |
503 | | #[must_use] |
504 | | pub enum RuntimeCall { |
505 | | /// Execution is over. |
506 | | Finished(Result<Success, Error>), |
507 | | /// Loading a storage value is required in order to continue. |
508 | | StorageGet(StorageGet), |
509 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
510 | | /// to continue. |
511 | | ClosestDescendantMerkleValue(ClosestDescendantMerkleValue), |
512 | | /// Fetching the key that follows a given one is required in order to continue. |
513 | | NextKey(NextKey), |
514 | | /// Verifying whether a signature is correct is required in order to continue. |
515 | | SignatureVerification(SignatureVerification), |
516 | | /// Runtime would like to emit some log. |
517 | | LogEmit(LogEmit), |
518 | | /// Setting an offchain storage value is required in order to continue. |
519 | | /// |
520 | | /// Contrary to [`OffchainContext::StorageSet`], this variant is allowed to happen |
521 | | /// outside of offchain workers. |
522 | | OffchainStorageSet(OffchainStorageSet), |
523 | | /// Functions that can only be called within the context of an offchain worker. |
524 | | Offchain(OffchainContext), |
525 | | } |
526 | | |
527 | | impl RuntimeCall { |
528 | | /// Cancels execution of the virtual machine and returns back the prototype. |
529 | 0 | pub fn into_prototype(self) -> host::HostVmPrototype { |
530 | 0 | match self { |
531 | 0 | RuntimeCall::Finished(Ok(inner)) => inner.virtual_machine.into_prototype(), |
532 | 0 | RuntimeCall::Finished(Err(inner)) => inner.prototype, |
533 | 0 | RuntimeCall::StorageGet(inner) => inner.inner.vm.into_prototype(), |
534 | 0 | RuntimeCall::ClosestDescendantMerkleValue(inner) => inner.inner.vm.into_prototype(), |
535 | 0 | RuntimeCall::NextKey(inner) => inner.inner.vm.into_prototype(), |
536 | 0 | RuntimeCall::SignatureVerification(inner) => inner.inner.vm.into_prototype(), |
537 | 0 | RuntimeCall::LogEmit(inner) => inner.inner.vm.into_prototype(), |
538 | 0 | RuntimeCall::OffchainStorageSet(inner) => inner.inner.vm.into_prototype(), |
539 | 0 | RuntimeCall::Offchain(inner) => inner.into_prototype(), |
540 | | } |
541 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_11RuntimeCall14into_prototype Unexecuted instantiation: _RNvMs4_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_11RuntimeCall14into_prototype |
542 | | } |
543 | | |
544 | | pub enum OffchainContext { |
545 | | /// Loading an offchain storage value is required in order to continue. |
546 | | StorageGet(OffchainStorageGet), |
547 | | /// Setting an offchain storage value is required in order to continue. |
548 | | /// |
549 | | /// Contrary to [`RuntimeCall::OffchainStorageSet`], this variant can only happen in offchain |
550 | | /// workers. |
551 | | StorageSet(OffchainStorageCompareSet), |
552 | | /// Timestamp for offchain worker. |
553 | | Timestamp(OffchainTimestamp), |
554 | | /// Random seed for offchain worker. |
555 | | RandomSeed(OffchainRandomSeed), |
556 | | /// Submit transaction from offchain worker. |
557 | | SubmitTransaction(OffchainSubmitTransaction), |
558 | | } |
559 | | |
560 | | impl OffchainContext { |
561 | 0 | pub fn into_prototype(self) -> host::HostVmPrototype { |
562 | 0 | match self { |
563 | 0 | OffchainContext::StorageGet(inner) => inner.inner.vm.into_prototype(), |
564 | 0 | OffchainContext::StorageSet(inner) => inner.inner.vm.into_prototype(), |
565 | 0 | OffchainContext::Timestamp(inner) => inner.inner.vm.into_prototype(), |
566 | 0 | OffchainContext::RandomSeed(inner) => inner.inner.vm.into_prototype(), |
567 | 0 | OffchainContext::SubmitTransaction(inner) => inner.inner.vm.into_prototype(), |
568 | | } |
569 | 0 | } Unexecuted instantiation: _RNvMs5_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_15OffchainContext14into_prototype Unexecuted instantiation: _RNvMs5_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_15OffchainContext14into_prototype |
570 | | } |
571 | | |
572 | | /// Loading a storage value is required in order to continue. |
573 | | #[must_use] |
574 | | pub struct StorageGet { |
575 | | inner: Inner, |
576 | | } |
577 | | |
578 | | impl StorageGet { |
579 | | /// Returns the key whose value must be passed to [`StorageGet::inject_value`]. |
580 | 9.27k | pub fn key(&self) -> impl AsRef<[u8]> { |
581 | | enum Three<A, B, C> { |
582 | | A(A), |
583 | | B(B), |
584 | | C(C), |
585 | | } |
586 | | |
587 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
588 | 9.27k | fn as_ref(&self) -> &[u8] { |
589 | 9.27k | match self { |
590 | 2.22k | Three::A(a) => a.as_ref(), |
591 | 8 | Three::B(b) => b.as_ref(), |
592 | 7.05k | Three::C(c) => c.as_ref(), |
593 | | } |
594 | 9.27k | } _RNvXNvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refBc_ Line | Count | Source | 588 | 9.19k | fn as_ref(&self) -> &[u8] { | 589 | 9.19k | match self { | 590 | 2.13k | Three::A(a) => a.as_ref(), | 591 | 8 | Three::B(b) => b.as_ref(), | 592 | 7.05k | Three::C(c) => c.as_ref(), | 593 | | } | 594 | 9.19k | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refCscoAnRPySggw_6author Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refCsfFWJyR6nd6r_17smoldot_full_node _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refBc_ Line | Count | Source | 588 | 84 | fn as_ref(&self) -> &[u8] { | 589 | 84 | match self { | 590 | 84 | Three::A(a) => a.as_ref(), | 591 | 0 | Three::B(b) => b.as_ref(), | 592 | 0 | Three::C(c) => c.as_ref(), | 593 | | } | 594 | 84 | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refCs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refCsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet3keyINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB29_11Interpreter11read_memory12AccessOffsetB1X_EEB1s_INtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB1Y_E6as_refCs4VrkfB1pvQ3_25json_rpc_general_requests |
595 | | } |
596 | | |
597 | 9.27k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
598 | 2.22k | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), |
599 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), |
600 | 7.05k | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { |
601 | | // TODO: optimize? |
602 | 49.3k | let key_nibbles7.05k = value_request7.05k .key7.05k ().fold7.05k (Vec::new7.05k (), |mut a, b| { |
603 | 49.3k | a.extend_from_slice(b.as_ref()); |
604 | 49.3k | a |
605 | 49.3k | }); _RNCNvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_10StorageGet3key0Bb_ Line | Count | Source | 602 | 49.3k | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 603 | 49.3k | a.extend_from_slice(b.as_ref()); | 604 | 49.3k | a | 605 | 49.3k | }); |
Unexecuted instantiation: _RNCNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_10StorageGet3key0Bb_ |
606 | 7.05k | debug_assert_eq!(key_nibbles.len() % 2, 0); |
607 | 7.05k | Three::C( |
608 | 7.05k | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) |
609 | 7.05k | .collect::<Vec<_>>(), |
610 | 7.05k | ) |
611 | | } |
612 | | |
613 | | // We only create a `StorageGet` if the state is one of the above. |
614 | 0 | _ => unreachable!(), |
615 | | } |
616 | 9.27k | } _RNvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_10StorageGet3key Line | Count | Source | 580 | 9.19k | pub fn key(&self) -> impl AsRef<[u8]> { | 581 | | enum Three<A, B, C> { | 582 | | A(A), | 583 | | B(B), | 584 | | C(C), | 585 | | } | 586 | | | 587 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 588 | | fn as_ref(&self) -> &[u8] { | 589 | | match self { | 590 | | Three::A(a) => a.as_ref(), | 591 | | Three::B(b) => b.as_ref(), | 592 | | Three::C(c) => c.as_ref(), | 593 | | } | 594 | | } | 595 | | } | 596 | | | 597 | 9.19k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 598 | 2.13k | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), | 599 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), | 600 | 7.05k | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 601 | | // TODO: optimize? | 602 | 7.05k | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 603 | | a.extend_from_slice(b.as_ref()); | 604 | | a | 605 | | }); | 606 | 7.05k | debug_assert_eq!(key_nibbles.len() % 2, 0); | 607 | 7.05k | Three::C( | 608 | 7.05k | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) | 609 | 7.05k | .collect::<Vec<_>>(), | 610 | 7.05k | ) | 611 | | } | 612 | | | 613 | | // We only create a `StorageGet` if the state is one of the above. | 614 | 0 | _ => unreachable!(), | 615 | | } | 616 | 9.19k | } |
_RNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_10StorageGet3key Line | Count | Source | 580 | 84 | pub fn key(&self) -> impl AsRef<[u8]> { | 581 | | enum Three<A, B, C> { | 582 | | A(A), | 583 | | B(B), | 584 | | C(C), | 585 | | } | 586 | | | 587 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 588 | | fn as_ref(&self) -> &[u8] { | 589 | | match self { | 590 | | Three::A(a) => a.as_ref(), | 591 | | Three::B(b) => b.as_ref(), | 592 | | Three::C(c) => c.as_ref(), | 593 | | } | 594 | | } | 595 | | } | 596 | | | 597 | 84 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 598 | 84 | (host::HostVm::ExternalStorageGet(req), None) => Three::A(req.key()), | 599 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => Three::B(req.key()), | 600 | 0 | (_, Some((_, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 601 | | // TODO: optimize? | 602 | 0 | let key_nibbles = value_request.key().fold(Vec::new(), |mut a, b| { | 603 | | a.extend_from_slice(b.as_ref()); | 604 | | a | 605 | | }); | 606 | 0 | debug_assert_eq!(key_nibbles.len() % 2, 0); | 607 | 0 | Three::C( | 608 | 0 | trie::nibbles_to_bytes_suffix_extend(key_nibbles.into_iter()) | 609 | 0 | .collect::<Vec<_>>(), | 610 | 0 | ) | 611 | | } | 612 | | | 613 | | // We only create a `StorageGet` if the state is one of the above. | 614 | 0 | _ => unreachable!(), | 615 | | } | 616 | 84 | } |
|
617 | | |
618 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
619 | 449 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
620 | | enum Three<A, B, C> { |
621 | | A(A), |
622 | | B(B), |
623 | | C(C), |
624 | | } |
625 | | |
626 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
627 | 11 | fn as_ref(&self) -> &[u8] { |
628 | 11 | match self { |
629 | 6 | Three::A(a) => a.as_ref(), |
630 | 0 | Three::B(b) => b.as_ref(), |
631 | 5 | Three::C(c) => c.as_ref(), |
632 | | } |
633 | 11 | } _RNvXNvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refBc_ Line | Count | Source | 627 | 11 | fn as_ref(&self) -> &[u8] { | 628 | 11 | match self { | 629 | 6 | Three::A(a) => a.as_ref(), | 630 | 0 | Three::B(b) => b.as_ref(), | 631 | 5 | Three::C(c) => c.as_ref(), | 632 | | } | 633 | 11 | } |
Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refCscoAnRPySggw_6author Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refCsfFWJyR6nd6r_17smoldot_full_node Unexecuted instantiation: _RNvXININvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBb_10StorageGet10child_trie0pppEINtB5_5ThreepppEINtNtCs1p5UDGgVI4d_4core7convert5AsRefShE6as_refBf_ Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refCs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refCsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2h_11Interpreter11read_memory12AccessOffsetB25_EEB25_RINtNtCsaFPxhswmqCN_5alloc3vec3VechEEINtNtCs1p5UDGgVI4d_4core7convert5AsRefB26_E6as_refCs4VrkfB1pvQ3_25json_rpc_general_requests |
634 | | } |
635 | | |
636 | 449 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
637 | 124 | (host::HostVm::ExternalStorageGet(req), None) => req.child_trie().map(Three::A), |
638 | 7 | (host::HostVm::ExternalStorageAppend(req), None) => req.child_trie().map(Three::B), |
639 | 318 | (_, Some((child_trie, trie_root_calculator::InProgress::StorageValue(_)))) => { |
640 | 318 | child_trie.as_ref().map(Three::C) |
641 | | } |
642 | | // We only create a `StorageGet` if the state is one of the above. |
643 | 0 | _ => unreachable!(), |
644 | | } |
645 | 449 | } _RNvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_10StorageGet10child_trie Line | Count | Source | 619 | 449 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { | 620 | | enum Three<A, B, C> { | 621 | | A(A), | 622 | | B(B), | 623 | | C(C), | 624 | | } | 625 | | | 626 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 627 | | fn as_ref(&self) -> &[u8] { | 628 | | match self { | 629 | | Three::A(a) => a.as_ref(), | 630 | | Three::B(b) => b.as_ref(), | 631 | | Three::C(c) => c.as_ref(), | 632 | | } | 633 | | } | 634 | | } | 635 | | | 636 | 449 | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 637 | 124 | (host::HostVm::ExternalStorageGet(req), None) => req.child_trie().map(Three::A), | 638 | 7 | (host::HostVm::ExternalStorageAppend(req), None) => req.child_trie().map(Three::B), | 639 | 318 | (_, Some((child_trie, trie_root_calculator::InProgress::StorageValue(_)))) => { | 640 | 318 | child_trie.as_ref().map(Three::C) | 641 | | } | 642 | | // We only create a `StorageGet` if the state is one of the above. | 643 | 0 | _ => unreachable!(), | 644 | | } | 645 | 449 | } |
Unexecuted instantiation: _RNvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_10StorageGet10child_trie |
646 | | |
647 | | /// Injects the corresponding storage value. |
648 | 697 | pub fn inject_value( |
649 | 697 | mut self, |
650 | 697 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, |
651 | 697 | ) -> RuntimeCall { |
652 | | // TODO: update the implementation to not require the folding here |
653 | 697 | let value = value.map(|(value, version)| {486 |
654 | 486 | let value = value.fold(Vec::new(), |mut a, b| { |
655 | 486 | a.extend_from_slice(b.as_ref()); |
656 | 486 | a |
657 | 486 | }); _RNCNCINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00Be_ Line | Count | Source | 654 | 402 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | 402 | a.extend_from_slice(b.as_ref()); | 656 | 402 | a | 657 | 402 | }); |
Unexecuted instantiation: _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00CscoAnRPySggw_6author Unexecuted instantiation: _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00CsfFWJyR6nd6r_17smoldot_full_node _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00Be_ Line | Count | Source | 654 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | 42 | a.extend_from_slice(b.as_ref()); | 656 | 42 | a | 657 | 42 | }); |
_RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00Be_ Line | Count | Source | 654 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | 42 | a.extend_from_slice(b.as_ref()); | 656 | 42 | a | 657 | 42 | }); |
Unexecuted instantiation: _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBa_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1s_EE00Cs4VrkfB1pvQ3_25json_rpc_general_requests |
658 | 486 | (value, version) |
659 | 486 | }); _RNCINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0Bc_ Line | Count | Source | 653 | 402 | let value = value.map(|(value, version)| { | 654 | 402 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | 402 | (value, version) | 659 | 402 | }); |
Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0CsfFWJyR6nd6r_17smoldot_full_node _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0Bc_ Line | Count | Source | 653 | 42 | let value = value.map(|(value, version)| { | 654 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | 42 | (value, version) | 659 | 42 | }); |
_RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0Bc_ Line | Count | Source | 653 | 42 | let value = value.map(|(value, version)| { | 654 | 42 | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | 42 | (value, version) | 659 | 42 | }); |
Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EE0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
660 | | |
661 | 697 | match (self.inner.vm, self.inner.root_calculation.take()) { |
662 | 251 | (host::HostVm::ExternalStorageGet(req), None) => { |
663 | | // TODO: should actually report the offset and max_size in the API |
664 | 251 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..]177 )); _RNCINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0Bc_ Line | Count | Source | 664 | 93 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0CsfFWJyR6nd6r_17smoldot_full_node _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0Bc_ Line | Count | Source | 664 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
_RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0Bc_ Line | Count | Source | 664 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); |
Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs_0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
665 | | } |
666 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => { |
667 | | // TODO: could be less overhead? |
668 | 8 | let trie = self |
669 | 8 | .inner |
670 | 8 | .pending_storage_changes |
671 | 8 | .trie_diffs |
672 | 8 | .entry(req.child_trie().map(|ct| ct.as_ref()0 .to_vec0 ())) Unexecuted instantiation: _RNCINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueppEs0_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueppEs0_0Bc_ |
673 | 8 | .or_insert(storage_diff::TrieDiff::empty()); |
674 | | |
675 | | // TODO: could be less overhead? |
676 | 8 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); |
677 | 8 | append_to_storage_value(&mut value, req.value().as_ref()); |
678 | 8 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); |
679 | | |
680 | 8 | self.inner.vm = req.resume(); |
681 | | } |
682 | 438 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { |
683 | 438 | self.inner.vm = vm; |
684 | 438 | self.inner.root_calculation = Some(( |
685 | 438 | trie, |
686 | 438 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..]308 , *vers308 ))), _RNCINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0Bc_ Line | Count | Source | 686 | 308 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), |
Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0CsfFWJyR6nd6r_17smoldot_full_node Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1q_EEs2_0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
687 | | )); |
688 | | } |
689 | | |
690 | | // We only create a `StorageGet` if the state is one of the above. |
691 | 0 | _ => unreachable!(), |
692 | | }; |
693 | | |
694 | 697 | self.inner.run() |
695 | 697 | } _RINvMs6_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EEBa_ Line | Count | Source | 648 | 613 | pub fn inject_value( | 649 | 613 | mut self, | 650 | 613 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 651 | 613 | ) -> RuntimeCall { | 652 | | // TODO: update the implementation to not require the folding here | 653 | 613 | let value = value.map(|(value, version)| { | 654 | | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | | (value, version) | 659 | | }); | 660 | | | 661 | 613 | match (self.inner.vm, self.inner.root_calculation.take()) { | 662 | 167 | (host::HostVm::ExternalStorageGet(req), None) => { | 663 | | // TODO: should actually report the offset and max_size in the API | 664 | 167 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 665 | | } | 666 | 8 | (host::HostVm::ExternalStorageAppend(req), None) => { | 667 | | // TODO: could be less overhead? | 668 | 8 | let trie = self | 669 | 8 | .inner | 670 | 8 | .pending_storage_changes | 671 | 8 | .trie_diffs | 672 | 8 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 673 | 8 | .or_insert(storage_diff::TrieDiff::empty()); | 674 | | | 675 | | // TODO: could be less overhead? | 676 | 8 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 677 | 8 | append_to_storage_value(&mut value, req.value().as_ref()); | 678 | 8 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 679 | | | 680 | 8 | self.inner.vm = req.resume(); | 681 | | } | 682 | 438 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 683 | 438 | self.inner.vm = vm; | 684 | 438 | self.inner.root_calculation = Some(( | 685 | 438 | trie, | 686 | 438 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 687 | | )); | 688 | | } | 689 | | | 690 | | // We only create a `StorageGet` if the state is one of the above. | 691 | 0 | _ => unreachable!(), | 692 | | }; | 693 | | | 694 | 613 | self.inner.run() | 695 | 613 | } |
Unexecuted instantiation: _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EECsfFWJyR6nd6r_17smoldot_full_node _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EEBa_ Line | Count | Source | 648 | 42 | pub fn inject_value( | 649 | 42 | mut self, | 650 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 651 | 42 | ) -> RuntimeCall { | 652 | | // TODO: update the implementation to not require the folding here | 653 | 42 | let value = value.map(|(value, version)| { | 654 | | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | | (value, version) | 659 | | }); | 660 | | | 661 | 42 | match (self.inner.vm, self.inner.root_calculation.take()) { | 662 | 42 | (host::HostVm::ExternalStorageGet(req), None) => { | 663 | | // TODO: should actually report the offset and max_size in the API | 664 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 665 | | } | 666 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => { | 667 | | // TODO: could be less overhead? | 668 | 0 | let trie = self | 669 | 0 | .inner | 670 | 0 | .pending_storage_changes | 671 | 0 | .trie_diffs | 672 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 673 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 674 | | | 675 | | // TODO: could be less overhead? | 676 | 0 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 677 | 0 | append_to_storage_value(&mut value, req.value().as_ref()); | 678 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 679 | | | 680 | 0 | self.inner.vm = req.resume(); | 681 | | } | 682 | 0 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 683 | 0 | self.inner.vm = vm; | 684 | 0 | self.inner.root_calculation = Some(( | 685 | 0 | trie, | 686 | 0 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 687 | | )); | 688 | | } | 689 | | | 690 | | // We only create a `StorageGet` if the state is one of the above. | 691 | 0 | _ => unreachable!(), | 692 | | }; | 693 | | | 694 | 42 | self.inner.run() | 695 | 42 | } |
_RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EEBa_ Line | Count | Source | 648 | 42 | pub fn inject_value( | 649 | 42 | mut self, | 650 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 651 | 42 | ) -> RuntimeCall { | 652 | | // TODO: update the implementation to not require the folding here | 653 | 42 | let value = value.map(|(value, version)| { | 654 | | let value = value.fold(Vec::new(), |mut a, b| { | 655 | | a.extend_from_slice(b.as_ref()); | 656 | | a | 657 | | }); | 658 | | (value, version) | 659 | | }); | 660 | | | 661 | 42 | match (self.inner.vm, self.inner.root_calculation.take()) { | 662 | 42 | (host::HostVm::ExternalStorageGet(req), None) => { | 663 | | // TODO: should actually report the offset and max_size in the API | 664 | 42 | self.inner.vm = req.resume_full_value(value.as_ref().map(|(v, _)| &v[..])); | 665 | | } | 666 | 0 | (host::HostVm::ExternalStorageAppend(req), None) => { | 667 | | // TODO: could be less overhead? | 668 | 0 | let trie = self | 669 | 0 | .inner | 670 | 0 | .pending_storage_changes | 671 | 0 | .trie_diffs | 672 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 673 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 674 | | | 675 | | // TODO: could be less overhead? | 676 | 0 | let mut value = value.map(|(v, _)| v).unwrap_or_default(); | 677 | 0 | append_to_storage_value(&mut value, req.value().as_ref()); | 678 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), value, ()); | 679 | | | 680 | 0 | self.inner.vm = req.resume(); | 681 | | } | 682 | 0 | (vm, Some((trie, trie_root_calculator::InProgress::StorageValue(value_request)))) => { | 683 | 0 | self.inner.vm = vm; | 684 | 0 | self.inner.root_calculation = Some(( | 685 | 0 | trie, | 686 | 0 | value_request.inject_value(value.as_ref().map(|(v, vers)| (&v[..], *vers))), | 687 | | )); | 688 | | } | 689 | | | 690 | | // We only create a `StorageGet` if the state is one of the above. | 691 | 0 | _ => unreachable!(), | 692 | | }; | 693 | | | 694 | 42 | self.inner.run() | 695 | 42 | } |
Unexecuted instantiation: _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EECs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs6_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1o_EECs4VrkfB1pvQ3_25json_rpc_general_requests |
696 | | } |
697 | | |
698 | | /// Fetching the key that follows a given one is required in order to continue. |
699 | | #[must_use] |
700 | | pub struct NextKey { |
701 | | inner: Inner, |
702 | | |
703 | | /// If `Some`, ask for the key inside of this field rather than the one of `inner`. |
704 | | key_overwrite: Option<Vec<u8>>, |
705 | | |
706 | | /// Number of keys removed. Used only to implement clearing a prefix, otherwise stays at 0. |
707 | | keys_removed_so_far: u32, |
708 | | } |
709 | | |
710 | | impl NextKey { |
711 | | /// Returns the key whose next key must be passed back. |
712 | 16.4k | pub fn key(&self) -> impl Iterator<Item = Nibble> { |
713 | 16.4k | if let Some(key_overwrite15 ) = &self.key_overwrite { |
714 | 15 | return either::Left(trie::bytes_to_nibbles(key_overwrite.iter().copied())); |
715 | 16.4k | } |
716 | | |
717 | | either::Right( |
718 | 16.4k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
719 | 1 | (host::HostVm::ExternalStorageNextKey(req), _) => { |
720 | 1 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.key()))) |
721 | | } |
722 | | |
723 | 16.4k | (_, Some((_, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { |
724 | 16.4k | either::Right(req.key().flat_map(util::as_ref_iter)) |
725 | | } |
726 | | |
727 | | // Note that in the case `ExternalStorageClearPrefix`, `key_overwrite` is |
728 | | // always `Some`. |
729 | 0 | _ => unreachable!(), |
730 | | }, |
731 | | ) |
732 | 16.4k | } _RNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7NextKey3key Line | Count | Source | 712 | 16.4k | pub fn key(&self) -> impl Iterator<Item = Nibble> { | 713 | 16.4k | if let Some(key_overwrite15 ) = &self.key_overwrite { | 714 | 15 | return either::Left(trie::bytes_to_nibbles(key_overwrite.iter().copied())); | 715 | 16.4k | } | 716 | | | 717 | | either::Right( | 718 | 16.4k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 719 | 1 | (host::HostVm::ExternalStorageNextKey(req), _) => { | 720 | 1 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.key()))) | 721 | | } | 722 | | | 723 | 16.4k | (_, Some((_, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { | 724 | 16.4k | either::Right(req.key().flat_map(util::as_ref_iter)) | 725 | | } | 726 | | | 727 | | // Note that in the case `ExternalStorageClearPrefix`, `key_overwrite` is | 728 | | // always `Some`. | 729 | 0 | _ => unreachable!(), | 730 | | }, | 731 | | ) | 732 | 16.4k | } |
Unexecuted instantiation: _RNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7NextKey3key |
733 | | |
734 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
735 | 12.9k | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
736 | | enum Three<A, B, C> { |
737 | | A(A), |
738 | | B(B), |
739 | | C(C), |
740 | | } |
741 | | |
742 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { |
743 | 144 | fn as_ref(&self) -> &[u8] { |
744 | 144 | match self { |
745 | 0 | Three::A(a) => a.as_ref(), |
746 | 140 | Three::B(b) => b.as_ref(), |
747 | 4 | Three::C(c) => c.as_ref(), |
748 | | } |
749 | 144 | } _RNvXNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refBc_ Line | Count | Source | 743 | 144 | fn as_ref(&self) -> &[u8] { | 744 | 144 | match self { | 745 | 0 | Three::A(a) => a.as_ref(), | 746 | 140 | Three::B(b) => b.as_ref(), | 747 | 4 | Three::C(c) => c.as_ref(), | 748 | | } | 749 | 144 | } |
Unexecuted instantiation: _RNvXNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refCscoAnRPySggw_6author Unexecuted instantiation: _RNvXNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refCsfFWJyR6nd6r_17smoldot_full_node Unexecuted instantiation: _RNvXININvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtBb_7NextKey10child_trie0pppEINtB5_5ThreepppEINtNtCs1p5UDGgVI4d_4core7convert5AsRefShE6as_refBf_ Unexecuted instantiation: _RNvXNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refCs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNvXNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refCsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNvXNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10child_trieINtB2_5ThreeINtCsfDbbEgL1j7J_6either6EitherRShINtNvMs5_NtNtBa_2vm11interpreterNtB2d_11Interpreter11read_memory12AccessOffsetB21_EERINtNtCsaFPxhswmqCN_5alloc3vec3VechEB1w_EINtNtCs1p5UDGgVI4d_4core7convert5AsRefB22_E6as_refCs4VrkfB1pvQ3_25json_rpc_general_requests |
750 | | } |
751 | | |
752 | 12.9k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
753 | 2 | (host::HostVm::ExternalStorageNextKey(req), _) => req.child_trie().map(Three::A), |
754 | 12.9k | (_, Some((child_trie, _))) => child_trie.as_ref().map(Three::B), |
755 | 28 | (host::HostVm::ExternalStorageClearPrefix(req), _) => req.child_trie().map(Three::C), |
756 | 0 | _ => unreachable!(), |
757 | | } |
758 | 12.9k | } _RNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7NextKey10child_trie Line | Count | Source | 735 | 12.9k | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { | 736 | | enum Three<A, B, C> { | 737 | | A(A), | 738 | | B(B), | 739 | | C(C), | 740 | | } | 741 | | | 742 | | impl<A: AsRef<[u8]>, B: AsRef<[u8]>, C: AsRef<[u8]>> AsRef<[u8]> for Three<A, B, C> { | 743 | | fn as_ref(&self) -> &[u8] { | 744 | | match self { | 745 | | Three::A(a) => a.as_ref(), | 746 | | Three::B(b) => b.as_ref(), | 747 | | Three::C(c) => c.as_ref(), | 748 | | } | 749 | | } | 750 | | } | 751 | | | 752 | 12.9k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 753 | 2 | (host::HostVm::ExternalStorageNextKey(req), _) => req.child_trie().map(Three::A), | 754 | 12.9k | (_, Some((child_trie, _))) => child_trie.as_ref().map(Three::B), | 755 | 28 | (host::HostVm::ExternalStorageClearPrefix(req), _) => req.child_trie().map(Three::C), | 756 | 0 | _ => unreachable!(), | 757 | | } | 758 | 12.9k | } |
Unexecuted instantiation: _RNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7NextKey10child_trie |
759 | | |
760 | | /// If `true`, then the provided value must the one superior or equal to the requested key. |
761 | | /// If `false`, then the provided value must be strictly superior to the requested key. |
762 | 8.25k | pub fn or_equal(&self) -> bool { |
763 | 8.25k | (matches!8.23k (self.inner.vm, host::HostVm::ExternalStorageClearPrefix(_)) |
764 | 15 | && self.keys_removed_so_far == 0) |
765 | 8.24k | || self.inner.root_calculation.is_some() |
766 | 8.25k | } _RNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7NextKey8or_equal Line | Count | Source | 762 | 8.25k | pub fn or_equal(&self) -> bool { | 763 | 8.25k | (matches!8.23k (self.inner.vm, host::HostVm::ExternalStorageClearPrefix(_)) | 764 | 15 | && self.keys_removed_so_far == 0) | 765 | 8.24k | || self.inner.root_calculation.is_some() | 766 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7NextKey8or_equal |
767 | | |
768 | | /// If `true`, then the search must include both branch nodes and storage nodes. If `false`, |
769 | | /// the search only covers storage nodes. |
770 | 8.25k | pub fn branch_nodes(&self) -> bool { |
771 | 8.25k | self.inner.root_calculation.is_some() |
772 | 8.25k | } _RNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7NextKey12branch_nodes Line | Count | Source | 770 | 8.25k | pub fn branch_nodes(&self) -> bool { | 771 | 8.25k | self.inner.root_calculation.is_some() | 772 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7NextKey12branch_nodes |
773 | | |
774 | | /// Returns the prefix the next key must start with. If the next key doesn't start with the |
775 | | /// given prefix, then `None` should be provided. |
776 | 8.25k | pub fn prefix(&self) -> impl Iterator<Item = Nibble> { |
777 | 8.25k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { |
778 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), _) => { |
779 | 15 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.prefix()))) |
780 | | } |
781 | 8.23k | (_, Some(_)) => either::Right(either::Left(self.key())), |
782 | 1 | _ => either::Right(either::Right(iter::empty())), |
783 | | } |
784 | 8.25k | } _RNvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7NextKey6prefix Line | Count | Source | 776 | 8.25k | pub fn prefix(&self) -> impl Iterator<Item = Nibble> { | 777 | 8.25k | match (&self.inner.vm, self.inner.root_calculation.as_ref()) { | 778 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), _) => { | 779 | 15 | either::Left(trie::bytes_to_nibbles(util::as_ref_iter(req.prefix()))) | 780 | | } | 781 | 8.23k | (_, Some(_)) => either::Right(either::Left(self.key())), | 782 | 1 | _ => either::Right(either::Right(iter::empty())), | 783 | | } | 784 | 8.25k | } |
Unexecuted instantiation: _RNvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7NextKey6prefix |
785 | | |
786 | | /// Injects the key. |
787 | | /// |
788 | | /// # Panic |
789 | | /// |
790 | | /// Panics if the key passed as parameter isn't strictly superior to the requested key. |
791 | | /// Panics if the key passed as parameter doesn't start with the requested prefix. |
792 | | /// |
793 | 8.25k | pub fn inject_key(mut self, key: Option<impl Iterator<Item = Nibble>>) -> RuntimeCall { |
794 | 8.25k | match (self.inner.vm, self.inner.root_calculation.take()) { |
795 | 1 | (host::HostVm::ExternalStorageNextKey(req), None) => { |
796 | 1 | let key = |
797 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); Unexecuted instantiation: _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsaFPxhswmqCN_5alloc3vec3VechEEE0Bc_ _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterE0Bc_ Line | Count | Source | 797 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); |
Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEE0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsfFWJyR6nd6r_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EE0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EE0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEE0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEE0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEE0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEE0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EE0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EE0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
798 | | |
799 | 1 | let trie = self |
800 | 1 | .inner |
801 | 1 | .pending_storage_changes |
802 | 1 | .trie_diffs |
803 | 1 | .get(&req.child_trie().map(|ct| ct.as_ref()0 .to_owned0 ())); // TODO: overhead Unexecuted instantiation: _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsaFPxhswmqCN_5alloc3vec3VechEEEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsfFWJyR6nd6r_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs_0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
804 | | |
805 | 1 | let empty = storage_diff::TrieDiff::empty(); // TODO: weird |
806 | 1 | let search = { |
807 | 1 | let req_key = req.key(); |
808 | 1 | let requested_key = if let Some(key_overwrite0 ) = &self.key_overwrite { |
809 | 0 | &key_overwrite[..] |
810 | | } else { |
811 | 1 | req_key.as_ref() |
812 | | }; |
813 | | // TODO: this code is a bit weird |
814 | 1 | trie.unwrap_or(&empty) |
815 | 1 | .storage_next_key(requested_key, key.as_deref(), false) |
816 | | }; |
817 | | |
818 | 1 | match search { |
819 | 1 | storage_diff::StorageNextKey::Found(k) => { |
820 | 1 | self.inner.vm = req.resume(k); |
821 | 1 | } |
822 | 0 | storage_diff::StorageNextKey::NextOf(next) => { |
823 | 0 | let key_overwrite = Some(next.to_owned()); |
824 | 0 | self.inner.vm = host::HostVm::ExternalStorageNextKey(req); |
825 | 0 | return RuntimeCall::NextKey(NextKey { |
826 | 0 | inner: self.inner, |
827 | 0 | key_overwrite, |
828 | 0 | keys_removed_so_far: 0, |
829 | 0 | }); |
830 | | } |
831 | | } |
832 | | } |
833 | | |
834 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), None) => { |
835 | | // TODO: there's some trickiness regarding the behavior w.r.t keys only in the overlay; figure out |
836 | | |
837 | 15 | if let Some(key9 ) = key { |
838 | 9 | let key = trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>(); |
839 | 9 | assert!(key.starts_with(req.prefix().as_ref())); |
840 | | |
841 | | // TODO: /!\ must clear keys from overlay as well |
842 | | |
843 | 9 | if req |
844 | 9 | .max_keys_to_remove() |
845 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) Unexecuted instantiation: _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsaFPxhswmqCN_5alloc3vec3VechEEEs0_0Bc_ _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs0_0Bc_ Line | Count | Source | 845 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) |
Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs0_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsfFWJyR6nd6r_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs0_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs0_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs0_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs0_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs0_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs0_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs0_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs0_0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
846 | 0 | { |
847 | 0 | self.inner.vm = req.resume(self.keys_removed_so_far, true); |
848 | 0 | } else { |
849 | | // TODO: overhead |
850 | 9 | let trie = self |
851 | 9 | .inner |
852 | 9 | .pending_storage_changes |
853 | 9 | .trie_diffs |
854 | 9 | .entry(req.child_trie().map(|ct| ct.as_ref()1 .to_vec1 ())) Unexecuted instantiation: _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtCsaFPxhswmqCN_5alloc3vec3VechEEEs1_0Bc_ _RNCINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyNtNtNtBc_4trie13branch_search21BranchTrieNodeKeyIterEs1_0Bc_ Line | Count | Source | 854 | 1 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs1_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0CscoAnRPySggw_6author Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsfFWJyR6nd6r_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEs1_0B3a_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB35_18SqliteFullDatabase20to_chain_informations_00EEs1_0Bc_ Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs1_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterRShEEs1_0Cs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs1_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0CsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEEs1_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB39_14SyncBackground12author_block0s6_00EEs1_0Cs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EEs1_0Cs4VrkfB1pvQ3_25json_rpc_general_requests |
855 | 9 | .or_insert(storage_diff::TrieDiff::empty()); |
856 | | |
857 | 9 | trie.diff_insert_erase(key.clone(), ()); |
858 | 9 | self.keys_removed_so_far += 1; |
859 | 9 | self.key_overwrite = Some(key); // TODO: might be expensive if lots of keys |
860 | 9 | self.inner.vm = req.into(); |
861 | | |
862 | 9 | return RuntimeCall::NextKey(self); |
863 | | } |
864 | 6 | } else { |
865 | 6 | self.inner.vm = req.resume(self.keys_removed_so_far, false); |
866 | 6 | } |
867 | | } |
868 | | |
869 | 8.23k | (vm, Some((trie, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { |
870 | 8.23k | self.inner.vm = vm; |
871 | 8.23k | self.inner.root_calculation = Some((trie, req.inject(key))); |
872 | 8.23k | } |
873 | | |
874 | | // We only create a `NextKey` if the state is one of the above. |
875 | 0 | _ => unreachable!(), |
876 | | }; |
877 | | |
878 | 8.24k | self.inner.run() |
879 | 8.25k | } Unexecuted instantiation: _RINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtCsaFPxhswmqCN_5alloc3vec3VechEEEBa_ _RINvMs7_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyNtNtNtBa_4trie13branch_search21BranchTrieNodeKeyIterEBa_ Line | Count | Source | 793 | 8.25k | pub fn inject_key(mut self, key: Option<impl Iterator<Item = Nibble>>) -> RuntimeCall { | 794 | 8.25k | match (self.inner.vm, self.inner.root_calculation.take()) { | 795 | 1 | (host::HostVm::ExternalStorageNextKey(req), None) => { | 796 | 1 | let key = | 797 | 1 | key.map(|key| trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>()); | 798 | | | 799 | 1 | let trie = self | 800 | 1 | .inner | 801 | 1 | .pending_storage_changes | 802 | 1 | .trie_diffs | 803 | 1 | .get(&req.child_trie().map(|ct| ct.as_ref().to_owned())); // TODO: overhead | 804 | | | 805 | 1 | let empty = storage_diff::TrieDiff::empty(); // TODO: weird | 806 | 1 | let search = { | 807 | 1 | let req_key = req.key(); | 808 | 1 | let requested_key = if let Some(key_overwrite0 ) = &self.key_overwrite { | 809 | 0 | &key_overwrite[..] | 810 | | } else { | 811 | 1 | req_key.as_ref() | 812 | | }; | 813 | | // TODO: this code is a bit weird | 814 | 1 | trie.unwrap_or(&empty) | 815 | 1 | .storage_next_key(requested_key, key.as_deref(), false) | 816 | | }; | 817 | | | 818 | 1 | match search { | 819 | 1 | storage_diff::StorageNextKey::Found(k) => { | 820 | 1 | self.inner.vm = req.resume(k); | 821 | 1 | } | 822 | 0 | storage_diff::StorageNextKey::NextOf(next) => { | 823 | 0 | let key_overwrite = Some(next.to_owned()); | 824 | 0 | self.inner.vm = host::HostVm::ExternalStorageNextKey(req); | 825 | 0 | return RuntimeCall::NextKey(NextKey { | 826 | 0 | inner: self.inner, | 827 | 0 | key_overwrite, | 828 | 0 | keys_removed_so_far: 0, | 829 | 0 | }); | 830 | | } | 831 | | } | 832 | | } | 833 | | | 834 | 15 | (host::HostVm::ExternalStorageClearPrefix(req), None) => { | 835 | | // TODO: there's some trickiness regarding the behavior w.r.t keys only in the overlay; figure out | 836 | | | 837 | 15 | if let Some(key9 ) = key { | 838 | 9 | let key = trie::nibbles_to_bytes_suffix_extend(key).collect::<Vec<_>>(); | 839 | 9 | assert!(key.starts_with(req.prefix().as_ref())); | 840 | | | 841 | | // TODO: /!\ must clear keys from overlay as well | 842 | | | 843 | 9 | if req | 844 | 9 | .max_keys_to_remove() | 845 | 9 | .map_or(false, |max| self.keys_removed_so_far >= max) | 846 | 0 | { | 847 | 0 | self.inner.vm = req.resume(self.keys_removed_so_far, true); | 848 | 0 | } else { | 849 | | // TODO: overhead | 850 | 9 | let trie = self | 851 | 9 | .inner | 852 | 9 | .pending_storage_changes | 853 | 9 | .trie_diffs | 854 | 9 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 855 | 9 | .or_insert(storage_diff::TrieDiff::empty()); | 856 | | | 857 | 9 | trie.diff_insert_erase(key.clone(), ()); | 858 | 9 | self.keys_removed_so_far += 1; | 859 | 9 | self.key_overwrite = Some(key); // TODO: might be expensive if lots of keys | 860 | 9 | self.inner.vm = req.into(); | 861 | | | 862 | 9 | return RuntimeCall::NextKey(self); | 863 | | } | 864 | 6 | } else { | 865 | 6 | self.inner.vm = req.resume(self.keys_removed_so_far, false); | 866 | 6 | } | 867 | | } | 868 | | | 869 | 8.23k | (vm, Some((trie, trie_root_calculator::InProgress::ClosestDescendant(req)))) => { | 870 | 8.23k | self.inner.vm = vm; | 871 | 8.23k | self.inner.root_calculation = Some((trie, req.inject(key))); | 872 | 8.23k | } | 873 | | | 874 | | // We only create a `NextKey` if the state is one of the above. | 875 | 0 | _ => unreachable!(), | 876 | | }; | 877 | | | 878 | 8.24k | self.inner.run() | 879 | 8.25k | } |
Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtNtCsfFWJyR6nd6r_17smoldot_full_node16json_rpc_service16requests_handler22spawn_requests_handler0se_00EEB38_ Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBa_8database11full_sqliteNtB33_18SqliteFullDatabase20to_chain_informations_00EEBa_ Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEECs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterRShEECs7snhGEhbuap_18smoldot_light_wasm Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtBa_4trie12proof_decode12EntryKeyIterINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhEEECs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB37_14SyncBackground12author_block0s6_00EECs4VrkfB1pvQ3_25json_rpc_general_requests Unexecuted instantiation: _RINvMs7_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvNtCsfFWJyR6nd6r_17smoldot_full_node17consensus_service12runtime_call0s7_00EECs4VrkfB1pvQ3_25json_rpc_general_requests |
880 | | } |
881 | | |
882 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order to |
883 | | /// continue. |
884 | | #[must_use] |
885 | | pub struct ClosestDescendantMerkleValue { |
886 | | inner: Inner, |
887 | | } |
888 | | |
889 | | impl ClosestDescendantMerkleValue { |
890 | | /// Returns the key whose closest descendant Merkle value must be passed to |
891 | | /// [`ClosestDescendantMerkleValue::inject_merkle_value`]. |
892 | 0 | pub fn key(&self) -> impl Iterator<Item = Nibble> { |
893 | 0 | let (_, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
894 | 0 | self.inner.root_calculation.as_ref().unwrap() |
895 | | else { |
896 | 0 | unreachable!() |
897 | | }; |
898 | 0 | request.key().flat_map(util::as_ref_iter) |
899 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue3key Unexecuted instantiation: _RNvMs8_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue3key |
900 | | |
901 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
902 | 0 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
903 | 0 | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(_)) = |
904 | 0 | self.inner.root_calculation.as_ref().unwrap() |
905 | | else { |
906 | 0 | unreachable!() |
907 | | }; |
908 | 0 | trie.as_ref() |
909 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue10child_trie Unexecuted instantiation: _RNvMs8_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue10child_trie |
910 | | |
911 | | /// Indicate that the value is unknown and resume the calculation. |
912 | | /// |
913 | | /// This function be used if you are unaware of the Merkle value. The algorithm will perform |
914 | | /// the calculation of this Merkle value manually, which takes more time. |
915 | 6.77k | pub fn resume_unknown(mut self) -> RuntimeCall { |
916 | 6.77k | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
917 | 6.77k | self.inner.root_calculation.take().unwrap() |
918 | | else { |
919 | 0 | unreachable!() |
920 | | }; |
921 | | |
922 | 6.77k | self.inner.root_calculation = Some((trie, request.resume_unknown())); |
923 | 6.77k | self.inner.run() |
924 | 6.77k | } _RNvMs8_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue14resume_unknown Line | Count | Source | 915 | 6.77k | pub fn resume_unknown(mut self) -> RuntimeCall { | 916 | 6.77k | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = | 917 | 6.77k | self.inner.root_calculation.take().unwrap() | 918 | | else { | 919 | 0 | unreachable!() | 920 | | }; | 921 | | | 922 | 6.77k | self.inner.root_calculation = Some((trie, request.resume_unknown())); | 923 | 6.77k | self.inner.run() | 924 | 6.77k | } |
Unexecuted instantiation: _RNvMs8_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue14resume_unknown |
925 | | |
926 | | /// Injects the corresponding Merkle value. |
927 | | /// |
928 | | /// `None` can be passed if there is no descendant or, in the case of a child trie read, in |
929 | | /// order to indicate that the child trie does not exist. |
930 | 0 | pub fn inject_merkle_value(mut self, merkle_value: Option<&[u8]>) -> RuntimeCall { |
931 | 0 | let (trie, trie_root_calculator::InProgress::ClosestDescendantMerkleValue(request)) = |
932 | 0 | self.inner.root_calculation.take().unwrap() |
933 | | else { |
934 | 0 | unreachable!() |
935 | | }; |
936 | | |
937 | 0 | self.inner.root_calculation = Some(( |
938 | 0 | trie, |
939 | 0 | match merkle_value { |
940 | 0 | Some(merkle_value) => request.inject_merkle_value(merkle_value), |
941 | | None => { |
942 | | // We don't properly handle the situation where there's no descendant or no child |
943 | | // trie. |
944 | 0 | request.resume_unknown() |
945 | | } |
946 | | }, |
947 | | )); |
948 | 0 | self.inner.run() |
949 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue19inject_merkle_value Unexecuted instantiation: _RNvMs8_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_28ClosestDescendantMerkleValue19inject_merkle_value |
950 | | } |
951 | | |
952 | | /// Verifying whether a signature is correct is required in order to continue. |
953 | | #[must_use] |
954 | | pub struct SignatureVerification { |
955 | | inner: Inner, |
956 | | } |
957 | | |
958 | | impl SignatureVerification { |
959 | | /// Returns the message that the signature is expected to sign. |
960 | 0 | pub fn message(&self) -> impl AsRef<[u8]> { |
961 | 0 | match self.inner.vm { |
962 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.message(), |
963 | 0 | _ => unreachable!(), |
964 | | } |
965 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification7message Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification7message |
966 | | |
967 | | /// Returns the signature. |
968 | | /// |
969 | | /// > **Note**: Be aware that this signature is untrusted input and might not be part of the |
970 | | /// > set of valid signatures. |
971 | 0 | pub fn signature(&self) -> impl AsRef<[u8]> { |
972 | 0 | match self.inner.vm { |
973 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.signature(), |
974 | 0 | _ => unreachable!(), |
975 | | } |
976 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification9signature Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification9signature |
977 | | |
978 | | /// Returns the public key the signature is against. |
979 | | /// |
980 | | /// > **Note**: Be aware that this public key is untrusted input and might not be part of the |
981 | | /// > set of valid public keys. |
982 | 0 | pub fn public_key(&self) -> impl AsRef<[u8]> { |
983 | 0 | match self.inner.vm { |
984 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.public_key(), |
985 | 0 | _ => unreachable!(), |
986 | | } |
987 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification10public_key Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification10public_key |
988 | | |
989 | | /// Verify the signature. Returns `true` if it is valid. |
990 | 0 | pub fn is_valid(&self) -> bool { |
991 | 0 | match self.inner.vm { |
992 | 0 | host::HostVm::SignatureVerification(ref sig) => sig.is_valid(), |
993 | 0 | _ => unreachable!(), |
994 | | } |
995 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification8is_valid Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification8is_valid |
996 | | |
997 | | /// Verify the signature and resume execution. |
998 | 6 | pub fn verify_and_resume(mut self) -> RuntimeCall { |
999 | 6 | match self.inner.vm { |
1000 | 6 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.verify_and_resume(), |
1001 | 0 | _ => unreachable!(), |
1002 | | } |
1003 | | |
1004 | 6 | self.inner.run() |
1005 | 6 | } _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification17verify_and_resume Line | Count | Source | 998 | 6 | pub fn verify_and_resume(mut self) -> RuntimeCall { | 999 | 6 | match self.inner.vm { | 1000 | 6 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.verify_and_resume(), | 1001 | 0 | _ => unreachable!(), | 1002 | | } | 1003 | | | 1004 | 6 | self.inner.run() | 1005 | 6 | } |
Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification17verify_and_resume |
1006 | | |
1007 | | /// Resume the execution assuming that the signature is valid. |
1008 | | /// |
1009 | | /// > **Note**: You are strongly encouraged to call |
1010 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
1011 | | /// > used only in debugging situations. |
1012 | 0 | pub fn resume_success(mut self) -> RuntimeCall { |
1013 | 0 | match self.inner.vm { |
1014 | 0 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.resume_success(), |
1015 | 0 | _ => unreachable!(), |
1016 | | } |
1017 | | |
1018 | 0 | self.inner.run() |
1019 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification14resume_success Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification14resume_success |
1020 | | |
1021 | | /// Resume the execution assuming that the signature is invalid. |
1022 | | /// |
1023 | | /// > **Note**: You are strongly encouraged to call |
1024 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
1025 | | /// > used only in debugging situations. |
1026 | 0 | pub fn resume_failed(mut self) -> RuntimeCall { |
1027 | 0 | match self.inner.vm { |
1028 | 0 | host::HostVm::SignatureVerification(sig) => self.inner.vm = sig.resume_failed(), |
1029 | 0 | _ => unreachable!(), |
1030 | | } |
1031 | | |
1032 | 0 | self.inner.run() |
1033 | 0 | } Unexecuted instantiation: _RNvMs9_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_21SignatureVerification13resume_failed Unexecuted instantiation: _RNvMs9_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_21SignatureVerification13resume_failed |
1034 | | } |
1035 | | |
1036 | | /// Loading an offchain storage value is required in order to continue. |
1037 | | #[must_use] |
1038 | | pub struct OffchainStorageGet { |
1039 | | inner: Inner, |
1040 | | } |
1041 | | |
1042 | | impl OffchainStorageGet { |
1043 | | /// Returns the key whose value must be passed to [`OffchainStorageGet::inject_value`]. |
1044 | 0 | pub fn key(&self) -> impl AsRef<[u8]> { |
1045 | 0 | match &self.inner.vm { |
1046 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => req.key(), |
1047 | | // We only create a `OffchainStorageGet` if the state is one of the above. |
1048 | 0 | _ => unreachable!(), |
1049 | | } |
1050 | 0 | } Unexecuted instantiation: _RNvMsa_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_18OffchainStorageGet3key Unexecuted instantiation: _RNvMsa_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_18OffchainStorageGet3key |
1051 | | |
1052 | | /// Injects the corresponding storage value. |
1053 | 0 | pub fn inject_value(mut self, value: Option<impl AsRef<[u8]>>) -> RuntimeCall { |
1054 | 0 | match self.inner.vm { |
1055 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { |
1056 | 0 | self.inner.vm = req.resume(value.as_ref().map(|v| v.as_ref())); Unexecuted instantiation: _RNCINvMsa_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB8_18OffchainStorageGet12inject_valuepE0Bc_ Unexecuted instantiation: _RNCINvMsa_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB8_18OffchainStorageGet12inject_valuepE0Bc_ |
1057 | | } |
1058 | | // We only create a `OffchainStorageGet` if the state is one of the above. |
1059 | 0 | _ => unreachable!(), |
1060 | | }; |
1061 | | |
1062 | 0 | self.inner.run() |
1063 | 0 | } Unexecuted instantiation: _RINvMsa_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB6_18OffchainStorageGet12inject_valuepEBa_ Unexecuted instantiation: _RINvMsa_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB6_18OffchainStorageGet12inject_valuepEBa_ |
1064 | | } |
1065 | | |
1066 | | /// Setting the value of an offchain storage value is required. |
1067 | | #[must_use] |
1068 | | pub struct OffchainStorageSet { |
1069 | | inner: Inner, |
1070 | | } |
1071 | | |
1072 | | impl OffchainStorageSet { |
1073 | | /// Returns the key whose value must be set. |
1074 | 0 | pub fn key(&self) -> impl AsRef<[u8]> { |
1075 | 0 | match &self.inner.vm { |
1076 | | host::HostVm::Finished(_) => { |
1077 | 0 | self.inner |
1078 | 0 | .offchain_storage_changes |
1079 | 0 | .first_key_value() |
1080 | 0 | .unwrap() |
1081 | 0 | .0 |
1082 | | } |
1083 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1084 | 0 | _ => unreachable!(), |
1085 | | } |
1086 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet3key Unexecuted instantiation: _RNvMsb_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet3key |
1087 | | |
1088 | | /// Returns the value to set. |
1089 | | /// |
1090 | | /// If `None` is returned, the key should be removed from the storage entirely. |
1091 | 0 | pub fn value(&self) -> Option<impl AsRef<[u8]>> { |
1092 | 0 | match &self.inner.vm { |
1093 | 0 | host::HostVm::Finished(_) => self |
1094 | 0 | .inner |
1095 | 0 | .offchain_storage_changes |
1096 | 0 | .first_key_value() |
1097 | 0 | .unwrap() |
1098 | 0 | .1 |
1099 | 0 | .as_ref(), |
1100 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1101 | 0 | _ => unreachable!(), |
1102 | | } |
1103 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet5value Unexecuted instantiation: _RNvMsb_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet5value |
1104 | | |
1105 | | /// Resumes execution after having set the value. |
1106 | 0 | pub fn resume(mut self) -> RuntimeCall { |
1107 | 0 | match self.inner.vm { |
1108 | 0 | host::HostVm::Finished(_) => { |
1109 | 0 | self.inner.offchain_storage_changes.pop_first(); |
1110 | 0 | } |
1111 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1112 | 0 | _ => unreachable!(), |
1113 | | }; |
1114 | | |
1115 | 0 | self.inner.run() |
1116 | 0 | } Unexecuted instantiation: _RNvMsb_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet6resume Unexecuted instantiation: _RNvMsb_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_18OffchainStorageSet6resume |
1117 | | } |
1118 | | |
1119 | | /// Setting the value of an offchain storage value is required. |
1120 | | #[must_use] |
1121 | | pub struct OffchainStorageCompareSet { |
1122 | | inner: Inner, |
1123 | | } |
1124 | | |
1125 | | impl OffchainStorageCompareSet { |
1126 | | /// Returns the key whose value must be set. |
1127 | 0 | pub fn key(&self) -> impl AsRef<[u8]> { |
1128 | 0 | match &self.inner.vm { |
1129 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => either::Left(req.key()), |
1130 | 0 | host::HostVm::Finished(_) => either::Right( |
1131 | 0 | self.inner |
1132 | 0 | .offchain_storage_changes |
1133 | 0 | .first_key_value() |
1134 | 0 | .unwrap() |
1135 | 0 | .0, |
1136 | 0 | ), |
1137 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1138 | 0 | _ => unreachable!(), |
1139 | | } |
1140 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet3key Unexecuted instantiation: _RNvMsc_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet3key |
1141 | | |
1142 | | /// Returns the value to set. |
1143 | | /// |
1144 | | /// If `None` is returned, the key should be removed from the storage entirely. |
1145 | 0 | pub fn value(&self) -> Option<impl AsRef<[u8]>> { |
1146 | 0 | match &self.inner.vm { |
1147 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => req.value().map(either::Left), |
1148 | 0 | host::HostVm::Finished(_) => self |
1149 | 0 | .inner |
1150 | 0 | .offchain_storage_changes |
1151 | 0 | .first_key_value() |
1152 | 0 | .unwrap() |
1153 | 0 | .1 |
1154 | 0 | .as_ref() |
1155 | 0 | .map(either::Right), |
1156 | | |
1157 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1158 | 0 | _ => unreachable!(), |
1159 | | } |
1160 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet5value Unexecuted instantiation: _RNvMsc_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet5value |
1161 | | |
1162 | | /// Returns the value the current value should be compared against. The operation is a no-op if they don't compare equal. |
1163 | 0 | pub fn old_value(&self) -> Option<impl AsRef<[u8]>> { |
1164 | 0 | match &self.inner.vm { |
1165 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => req.old_value(), |
1166 | 0 | host::HostVm::Finished(_) => None, |
1167 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1168 | 0 | _ => unreachable!(), |
1169 | | } |
1170 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet9old_value Unexecuted instantiation: _RNvMsc_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet9old_value |
1171 | | |
1172 | | /// Resumes execution after having set the value. Must indicate whether a value was written. |
1173 | 0 | pub fn resume(mut self, replaced: bool) -> RuntimeCall { |
1174 | 0 | match self.inner.vm { |
1175 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { |
1176 | 0 | self.inner.vm = req.resume(replaced); |
1177 | 0 | } |
1178 | 0 | host::HostVm::Finished(_) => { |
1179 | 0 | self.inner.offchain_storage_changes.pop_first(); |
1180 | 0 | } |
1181 | | // We only create a `OffchainStorageSet` if the state is one of the above. |
1182 | 0 | _ => unreachable!(), |
1183 | | }; |
1184 | | |
1185 | 0 | self.inner.run() |
1186 | 0 | } Unexecuted instantiation: _RNvMsc_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet6resume Unexecuted instantiation: _RNvMsc_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainStorageCompareSet6resume |
1187 | | } |
1188 | | |
1189 | | /// Providing the current UNIX timestamp is required in order to continue. |
1190 | | #[must_use] |
1191 | | pub struct OffchainTimestamp { |
1192 | | inner: Inner, |
1193 | | } |
1194 | | |
1195 | | impl OffchainTimestamp { |
1196 | | /// Resume execution by providing the current UNIX timestamp. |
1197 | 0 | pub fn inject_timestamp(mut self, value: u64) -> RuntimeCall { |
1198 | 0 | match self.inner.vm { |
1199 | 0 | host::HostVm::OffchainTimestamp(req) => { |
1200 | 0 | self.inner.vm = req.resume(value); |
1201 | 0 | } |
1202 | | // We only create a `OffchainTimestamp` if the state is one of the above. |
1203 | 0 | _ => unreachable!(), |
1204 | | }; |
1205 | | |
1206 | 0 | self.inner.run() |
1207 | 0 | } Unexecuted instantiation: _RNvMsd_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_17OffchainTimestamp16inject_timestamp Unexecuted instantiation: _RNvMsd_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_17OffchainTimestamp16inject_timestamp |
1208 | | } |
1209 | | |
1210 | | /// Providing a random number is required in order to continue. |
1211 | | #[must_use] |
1212 | | pub struct OffchainRandomSeed { |
1213 | | inner: Inner, |
1214 | | } |
1215 | | |
1216 | | impl OffchainRandomSeed { |
1217 | | /// Resume execution by providing a random number. |
1218 | 0 | pub fn inject_random_seed(mut self, value: [u8; 32]) -> RuntimeCall { |
1219 | 0 | match self.inner.vm { |
1220 | 0 | host::HostVm::OffchainRandomSeed(req) => { |
1221 | 0 | self.inner.vm = req.resume(value); |
1222 | 0 | } |
1223 | | // We only create a `OffchainRandomSeed` if the state is one of the above. |
1224 | 0 | _ => unreachable!(), |
1225 | | }; |
1226 | | |
1227 | 0 | self.inner.run() |
1228 | 0 | } Unexecuted instantiation: _RNvMse_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_18OffchainRandomSeed18inject_random_seed Unexecuted instantiation: _RNvMse_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_18OffchainRandomSeed18inject_random_seed |
1229 | | } |
1230 | | |
1231 | | /// The runtime requests submitting a transaction. |
1232 | | #[must_use] |
1233 | | pub struct OffchainSubmitTransaction { |
1234 | | inner: Inner, |
1235 | | } |
1236 | | |
1237 | | impl OffchainSubmitTransaction { |
1238 | | /// Returns the SCALE-encoded transaction that must be submitted. |
1239 | 0 | pub fn transaction(&self) -> impl AsRef<[u8]> { |
1240 | 0 | match &self.inner.vm { |
1241 | 0 | host::HostVm::OffchainSubmitTransaction(req) => req.transaction(), |
1242 | | // We only create a `OffchainSubmitTransaction` if the state is one of the above. |
1243 | 0 | _ => unreachable!(), |
1244 | | } |
1245 | 0 | } Unexecuted instantiation: _RNvMsf_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction11transaction Unexecuted instantiation: _RNvMsf_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction11transaction |
1246 | | |
1247 | | /// Resume execution. Must indicate whether the transaction has been successfully submitted. |
1248 | 0 | pub fn resume(mut self, success: bool) -> RuntimeCall { |
1249 | 0 | match self.inner.vm { |
1250 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { |
1251 | 0 | self.inner.vm = req.resume(success); |
1252 | 0 | } |
1253 | | // We only create a `OffchainSubmitTransaction` if the state is one of the above. |
1254 | 0 | _ => unreachable!(), |
1255 | | }; |
1256 | | |
1257 | 0 | self.inner.run() |
1258 | 0 | } Unexecuted instantiation: _RNvMsf_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction6resume Unexecuted instantiation: _RNvMsf_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_25OffchainSubmitTransaction6resume |
1259 | | } |
1260 | | |
1261 | | /// Report about a log entry being emitted. |
1262 | | /// |
1263 | | /// Use [`LogEmit::info`] to obtain what must be printed. |
1264 | | #[must_use] |
1265 | | pub struct LogEmit { |
1266 | | inner: Inner, |
1267 | | } |
1268 | | |
1269 | | impl LogEmit { |
1270 | | /// Returns the data that the runtime would like to print. |
1271 | 0 | pub fn info(&self) -> LogEmitInfo { |
1272 | 0 | match &self.inner.vm { |
1273 | 0 | host::HostVm::LogEmit(req) => req.info(), |
1274 | | // We only create a `LogEmit` if the inner state is `LogEmit`. |
1275 | 0 | _ => unreachable!(), |
1276 | | } |
1277 | 0 | } Unexecuted instantiation: _RNvMsg_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7LogEmit4info Unexecuted instantiation: _RNvMsg_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7LogEmit4info |
1278 | | |
1279 | | /// Resume execution. |
1280 | 0 | pub fn resume(mut self) -> RuntimeCall { |
1281 | 0 | match self.inner.vm { |
1282 | 0 | host::HostVm::LogEmit(req) => { |
1283 | 0 | self.inner.vm = req.resume(); |
1284 | 0 | } |
1285 | | // We only create a `LogEmit` if the inner state is `LogEmit`. |
1286 | 0 | _ => unreachable!(), |
1287 | | }; |
1288 | | |
1289 | 0 | self.inner.run() |
1290 | 0 | } Unexecuted instantiation: _RNvMsg_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_7LogEmit6resume Unexecuted instantiation: _RNvMsg_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_7LogEmit6resume |
1291 | | } |
1292 | | |
1293 | | /// Implementation detail of the execution. Shared by all the variants of [`RuntimeCall`] |
1294 | | /// other than [`RuntimeCall::Finished`]. |
1295 | | struct Inner { |
1296 | | /// Virtual machine running the call. |
1297 | | vm: host::HostVm, |
1298 | | |
1299 | | /// Pending changes to the storage that this execution performs. |
1300 | | pending_storage_changes: PendingStorageChanges, |
1301 | | |
1302 | | /// Contains a copy of [`Inner::pending_storage_changes`] at the time when the transaction |
1303 | | /// started. When the storage transaction ends, either the entry is silently discarded (to |
1304 | | /// commit), or is written over [`Inner::pending_storage_changes`] (to rollback). |
1305 | | /// |
1306 | | /// Contains a `Vec` in case transactions are stacked. |
1307 | | transactions_stack: Vec<PendingStorageChanges>, |
1308 | | |
1309 | | /// State trie version indicated by the runtime. All the storage changes that are performed |
1310 | | /// use this version. |
1311 | | state_trie_version: TrieEntryVersion, |
1312 | | |
1313 | | /// Pending changes to the off-chain storage that this execution performs. |
1314 | | offchain_storage_changes: BTreeMap<Vec<u8>, Option<Vec<u8>>>, |
1315 | | |
1316 | | /// Trie root calculation in progress. Contains the trie whose root is being calculated |
1317 | | /// (`Some` for a child trie or `None` for the main trie) and the calculation state machine. |
1318 | | root_calculation: Option<(Option<Vec<u8>>, trie_root_calculator::InProgress)>, |
1319 | | |
1320 | | /// Value provided by [`Config::max_log_level`]. |
1321 | | max_log_level: u32, |
1322 | | |
1323 | | /// See [`Config::calculate_trie_changes`]. |
1324 | | calculate_trie_changes: bool, |
1325 | | } |
1326 | | |
1327 | | /// See [`Inner::pending_storage_changes`]. |
1328 | | #[derive(Clone)] |
1329 | | struct PendingStorageChanges { |
1330 | | /// For each trie, the values that have been written to it. |
1331 | | trie_diffs: hashbrown::HashMap<Option<Vec<u8>>, storage_diff::TrieDiff, fnv::FnvBuildHasher>, |
1332 | | |
1333 | | /// List of tries (`None` for the main trie and `Some` for child tries) whose root hash must |
1334 | | /// be recalculated (and for child tries stored into the main trie). |
1335 | | /// This is necessary in order to populate [`PendingStorageChanges::tries_changes`]. |
1336 | | stale_child_tries_root_hashes: hashbrown::HashSet<Option<Vec<u8>>, fnv::FnvBuildHasher>, |
1337 | | |
1338 | | /// Changes to the trie nodes of all the tries. |
1339 | | tries_changes: BTreeMap<(Option<Vec<u8>>, Vec<Nibble>), PendingStorageChangesTrieNode>, |
1340 | | |
1341 | | /// Changes to the off-chain storage committed by on-chain transactions. |
1342 | | offchain_storage_changes: BTreeMap<Vec<u8>, Option<Vec<u8>>>, |
1343 | | } |
1344 | | |
1345 | | /// See [`PendingStorageChanges::tries_changes`]. |
1346 | | #[derive(Clone)] |
1347 | | enum PendingStorageChangesTrieNode { |
1348 | | Removed, |
1349 | | InsertUpdate { |
1350 | | new_merkle_value: Vec<u8>, |
1351 | | partial_key: Vec<Nibble>, |
1352 | | children_merkle_values: Box<[Option<Vec<u8>>; 16]>, |
1353 | | }, |
1354 | | } |
1355 | | |
1356 | | /// Writing and reading keys the main trie under this prefix obeys special rules. |
1357 | | const CHILD_STORAGE_SPECIAL_PREFIX: &[u8] = b":child_storage:"; |
1358 | | /// Writing and reading keys the main trie under this prefix obeys special rules. |
1359 | | const DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX: &[u8] = b":child_storage:default:"; |
1360 | | |
1361 | | impl Inner { |
1362 | | /// Continues the execution. |
1363 | 15.8k | fn run(mut self) -> RuntimeCall { |
1364 | | loop { |
1365 | 18.9k | match self.root_calculation.take() { |
1366 | 2.90k | None => {} |
1367 | 8.23k | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { |
1368 | 8.23k | self.root_calculation = Some(( |
1369 | 8.23k | trie, |
1370 | 8.23k | trie_root_calculator::InProgress::ClosestDescendant(calc_req), |
1371 | 8.23k | )); |
1372 | 8.23k | return RuntimeCall::NextKey(NextKey { |
1373 | 8.23k | inner: self, |
1374 | 8.23k | key_overwrite: None, |
1375 | 8.23k | keys_removed_so_far: 0, |
1376 | 8.23k | }); |
1377 | | } |
1378 | 514 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { |
1379 | 514 | if calc_req |
1380 | 514 | .key() |
1381 | 3.56k | .fold514 (0, |count, slice| count + slice.as_ref().len()) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3run0Bb_ Line | Count | Source | 1381 | 3.56k | .fold(0, |count, slice| count + slice.as_ref().len()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3run0Bb_ |
1382 | | % 2 |
1383 | | == 0 |
1384 | | { |
1385 | 438 | self.root_calculation = Some(( |
1386 | 438 | trie, |
1387 | 438 | trie_root_calculator::InProgress::StorageValue(calc_req), |
1388 | 438 | )); |
1389 | 438 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1390 | | } else { |
1391 | | // If the number of nibbles in the key is uneven, we are sure that |
1392 | | // there exists no storage value. |
1393 | 76 | self.root_calculation = Some((trie, calc_req.inject_value(None))); |
1394 | 76 | continue; |
1395 | | } |
1396 | | } |
1397 | | Some(( |
1398 | 6.77k | trie, |
1399 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), |
1400 | | )) => { |
1401 | 6.77k | self.root_calculation = Some(( |
1402 | 6.77k | trie, |
1403 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), |
1404 | 6.77k | )); |
1405 | 6.77k | return RuntimeCall::ClosestDescendantMerkleValue( |
1406 | 6.77k | ClosestDescendantMerkleValue { inner: self }, |
1407 | 6.77k | ); |
1408 | | } |
1409 | 500 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { |
1410 | 500 | self.pending_storage_changes.tries_changes.insert( |
1411 | 500 | (trie.clone(), ev.key_as_vec()), |
1412 | | PendingStorageChangesTrieNode::InsertUpdate { |
1413 | 500 | new_merkle_value: ev.merkle_value().to_owned(), |
1414 | 500 | partial_key: ev.partial_key().to_owned(), |
1415 | 500 | children_merkle_values: TryFrom::try_from( |
1416 | 500 | ev.children_merkle_values() |
1417 | 8.00k | .map500 (|mv| mv.map(|mv| mv489 .to_owned489 ())) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs_0Bb_ Line | Count | Source | 1417 | 8.00k | .map(|mv| mv.map(|mv| mv.to_owned())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs_0Bb_ _RNCNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB9_5Inner3runs_00Bd_ Line | Count | Source | 1417 | 489 | .map(|mv| mv.map(|mv| mv.to_owned())) |
Unexecuted instantiation: _RNCNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB9_5Inner3runs_00Bd_ |
1418 | 500 | .collect::<Vec<_>>() |
1419 | 500 | .into_boxed_slice(), |
1420 | | ) |
1421 | 500 | .unwrap(), |
1422 | | }, |
1423 | | ); |
1424 | | |
1425 | 500 | self.root_calculation = Some((trie, ev.resume())); |
1426 | 500 | continue; |
1427 | | } |
1428 | 13 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { |
1429 | 13 | self.pending_storage_changes.tries_changes.insert( |
1430 | 13 | (trie.clone(), ev.key_as_vec()), |
1431 | 13 | PendingStorageChangesTrieNode::Removed, |
1432 | | ); |
1433 | | |
1434 | 13 | self.root_calculation = Some((trie, ev.resume())); |
1435 | 13 | continue; |
1436 | | } |
1437 | 10 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { |
1438 | 10 | self.pending_storage_changes |
1439 | 10 | .stale_child_tries_root_hashes |
1440 | 10 | .remove(&trie); |
1441 | | |
1442 | | // If we've finished calculating a child trie, update its entry in the |
1443 | | // main trie. |
1444 | 10 | if let Some(child_trie5 ) = &trie { |
1445 | 5 | let mut main_trie_key = Vec::with_capacity( |
1446 | 5 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), |
1447 | | ); |
1448 | 5 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); |
1449 | 5 | main_trie_key.extend_from_slice(child_trie); |
1450 | | |
1451 | 5 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { |
1452 | 4 | self.pending_storage_changes |
1453 | 4 | .trie_diffs |
1454 | 4 | .entry(None) |
1455 | 4 | .or_default() |
1456 | 4 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); |
1457 | 4 | } else { |
1458 | 1 | self.pending_storage_changes |
1459 | 1 | .trie_diffs |
1460 | 1 | .entry(None) |
1461 | 1 | .or_default() |
1462 | 1 | .diff_insert_erase(main_trie_key, ()); |
1463 | 1 | } |
1464 | | |
1465 | 5 | self.pending_storage_changes |
1466 | 5 | .stale_child_tries_root_hashes |
1467 | 5 | .insert(None); |
1468 | 5 | } |
1469 | | |
1470 | | // Resume the VM execution only if the calculated trie is the one that was |
1471 | | // requested by the runtime. |
1472 | 10 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { |
1473 | | // Code below is a bit convoluted due to borrow checker issues. |
1474 | 10 | let trie_match = match (req.child_trie(), trie) { |
1475 | 5 | (None, None) => true, |
1476 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, |
1477 | 5 | _ => false, |
1478 | | }; |
1479 | 10 | if trie_match { |
1480 | 5 | self.vm = req.resume(&trie_root_hash); |
1481 | 5 | } else { |
1482 | 5 | self.vm = host::HostVm::ExternalStorageRoot(req); |
1483 | 5 | } |
1484 | 0 | } |
1485 | | |
1486 | 10 | continue; |
1487 | | } |
1488 | | } |
1489 | | |
1490 | | // If the runtime requests the trie root hash of the main trie, we must first |
1491 | | // recalculate the trie root hash of every single child trie that has been modified |
1492 | | // since the previous trie root hash calculation. |
1493 | | // This is also done if execution is finished, in order for the diff provided as |
1494 | | // output to be accurate. |
1495 | | { |
1496 | 2.90k | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { |
1497 | | host::HostVm::Finished(_) => { |
1498 | 138 | if let Some(child_trie0 ) = self |
1499 | 138 | .pending_storage_changes |
1500 | 138 | .stale_child_tries_root_hashes |
1501 | 138 | .iter() |
1502 | 138 | .find_map(|ct| ct3 .as_ref3 ()) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs0_0Bb_ Line | Count | Source | 1502 | 3 | .find_map(|ct| ct.as_ref()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs0_0Bb_ |
1503 | | { |
1504 | 0 | Some(Some(either::Right(child_trie))) |
1505 | 138 | } else if self |
1506 | 138 | .pending_storage_changes |
1507 | 138 | .stale_child_tries_root_hashes |
1508 | 138 | .contains(&None) |
1509 | 3 | && self.calculate_trie_changes |
1510 | | { |
1511 | 0 | Some(None) |
1512 | | } else { |
1513 | 138 | None |
1514 | | } |
1515 | | } |
1516 | 10 | host::HostVm::ExternalStorageRoot(req) => { |
1517 | 10 | if let Some(child_trie0 ) = req.child_trie() { |
1518 | 0 | Some(Some(either::Left(child_trie))) |
1519 | | } else { |
1520 | | // Find any child trie in `pending_storage_changes`. If `None` is |
1521 | | // found, calculate the main trie. |
1522 | | // It is important to calculate the child tries before the main tries. |
1523 | | Some( |
1524 | 10 | self.pending_storage_changes |
1525 | 10 | .stale_child_tries_root_hashes |
1526 | 10 | .iter() |
1527 | 12 | .find_map10 (|ct| ct.as_ref()) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs1_0Bb_ Line | Count | Source | 1527 | 12 | .find_map(|ct| ct.as_ref()) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs1_0Bb_ |
1528 | 10 | .map(|t| either::Right(&t[..]5 )), _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs2_0Bb_ Line | Count | Source | 1528 | 5 | .map(|t| either::Right(&t[..])), |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs2_0Bb_ |
1529 | | ) |
1530 | | } |
1531 | | } |
1532 | 2.75k | _ => None, |
1533 | | }; |
1534 | | |
1535 | 2.90k | if let Some(trie_to_flush10 ) = trie_to_flush { |
1536 | | // Remove from `tries_changes` all the changes concerning this trie. |
1537 | | // TODO: O(n) and generally not optimized |
1538 | | { |
1539 | 10 | let to_remove = self |
1540 | 10 | .pending_storage_changes |
1541 | 10 | .tries_changes |
1542 | 10 | .range(( |
1543 | | ops::Bound::Included(( |
1544 | 10 | trie_to_flush |
1545 | 10 | .as_ref() |
1546 | 10 | .map(|t| AsRef::<[u8]>::as_ref(t)5 .to_owned5 ()), _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs3_0Bb_ Line | Count | Source | 1546 | 5 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs3_0Bb_ |
1547 | 10 | Vec::new(), |
1548 | | )), |
1549 | 10 | ops::Bound::Unbounded, |
1550 | | )) |
1551 | 10 | .take_while(|((ct, _), _)| {4 |
1552 | 4 | ct.as_ref().map(|ct| &ct[..]) _RNCNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB9_5Inner3runs4_00Bd_ Line | Count | Source | 1552 | 4 | ct.as_ref().map(|ct| &ct[..]) |
Unexecuted instantiation: _RNCNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB9_5Inner3runs4_00Bd_ |
1553 | 4 | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) |
1554 | 4 | }) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs4_0Bb_ Line | Count | Source | 1551 | 4 | .take_while(|((ct, _), _)| { | 1552 | 4 | ct.as_ref().map(|ct| &ct[..]) | 1553 | 4 | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1554 | 4 | }) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs4_0Bb_ |
1555 | 10 | .map(|(k, _)| k0 .clone0 ()) Unexecuted instantiation: _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs5_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs5_0Bb_ |
1556 | 10 | .collect::<Vec<_>>(); |
1557 | 10 | for to_remove0 in to_remove { |
1558 | 0 | self.pending_storage_changes |
1559 | 0 | .tries_changes |
1560 | 0 | .remove(&to_remove); |
1561 | 0 | } |
1562 | | } |
1563 | | |
1564 | | // TODO: don't clone? |
1565 | 10 | let diff = match self |
1566 | 10 | .pending_storage_changes |
1567 | 10 | .trie_diffs |
1568 | 10 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t)5 .to_owned5 ())) // TODO: overhead _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs6_0Bb_ Line | Count | Source | 1568 | 5 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs6_0Bb_ |
1569 | | { |
1570 | 0 | None => storage_diff::TrieDiff::empty(), |
1571 | 10 | Some(diff) => diff.clone(), |
1572 | | }; |
1573 | | |
1574 | 10 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. |
1575 | 10 | self.root_calculation = Some(( |
1576 | 10 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t)5 .to_owned5 ()), _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs7_0Bb_ Line | Count | Source | 1576 | 5 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs7_0Bb_ |
1577 | 10 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { |
1578 | 10 | diff, |
1579 | 10 | diff_trie_entries_version: self.state_trie_version, |
1580 | 10 | max_trie_recalculation_depth_hint: 16, // TODO: ?! |
1581 | 10 | }), |
1582 | | )); |
1583 | 10 | continue; |
1584 | 2.89k | } |
1585 | | } |
1586 | | |
1587 | 2.89k | if matches!2.75k (self.vm, host::HostVm::Finished(_)) |
1588 | 138 | && !self.offchain_storage_changes.is_empty() |
1589 | | { |
1590 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); |
1591 | 2.89k | } |
1592 | | |
1593 | 2.89k | match self.vm { |
1594 | 1.44k | host::HostVm::ReadyToRun(r) => self.vm = r.run(), |
1595 | | |
1596 | 0 | host::HostVm::Error { error, prototype } => { |
1597 | 0 | return RuntimeCall::Finished(Err(Error { |
1598 | 0 | detail: error, |
1599 | 0 | prototype, |
1600 | 0 | })); |
1601 | | } |
1602 | | |
1603 | 138 | host::HostVm::Finished(finished) => { |
1604 | 138 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. |
1605 | 138 | debug_assert!( |
1606 | 138 | self.pending_storage_changes |
1607 | 138 | .stale_child_tries_root_hashes |
1608 | 138 | .is_empty() |
1609 | 3 | || (!self.calculate_trie_changes |
1610 | 3 | && self |
1611 | 3 | .pending_storage_changes |
1612 | 3 | .stale_child_tries_root_hashes |
1613 | 3 | .len() |
1614 | 3 | == 1 |
1615 | 3 | && self |
1616 | 3 | .pending_storage_changes |
1617 | 3 | .stale_child_tries_root_hashes |
1618 | 3 | .contains(&None)) |
1619 | | ); |
1620 | 138 | debug_assert!(self.offchain_storage_changes.is_empty()); |
1621 | | |
1622 | 138 | return RuntimeCall::Finished(Ok(Success { |
1623 | 138 | virtual_machine: SuccessVirtualMachine(finished), |
1624 | 138 | storage_changes: StorageChanges { |
1625 | 138 | inner: self.pending_storage_changes, |
1626 | 138 | calculate_trie_changes: self.calculate_trie_changes, |
1627 | 138 | }, |
1628 | 138 | state_trie_version: self.state_trie_version, |
1629 | 138 | })); |
1630 | | } |
1631 | | |
1632 | 687 | host::HostVm::ExternalStorageGet(req) => { |
1633 | 687 | let diff_search = self |
1634 | 687 | .pending_storage_changes |
1635 | 687 | .trie_diffs |
1636 | 687 | .get(&req.child_trie().map(|ct| ct.as_ref()6 .to_vec6 ())) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs8_0Bb_ Line | Count | Source | 1636 | 6 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs8_0Bb_ |
1637 | 687 | .and_then(|diff| diff681 .diff_get681 (req.key().as_ref()681 )); _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runs9_0Bb_ Line | Count | Source | 1637 | 597 | .and_then(|diff| diff.diff_get(req.key().as_ref())); |
_RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runs9_0Bb_ Line | Count | Source | 1637 | 84 | .and_then(|diff| diff.diff_get(req.key().as_ref())); |
|
1638 | | |
1639 | 687 | if let Some((value_in_diff436 , _)) = diff_search { |
1640 | 436 | self.vm = req.resume_full_value(value_in_diff); |
1641 | 436 | } else { |
1642 | 251 | self.vm = req.into(); |
1643 | 251 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1644 | | } |
1645 | | } |
1646 | | |
1647 | 375 | host::HostVm::ExternalStorageSet(req) => { |
1648 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` |
1649 | | // is silently ignored, as per spec. |
1650 | 375 | if req.child_trie().is_none() |
1651 | 371 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) |
1652 | | { |
1653 | 0 | self.vm = req.resume(); |
1654 | 0 | continue; |
1655 | 375 | } |
1656 | | |
1657 | | // TOOD: to_owned overhead |
1658 | 375 | self.pending_storage_changes |
1659 | 375 | .stale_child_tries_root_hashes |
1660 | 375 | .insert(req.child_trie().map(|ct| ct.as_ref()4 .to_owned4 ())); _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsa_0Bb_ Line | Count | Source | 1660 | 4 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsa_0Bb_ |
1661 | | |
1662 | 375 | let trie = self |
1663 | 375 | .pending_storage_changes |
1664 | 375 | .trie_diffs |
1665 | 375 | .entry(req.child_trie().map(|ct| ct.as_ref()4 .to_vec4 ())) _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsb_0Bb_ Line | Count | Source | 1665 | 4 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsb_0Bb_ |
1666 | 375 | .or_insert(storage_diff::TrieDiff::empty()); |
1667 | | |
1668 | 375 | if let Some(value304 ) = req.value() { |
1669 | 304 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); |
1670 | 304 | } else { |
1671 | 71 | trie.diff_insert_erase(req.key().as_ref(), ()); |
1672 | 71 | } |
1673 | | |
1674 | 375 | self.vm = req.resume() |
1675 | | } |
1676 | | |
1677 | 71 | host::HostVm::ExternalStorageAppend(req) => { |
1678 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` |
1679 | | // is silently ignored, as per spec. |
1680 | 71 | if req.child_trie().is_none() |
1681 | 71 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) |
1682 | | { |
1683 | 0 | self.vm = req.resume(); |
1684 | 0 | continue; |
1685 | 71 | } |
1686 | | |
1687 | | // TOOD: to_owned overhead |
1688 | 71 | self.pending_storage_changes |
1689 | 71 | .stale_child_tries_root_hashes |
1690 | 71 | .insert(req.child_trie().map(|ct| ct.as_ref()0 .to_owned0 ())); Unexecuted instantiation: _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsc_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsc_0Bb_ |
1691 | | |
1692 | 71 | let trie = self |
1693 | 71 | .pending_storage_changes |
1694 | 71 | .trie_diffs |
1695 | 71 | .entry(req.child_trie().map(|ct| ct.as_ref()0 .to_vec0 ())) Unexecuted instantiation: _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsd_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsd_0Bb_ |
1696 | 71 | .or_insert(storage_diff::TrieDiff::empty()); |
1697 | | |
1698 | 71 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); |
1699 | | |
1700 | 71 | if let Some(current_value63 ) = current_value { |
1701 | 63 | let mut current_value = current_value.unwrap_or_default().to_vec(); |
1702 | 63 | append_to_storage_value(&mut current_value, req.value().as_ref()); |
1703 | 63 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); |
1704 | 63 | self.vm = req.resume(); |
1705 | 63 | } else { |
1706 | 8 | self.vm = req.into(); |
1707 | 8 | return RuntimeCall::StorageGet(StorageGet { inner: self }); |
1708 | | } |
1709 | | } |
1710 | | |
1711 | 6 | host::HostVm::ExternalStorageClearPrefix(req) => { |
1712 | | // Any attempt at clear a prefix that "intersects" (see code) with |
1713 | | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. |
1714 | 6 | if req.child_trie().is_none() |
1715 | 5 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) |
1716 | | { |
1717 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? |
1718 | 0 | continue; |
1719 | 6 | } |
1720 | | |
1721 | | // TODO: consider doing this only if at least one key was actually removed |
1722 | | // TOOD: to_owned overhead |
1723 | 6 | self.pending_storage_changes |
1724 | 6 | .stale_child_tries_root_hashes |
1725 | 6 | .insert(req.child_trie().map(|ct| ct.as_ref()1 .to_owned1 ())); _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsf_0Bb_ Line | Count | Source | 1725 | 1 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); |
Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsf_0Bb_ |
1726 | | |
1727 | 6 | let prefix = req.prefix().as_ref().to_owned(); |
1728 | 6 | self.vm = req.into(); |
1729 | 6 | return RuntimeCall::NextKey(NextKey { |
1730 | 6 | inner: self, |
1731 | 6 | key_overwrite: Some(prefix), |
1732 | 6 | keys_removed_so_far: 0, |
1733 | 6 | }); |
1734 | | } |
1735 | | |
1736 | | host::HostVm::ExternalStorageRoot(_) => { |
1737 | | // Handled above. |
1738 | 0 | unreachable!() |
1739 | | } |
1740 | | |
1741 | 1 | host::HostVm::ExternalStorageNextKey(req) => { |
1742 | 1 | self.vm = req.into(); |
1743 | 1 | return RuntimeCall::NextKey(NextKey { |
1744 | 1 | inner: self, |
1745 | 1 | key_overwrite: None, |
1746 | 1 | keys_removed_so_far: 0, |
1747 | 1 | }); |
1748 | | } |
1749 | | |
1750 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { |
1751 | 0 | self.pending_storage_changes |
1752 | 0 | .offchain_storage_changes |
1753 | 0 | .insert( |
1754 | 0 | req.key().as_ref().to_vec(), |
1755 | 0 | req.value().map(|v| v.as_ref().to_vec()), Unexecuted instantiation: _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsg_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsg_0Bb_ |
1756 | | ); |
1757 | | |
1758 | 0 | self.vm = req.resume(); |
1759 | | } |
1760 | | |
1761 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { |
1762 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); |
1763 | 0 | match current_value { |
1764 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), Unexecuted instantiation: _RNCNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB7_5Inner3runsh_0Bb_ Unexecuted instantiation: _RNCNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB7_5Inner3runsh_0Bb_ |
1765 | | None => { |
1766 | 0 | self.vm = req.into(); |
1767 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( |
1768 | 0 | OffchainStorageGet { inner: self }, |
1769 | 0 | )); |
1770 | | } |
1771 | | } |
1772 | | } |
1773 | | |
1774 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { |
1775 | 0 | self.vm = req.into(); |
1776 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( |
1777 | 0 | OffchainStorageCompareSet { inner: self }, |
1778 | 0 | )); |
1779 | | } |
1780 | | |
1781 | 6 | host::HostVm::SignatureVerification(req) => { |
1782 | 6 | self.vm = req.into(); |
1783 | 6 | return RuntimeCall::SignatureVerification(SignatureVerification { |
1784 | 6 | inner: self, |
1785 | 6 | }); |
1786 | | } |
1787 | | |
1788 | 0 | host::HostVm::CallRuntimeVersion(req) => { |
1789 | | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 |
1790 | | // The code below compiles the provided WebAssembly runtime code, which is a |
1791 | | // relatively expensive operation (in the order of milliseconds). |
1792 | | // While it could be tempting to use a system cache, this function is expected |
1793 | | // to be called only right before runtime upgrades. Considering that runtime |
1794 | | // upgrades are quite uncommon and that a caching system is rather non-trivial |
1795 | | // to set up, the approach of recompiling every single time is preferred here. |
1796 | | // 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 |
1797 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { |
1798 | 0 | module: req.wasm_code(), |
1799 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, |
1800 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, |
1801 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? |
1802 | 0 | }) { |
1803 | 0 | Ok(w) => w, |
1804 | | Err(_) => { |
1805 | 0 | self.vm = req.resume(Err(())); |
1806 | 0 | continue; |
1807 | | } |
1808 | | }; |
1809 | | |
1810 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); |
1811 | | } |
1812 | | |
1813 | 14 | host::HostVm::StartStorageTransaction(tx) => { |
1814 | 14 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated |
1815 | 14 | self.transactions_stack |
1816 | 14 | .push(self.pending_storage_changes.clone()); |
1817 | 14 | self.vm = tx.resume(); |
1818 | 14 | } |
1819 | | |
1820 | 14 | host::HostVm::EndStorageTransaction { resume, rollback } => { |
1821 | | // The inner implementation guarantees that a storage transaction can only |
1822 | | // end if it has earlier been started. |
1823 | 14 | debug_assert!(!self.transactions_stack.is_empty()); |
1824 | 14 | let rollback_diff = self.transactions_stack.pop().unwrap(); |
1825 | | |
1826 | 14 | if rollback { |
1827 | 0 | self.pending_storage_changes = rollback_diff; |
1828 | 14 | } |
1829 | | |
1830 | 14 | self.vm = resume.resume(); |
1831 | | } |
1832 | | |
1833 | 132 | host::HostVm::GetMaxLogLevel(resume) => { |
1834 | 132 | self.vm = resume.resume(self.max_log_level); |
1835 | 132 | } |
1836 | | |
1837 | 0 | host::HostVm::LogEmit(req) => { |
1838 | 0 | self.vm = req.into(); |
1839 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); |
1840 | | } |
1841 | 0 | host::HostVm::OffchainTimestamp(req) => { |
1842 | 0 | self.vm = req.into(); |
1843 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { |
1844 | 0 | inner: self, |
1845 | 0 | })); |
1846 | | } |
1847 | 0 | host::HostVm::OffchainRandomSeed(req) => { |
1848 | 0 | self.vm = req.into(); |
1849 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( |
1850 | 0 | OffchainRandomSeed { inner: self }, |
1851 | 0 | )); |
1852 | | } |
1853 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { |
1854 | 0 | self.vm = req.into(); |
1855 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( |
1856 | 0 | OffchainSubmitTransaction { inner: self }, |
1857 | 0 | )); |
1858 | | } |
1859 | | } |
1860 | | } |
1861 | 15.8k | } _RNvMsh_NtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_callNtB5_5Inner3run Line | Count | Source | 1363 | 15.6k | fn run(mut self) -> RuntimeCall { | 1364 | | loop { | 1365 | 18.2k | match self.root_calculation.take() { | 1366 | 2.22k | None => {} | 1367 | 8.23k | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { | 1368 | 8.23k | self.root_calculation = Some(( | 1369 | 8.23k | trie, | 1370 | 8.23k | trie_root_calculator::InProgress::ClosestDescendant(calc_req), | 1371 | 8.23k | )); | 1372 | 8.23k | return RuntimeCall::NextKey(NextKey { | 1373 | 8.23k | inner: self, | 1374 | 8.23k | key_overwrite: None, | 1375 | 8.23k | keys_removed_so_far: 0, | 1376 | 8.23k | }); | 1377 | | } | 1378 | 514 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { | 1379 | 514 | if calc_req | 1380 | 514 | .key() | 1381 | 514 | .fold(0, |count, slice| count + slice.as_ref().len()) | 1382 | | % 2 | 1383 | | == 0 | 1384 | | { | 1385 | 438 | self.root_calculation = Some(( | 1386 | 438 | trie, | 1387 | 438 | trie_root_calculator::InProgress::StorageValue(calc_req), | 1388 | 438 | )); | 1389 | 438 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1390 | | } else { | 1391 | | // If the number of nibbles in the key is uneven, we are sure that | 1392 | | // there exists no storage value. | 1393 | 76 | self.root_calculation = Some((trie, calc_req.inject_value(None))); | 1394 | 76 | continue; | 1395 | | } | 1396 | | } | 1397 | | Some(( | 1398 | 6.77k | trie, | 1399 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1400 | | )) => { | 1401 | 6.77k | self.root_calculation = Some(( | 1402 | 6.77k | trie, | 1403 | 6.77k | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1404 | 6.77k | )); | 1405 | 6.77k | return RuntimeCall::ClosestDescendantMerkleValue( | 1406 | 6.77k | ClosestDescendantMerkleValue { inner: self }, | 1407 | 6.77k | ); | 1408 | | } | 1409 | 500 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { | 1410 | 500 | self.pending_storage_changes.tries_changes.insert( | 1411 | 500 | (trie.clone(), ev.key_as_vec()), | 1412 | | PendingStorageChangesTrieNode::InsertUpdate { | 1413 | 500 | new_merkle_value: ev.merkle_value().to_owned(), | 1414 | 500 | partial_key: ev.partial_key().to_owned(), | 1415 | 500 | children_merkle_values: TryFrom::try_from( | 1416 | 500 | ev.children_merkle_values() | 1417 | 500 | .map(|mv| mv.map(|mv| mv.to_owned())) | 1418 | 500 | .collect::<Vec<_>>() | 1419 | 500 | .into_boxed_slice(), | 1420 | | ) | 1421 | 500 | .unwrap(), | 1422 | | }, | 1423 | | ); | 1424 | | | 1425 | 500 | self.root_calculation = Some((trie, ev.resume())); | 1426 | 500 | continue; | 1427 | | } | 1428 | 13 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { | 1429 | 13 | self.pending_storage_changes.tries_changes.insert( | 1430 | 13 | (trie.clone(), ev.key_as_vec()), | 1431 | 13 | PendingStorageChangesTrieNode::Removed, | 1432 | | ); | 1433 | | | 1434 | 13 | self.root_calculation = Some((trie, ev.resume())); | 1435 | 13 | continue; | 1436 | | } | 1437 | 10 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { | 1438 | 10 | self.pending_storage_changes | 1439 | 10 | .stale_child_tries_root_hashes | 1440 | 10 | .remove(&trie); | 1441 | | | 1442 | | // If we've finished calculating a child trie, update its entry in the | 1443 | | // main trie. | 1444 | 10 | if let Some(child_trie5 ) = &trie { | 1445 | 5 | let mut main_trie_key = Vec::with_capacity( | 1446 | 5 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), | 1447 | | ); | 1448 | 5 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); | 1449 | 5 | main_trie_key.extend_from_slice(child_trie); | 1450 | | | 1451 | 5 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { | 1452 | 4 | self.pending_storage_changes | 1453 | 4 | .trie_diffs | 1454 | 4 | .entry(None) | 1455 | 4 | .or_default() | 1456 | 4 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); | 1457 | 4 | } else { | 1458 | 1 | self.pending_storage_changes | 1459 | 1 | .trie_diffs | 1460 | 1 | .entry(None) | 1461 | 1 | .or_default() | 1462 | 1 | .diff_insert_erase(main_trie_key, ()); | 1463 | 1 | } | 1464 | | | 1465 | 5 | self.pending_storage_changes | 1466 | 5 | .stale_child_tries_root_hashes | 1467 | 5 | .insert(None); | 1468 | 5 | } | 1469 | | | 1470 | | // Resume the VM execution only if the calculated trie is the one that was | 1471 | | // requested by the runtime. | 1472 | 10 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { | 1473 | | // Code below is a bit convoluted due to borrow checker issues. | 1474 | 10 | let trie_match = match (req.child_trie(), trie) { | 1475 | 5 | (None, None) => true, | 1476 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, | 1477 | 5 | _ => false, | 1478 | | }; | 1479 | 10 | if trie_match { | 1480 | 5 | self.vm = req.resume(&trie_root_hash); | 1481 | 5 | } else { | 1482 | 5 | self.vm = host::HostVm::ExternalStorageRoot(req); | 1483 | 5 | } | 1484 | 0 | } | 1485 | | | 1486 | 10 | continue; | 1487 | | } | 1488 | | } | 1489 | | | 1490 | | // If the runtime requests the trie root hash of the main trie, we must first | 1491 | | // recalculate the trie root hash of every single child trie that has been modified | 1492 | | // since the previous trie root hash calculation. | 1493 | | // This is also done if execution is finished, in order for the diff provided as | 1494 | | // output to be accurate. | 1495 | | { | 1496 | 2.22k | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { | 1497 | | host::HostVm::Finished(_) => { | 1498 | 11 | if let Some(child_trie0 ) = self | 1499 | 11 | .pending_storage_changes | 1500 | 11 | .stale_child_tries_root_hashes | 1501 | 11 | .iter() | 1502 | 11 | .find_map(|ct| ct.as_ref()) | 1503 | | { | 1504 | 0 | Some(Some(either::Right(child_trie))) | 1505 | 11 | } else if self | 1506 | 11 | .pending_storage_changes | 1507 | 11 | .stale_child_tries_root_hashes | 1508 | 11 | .contains(&None) | 1509 | 3 | && self.calculate_trie_changes | 1510 | | { | 1511 | 0 | Some(None) | 1512 | | } else { | 1513 | 11 | None | 1514 | | } | 1515 | | } | 1516 | 10 | host::HostVm::ExternalStorageRoot(req) => { | 1517 | 10 | if let Some(child_trie0 ) = req.child_trie() { | 1518 | 0 | Some(Some(either::Left(child_trie))) | 1519 | | } else { | 1520 | | // Find any child trie in `pending_storage_changes`. If `None` is | 1521 | | // found, calculate the main trie. | 1522 | | // It is important to calculate the child tries before the main tries. | 1523 | | Some( | 1524 | 10 | self.pending_storage_changes | 1525 | 10 | .stale_child_tries_root_hashes | 1526 | 10 | .iter() | 1527 | 10 | .find_map(|ct| ct.as_ref()) | 1528 | 10 | .map(|t| either::Right(&t[..])), | 1529 | | ) | 1530 | | } | 1531 | | } | 1532 | 2.20k | _ => None, | 1533 | | }; | 1534 | | | 1535 | 2.22k | if let Some(trie_to_flush10 ) = trie_to_flush { | 1536 | | // Remove from `tries_changes` all the changes concerning this trie. | 1537 | | // TODO: O(n) and generally not optimized | 1538 | | { | 1539 | 10 | let to_remove = self | 1540 | 10 | .pending_storage_changes | 1541 | 10 | .tries_changes | 1542 | 10 | .range(( | 1543 | | ops::Bound::Included(( | 1544 | 10 | trie_to_flush | 1545 | 10 | .as_ref() | 1546 | 10 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), | 1547 | 10 | Vec::new(), | 1548 | | )), | 1549 | 10 | ops::Bound::Unbounded, | 1550 | | )) | 1551 | 10 | .take_while(|((ct, _), _)| { | 1552 | | ct.as_ref().map(|ct| &ct[..]) | 1553 | | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1554 | | }) | 1555 | 10 | .map(|(k, _)| k.clone()) | 1556 | 10 | .collect::<Vec<_>>(); | 1557 | 10 | for to_remove0 in to_remove { | 1558 | 0 | self.pending_storage_changes | 1559 | 0 | .tries_changes | 1560 | 0 | .remove(&to_remove); | 1561 | 0 | } | 1562 | | } | 1563 | | | 1564 | | // TODO: don't clone? | 1565 | 10 | let diff = match self | 1566 | 10 | .pending_storage_changes | 1567 | 10 | .trie_diffs | 1568 | 10 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead | 1569 | | { | 1570 | 0 | None => storage_diff::TrieDiff::empty(), | 1571 | 10 | Some(diff) => diff.clone(), | 1572 | | }; | 1573 | | | 1574 | 10 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. | 1575 | 10 | self.root_calculation = Some(( | 1576 | 10 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), | 1577 | 10 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { | 1578 | 10 | diff, | 1579 | 10 | diff_trie_entries_version: self.state_trie_version, | 1580 | 10 | max_trie_recalculation_depth_hint: 16, // TODO: ?! | 1581 | 10 | }), | 1582 | | )); | 1583 | 10 | continue; | 1584 | 2.21k | } | 1585 | | } | 1586 | | | 1587 | 2.21k | if matches!2.20k (self.vm, host::HostVm::Finished(_)) | 1588 | 11 | && !self.offchain_storage_changes.is_empty() | 1589 | | { | 1590 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); | 1591 | 2.21k | } | 1592 | | | 1593 | 2.21k | match self.vm { | 1594 | 1.11k | host::HostVm::ReadyToRun(r) => self.vm = r.run(), | 1595 | | | 1596 | 0 | host::HostVm::Error { error, prototype } => { | 1597 | 0 | return RuntimeCall::Finished(Err(Error { | 1598 | 0 | detail: error, | 1599 | 0 | prototype, | 1600 | 0 | })); | 1601 | | } | 1602 | | | 1603 | 11 | host::HostVm::Finished(finished) => { | 1604 | 11 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. | 1605 | 11 | debug_assert!( | 1606 | 11 | self.pending_storage_changes | 1607 | 11 | .stale_child_tries_root_hashes | 1608 | 11 | .is_empty() | 1609 | 3 | || (!self.calculate_trie_changes | 1610 | 3 | && self | 1611 | 3 | .pending_storage_changes | 1612 | 3 | .stale_child_tries_root_hashes | 1613 | 3 | .len() | 1614 | 3 | == 1 | 1615 | 3 | && self | 1616 | 3 | .pending_storage_changes | 1617 | 3 | .stale_child_tries_root_hashes | 1618 | 3 | .contains(&None)) | 1619 | | ); | 1620 | 11 | debug_assert!(self.offchain_storage_changes.is_empty()); | 1621 | | | 1622 | 11 | return RuntimeCall::Finished(Ok(Success { | 1623 | 11 | virtual_machine: SuccessVirtualMachine(finished), | 1624 | 11 | storage_changes: StorageChanges { | 1625 | 11 | inner: self.pending_storage_changes, | 1626 | 11 | calculate_trie_changes: self.calculate_trie_changes, | 1627 | 11 | }, | 1628 | 11 | state_trie_version: self.state_trie_version, | 1629 | 11 | })); | 1630 | | } | 1631 | | | 1632 | 603 | host::HostVm::ExternalStorageGet(req) => { | 1633 | 603 | let diff_search = self | 1634 | 603 | .pending_storage_changes | 1635 | 603 | .trie_diffs | 1636 | 603 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1637 | 603 | .and_then(|diff| diff.diff_get(req.key().as_ref())); | 1638 | | | 1639 | 603 | if let Some((value_in_diff436 , _)) = diff_search { | 1640 | 436 | self.vm = req.resume_full_value(value_in_diff); | 1641 | 436 | } else { | 1642 | 167 | self.vm = req.into(); | 1643 | 167 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1644 | | } | 1645 | | } | 1646 | | | 1647 | 375 | host::HostVm::ExternalStorageSet(req) => { | 1648 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1649 | | // is silently ignored, as per spec. | 1650 | 375 | if req.child_trie().is_none() | 1651 | 371 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1652 | | { | 1653 | 0 | self.vm = req.resume(); | 1654 | 0 | continue; | 1655 | 375 | } | 1656 | | | 1657 | | // TOOD: to_owned overhead | 1658 | 375 | self.pending_storage_changes | 1659 | 375 | .stale_child_tries_root_hashes | 1660 | 375 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1661 | | | 1662 | 375 | let trie = self | 1663 | 375 | .pending_storage_changes | 1664 | 375 | .trie_diffs | 1665 | 375 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1666 | 375 | .or_insert(storage_diff::TrieDiff::empty()); | 1667 | | | 1668 | 375 | if let Some(value304 ) = req.value() { | 1669 | 304 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); | 1670 | 304 | } else { | 1671 | 71 | trie.diff_insert_erase(req.key().as_ref(), ()); | 1672 | 71 | } | 1673 | | | 1674 | 375 | self.vm = req.resume() | 1675 | | } | 1676 | | | 1677 | 71 | host::HostVm::ExternalStorageAppend(req) => { | 1678 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1679 | | // is silently ignored, as per spec. | 1680 | 71 | if req.child_trie().is_none() | 1681 | 71 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1682 | | { | 1683 | 0 | self.vm = req.resume(); | 1684 | 0 | continue; | 1685 | 71 | } | 1686 | | | 1687 | | // TOOD: to_owned overhead | 1688 | 71 | self.pending_storage_changes | 1689 | 71 | .stale_child_tries_root_hashes | 1690 | 71 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1691 | | | 1692 | 71 | let trie = self | 1693 | 71 | .pending_storage_changes | 1694 | 71 | .trie_diffs | 1695 | 71 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1696 | 71 | .or_insert(storage_diff::TrieDiff::empty()); | 1697 | | | 1698 | 71 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); | 1699 | | | 1700 | 71 | if let Some(current_value63 ) = current_value { | 1701 | 63 | let mut current_value = current_value.unwrap_or_default().to_vec(); | 1702 | 63 | append_to_storage_value(&mut current_value, req.value().as_ref()); | 1703 | 63 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); | 1704 | 63 | self.vm = req.resume(); | 1705 | 63 | } else { | 1706 | 8 | self.vm = req.into(); | 1707 | 8 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1708 | | } | 1709 | | } | 1710 | | | 1711 | 6 | host::HostVm::ExternalStorageClearPrefix(req) => { | 1712 | | // Any attempt at clear a prefix that "intersects" (see code) with | 1713 | | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. | 1714 | 6 | if req.child_trie().is_none() | 1715 | 5 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) | 1716 | | { | 1717 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? | 1718 | 0 | continue; | 1719 | 6 | } | 1720 | | | 1721 | | // TODO: consider doing this only if at least one key was actually removed | 1722 | | // TOOD: to_owned overhead | 1723 | 6 | self.pending_storage_changes | 1724 | 6 | .stale_child_tries_root_hashes | 1725 | 6 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1726 | | | 1727 | 6 | let prefix = req.prefix().as_ref().to_owned(); | 1728 | 6 | self.vm = req.into(); | 1729 | 6 | return RuntimeCall::NextKey(NextKey { | 1730 | 6 | inner: self, | 1731 | 6 | key_overwrite: Some(prefix), | 1732 | 6 | keys_removed_so_far: 0, | 1733 | 6 | }); | 1734 | | } | 1735 | | | 1736 | | host::HostVm::ExternalStorageRoot(_) => { | 1737 | | // Handled above. | 1738 | 0 | unreachable!() | 1739 | | } | 1740 | | | 1741 | 1 | host::HostVm::ExternalStorageNextKey(req) => { | 1742 | 1 | self.vm = req.into(); | 1743 | 1 | return RuntimeCall::NextKey(NextKey { | 1744 | 1 | inner: self, | 1745 | 1 | key_overwrite: None, | 1746 | 1 | keys_removed_so_far: 0, | 1747 | 1 | }); | 1748 | | } | 1749 | | | 1750 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { | 1751 | 0 | self.pending_storage_changes | 1752 | 0 | .offchain_storage_changes | 1753 | 0 | .insert( | 1754 | 0 | req.key().as_ref().to_vec(), | 1755 | 0 | req.value().map(|v| v.as_ref().to_vec()), | 1756 | | ); | 1757 | | | 1758 | 0 | self.vm = req.resume(); | 1759 | | } | 1760 | | | 1761 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { | 1762 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); | 1763 | 0 | match current_value { | 1764 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), | 1765 | | None => { | 1766 | 0 | self.vm = req.into(); | 1767 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( | 1768 | 0 | OffchainStorageGet { inner: self }, | 1769 | 0 | )); | 1770 | | } | 1771 | | } | 1772 | | } | 1773 | | | 1774 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { | 1775 | 0 | self.vm = req.into(); | 1776 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( | 1777 | 0 | OffchainStorageCompareSet { inner: self }, | 1778 | 0 | )); | 1779 | | } | 1780 | | | 1781 | 6 | host::HostVm::SignatureVerification(req) => { | 1782 | 6 | self.vm = req.into(); | 1783 | 6 | return RuntimeCall::SignatureVerification(SignatureVerification { | 1784 | 6 | inner: self, | 1785 | 6 | }); | 1786 | | } | 1787 | | | 1788 | 0 | host::HostVm::CallRuntimeVersion(req) => { | 1789 | | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 | 1790 | | // The code below compiles the provided WebAssembly runtime code, which is a | 1791 | | // relatively expensive operation (in the order of milliseconds). | 1792 | | // While it could be tempting to use a system cache, this function is expected | 1793 | | // to be called only right before runtime upgrades. Considering that runtime | 1794 | | // upgrades are quite uncommon and that a caching system is rather non-trivial | 1795 | | // to set up, the approach of recompiling every single time is preferred here. | 1796 | | // 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 | 1797 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { | 1798 | 0 | module: req.wasm_code(), | 1799 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, | 1800 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, | 1801 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? | 1802 | 0 | }) { | 1803 | 0 | Ok(w) => w, | 1804 | | Err(_) => { | 1805 | 0 | self.vm = req.resume(Err(())); | 1806 | 0 | continue; | 1807 | | } | 1808 | | }; | 1809 | | | 1810 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); | 1811 | | } | 1812 | | | 1813 | 14 | host::HostVm::StartStorageTransaction(tx) => { | 1814 | 14 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated | 1815 | 14 | self.transactions_stack | 1816 | 14 | .push(self.pending_storage_changes.clone()); | 1817 | 14 | self.vm = tx.resume(); | 1818 | 14 | } | 1819 | | | 1820 | 14 | host::HostVm::EndStorageTransaction { resume, rollback } => { | 1821 | | // The inner implementation guarantees that a storage transaction can only | 1822 | | // end if it has earlier been started. | 1823 | 14 | debug_assert!(!self.transactions_stack.is_empty()); | 1824 | 14 | let rollback_diff = self.transactions_stack.pop().unwrap(); | 1825 | | | 1826 | 14 | if rollback { | 1827 | 0 | self.pending_storage_changes = rollback_diff; | 1828 | 14 | } | 1829 | | | 1830 | 14 | self.vm = resume.resume(); | 1831 | | } | 1832 | | | 1833 | 5 | host::HostVm::GetMaxLogLevel(resume) => { | 1834 | 5 | self.vm = resume.resume(self.max_log_level); | 1835 | 5 | } | 1836 | | | 1837 | 0 | host::HostVm::LogEmit(req) => { | 1838 | 0 | self.vm = req.into(); | 1839 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); | 1840 | | } | 1841 | 0 | host::HostVm::OffchainTimestamp(req) => { | 1842 | 0 | self.vm = req.into(); | 1843 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { | 1844 | 0 | inner: self, | 1845 | 0 | })); | 1846 | | } | 1847 | 0 | host::HostVm::OffchainRandomSeed(req) => { | 1848 | 0 | self.vm = req.into(); | 1849 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( | 1850 | 0 | OffchainRandomSeed { inner: self }, | 1851 | 0 | )); | 1852 | | } | 1853 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { | 1854 | 0 | self.vm = req.into(); | 1855 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( | 1856 | 0 | OffchainSubmitTransaction { inner: self }, | 1857 | 0 | )); | 1858 | | } | 1859 | | } | 1860 | | } | 1861 | 15.6k | } |
_RNvMsh_NtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_callNtB5_5Inner3run Line | Count | Source | 1363 | 211 | fn run(mut self) -> RuntimeCall { | 1364 | | loop { | 1365 | 676 | match self.root_calculation.take() { | 1366 | 676 | None => {} | 1367 | 0 | Some((trie, trie_root_calculator::InProgress::ClosestDescendant(calc_req))) => { | 1368 | 0 | self.root_calculation = Some(( | 1369 | 0 | trie, | 1370 | 0 | trie_root_calculator::InProgress::ClosestDescendant(calc_req), | 1371 | 0 | )); | 1372 | 0 | return RuntimeCall::NextKey(NextKey { | 1373 | 0 | inner: self, | 1374 | 0 | key_overwrite: None, | 1375 | 0 | keys_removed_so_far: 0, | 1376 | 0 | }); | 1377 | | } | 1378 | 0 | Some((trie, trie_root_calculator::InProgress::StorageValue(calc_req))) => { | 1379 | 0 | if calc_req | 1380 | 0 | .key() | 1381 | 0 | .fold(0, |count, slice| count + slice.as_ref().len()) | 1382 | | % 2 | 1383 | | == 0 | 1384 | | { | 1385 | 0 | self.root_calculation = Some(( | 1386 | 0 | trie, | 1387 | 0 | trie_root_calculator::InProgress::StorageValue(calc_req), | 1388 | 0 | )); | 1389 | 0 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1390 | | } else { | 1391 | | // If the number of nibbles in the key is uneven, we are sure that | 1392 | | // there exists no storage value. | 1393 | 0 | self.root_calculation = Some((trie, calc_req.inject_value(None))); | 1394 | 0 | continue; | 1395 | | } | 1396 | | } | 1397 | | Some(( | 1398 | 0 | trie, | 1399 | 0 | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1400 | | )) => { | 1401 | 0 | self.root_calculation = Some(( | 1402 | 0 | trie, | 1403 | 0 | trie_root_calculator::InProgress::ClosestDescendantMerkleValue(calc_req), | 1404 | 0 | )); | 1405 | 0 | return RuntimeCall::ClosestDescendantMerkleValue( | 1406 | 0 | ClosestDescendantMerkleValue { inner: self }, | 1407 | 0 | ); | 1408 | | } | 1409 | 0 | Some((trie, trie_root_calculator::InProgress::TrieNodeInsertUpdateEvent(ev))) => { | 1410 | 0 | self.pending_storage_changes.tries_changes.insert( | 1411 | 0 | (trie.clone(), ev.key_as_vec()), | 1412 | | PendingStorageChangesTrieNode::InsertUpdate { | 1413 | 0 | new_merkle_value: ev.merkle_value().to_owned(), | 1414 | 0 | partial_key: ev.partial_key().to_owned(), | 1415 | 0 | children_merkle_values: TryFrom::try_from( | 1416 | 0 | ev.children_merkle_values() | 1417 | 0 | .map(|mv| mv.map(|mv| mv.to_owned())) | 1418 | 0 | .collect::<Vec<_>>() | 1419 | 0 | .into_boxed_slice(), | 1420 | | ) | 1421 | 0 | .unwrap(), | 1422 | | }, | 1423 | | ); | 1424 | | | 1425 | 0 | self.root_calculation = Some((trie, ev.resume())); | 1426 | 0 | continue; | 1427 | | } | 1428 | 0 | Some((trie, trie_root_calculator::InProgress::TrieNodeRemoveEvent(ev))) => { | 1429 | 0 | self.pending_storage_changes.tries_changes.insert( | 1430 | 0 | (trie.clone(), ev.key_as_vec()), | 1431 | 0 | PendingStorageChangesTrieNode::Removed, | 1432 | | ); | 1433 | | | 1434 | 0 | self.root_calculation = Some((trie, ev.resume())); | 1435 | 0 | continue; | 1436 | | } | 1437 | 0 | Some((trie, trie_root_calculator::InProgress::Finished { trie_root_hash })) => { | 1438 | 0 | self.pending_storage_changes | 1439 | 0 | .stale_child_tries_root_hashes | 1440 | 0 | .remove(&trie); | 1441 | | | 1442 | | // If we've finished calculating a child trie, update its entry in the | 1443 | | // main trie. | 1444 | 0 | if let Some(child_trie) = &trie { | 1445 | 0 | let mut main_trie_key = Vec::with_capacity( | 1446 | 0 | DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX.len() + child_trie.len(), | 1447 | | ); | 1448 | 0 | main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX); | 1449 | 0 | main_trie_key.extend_from_slice(child_trie); | 1450 | | | 1451 | 0 | if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE { | 1452 | 0 | self.pending_storage_changes | 1453 | 0 | .trie_diffs | 1454 | 0 | .entry(None) | 1455 | 0 | .or_default() | 1456 | 0 | .diff_insert(main_trie_key, trie_root_hash.to_vec(), ()); | 1457 | 0 | } else { | 1458 | 0 | self.pending_storage_changes | 1459 | 0 | .trie_diffs | 1460 | 0 | .entry(None) | 1461 | 0 | .or_default() | 1462 | 0 | .diff_insert_erase(main_trie_key, ()); | 1463 | 0 | } | 1464 | | | 1465 | 0 | self.pending_storage_changes | 1466 | 0 | .stale_child_tries_root_hashes | 1467 | 0 | .insert(None); | 1468 | 0 | } | 1469 | | | 1470 | | // Resume the VM execution only if the calculated trie is the one that was | 1471 | | // requested by the runtime. | 1472 | 0 | if let host::HostVm::ExternalStorageRoot(req) = self.vm { | 1473 | | // Code below is a bit convoluted due to borrow checker issues. | 1474 | 0 | let trie_match = match (req.child_trie(), trie) { | 1475 | 0 | (None, None) => true, | 1476 | 0 | (Some(a), Some(b)) if a.as_ref() == b => true, | 1477 | 0 | _ => false, | 1478 | | }; | 1479 | 0 | if trie_match { | 1480 | 0 | self.vm = req.resume(&trie_root_hash); | 1481 | 0 | } else { | 1482 | 0 | self.vm = host::HostVm::ExternalStorageRoot(req); | 1483 | 0 | } | 1484 | 0 | } | 1485 | | | 1486 | 0 | continue; | 1487 | | } | 1488 | | } | 1489 | | | 1490 | | // If the runtime requests the trie root hash of the main trie, we must first | 1491 | | // recalculate the trie root hash of every single child trie that has been modified | 1492 | | // since the previous trie root hash calculation. | 1493 | | // This is also done if execution is finished, in order for the diff provided as | 1494 | | // output to be accurate. | 1495 | | { | 1496 | 676 | let trie_to_flush: Option<Option<either::Either<_, &[u8]>>> = match &self.vm { | 1497 | | host::HostVm::Finished(_) => { | 1498 | 127 | if let Some(child_trie0 ) = self | 1499 | 127 | .pending_storage_changes | 1500 | 127 | .stale_child_tries_root_hashes | 1501 | 127 | .iter() | 1502 | 127 | .find_map(|ct| ct.as_ref()) | 1503 | | { | 1504 | 0 | Some(Some(either::Right(child_trie))) | 1505 | 127 | } else if self | 1506 | 127 | .pending_storage_changes | 1507 | 127 | .stale_child_tries_root_hashes | 1508 | 127 | .contains(&None) | 1509 | 0 | && self.calculate_trie_changes | 1510 | | { | 1511 | 0 | Some(None) | 1512 | | } else { | 1513 | 127 | None | 1514 | | } | 1515 | | } | 1516 | 0 | host::HostVm::ExternalStorageRoot(req) => { | 1517 | 0 | if let Some(child_trie) = req.child_trie() { | 1518 | 0 | Some(Some(either::Left(child_trie))) | 1519 | | } else { | 1520 | | // Find any child trie in `pending_storage_changes`. If `None` is | 1521 | | // found, calculate the main trie. | 1522 | | // It is important to calculate the child tries before the main tries. | 1523 | | Some( | 1524 | 0 | self.pending_storage_changes | 1525 | 0 | .stale_child_tries_root_hashes | 1526 | 0 | .iter() | 1527 | 0 | .find_map(|ct| ct.as_ref()) | 1528 | 0 | .map(|t| either::Right(&t[..])), | 1529 | | ) | 1530 | | } | 1531 | | } | 1532 | 549 | _ => None, | 1533 | | }; | 1534 | | | 1535 | 676 | if let Some(trie_to_flush0 ) = trie_to_flush { | 1536 | | // Remove from `tries_changes` all the changes concerning this trie. | 1537 | | // TODO: O(n) and generally not optimized | 1538 | | { | 1539 | 0 | let to_remove = self | 1540 | 0 | .pending_storage_changes | 1541 | 0 | .tries_changes | 1542 | 0 | .range(( | 1543 | | ops::Bound::Included(( | 1544 | 0 | trie_to_flush | 1545 | 0 | .as_ref() | 1546 | 0 | .map(|t| AsRef::<[u8]>::as_ref(t).to_owned()), | 1547 | 0 | Vec::new(), | 1548 | | )), | 1549 | 0 | ops::Bound::Unbounded, | 1550 | | )) | 1551 | 0 | .take_while(|((ct, _), _)| { | 1552 | | ct.as_ref().map(|ct| &ct[..]) | 1553 | | == trie_to_flush.as_ref().map(AsRef::<[u8]>::as_ref) | 1554 | | }) | 1555 | 0 | .map(|(k, _)| k.clone()) | 1556 | 0 | .collect::<Vec<_>>(); | 1557 | 0 | for to_remove in to_remove { | 1558 | 0 | self.pending_storage_changes | 1559 | 0 | .tries_changes | 1560 | 0 | .remove(&to_remove); | 1561 | 0 | } | 1562 | | } | 1563 | | | 1564 | | // TODO: don't clone? | 1565 | 0 | let diff = match self | 1566 | 0 | .pending_storage_changes | 1567 | 0 | .trie_diffs | 1568 | 0 | .get(&trie_to_flush.as_ref().map(|t| AsRef::<[u8]>::as_ref(&t).to_owned())) // TODO: overhead | 1569 | | { | 1570 | 0 | None => storage_diff::TrieDiff::empty(), | 1571 | 0 | Some(diff) => diff.clone(), | 1572 | | }; | 1573 | | | 1574 | 0 | debug_assert!(self.root_calculation.is_none()); // `Some` handled above. | 1575 | 0 | self.root_calculation = Some(( | 1576 | 0 | trie_to_flush.map(|t| AsRef::<[u8]>::as_ref(&t).to_owned()), | 1577 | 0 | trie_root_calculator::trie_root_calculator(trie_root_calculator::Config { | 1578 | 0 | diff, | 1579 | 0 | diff_trie_entries_version: self.state_trie_version, | 1580 | 0 | max_trie_recalculation_depth_hint: 16, // TODO: ?! | 1581 | 0 | }), | 1582 | | )); | 1583 | 0 | continue; | 1584 | 676 | } | 1585 | | } | 1586 | | | 1587 | 676 | if matches!549 (self.vm, host::HostVm::Finished(_)) | 1588 | 127 | && !self.offchain_storage_changes.is_empty() | 1589 | | { | 1590 | 0 | return RuntimeCall::OffchainStorageSet(OffchainStorageSet { inner: self }); | 1591 | 676 | } | 1592 | | | 1593 | 676 | match self.vm { | 1594 | 338 | host::HostVm::ReadyToRun(r) => self.vm = r.run(), | 1595 | | | 1596 | 0 | host::HostVm::Error { error, prototype } => { | 1597 | 0 | return RuntimeCall::Finished(Err(Error { | 1598 | 0 | detail: error, | 1599 | 0 | prototype, | 1600 | 0 | })); | 1601 | | } | 1602 | | | 1603 | 127 | host::HostVm::Finished(finished) => { | 1604 | 127 | debug_assert!(self.transactions_stack.is_empty()); // Guaranteed by `host`. | 1605 | 127 | debug_assert!( | 1606 | 127 | self.pending_storage_changes | 1607 | 127 | .stale_child_tries_root_hashes | 1608 | 127 | .is_empty() | 1609 | 0 | || (!self.calculate_trie_changes | 1610 | 0 | && self | 1611 | 0 | .pending_storage_changes | 1612 | 0 | .stale_child_tries_root_hashes | 1613 | 0 | .len() | 1614 | 0 | == 1 | 1615 | 0 | && self | 1616 | 0 | .pending_storage_changes | 1617 | 0 | .stale_child_tries_root_hashes | 1618 | 0 | .contains(&None)) | 1619 | | ); | 1620 | 127 | debug_assert!(self.offchain_storage_changes.is_empty()); | 1621 | | | 1622 | 127 | return RuntimeCall::Finished(Ok(Success { | 1623 | 127 | virtual_machine: SuccessVirtualMachine(finished), | 1624 | 127 | storage_changes: StorageChanges { | 1625 | 127 | inner: self.pending_storage_changes, | 1626 | 127 | calculate_trie_changes: self.calculate_trie_changes, | 1627 | 127 | }, | 1628 | 127 | state_trie_version: self.state_trie_version, | 1629 | 127 | })); | 1630 | | } | 1631 | | | 1632 | 84 | host::HostVm::ExternalStorageGet(req) => { | 1633 | 84 | let diff_search = self | 1634 | 84 | .pending_storage_changes | 1635 | 84 | .trie_diffs | 1636 | 84 | .get(&req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1637 | 84 | .and_then(|diff| diff.diff_get(req.key().as_ref())); | 1638 | | | 1639 | 84 | if let Some((value_in_diff0 , _)) = diff_search { | 1640 | 0 | self.vm = req.resume_full_value(value_in_diff); | 1641 | 0 | } else { | 1642 | 84 | self.vm = req.into(); | 1643 | 84 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1644 | | } | 1645 | | } | 1646 | | | 1647 | 0 | host::HostVm::ExternalStorageSet(req) => { | 1648 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1649 | | // is silently ignored, as per spec. | 1650 | 0 | if req.child_trie().is_none() | 1651 | 0 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1652 | | { | 1653 | 0 | self.vm = req.resume(); | 1654 | 0 | continue; | 1655 | 0 | } | 1656 | | | 1657 | | // TOOD: to_owned overhead | 1658 | 0 | self.pending_storage_changes | 1659 | 0 | .stale_child_tries_root_hashes | 1660 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1661 | | | 1662 | 0 | let trie = self | 1663 | 0 | .pending_storage_changes | 1664 | 0 | .trie_diffs | 1665 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1666 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 1667 | | | 1668 | 0 | if let Some(value) = req.value() { | 1669 | 0 | trie.diff_insert(req.key().as_ref(), value.as_ref(), ()); | 1670 | 0 | } else { | 1671 | 0 | trie.diff_insert_erase(req.key().as_ref(), ()); | 1672 | 0 | } | 1673 | | | 1674 | 0 | self.vm = req.resume() | 1675 | | } | 1676 | | | 1677 | 0 | host::HostVm::ExternalStorageAppend(req) => { | 1678 | | // Any attempt at writing a key that starts with `CHILD_STORAGE_SPECIAL_PREFIX` | 1679 | | // is silently ignored, as per spec. | 1680 | 0 | if req.child_trie().is_none() | 1681 | 0 | && req.key().as_ref().starts_with(CHILD_STORAGE_SPECIAL_PREFIX) | 1682 | | { | 1683 | 0 | self.vm = req.resume(); | 1684 | 0 | continue; | 1685 | 0 | } | 1686 | | | 1687 | | // TOOD: to_owned overhead | 1688 | 0 | self.pending_storage_changes | 1689 | 0 | .stale_child_tries_root_hashes | 1690 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1691 | | | 1692 | 0 | let trie = self | 1693 | 0 | .pending_storage_changes | 1694 | 0 | .trie_diffs | 1695 | 0 | .entry(req.child_trie().map(|ct| ct.as_ref().to_vec())) | 1696 | 0 | .or_insert(storage_diff::TrieDiff::empty()); | 1697 | | | 1698 | 0 | let current_value = trie.diff_get(req.key().as_ref()).map(|(v, _)| v); | 1699 | | | 1700 | 0 | if let Some(current_value) = current_value { | 1701 | 0 | let mut current_value = current_value.unwrap_or_default().to_vec(); | 1702 | 0 | append_to_storage_value(&mut current_value, req.value().as_ref()); | 1703 | 0 | trie.diff_insert(req.key().as_ref().to_vec(), current_value, ()); | 1704 | 0 | self.vm = req.resume(); | 1705 | 0 | } else { | 1706 | 0 | self.vm = req.into(); | 1707 | 0 | return RuntimeCall::StorageGet(StorageGet { inner: self }); | 1708 | | } | 1709 | | } | 1710 | | | 1711 | 0 | host::HostVm::ExternalStorageClearPrefix(req) => { | 1712 | | // Any attempt at clear a prefix that "intersects" (see code) with | 1713 | | // `CHILD_STORAGE_SPECIAL_PREFIX` is silently ignored, as per spec. | 1714 | 0 | if req.child_trie().is_none() | 1715 | 0 | && CHILD_STORAGE_SPECIAL_PREFIX.starts_with(req.prefix().as_ref()) | 1716 | | { | 1717 | 0 | self.vm = req.resume(0, false); // TODO: what's the correct return value for `some_keys_remain`? | 1718 | 0 | continue; | 1719 | 0 | } | 1720 | | | 1721 | | // TODO: consider doing this only if at least one key was actually removed | 1722 | | // TOOD: to_owned overhead | 1723 | 0 | self.pending_storage_changes | 1724 | 0 | .stale_child_tries_root_hashes | 1725 | 0 | .insert(req.child_trie().map(|ct| ct.as_ref().to_owned())); | 1726 | | | 1727 | 0 | let prefix = req.prefix().as_ref().to_owned(); | 1728 | 0 | self.vm = req.into(); | 1729 | 0 | return RuntimeCall::NextKey(NextKey { | 1730 | 0 | inner: self, | 1731 | 0 | key_overwrite: Some(prefix), | 1732 | 0 | keys_removed_so_far: 0, | 1733 | 0 | }); | 1734 | | } | 1735 | | | 1736 | | host::HostVm::ExternalStorageRoot(_) => { | 1737 | | // Handled above. | 1738 | 0 | unreachable!() | 1739 | | } | 1740 | | | 1741 | 0 | host::HostVm::ExternalStorageNextKey(req) => { | 1742 | 0 | self.vm = req.into(); | 1743 | 0 | return RuntimeCall::NextKey(NextKey { | 1744 | 0 | inner: self, | 1745 | 0 | key_overwrite: None, | 1746 | 0 | keys_removed_so_far: 0, | 1747 | 0 | }); | 1748 | | } | 1749 | | | 1750 | 0 | host::HostVm::ExternalOffchainIndexSet(req) => { | 1751 | 0 | self.pending_storage_changes | 1752 | 0 | .offchain_storage_changes | 1753 | 0 | .insert( | 1754 | 0 | req.key().as_ref().to_vec(), | 1755 | 0 | req.value().map(|v| v.as_ref().to_vec()), | 1756 | | ); | 1757 | | | 1758 | 0 | self.vm = req.resume(); | 1759 | | } | 1760 | | | 1761 | 0 | host::HostVm::ExternalOffchainStorageGet(req) => { | 1762 | 0 | let current_value = self.offchain_storage_changes.get(req.key().as_ref()); | 1763 | 0 | match current_value { | 1764 | 0 | Some(value) => self.vm = req.resume(value.as_ref().map(|v| &v[..])), | 1765 | | None => { | 1766 | 0 | self.vm = req.into(); | 1767 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageGet( | 1768 | 0 | OffchainStorageGet { inner: self }, | 1769 | 0 | )); | 1770 | | } | 1771 | | } | 1772 | | } | 1773 | | | 1774 | 0 | host::HostVm::ExternalOffchainStorageSet(req) => { | 1775 | 0 | self.vm = req.into(); | 1776 | 0 | return RuntimeCall::Offchain(OffchainContext::StorageSet( | 1777 | 0 | OffchainStorageCompareSet { inner: self }, | 1778 | 0 | )); | 1779 | | } | 1780 | | | 1781 | 0 | host::HostVm::SignatureVerification(req) => { | 1782 | 0 | self.vm = req.into(); | 1783 | 0 | return RuntimeCall::SignatureVerification(SignatureVerification { | 1784 | 0 | inner: self, | 1785 | 0 | }); | 1786 | | } | 1787 | | | 1788 | 0 | host::HostVm::CallRuntimeVersion(req) => { | 1789 | | // TODO: make the user execute this ; see https://github.com/paritytech/smoldot/issues/144 | 1790 | | // The code below compiles the provided WebAssembly runtime code, which is a | 1791 | | // relatively expensive operation (in the order of milliseconds). | 1792 | | // While it could be tempting to use a system cache, this function is expected | 1793 | | // to be called only right before runtime upgrades. Considering that runtime | 1794 | | // upgrades are quite uncommon and that a caching system is rather non-trivial | 1795 | | // to set up, the approach of recompiling every single time is preferred here. | 1796 | | // 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 | 1797 | 0 | let vm_prototype = match host::HostVmPrototype::new(host::Config { | 1798 | 0 | module: req.wasm_code(), | 1799 | 0 | heap_pages: executor::DEFAULT_HEAP_PAGES, | 1800 | 0 | exec_hint: vm::ExecHint::ValidateAndExecuteOnce, | 1801 | 0 | allow_unresolved_imports: false, // TODO: what is a correct value here? | 1802 | 0 | }) { | 1803 | 0 | Ok(w) => w, | 1804 | | Err(_) => { | 1805 | 0 | self.vm = req.resume(Err(())); | 1806 | 0 | continue; | 1807 | | } | 1808 | | }; | 1809 | | | 1810 | 0 | self.vm = req.resume(Ok(vm_prototype.runtime_version().as_ref())); | 1811 | | } | 1812 | | | 1813 | 0 | host::HostVm::StartStorageTransaction(tx) => { | 1814 | 0 | // TODO: this cloning is very expensive, but providing a more optimized implementation is very complicated | 1815 | 0 | self.transactions_stack | 1816 | 0 | .push(self.pending_storage_changes.clone()); | 1817 | 0 | self.vm = tx.resume(); | 1818 | 0 | } | 1819 | | | 1820 | 0 | host::HostVm::EndStorageTransaction { resume, rollback } => { | 1821 | | // The inner implementation guarantees that a storage transaction can only | 1822 | | // end if it has earlier been started. | 1823 | 0 | debug_assert!(!self.transactions_stack.is_empty()); | 1824 | 0 | let rollback_diff = self.transactions_stack.pop().unwrap(); | 1825 | | | 1826 | 0 | if rollback { | 1827 | 0 | self.pending_storage_changes = rollback_diff; | 1828 | 0 | } | 1829 | | | 1830 | 0 | self.vm = resume.resume(); | 1831 | | } | 1832 | | | 1833 | 127 | host::HostVm::GetMaxLogLevel(resume) => { | 1834 | 127 | self.vm = resume.resume(self.max_log_level); | 1835 | 127 | } | 1836 | | | 1837 | 0 | host::HostVm::LogEmit(req) => { | 1838 | 0 | self.vm = req.into(); | 1839 | 0 | return RuntimeCall::LogEmit(LogEmit { inner: self }); | 1840 | | } | 1841 | 0 | host::HostVm::OffchainTimestamp(req) => { | 1842 | 0 | self.vm = req.into(); | 1843 | 0 | return RuntimeCall::Offchain(OffchainContext::Timestamp(OffchainTimestamp { | 1844 | 0 | inner: self, | 1845 | 0 | })); | 1846 | | } | 1847 | 0 | host::HostVm::OffchainRandomSeed(req) => { | 1848 | 0 | self.vm = req.into(); | 1849 | 0 | return RuntimeCall::Offchain(OffchainContext::RandomSeed( | 1850 | 0 | OffchainRandomSeed { inner: self }, | 1851 | 0 | )); | 1852 | | } | 1853 | 0 | host::HostVm::OffchainSubmitTransaction(req) => { | 1854 | 0 | self.vm = req.into(); | 1855 | 0 | return RuntimeCall::Offchain(OffchainContext::SubmitTransaction( | 1856 | 0 | OffchainSubmitTransaction { inner: self }, | 1857 | 0 | )); | 1858 | | } | 1859 | | } | 1860 | | } | 1861 | 211 | } |
|
1862 | | } |
1863 | | |
1864 | | /// Performs the action described by [`host::HostVm::ExternalStorageAppend`] on an |
1865 | | /// encoded storage value. |
1866 | 71 | fn append_to_storage_value(value: &mut Vec<u8>, to_add: &[u8]) { |
1867 | 55 | let (curr_len, curr_len_encoded_size) = |
1868 | 71 | match util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(value) { |
1869 | 55 | Ok((rest, l)) => (l, value.len() - rest.len()), |
1870 | | Err(_) => { |
1871 | 16 | value.clear(); |
1872 | 16 | value.reserve(to_add.len() + 1); |
1873 | 16 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); |
1874 | 16 | value.extend_from_slice(to_add); |
1875 | 16 | return; |
1876 | | } |
1877 | | }; |
1878 | | |
1879 | | // Note: we use `checked_add`, as it is possible that the storage entry erroneously starts |
1880 | | // with `u64::MAX`. |
1881 | 55 | let new_len = match curr_len.checked_add(1) { |
1882 | 55 | Some(l) => l, |
1883 | | None => { |
1884 | 0 | value.clear(); |
1885 | 0 | value.reserve(to_add.len() + 1); |
1886 | 0 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); |
1887 | 0 | value.extend_from_slice(to_add); |
1888 | 0 | return; |
1889 | | } |
1890 | | }; |
1891 | | |
1892 | 55 | let new_len_encoded = util::encode_scale_compact_usize(new_len); |
1893 | | |
1894 | 55 | let new_len_encoded_size = new_len_encoded.as_ref().len(); |
1895 | 55 | debug_assert!( |
1896 | 55 | new_len_encoded_size == curr_len_encoded_size |
1897 | 0 | || new_len_encoded_size == curr_len_encoded_size + 1 |
1898 | | ); |
1899 | | |
1900 | 55 | value.reserve(to_add.len() + (new_len_encoded_size - curr_len_encoded_size)); |
1901 | | |
1902 | | // Since `new_len_encoded_size` is either equal to `curr_len_encoded_size` or equal to |
1903 | | // `curr_len_encoded_size + 1`, we simply use `insert(0, _)` in the latter case. |
1904 | 55 | if new_len_encoded_size != curr_len_encoded_size { |
1905 | 0 | value.insert(0, 0); |
1906 | 55 | } |
1907 | | |
1908 | 55 | value[..new_len_encoded_size].copy_from_slice(new_len_encoded.as_ref()); |
1909 | 55 | value.extend_from_slice(to_add); |
1910 | 71 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot8executor12runtime_call23append_to_storage_value Line | Count | Source | 1866 | 71 | fn append_to_storage_value(value: &mut Vec<u8>, to_add: &[u8]) { | 1867 | 55 | let (curr_len, curr_len_encoded_size) = | 1868 | 71 | match util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(value) { | 1869 | 55 | Ok((rest, l)) => (l, value.len() - rest.len()), | 1870 | | Err(_) => { | 1871 | 16 | value.clear(); | 1872 | 16 | value.reserve(to_add.len() + 1); | 1873 | 16 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); | 1874 | 16 | value.extend_from_slice(to_add); | 1875 | 16 | return; | 1876 | | } | 1877 | | }; | 1878 | | | 1879 | | // Note: we use `checked_add`, as it is possible that the storage entry erroneously starts | 1880 | | // with `u64::MAX`. | 1881 | 55 | let new_len = match curr_len.checked_add(1) { | 1882 | 55 | Some(l) => l, | 1883 | | None => { | 1884 | 0 | value.clear(); | 1885 | 0 | value.reserve(to_add.len() + 1); | 1886 | 0 | value.extend_from_slice(util::encode_scale_compact_usize(1).as_ref()); | 1887 | 0 | value.extend_from_slice(to_add); | 1888 | 0 | return; | 1889 | | } | 1890 | | }; | 1891 | | | 1892 | 55 | let new_len_encoded = util::encode_scale_compact_usize(new_len); | 1893 | | | 1894 | 55 | let new_len_encoded_size = new_len_encoded.as_ref().len(); | 1895 | 55 | debug_assert!( | 1896 | 55 | new_len_encoded_size == curr_len_encoded_size | 1897 | 0 | || new_len_encoded_size == curr_len_encoded_size + 1 | 1898 | | ); | 1899 | | | 1900 | 55 | value.reserve(to_add.len() + (new_len_encoded_size - curr_len_encoded_size)); | 1901 | | | 1902 | | // Since `new_len_encoded_size` is either equal to `curr_len_encoded_size` or equal to | 1903 | | // `curr_len_encoded_size + 1`, we simply use `insert(0, _)` in the latter case. | 1904 | 55 | if new_len_encoded_size != curr_len_encoded_size { | 1905 | 0 | value.insert(0, 0); | 1906 | 55 | } | 1907 | | | 1908 | 55 | value[..new_len_encoded_size].copy_from_slice(new_len_encoded.as_ref()); | 1909 | 55 | value.extend_from_slice(to_add); | 1910 | 71 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot8executor12runtime_call23append_to_storage_value |