Coverage Report

Created: 2024-05-16 12:16

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