/__w/smoldot/smoldot/repo/lib/src/chain/chain_information/build.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 | | //! Build the chain information of a chain given its runtime. |
19 | | //! |
20 | | //! This module contains the [`ChainInformationBuild`] struct, a state machine that drives the |
21 | | //! process of building the chain information of a certain finalized point of a chain. |
22 | | |
23 | | use alloc::{boxed::Box, vec::Vec}; |
24 | | use core::{fmt, iter, num::NonZeroU64}; |
25 | | |
26 | | use crate::{ |
27 | | chain::chain_information, |
28 | | executor::{host, runtime_call}, |
29 | | header, trie, |
30 | | }; |
31 | | |
32 | | pub use runtime_call::{Nibble, TrieEntryVersion}; |
33 | | |
34 | | /// Configuration to provide to [`ChainInformationBuild::new`]. |
35 | | pub struct Config { |
36 | | /// Header of the finalized block, whose chain information is to retrieve. |
37 | | /// |
38 | | /// Stored within the chain information at the end. |
39 | | pub finalized_block_header: ConfigFinalizedBlockHeader, |
40 | | |
41 | | /// Runtime of the finalized block. Must be built using the Wasm code found at the `:code` key |
42 | | /// of the block storage. |
43 | | pub runtime: host::HostVmPrototype, |
44 | | |
45 | | /// Number of bytes of the block number encoded in the block header. |
46 | | pub block_number_bytes: usize, |
47 | | } |
48 | | |
49 | | /// See [`Config::finalized_block_header`]. |
50 | | pub enum ConfigFinalizedBlockHeader { |
51 | | /// The block is the genesis block of the chain. |
52 | | Genesis { |
53 | | /// Hash of the root of the state trie of the genesis. |
54 | | state_trie_root_hash: [u8; 32], |
55 | | }, |
56 | | /// The block can any block, genesis block of the chain or not. |
57 | | Any { |
58 | | /// Header of the block. |
59 | | scale_encoded_header: Vec<u8>, |
60 | | /// Can be used to pass information about the finality of the chain, if already known. |
61 | | known_finality: Option<chain_information::ChainInformationFinality>, |
62 | | }, |
63 | | } |
64 | | |
65 | | /// Current state of the operation. |
66 | | #[must_use] |
67 | | pub enum ChainInformationBuild { |
68 | | /// Fetching the chain information is over. |
69 | | Finished { |
70 | | /// The result of the computation. |
71 | | /// |
72 | | /// If successful, the chain information is guaranteed to be valid. |
73 | | result: Result<chain_information::ValidChainInformation, Error>, |
74 | | /// Value of [`Config::runtime`] passed back. |
75 | | virtual_machine: host::HostVmPrototype, |
76 | | }, |
77 | | |
78 | | /// Still in progress. |
79 | | InProgress(InProgress), |
80 | | } |
81 | | |
82 | | /// Chain information building is still in progress. |
83 | | #[must_use] |
84 | | pub enum InProgress { |
85 | | /// Loading a storage value is required in order to continue. |
86 | | StorageGet(StorageGet), |
87 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
88 | | /// to continue. |
89 | | ClosestDescendantMerkleValue(ClosestDescendantMerkleValue), |
90 | | /// Fetching the key that follows a given one is required in order to continue. |
91 | | NextKey(NextKey), |
92 | | } |
93 | | |
94 | | /// Problem encountered during the chain building process. |
95 | 0 | #[derive(Debug, derive_more::Display)] Unexecuted instantiation: _RNvXs7_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs7_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
96 | | pub enum Error { |
97 | | /// Error while starting the Wasm virtual machine. |
98 | | #[display(fmt = "While calling {call:?}: {error}")] |
99 | | WasmStart { |
100 | | call: RuntimeCall, |
101 | | error: host::StartErr, |
102 | | }, |
103 | | /// Error while running the Wasm virtual machine. |
104 | | #[display(fmt = "While calling {call:?}: {error}")] |
105 | | WasmVm { |
106 | | call: RuntimeCall, |
107 | | error: runtime_call::ErrorDetail, |
108 | | }, |
109 | | /// Runtime has called an offchain worker host function. |
110 | | OffchainWorkerHostFunction, |
111 | | /// Failed to decode the output of the `AuraApi_slot_duration` runtime call. |
112 | | AuraSlotDurationOutputDecode, |
113 | | /// Failed to decode the output of the `AuraApi_authorities` runtime call. |
114 | | AuraAuthoritiesOutputDecode, |
115 | | /// Failed to decode the output of the `BabeApi_current_epoch` runtime call. |
116 | | BabeCurrentEpochOutputDecode, |
117 | | /// Failed to decode the output of the `BabeApi_next_epoch` runtime call. |
118 | | BabeNextEpochOutputDecode, |
119 | | /// Failed to decode the output of the `BabeApi_configuration` runtime call. |
120 | | BabeConfigurationOutputDecode, |
121 | | /// The version of `GrandaApi` is too old to be able to build the chain information. |
122 | | GrandpaApiTooOld, |
123 | | /// Failed to decode the output of the `GrandpaApi_authorities` runtime call. |
124 | | GrandpaAuthoritiesOutputDecode, |
125 | | /// Failed to decode the output of the `GrandpaApi_current_set_id` runtime call. |
126 | | GrandpaCurrentSetIdOutputDecode, |
127 | | /// The combination of the information retrieved from the runtime doesn't make sense together. |
128 | | #[display(fmt = "{_0}")] |
129 | | InvalidChainInformation(chain_information::ValidityError), |
130 | | /// Multiple consensus algorithms have been detected. |
131 | | MultipleConsensusAlgorithms, |
132 | | } |
133 | | |
134 | | /// Function call to perform or being performed. |
135 | | #[derive(Copy, Clone, PartialEq, Eq, Hash)] |
136 | | pub enum RuntimeCall { |
137 | | AuraApiSlotDuration, |
138 | | AuraApiAuthorities, |
139 | | BabeApiCurrentEpoch, |
140 | | BabeApiNextEpoch, |
141 | | BabeApiConfiguration, |
142 | | GrandpaApiAuthorities, |
143 | | GrandpaApiCurrentSetId, |
144 | | } |
145 | | |
146 | | impl RuntimeCall { |
147 | | /// Name of the runtime function corresponding to this call. |
148 | 128 | pub fn function_name(&self) -> &'static str { |
149 | 128 | match self { |
150 | 42 | RuntimeCall::AuraApiSlotDuration => "AuraApi_slot_duration", |
151 | 42 | RuntimeCall::AuraApiAuthorities => "AuraApi_authorities", |
152 | 0 | RuntimeCall::BabeApiCurrentEpoch => "BabeApi_current_epoch", |
153 | 0 | RuntimeCall::BabeApiNextEpoch => "BabeApi_next_epoch", |
154 | 1 | RuntimeCall::BabeApiConfiguration => "BabeApi_configuration", |
155 | 43 | RuntimeCall::GrandpaApiAuthorities => "GrandpaApi_grandpa_authorities", |
156 | 0 | RuntimeCall::GrandpaApiCurrentSetId => "GrandpaApi_current_set_id", |
157 | | } |
158 | 128 | } _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall13function_name Line | Count | Source | 148 | 2 | pub fn function_name(&self) -> &'static str { | 149 | 2 | match self { | 150 | 0 | RuntimeCall::AuraApiSlotDuration => "AuraApi_slot_duration", | 151 | 0 | RuntimeCall::AuraApiAuthorities => "AuraApi_authorities", | 152 | 0 | RuntimeCall::BabeApiCurrentEpoch => "BabeApi_current_epoch", | 153 | 0 | RuntimeCall::BabeApiNextEpoch => "BabeApi_next_epoch", | 154 | 1 | RuntimeCall::BabeApiConfiguration => "BabeApi_configuration", | 155 | 1 | RuntimeCall::GrandpaApiAuthorities => "GrandpaApi_grandpa_authorities", | 156 | 0 | RuntimeCall::GrandpaApiCurrentSetId => "GrandpaApi_current_set_id", | 157 | | } | 158 | 2 | } |
_RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall13function_name Line | Count | Source | 148 | 126 | pub fn function_name(&self) -> &'static str { | 149 | 126 | match self { | 150 | 42 | RuntimeCall::AuraApiSlotDuration => "AuraApi_slot_duration", | 151 | 42 | RuntimeCall::AuraApiAuthorities => "AuraApi_authorities", | 152 | 0 | RuntimeCall::BabeApiCurrentEpoch => "BabeApi_current_epoch", | 153 | 0 | RuntimeCall::BabeApiNextEpoch => "BabeApi_next_epoch", | 154 | 0 | RuntimeCall::BabeApiConfiguration => "BabeApi_configuration", | 155 | 42 | RuntimeCall::GrandpaApiAuthorities => "GrandpaApi_grandpa_authorities", | 156 | 0 | RuntimeCall::GrandpaApiCurrentSetId => "GrandpaApi_current_set_id", | 157 | | } | 158 | 126 | } |
|
159 | | |
160 | | /// Returns the list of parameters to pass when making the call. |
161 | | /// |
162 | | /// The actual parameters are obtained by putting together all the returned buffers together. |
163 | 128 | pub fn parameter_vectored( |
164 | 128 | &'_ self, |
165 | 128 | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_ { |
166 | 128 | iter::empty::<Vec<u8>>() |
167 | 128 | } _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall18parameter_vectored Line | Count | Source | 163 | 2 | pub fn parameter_vectored( | 164 | 2 | &'_ self, | 165 | 2 | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_ { | 166 | 2 | iter::empty::<Vec<u8>>() | 167 | 2 | } |
_RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall18parameter_vectored Line | Count | Source | 163 | 126 | pub fn parameter_vectored( | 164 | 126 | &'_ self, | 165 | 126 | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_ { | 166 | 126 | iter::empty::<Vec<u8>>() | 167 | 126 | } |
|
168 | | |
169 | | /// Returns the list of parameters to pass when making the call. |
170 | | /// |
171 | | /// This function is a convenience around [`RuntimeCall::parameter_vectored`]. |
172 | 0 | pub fn parameter_vectored_vec(&self) -> Vec<u8> { |
173 | 0 | Vec::new() |
174 | 0 | } Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall22parameter_vectored_vec Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB2_11RuntimeCall22parameter_vectored_vec |
175 | | } |
176 | | |
177 | | impl fmt::Debug for RuntimeCall { |
178 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
179 | 0 | fmt::Debug::fmt(&self.function_name(), f) |
180 | 0 | } Unexecuted instantiation: _RNvXs_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB4_11RuntimeCallNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB4_11RuntimeCallNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
181 | | } |
182 | | |
183 | | impl ChainInformationBuild { |
184 | | /// Starts a new chain information build process. |
185 | | /// |
186 | | /// # Panic |
187 | | /// |
188 | | /// Panics if a [`ConfigFinalizedBlockHeader::Any`] is provided, and the header can't be |
189 | | /// decoded. |
190 | | /// |
191 | 43 | pub fn new(config: Config) -> Self { |
192 | 43 | let [aura_version, babe_version, grandpa_version] = config |
193 | 43 | .runtime |
194 | 43 | .runtime_version() |
195 | 43 | .decode() |
196 | 43 | .apis |
197 | 43 | .find_versions(["AuraApi", "BabeApi", "GrandpaApi"]); |
198 | 43 | let runtime_has_aura = aura_version.map_or(false, |version_number| version_number == 142 ); Unexecuted instantiation: _RNCNvMs0_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3new0Bd_ _RNCNvMs0_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3new0Bd_ Line | Count | Source | 198 | 42 | let runtime_has_aura = aura_version.map_or(false, |version_number| version_number == 1); |
|
199 | 43 | let runtime_babeapi_is_v1 = babe_version.and_then(|version_number| match version_number1 { |
200 | 0 | 1 => Some(true), |
201 | 1 | 2 => Some(false), |
202 | 0 | _ => None, |
203 | 43 | }1 ); _RNCNvMs0_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3news_0Bd_ Line | Count | Source | 199 | 1 | let runtime_babeapi_is_v1 = babe_version.and_then(|version_number| match version_number { | 200 | 0 | 1 => Some(true), | 201 | 1 | 2 => Some(false), | 202 | 0 | _ => None, | 203 | 1 | }); |
Unexecuted instantiation: _RNCNvMs0_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3news_0Bd_ |
204 | 43 | let runtime_grandpa_supports_currentsetid = |
205 | 43 | grandpa_version.and_then(|version_number| match version_number { |
206 | | // Version 1 is from 2019 and isn't used by any chain in production, so we don't |
207 | | // care about it. |
208 | 1 | 2 => Some(false), |
209 | 42 | 3 => Some(true), |
210 | 0 | _ => None, |
211 | 43 | }); _RNCNvMs0_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3news0_0Bd_ Line | Count | Source | 205 | 1 | grandpa_version.and_then(|version_number| match version_number { | 206 | | // Version 1 is from 2019 and isn't used by any chain in production, so we don't | 207 | | // care about it. | 208 | 1 | 2 => Some(false), | 209 | 0 | 3 => Some(true), | 210 | 0 | _ => None, | 211 | 1 | }); |
_RNCNvMs0_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB7_21ChainInformationBuild3news0_0Bd_ Line | Count | Source | 205 | 42 | grandpa_version.and_then(|version_number| match version_number { | 206 | | // Version 1 is from 2019 and isn't used by any chain in production, so we don't | 207 | | // care about it. | 208 | 0 | 2 => Some(false), | 209 | 42 | 3 => Some(true), | 210 | 0 | _ => None, | 211 | 42 | }); |
|
212 | 43 | |
213 | 43 | let inner = ChainInformationBuildInner { |
214 | 43 | finalized_block_header: config.finalized_block_header, |
215 | 43 | block_number_bytes: config.block_number_bytes, |
216 | 43 | call_in_progress: None, |
217 | 43 | virtual_machine: Some(config.runtime), |
218 | 43 | runtime_has_aura, |
219 | 43 | runtime_babeapi_is_v1, |
220 | 43 | runtime_grandpa_supports_currentsetid, |
221 | 43 | aura_autorities_call_output: None, |
222 | 43 | aura_slot_duration_call_output: None, |
223 | 43 | babe_current_epoch_call_output: None, |
224 | 43 | babe_next_epoch_call_output: None, |
225 | 43 | babe_configuration_call_output: None, |
226 | 43 | grandpa_autorities_call_output: None, |
227 | 43 | grandpa_current_set_id_call_output: None, |
228 | 43 | }; |
229 | 43 | |
230 | 43 | ChainInformationBuild::start_next_call(inner) |
231 | 43 | } _RNvMs0_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild3new Line | Count | Source | 191 | 1 | pub fn new(config: Config) -> Self { | 192 | 1 | let [aura_version, babe_version, grandpa_version] = config | 193 | 1 | .runtime | 194 | 1 | .runtime_version() | 195 | 1 | .decode() | 196 | 1 | .apis | 197 | 1 | .find_versions(["AuraApi", "BabeApi", "GrandpaApi"]); | 198 | 1 | let runtime_has_aura = aura_version.map_or(false, |version_number| version_number == 1); | 199 | 1 | let runtime_babeapi_is_v1 = babe_version.and_then(|version_number| match version_number { | 200 | | 1 => Some(true), | 201 | | 2 => Some(false), | 202 | | _ => None, | 203 | 1 | }); | 204 | 1 | let runtime_grandpa_supports_currentsetid = | 205 | 1 | grandpa_version.and_then(|version_number| match version_number { | 206 | | // Version 1 is from 2019 and isn't used by any chain in production, so we don't | 207 | | // care about it. | 208 | | 2 => Some(false), | 209 | | 3 => Some(true), | 210 | | _ => None, | 211 | 1 | }); | 212 | 1 | | 213 | 1 | let inner = ChainInformationBuildInner { | 214 | 1 | finalized_block_header: config.finalized_block_header, | 215 | 1 | block_number_bytes: config.block_number_bytes, | 216 | 1 | call_in_progress: None, | 217 | 1 | virtual_machine: Some(config.runtime), | 218 | 1 | runtime_has_aura, | 219 | 1 | runtime_babeapi_is_v1, | 220 | 1 | runtime_grandpa_supports_currentsetid, | 221 | 1 | aura_autorities_call_output: None, | 222 | 1 | aura_slot_duration_call_output: None, | 223 | 1 | babe_current_epoch_call_output: None, | 224 | 1 | babe_next_epoch_call_output: None, | 225 | 1 | babe_configuration_call_output: None, | 226 | 1 | grandpa_autorities_call_output: None, | 227 | 1 | grandpa_current_set_id_call_output: None, | 228 | 1 | }; | 229 | 1 | | 230 | 1 | ChainInformationBuild::start_next_call(inner) | 231 | 1 | } |
_RNvMs0_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild3new Line | Count | Source | 191 | 42 | pub fn new(config: Config) -> Self { | 192 | 42 | let [aura_version, babe_version, grandpa_version] = config | 193 | 42 | .runtime | 194 | 42 | .runtime_version() | 195 | 42 | .decode() | 196 | 42 | .apis | 197 | 42 | .find_versions(["AuraApi", "BabeApi", "GrandpaApi"]); | 198 | 42 | let runtime_has_aura = aura_version.map_or(false, |version_number| version_number == 1); | 199 | 42 | let runtime_babeapi_is_v1 = babe_version.and_then(|version_number| match version_number { | 200 | | 1 => Some(true), | 201 | | 2 => Some(false), | 202 | | _ => None, | 203 | 42 | }); | 204 | 42 | let runtime_grandpa_supports_currentsetid = | 205 | 42 | grandpa_version.and_then(|version_number| match version_number { | 206 | | // Version 1 is from 2019 and isn't used by any chain in production, so we don't | 207 | | // care about it. | 208 | | 2 => Some(false), | 209 | | 3 => Some(true), | 210 | | _ => None, | 211 | 42 | }); | 212 | 42 | | 213 | 42 | let inner = ChainInformationBuildInner { | 214 | 42 | finalized_block_header: config.finalized_block_header, | 215 | 42 | block_number_bytes: config.block_number_bytes, | 216 | 42 | call_in_progress: None, | 217 | 42 | virtual_machine: Some(config.runtime), | 218 | 42 | runtime_has_aura, | 219 | 42 | runtime_babeapi_is_v1, | 220 | 42 | runtime_grandpa_supports_currentsetid, | 221 | 42 | aura_autorities_call_output: None, | 222 | 42 | aura_slot_duration_call_output: None, | 223 | 42 | babe_current_epoch_call_output: None, | 224 | 42 | babe_next_epoch_call_output: None, | 225 | 42 | babe_configuration_call_output: None, | 226 | 42 | grandpa_autorities_call_output: None, | 227 | 42 | grandpa_current_set_id_call_output: None, | 228 | 42 | }; | 229 | 42 | | 230 | 42 | ChainInformationBuild::start_next_call(inner) | 231 | 42 | } |
|
232 | | } |
233 | | |
234 | | impl InProgress { |
235 | | /// Returns the list of runtime calls that will be performed. Always includes the value |
236 | | /// returned by [`InProgress::call_in_progress`]. |
237 | | /// |
238 | | /// This list never changes, except for the fact that it gets shorter over time. |
239 | 0 | pub fn remaining_calls(&self) -> impl Iterator<Item = RuntimeCall> { |
240 | 0 | let inner = match self { |
241 | 0 | InProgress::StorageGet(StorageGet(_, shared)) => shared, |
242 | 0 | InProgress::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue(_, shared)) => { |
243 | 0 | shared |
244 | | } |
245 | 0 | InProgress::NextKey(NextKey(_, shared)) => shared, |
246 | | }; |
247 | | |
248 | 0 | ChainInformationBuild::necessary_calls(inner) |
249 | 0 | } Unexecuted instantiation: _RNvMs1_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_10InProgress15remaining_calls Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_10InProgress15remaining_calls |
250 | | |
251 | | /// Returns the runtime call currently being made. |
252 | 0 | pub fn call_in_progress(&self) -> RuntimeCall { |
253 | 0 | let inner = match self { |
254 | 0 | InProgress::StorageGet(StorageGet(_, shared)) => shared, |
255 | 0 | InProgress::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue(_, shared)) => { |
256 | 0 | shared |
257 | | } |
258 | 0 | InProgress::NextKey(NextKey(_, shared)) => shared, |
259 | | }; |
260 | | |
261 | 0 | inner.call_in_progress.unwrap() |
262 | 0 | } Unexecuted instantiation: _RNvMs1_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_10InProgress16call_in_progress Unexecuted instantiation: _RNvMs1_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_10InProgress16call_in_progress |
263 | | } |
264 | | |
265 | | /// Loading a storage value is required in order to continue. |
266 | | #[must_use] |
267 | | pub struct StorageGet(runtime_call::StorageGet, ChainInformationBuildInner); |
268 | | |
269 | | impl StorageGet { |
270 | | /// Returns the key whose value must be passed to [`StorageGet::inject_value`]. |
271 | 87 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
272 | 87 | self.0.key() |
273 | 87 | } _RNvMs2_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_10StorageGet3key Line | Count | Source | 271 | 3 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 272 | 3 | self.0.key() | 273 | 3 | } |
_RNvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_10StorageGet3key Line | Count | Source | 271 | 84 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 272 | 84 | self.0.key() | 273 | 84 | } |
|
274 | | |
275 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
276 | 0 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
277 | 0 | self.0.child_trie() |
278 | 0 | } Unexecuted instantiation: _RNvMs2_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_10StorageGet10child_trie Unexecuted instantiation: _RNvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_10StorageGet10child_trie |
279 | | |
280 | | /// Injects the corresponding storage value. |
281 | 87 | pub fn inject_value( |
282 | 87 | self, |
283 | 87 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, |
284 | 87 | ) -> ChainInformationBuild { |
285 | 87 | ChainInformationBuild::from_call_in_progress(self.0.inject_value(value), self.1) |
286 | 87 | } _RINvMs2_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EEBc_ Line | Count | Source | 281 | 3 | pub fn inject_value( | 282 | 3 | self, | 283 | 3 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 284 | 3 | ) -> ChainInformationBuild { | 285 | 3 | ChainInformationBuild::from_call_in_progress(self.0.inject_value(value), self.1) | 286 | 3 | } |
Unexecuted instantiation: _RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EECsDDUKWWCHAU_18smoldot_light_wasm _RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EEBc_ Line | Count | Source | 281 | 42 | pub fn inject_value( | 282 | 42 | self, | 283 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 284 | 42 | ) -> ChainInformationBuild { | 285 | 42 | ChainInformationBuild::from_call_in_progress(self.0.inject_value(value), self.1) | 286 | 42 | } |
_RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EEBc_ Line | Count | Source | 281 | 42 | pub fn inject_value( | 282 | 42 | self, | 283 | 42 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 284 | 42 | ) -> ChainInformationBuild { | 285 | 42 | ChainInformationBuild::from_call_in_progress(self.0.inject_value(value), self.1) | 286 | 42 | } |
Unexecuted instantiation: _RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EECsibGXYHQB8Ea_25json_rpc_general_requests |
287 | | |
288 | | /// Returns the runtime call currently being made. |
289 | 0 | pub fn call_in_progress(&self) -> RuntimeCall { |
290 | 0 | self.1.call_in_progress.unwrap() |
291 | 0 | } Unexecuted instantiation: _RNvMs2_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_10StorageGet16call_in_progress Unexecuted instantiation: _RNvMs2_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_10StorageGet16call_in_progress |
292 | | } |
293 | | |
294 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
295 | | /// to continue. |
296 | | #[must_use] |
297 | | pub struct ClosestDescendantMerkleValue( |
298 | | runtime_call::ClosestDescendantMerkleValue, |
299 | | ChainInformationBuildInner, |
300 | | ); |
301 | | |
302 | | impl ClosestDescendantMerkleValue { |
303 | | /// Returns the key whose closest descendant Merkle value must be passed to |
304 | | /// [`ClosestDescendantMerkleValue::inject_merkle_value`]. |
305 | 0 | pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
306 | 0 | self.0.key() |
307 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue3key Unexecuted instantiation: _RNvMs3_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue3key |
308 | | |
309 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
310 | 0 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
311 | 0 | self.0.child_trie() |
312 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue10child_trie Unexecuted instantiation: _RNvMs3_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue10child_trie |
313 | | |
314 | | /// Indicate that the value is unknown and resume the calculation. |
315 | | /// |
316 | | /// This function be used if you are unaware of the Merkle value. The algorithm will perform |
317 | | /// the calculation of this Merkle value manually, which takes more time. |
318 | 0 | pub fn resume_unknown(self) -> ChainInformationBuild { |
319 | 0 | ChainInformationBuild::from_call_in_progress(self.0.resume_unknown(), self.1) |
320 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue14resume_unknown Unexecuted instantiation: _RNvMs3_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue14resume_unknown |
321 | | |
322 | | /// Injects the corresponding Merkle value. |
323 | | /// |
324 | | /// `None` can be passed if there is no descendant or, in the case of a child trie read, in |
325 | | /// order to indicate that the child trie does not exist. |
326 | 0 | pub fn inject_merkle_value(self, merkle_value: Option<&[u8]>) -> ChainInformationBuild { |
327 | 0 | ChainInformationBuild::from_call_in_progress( |
328 | 0 | self.0.inject_merkle_value(merkle_value), |
329 | 0 | self.1, |
330 | 0 | ) |
331 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue19inject_merkle_value Unexecuted instantiation: _RNvMs3_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue19inject_merkle_value |
332 | | |
333 | | /// Returns the runtime call currently being made. |
334 | 0 | pub fn call_in_progress(&self) -> RuntimeCall { |
335 | 0 | self.1.call_in_progress.unwrap() |
336 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue16call_in_progress Unexecuted instantiation: _RNvMs3_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_28ClosestDescendantMerkleValue16call_in_progress |
337 | | } |
338 | | |
339 | | /// Fetching the key that follows a given one is required in order to continue. |
340 | | #[must_use] |
341 | | pub struct NextKey(runtime_call::NextKey, ChainInformationBuildInner); |
342 | | |
343 | | impl NextKey { |
344 | | /// Returns the key whose next key must be passed back. |
345 | 0 | pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
346 | 0 | self.0.key() |
347 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey3key Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey3key |
348 | | |
349 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
350 | 0 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
351 | 0 | self.0.child_trie() |
352 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey10child_trie Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey10child_trie |
353 | | |
354 | | /// If `true`, then the provided value must the one superior or equal to the requested key. |
355 | | /// If `false`, then the provided value must be strictly superior to the requested key. |
356 | 0 | pub fn or_equal(&self) -> bool { |
357 | 0 | self.0.or_equal() |
358 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey8or_equal Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey8or_equal |
359 | | |
360 | | /// If `true`, then the search must include both branch nodes and storage nodes. If `false`, |
361 | | /// the search only covers storage nodes. |
362 | 0 | pub fn branch_nodes(&self) -> bool { |
363 | 0 | self.0.branch_nodes() |
364 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey12branch_nodes Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey12branch_nodes |
365 | | |
366 | | /// Returns the prefix the next key must start with. If the next key doesn't start with the |
367 | | /// given prefix, then `None` should be provided. |
368 | 0 | pub fn prefix(&'_ self) -> impl Iterator<Item = Nibble> + '_ { |
369 | 0 | self.0.prefix() |
370 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey6prefix Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey6prefix |
371 | | |
372 | | /// Injects the key. |
373 | | /// |
374 | | /// # Panic |
375 | | /// |
376 | | /// Panics if the key passed as parameter isn't strictly superior to the requested key. |
377 | | /// Panics if the key passed as parameter doesn't start with the requested prefix. |
378 | | /// |
379 | 0 | pub fn inject_key(self, key: Option<impl Iterator<Item = Nibble>>) -> ChainInformationBuild { |
380 | 0 | ChainInformationBuild::from_call_in_progress(self.0.inject_key(key), self.1) |
381 | 0 | } Unexecuted instantiation: _RINvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keypEBc_ Unexecuted instantiation: _RINvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNvMNtNtBc_8database11full_sqliteNtB3d_18SqliteFullDatabase20to_chain_informations_00EEBc_ Unexecuted instantiation: _RINvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB6_7NextKey10inject_keyINtNtNtBc_4trie12proof_decode12EntryKeyIterINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhEEECsibGXYHQB8Ea_25json_rpc_general_requests |
382 | | |
383 | | /// Returns the runtime call currently being made. |
384 | 0 | pub fn call_in_progress(&self) -> RuntimeCall { |
385 | 0 | self.1.call_in_progress.unwrap() |
386 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_7NextKey16call_in_progress Unexecuted instantiation: _RNvMs4_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_7NextKey16call_in_progress |
387 | | } |
388 | | |
389 | | impl ChainInformationBuild { |
390 | 171 | fn necessary_calls(inner: &ChainInformationBuildInner) -> impl Iterator<Item = RuntimeCall> { |
391 | 171 | let aura_api_authorities = |
392 | 171 | if inner.runtime_has_aura && inner.aura_autorities_call_output.is_none()168 { |
393 | 42 | Some(RuntimeCall::AuraApiAuthorities) |
394 | | } else { |
395 | 129 | None |
396 | | }; |
397 | | |
398 | 171 | let aura_slot_duration = |
399 | 171 | if inner.runtime_has_aura && inner.aura_slot_duration_call_output.is_none()168 { |
400 | 84 | Some(RuntimeCall::AuraApiSlotDuration) |
401 | | } else { |
402 | 87 | None |
403 | | }; |
404 | | |
405 | 171 | let babe_current_epoch = if matches!0 ( |
406 | 84 | inner.finalized_block_header, |
407 | 84 | ConfigFinalizedBlockHeader::Any { |
408 | 84 | ref scale_encoded_header, |
409 | 84 | .. |
410 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 |
411 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() |
412 | 0 | && inner.babe_current_epoch_call_output.is_none() |
413 | | { |
414 | 0 | Some(RuntimeCall::BabeApiCurrentEpoch) |
415 | | } else { |
416 | 171 | None |
417 | | }; |
418 | | |
419 | 171 | let babe_next_epoch = if matches!0 ( |
420 | 84 | inner.finalized_block_header, |
421 | 84 | ConfigFinalizedBlockHeader::Any { |
422 | 84 | ref scale_encoded_header, |
423 | 84 | .. |
424 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 |
425 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() |
426 | 0 | && inner.babe_next_epoch_call_output.is_none() |
427 | | { |
428 | 0 | Some(RuntimeCall::BabeApiNextEpoch) |
429 | | } else { |
430 | 171 | None |
431 | | }; |
432 | | |
433 | 171 | let babe_configuration = if inner.runtime_babeapi_is_v1.is_some() |
434 | 3 | && inner.babe_configuration_call_output.is_none() |
435 | | { |
436 | 1 | Some(RuntimeCall::BabeApiConfiguration) |
437 | | } else { |
438 | 170 | None |
439 | | }; |
440 | | |
441 | 171 | let grandpa_authorities = if !matches!( |
442 | 0 | inner.finalized_block_header, |
443 | | ConfigFinalizedBlockHeader::Any { |
444 | | known_finality: Some(chain_information::ChainInformationFinality::Grandpa { .. }), |
445 | | .. |
446 | | }, |
447 | 171 | ) && inner.runtime_grandpa_supports_currentsetid.is_some() |
448 | 171 | && inner.grandpa_autorities_call_output.is_none() |
449 | | { |
450 | 128 | Some(RuntimeCall::GrandpaApiAuthorities) |
451 | | } else { |
452 | 43 | None |
453 | | }; |
454 | | |
455 | | // The grandpa set ID doesn't need to be retrieved if finality was provided by the user, |
456 | | // but also doesn't need to be retrieved for the genesis block because we know it's |
457 | | // always 0. |
458 | 171 | let grandpa_current_set_id = if matches!0 ( |
459 | 84 | inner.finalized_block_header, |
460 | 84 | ConfigFinalizedBlockHeader::Any { |
461 | 84 | ref scale_encoded_header, |
462 | 84 | known_finality: None, |
463 | 84 | .. |
464 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 , |
465 | 0 | ) && inner.runtime_grandpa_supports_currentsetid |
466 | 0 | == Some(true) |
467 | 0 | && inner.grandpa_current_set_id_call_output.is_none() |
468 | | { |
469 | 0 | Some(RuntimeCall::GrandpaApiCurrentSetId) |
470 | | } else { |
471 | 171 | None |
472 | | }; |
473 | | |
474 | 171 | [ |
475 | 171 | aura_api_authorities, |
476 | 171 | aura_slot_duration, |
477 | 171 | babe_current_epoch, |
478 | 171 | babe_next_epoch, |
479 | 171 | babe_configuration, |
480 | 171 | grandpa_authorities, |
481 | 171 | grandpa_current_set_id, |
482 | 171 | ] |
483 | 171 | .into_iter() |
484 | 171 | .flatten() |
485 | 171 | } _RNvMs5_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild15necessary_calls Line | Count | Source | 390 | 3 | fn necessary_calls(inner: &ChainInformationBuildInner) -> impl Iterator<Item = RuntimeCall> { | 391 | 3 | let aura_api_authorities = | 392 | 3 | if inner.runtime_has_aura && inner.aura_autorities_call_output.is_none()0 { | 393 | 0 | Some(RuntimeCall::AuraApiAuthorities) | 394 | | } else { | 395 | 3 | None | 396 | | }; | 397 | | | 398 | 3 | let aura_slot_duration = | 399 | 3 | if inner.runtime_has_aura && inner.aura_slot_duration_call_output.is_none()0 { | 400 | 0 | Some(RuntimeCall::AuraApiSlotDuration) | 401 | | } else { | 402 | 3 | None | 403 | | }; | 404 | | | 405 | 3 | let babe_current_epoch = if matches!0 ( | 406 | 0 | inner.finalized_block_header, | 407 | 0 | ConfigFinalizedBlockHeader::Any { | 408 | 0 | ref scale_encoded_header, | 409 | 0 | .. | 410 | 0 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 0 | 411 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() | 412 | 0 | && inner.babe_current_epoch_call_output.is_none() | 413 | | { | 414 | 0 | Some(RuntimeCall::BabeApiCurrentEpoch) | 415 | | } else { | 416 | 3 | None | 417 | | }; | 418 | | | 419 | 3 | let babe_next_epoch = if matches!0 ( | 420 | 0 | inner.finalized_block_header, | 421 | 0 | ConfigFinalizedBlockHeader::Any { | 422 | 0 | ref scale_encoded_header, | 423 | 0 | .. | 424 | 0 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 0 | 425 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() | 426 | 0 | && inner.babe_next_epoch_call_output.is_none() | 427 | | { | 428 | 0 | Some(RuntimeCall::BabeApiNextEpoch) | 429 | | } else { | 430 | 3 | None | 431 | | }; | 432 | | | 433 | 3 | let babe_configuration = if inner.runtime_babeapi_is_v1.is_some() | 434 | 3 | && inner.babe_configuration_call_output.is_none() | 435 | | { | 436 | 1 | Some(RuntimeCall::BabeApiConfiguration) | 437 | | } else { | 438 | 2 | None | 439 | | }; | 440 | | | 441 | 3 | let grandpa_authorities = if !matches!( | 442 | 0 | inner.finalized_block_header, | 443 | | ConfigFinalizedBlockHeader::Any { | 444 | | known_finality: Some(chain_information::ChainInformationFinality::Grandpa { .. }), | 445 | | .. | 446 | | }, | 447 | 3 | ) && inner.runtime_grandpa_supports_currentsetid.is_some() | 448 | 3 | && inner.grandpa_autorities_call_output.is_none() | 449 | | { | 450 | 2 | Some(RuntimeCall::GrandpaApiAuthorities) | 451 | | } else { | 452 | 1 | None | 453 | | }; | 454 | | | 455 | | // The grandpa set ID doesn't need to be retrieved if finality was provided by the user, | 456 | | // but also doesn't need to be retrieved for the genesis block because we know it's | 457 | | // always 0. | 458 | 3 | let grandpa_current_set_id = if matches!0 ( | 459 | 0 | inner.finalized_block_header, | 460 | 0 | ConfigFinalizedBlockHeader::Any { | 461 | 0 | ref scale_encoded_header, | 462 | 0 | known_finality: None, | 463 | 0 | .. | 464 | 0 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 0, | 465 | 0 | ) && inner.runtime_grandpa_supports_currentsetid | 466 | 0 | == Some(true) | 467 | 0 | && inner.grandpa_current_set_id_call_output.is_none() | 468 | | { | 469 | 0 | Some(RuntimeCall::GrandpaApiCurrentSetId) | 470 | | } else { | 471 | 3 | None | 472 | | }; | 473 | | | 474 | 3 | [ | 475 | 3 | aura_api_authorities, | 476 | 3 | aura_slot_duration, | 477 | 3 | babe_current_epoch, | 478 | 3 | babe_next_epoch, | 479 | 3 | babe_configuration, | 480 | 3 | grandpa_authorities, | 481 | 3 | grandpa_current_set_id, | 482 | 3 | ] | 483 | 3 | .into_iter() | 484 | 3 | .flatten() | 485 | 3 | } |
_RNvMs5_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild15necessary_calls Line | Count | Source | 390 | 168 | fn necessary_calls(inner: &ChainInformationBuildInner) -> impl Iterator<Item = RuntimeCall> { | 391 | 168 | let aura_api_authorities = | 392 | 168 | if inner.runtime_has_aura && inner.aura_autorities_call_output.is_none() { | 393 | 42 | Some(RuntimeCall::AuraApiAuthorities) | 394 | | } else { | 395 | 126 | None | 396 | | }; | 397 | | | 398 | 168 | let aura_slot_duration = | 399 | 168 | if inner.runtime_has_aura && inner.aura_slot_duration_call_output.is_none() { | 400 | 84 | Some(RuntimeCall::AuraApiSlotDuration) | 401 | | } else { | 402 | 84 | None | 403 | | }; | 404 | | | 405 | 168 | let babe_current_epoch = if matches!0 ( | 406 | 84 | inner.finalized_block_header, | 407 | 84 | ConfigFinalizedBlockHeader::Any { | 408 | 84 | ref scale_encoded_header, | 409 | 84 | .. | 410 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 | 411 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() | 412 | 0 | && inner.babe_current_epoch_call_output.is_none() | 413 | | { | 414 | 0 | Some(RuntimeCall::BabeApiCurrentEpoch) | 415 | | } else { | 416 | 168 | None | 417 | | }; | 418 | | | 419 | 168 | let babe_next_epoch = if matches!0 ( | 420 | 84 | inner.finalized_block_header, | 421 | 84 | ConfigFinalizedBlockHeader::Any { | 422 | 84 | ref scale_encoded_header, | 423 | 84 | .. | 424 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 | 425 | 0 | ) && inner.runtime_babeapi_is_v1.is_some() | 426 | 0 | && inner.babe_next_epoch_call_output.is_none() | 427 | | { | 428 | 0 | Some(RuntimeCall::BabeApiNextEpoch) | 429 | | } else { | 430 | 168 | None | 431 | | }; | 432 | | | 433 | 168 | let babe_configuration = if inner.runtime_babeapi_is_v1.is_some() | 434 | 0 | && inner.babe_configuration_call_output.is_none() | 435 | | { | 436 | 0 | Some(RuntimeCall::BabeApiConfiguration) | 437 | | } else { | 438 | 168 | None | 439 | | }; | 440 | | | 441 | 168 | let grandpa_authorities = if !matches!( | 442 | 0 | inner.finalized_block_header, | 443 | | ConfigFinalizedBlockHeader::Any { | 444 | | known_finality: Some(chain_information::ChainInformationFinality::Grandpa { .. }), | 445 | | .. | 446 | | }, | 447 | 168 | ) && inner.runtime_grandpa_supports_currentsetid.is_some() | 448 | 168 | && inner.grandpa_autorities_call_output.is_none() | 449 | | { | 450 | 126 | Some(RuntimeCall::GrandpaApiAuthorities) | 451 | | } else { | 452 | 42 | None | 453 | | }; | 454 | | | 455 | | // The grandpa set ID doesn't need to be retrieved if finality was provided by the user, | 456 | | // but also doesn't need to be retrieved for the genesis block because we know it's | 457 | | // always 0. | 458 | 168 | let grandpa_current_set_id = if matches!0 ( | 459 | 84 | inner.finalized_block_header, | 460 | 84 | ConfigFinalizedBlockHeader::Any { | 461 | 84 | ref scale_encoded_header, | 462 | 84 | known_finality: None, | 463 | 84 | .. | 464 | 84 | } if header::decode(scale_encoded_header, inner.block_number_bytes).unwrap().number != 00 , | 465 | 0 | ) && inner.runtime_grandpa_supports_currentsetid | 466 | 0 | == Some(true) | 467 | 0 | && inner.grandpa_current_set_id_call_output.is_none() | 468 | | { | 469 | 0 | Some(RuntimeCall::GrandpaApiCurrentSetId) | 470 | | } else { | 471 | 168 | None | 472 | | }; | 473 | | | 474 | 168 | [ | 475 | 168 | aura_api_authorities, | 476 | 168 | aura_slot_duration, | 477 | 168 | babe_current_epoch, | 478 | 168 | babe_next_epoch, | 479 | 168 | babe_configuration, | 480 | 168 | grandpa_authorities, | 481 | 168 | grandpa_current_set_id, | 482 | 168 | ] | 483 | 168 | .into_iter() | 484 | 168 | .flatten() | 485 | 168 | } |
|
486 | | |
487 | 171 | fn start_next_call(mut inner: ChainInformationBuildInner) -> Self { |
488 | 171 | debug_assert!(inner.call_in_progress.is_none()); |
489 | 171 | debug_assert!(inner.virtual_machine.is_some()); |
490 | | |
491 | 171 | if let Some(call128 ) = ChainInformationBuild::necessary_calls(&inner).next() { |
492 | 128 | let vm_start_result = runtime_call::run(runtime_call::Config { |
493 | 128 | function_to_call: call.function_name(), |
494 | 128 | parameter: call.parameter_vectored(), |
495 | 128 | virtual_machine: inner.virtual_machine.take().unwrap(), |
496 | 128 | max_log_level: 0, |
497 | 128 | storage_proof_size_behavior: |
498 | 128 | runtime_call::StorageProofSizeBehavior::proof_recording_disabled(), |
499 | 128 | storage_main_trie_changes: Default::default(), |
500 | 128 | calculate_trie_changes: false, |
501 | 128 | }); |
502 | | |
503 | 128 | let vm = match vm_start_result { |
504 | 128 | Ok(vm) => vm, |
505 | 0 | Err((error, virtual_machine)) => { |
506 | 0 | return ChainInformationBuild::Finished { |
507 | 0 | result: Err(Error::WasmStart { call, error }), |
508 | 0 | virtual_machine, |
509 | 0 | } |
510 | | } |
511 | | }; |
512 | | |
513 | 128 | inner.call_in_progress = Some(call); |
514 | 128 | ChainInformationBuild::from_call_in_progress(vm, inner) |
515 | | } else { |
516 | | // If the logic of this module is correct, all the information that we need has been |
517 | | // retrieved at this point. |
518 | | |
519 | 43 | let consensus = match ( |
520 | 43 | inner.runtime_has_aura, |
521 | 43 | inner.runtime_babeapi_is_v1, |
522 | 43 | &inner.finalized_block_header, |
523 | | ) { |
524 | | (true, Some(_), _) => { |
525 | 0 | return ChainInformationBuild::Finished { |
526 | 0 | result: Err(Error::MultipleConsensusAlgorithms), |
527 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), |
528 | 0 | } |
529 | | } |
530 | 0 | (false, None, _) => chain_information::ChainInformationConsensus::Unknown, |
531 | | ( |
532 | | false, |
533 | | Some(_), |
534 | | ConfigFinalizedBlockHeader::Any { |
535 | 0 | scale_encoded_header, |
536 | 0 | .. |
537 | 0 | }, |
538 | 0 | ) if header::decode(scale_encoded_header, inner.block_number_bytes) |
539 | 0 | .unwrap() |
540 | 0 | .number |
541 | 0 | != 0 => |
542 | 0 | { |
543 | 0 | chain_information::ChainInformationConsensus::Babe { |
544 | 0 | finalized_block_epoch_information: Some(Box::new( |
545 | 0 | inner.babe_current_epoch_call_output.take().unwrap(), |
546 | 0 | )), |
547 | 0 | finalized_next_epoch_transition: Box::new( |
548 | 0 | inner.babe_next_epoch_call_output.take().unwrap(), |
549 | 0 | ), |
550 | 0 | slots_per_epoch: inner |
551 | 0 | .babe_configuration_call_output |
552 | 0 | .take() |
553 | 0 | .unwrap() |
554 | 0 | .slots_per_epoch, |
555 | 0 | } |
556 | | } |
557 | | (false, Some(_), _) => { |
558 | 1 | let config = inner.babe_configuration_call_output.take().unwrap(); |
559 | 1 | chain_information::ChainInformationConsensus::Babe { |
560 | 1 | slots_per_epoch: config.slots_per_epoch, |
561 | 1 | finalized_block_epoch_information: None, |
562 | 1 | finalized_next_epoch_transition: Box::new( |
563 | 1 | chain_information::BabeEpochInformation { |
564 | 1 | epoch_index: 0, |
565 | 1 | start_slot_number: None, |
566 | 1 | authorities: config.epoch0_information.authorities, |
567 | 1 | randomness: config.epoch0_information.randomness, |
568 | 1 | c: config.epoch0_configuration.c, |
569 | 1 | allowed_slots: config.epoch0_configuration.allowed_slots, |
570 | 1 | }, |
571 | 1 | ), |
572 | 1 | } |
573 | | } |
574 | 42 | (true, None, _) => chain_information::ChainInformationConsensus::Aura { |
575 | 42 | finalized_authorities_list: inner.aura_autorities_call_output.take().unwrap(), |
576 | 42 | slot_duration: inner.aura_slot_duration_call_output.take().unwrap(), |
577 | 42 | }, |
578 | | }; |
579 | | |
580 | | // Build the finalized block header, and extract the information about finality if it |
581 | | // was already provided by the API user. |
582 | 43 | let (finalized_block_header, known_finality) = match inner.finalized_block_header { |
583 | | ConfigFinalizedBlockHeader::Genesis { |
584 | 22 | state_trie_root_hash, |
585 | 22 | } => { |
586 | 22 | let header = header::HeaderRef { |
587 | 22 | parent_hash: &[0; 32], |
588 | 22 | number: 0, |
589 | 22 | state_root: &state_trie_root_hash, |
590 | 22 | extrinsics_root: &trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE, |
591 | 22 | digest: header::DigestRef::empty(), |
592 | 22 | } |
593 | 22 | .scale_encoding_vec(inner.block_number_bytes); |
594 | 22 | |
595 | 22 | (header, None) |
596 | | } |
597 | | ConfigFinalizedBlockHeader::Any { |
598 | 21 | scale_encoded_header: header, |
599 | 21 | known_finality, |
600 | 21 | } => (header, known_finality), |
601 | | }; |
602 | | |
603 | | // Build the finality information if not known yet. |
604 | 43 | let finality = if let Some(known_finality0 ) = known_finality { |
605 | 0 | known_finality |
606 | 43 | } else if inner.runtime_grandpa_supports_currentsetid.is_some() { |
607 | | chain_information::ChainInformationFinality::Grandpa { |
608 | 43 | after_finalized_block_authorities_set_id: if header::decode( |
609 | 43 | &finalized_block_header, |
610 | 43 | inner.block_number_bytes, |
611 | 43 | ) |
612 | 43 | .unwrap() |
613 | 43 | .number |
614 | 43 | == 0 |
615 | | { |
616 | 43 | 0 |
617 | | } else { |
618 | | // If the GrandPa runtime API version is too old, it is not possible to |
619 | | // determine the current set ID. |
620 | 0 | let Some(grandpa_current_set_id_call_output) = |
621 | 0 | inner.grandpa_current_set_id_call_output.take() |
622 | | else { |
623 | 0 | debug_assert_eq!( |
624 | 0 | inner.runtime_grandpa_supports_currentsetid, |
625 | 0 | Some(false) |
626 | 0 | ); |
627 | 0 | return ChainInformationBuild::Finished { |
628 | 0 | result: Err(Error::GrandpaApiTooOld), |
629 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), |
630 | 0 | }; |
631 | | }; |
632 | | |
633 | 0 | grandpa_current_set_id_call_output |
634 | | }, |
635 | | // TODO: The runtime doesn't give us a way to know the current scheduled change. At the moment the runtime it never schedules changes with a delay of more than 0. So in practice this `None` is correct, but it relies on implementation details |
636 | 43 | finalized_scheduled_change: None, |
637 | 43 | finalized_triggered_authorities: inner |
638 | 43 | .grandpa_autorities_call_output |
639 | 43 | .take() |
640 | 43 | .unwrap(), |
641 | | } |
642 | | } else { |
643 | 0 | chain_information::ChainInformationFinality::Outsourced |
644 | | }; |
645 | | |
646 | | // Build a `ChainInformation` using the parameters found in the runtime. |
647 | | // It is possible, however, that the runtime produces parameters that aren't |
648 | | // coherent. For example the runtime could give "current" and "next" Babe |
649 | | // epochs that don't follow each other. |
650 | 43 | let chain_information = match chain_information::ValidChainInformation::try_from( |
651 | 43 | chain_information::ChainInformation { |
652 | 43 | finalized_block_header: Box::new( |
653 | 43 | header::decode(&finalized_block_header, inner.block_number_bytes) |
654 | 43 | .unwrap() |
655 | 43 | .into(), |
656 | 43 | ), |
657 | 43 | finality, |
658 | 43 | consensus, |
659 | 43 | }, |
660 | 43 | ) { |
661 | 43 | Ok(ci) => ci, |
662 | 0 | Err(err) => { |
663 | 0 | return ChainInformationBuild::Finished { |
664 | 0 | result: Err(Error::InvalidChainInformation(err)), |
665 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), |
666 | 0 | } |
667 | | } |
668 | | }; |
669 | | |
670 | 43 | ChainInformationBuild::Finished { |
671 | 43 | result: Ok(chain_information), |
672 | 43 | virtual_machine: inner.virtual_machine.take().unwrap(), |
673 | 43 | } |
674 | | } |
675 | 171 | } _RNvMs5_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild15start_next_call Line | Count | Source | 487 | 3 | fn start_next_call(mut inner: ChainInformationBuildInner) -> Self { | 488 | 3 | debug_assert!(inner.call_in_progress.is_none()); | 489 | 3 | debug_assert!(inner.virtual_machine.is_some()); | 490 | | | 491 | 3 | if let Some(call2 ) = ChainInformationBuild::necessary_calls(&inner).next() { | 492 | 2 | let vm_start_result = runtime_call::run(runtime_call::Config { | 493 | 2 | function_to_call: call.function_name(), | 494 | 2 | parameter: call.parameter_vectored(), | 495 | 2 | virtual_machine: inner.virtual_machine.take().unwrap(), | 496 | 2 | max_log_level: 0, | 497 | 2 | storage_proof_size_behavior: | 498 | 2 | runtime_call::StorageProofSizeBehavior::proof_recording_disabled(), | 499 | 2 | storage_main_trie_changes: Default::default(), | 500 | 2 | calculate_trie_changes: false, | 501 | 2 | }); | 502 | | | 503 | 2 | let vm = match vm_start_result { | 504 | 2 | Ok(vm) => vm, | 505 | 0 | Err((error, virtual_machine)) => { | 506 | 0 | return ChainInformationBuild::Finished { | 507 | 0 | result: Err(Error::WasmStart { call, error }), | 508 | 0 | virtual_machine, | 509 | 0 | } | 510 | | } | 511 | | }; | 512 | | | 513 | 2 | inner.call_in_progress = Some(call); | 514 | 2 | ChainInformationBuild::from_call_in_progress(vm, inner) | 515 | | } else { | 516 | | // If the logic of this module is correct, all the information that we need has been | 517 | | // retrieved at this point. | 518 | | | 519 | 1 | let consensus = match ( | 520 | 1 | inner.runtime_has_aura, | 521 | 1 | inner.runtime_babeapi_is_v1, | 522 | 1 | &inner.finalized_block_header, | 523 | | ) { | 524 | | (true, Some(_), _) => { | 525 | 0 | return ChainInformationBuild::Finished { | 526 | 0 | result: Err(Error::MultipleConsensusAlgorithms), | 527 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 528 | 0 | } | 529 | | } | 530 | 0 | (false, None, _) => chain_information::ChainInformationConsensus::Unknown, | 531 | | ( | 532 | | false, | 533 | | Some(_), | 534 | | ConfigFinalizedBlockHeader::Any { | 535 | 0 | scale_encoded_header, | 536 | 0 | .. | 537 | 0 | }, | 538 | 0 | ) if header::decode(scale_encoded_header, inner.block_number_bytes) | 539 | 0 | .unwrap() | 540 | 0 | .number | 541 | 0 | != 0 => | 542 | 0 | { | 543 | 0 | chain_information::ChainInformationConsensus::Babe { | 544 | 0 | finalized_block_epoch_information: Some(Box::new( | 545 | 0 | inner.babe_current_epoch_call_output.take().unwrap(), | 546 | 0 | )), | 547 | 0 | finalized_next_epoch_transition: Box::new( | 548 | 0 | inner.babe_next_epoch_call_output.take().unwrap(), | 549 | 0 | ), | 550 | 0 | slots_per_epoch: inner | 551 | 0 | .babe_configuration_call_output | 552 | 0 | .take() | 553 | 0 | .unwrap() | 554 | 0 | .slots_per_epoch, | 555 | 0 | } | 556 | | } | 557 | | (false, Some(_), _) => { | 558 | 1 | let config = inner.babe_configuration_call_output.take().unwrap(); | 559 | 1 | chain_information::ChainInformationConsensus::Babe { | 560 | 1 | slots_per_epoch: config.slots_per_epoch, | 561 | 1 | finalized_block_epoch_information: None, | 562 | 1 | finalized_next_epoch_transition: Box::new( | 563 | 1 | chain_information::BabeEpochInformation { | 564 | 1 | epoch_index: 0, | 565 | 1 | start_slot_number: None, | 566 | 1 | authorities: config.epoch0_information.authorities, | 567 | 1 | randomness: config.epoch0_information.randomness, | 568 | 1 | c: config.epoch0_configuration.c, | 569 | 1 | allowed_slots: config.epoch0_configuration.allowed_slots, | 570 | 1 | }, | 571 | 1 | ), | 572 | 1 | } | 573 | | } | 574 | 0 | (true, None, _) => chain_information::ChainInformationConsensus::Aura { | 575 | 0 | finalized_authorities_list: inner.aura_autorities_call_output.take().unwrap(), | 576 | 0 | slot_duration: inner.aura_slot_duration_call_output.take().unwrap(), | 577 | 0 | }, | 578 | | }; | 579 | | | 580 | | // Build the finalized block header, and extract the information about finality if it | 581 | | // was already provided by the API user. | 582 | 1 | let (finalized_block_header, known_finality) = match inner.finalized_block_header { | 583 | | ConfigFinalizedBlockHeader::Genesis { | 584 | 1 | state_trie_root_hash, | 585 | 1 | } => { | 586 | 1 | let header = header::HeaderRef { | 587 | 1 | parent_hash: &[0; 32], | 588 | 1 | number: 0, | 589 | 1 | state_root: &state_trie_root_hash, | 590 | 1 | extrinsics_root: &trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE, | 591 | 1 | digest: header::DigestRef::empty(), | 592 | 1 | } | 593 | 1 | .scale_encoding_vec(inner.block_number_bytes); | 594 | 1 | | 595 | 1 | (header, None) | 596 | | } | 597 | | ConfigFinalizedBlockHeader::Any { | 598 | 0 | scale_encoded_header: header, | 599 | 0 | known_finality, | 600 | 0 | } => (header, known_finality), | 601 | | }; | 602 | | | 603 | | // Build the finality information if not known yet. | 604 | 1 | let finality = if let Some(known_finality0 ) = known_finality { | 605 | 0 | known_finality | 606 | 1 | } else if inner.runtime_grandpa_supports_currentsetid.is_some() { | 607 | | chain_information::ChainInformationFinality::Grandpa { | 608 | 1 | after_finalized_block_authorities_set_id: if header::decode( | 609 | 1 | &finalized_block_header, | 610 | 1 | inner.block_number_bytes, | 611 | 1 | ) | 612 | 1 | .unwrap() | 613 | 1 | .number | 614 | 1 | == 0 | 615 | | { | 616 | 1 | 0 | 617 | | } else { | 618 | | // If the GrandPa runtime API version is too old, it is not possible to | 619 | | // determine the current set ID. | 620 | 0 | let Some(grandpa_current_set_id_call_output) = | 621 | 0 | inner.grandpa_current_set_id_call_output.take() | 622 | | else { | 623 | 0 | debug_assert_eq!( | 624 | 0 | inner.runtime_grandpa_supports_currentsetid, | 625 | 0 | Some(false) | 626 | 0 | ); | 627 | 0 | return ChainInformationBuild::Finished { | 628 | 0 | result: Err(Error::GrandpaApiTooOld), | 629 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 630 | 0 | }; | 631 | | }; | 632 | | | 633 | 0 | grandpa_current_set_id_call_output | 634 | | }, | 635 | | // TODO: The runtime doesn't give us a way to know the current scheduled change. At the moment the runtime it never schedules changes with a delay of more than 0. So in practice this `None` is correct, but it relies on implementation details | 636 | 1 | finalized_scheduled_change: None, | 637 | 1 | finalized_triggered_authorities: inner | 638 | 1 | .grandpa_autorities_call_output | 639 | 1 | .take() | 640 | 1 | .unwrap(), | 641 | | } | 642 | | } else { | 643 | 0 | chain_information::ChainInformationFinality::Outsourced | 644 | | }; | 645 | | | 646 | | // Build a `ChainInformation` using the parameters found in the runtime. | 647 | | // It is possible, however, that the runtime produces parameters that aren't | 648 | | // coherent. For example the runtime could give "current" and "next" Babe | 649 | | // epochs that don't follow each other. | 650 | 1 | let chain_information = match chain_information::ValidChainInformation::try_from( | 651 | 1 | chain_information::ChainInformation { | 652 | 1 | finalized_block_header: Box::new( | 653 | 1 | header::decode(&finalized_block_header, inner.block_number_bytes) | 654 | 1 | .unwrap() | 655 | 1 | .into(), | 656 | 1 | ), | 657 | 1 | finality, | 658 | 1 | consensus, | 659 | 1 | }, | 660 | 1 | ) { | 661 | 1 | Ok(ci) => ci, | 662 | 0 | Err(err) => { | 663 | 0 | return ChainInformationBuild::Finished { | 664 | 0 | result: Err(Error::InvalidChainInformation(err)), | 665 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 666 | 0 | } | 667 | | } | 668 | | }; | 669 | | | 670 | 1 | ChainInformationBuild::Finished { | 671 | 1 | result: Ok(chain_information), | 672 | 1 | virtual_machine: inner.virtual_machine.take().unwrap(), | 673 | 1 | } | 674 | | } | 675 | 3 | } |
_RNvMs5_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild15start_next_call Line | Count | Source | 487 | 168 | fn start_next_call(mut inner: ChainInformationBuildInner) -> Self { | 488 | 168 | debug_assert!(inner.call_in_progress.is_none()); | 489 | 168 | debug_assert!(inner.virtual_machine.is_some()); | 490 | | | 491 | 168 | if let Some(call126 ) = ChainInformationBuild::necessary_calls(&inner).next() { | 492 | 126 | let vm_start_result = runtime_call::run(runtime_call::Config { | 493 | 126 | function_to_call: call.function_name(), | 494 | 126 | parameter: call.parameter_vectored(), | 495 | 126 | virtual_machine: inner.virtual_machine.take().unwrap(), | 496 | 126 | max_log_level: 0, | 497 | 126 | storage_proof_size_behavior: | 498 | 126 | runtime_call::StorageProofSizeBehavior::proof_recording_disabled(), | 499 | 126 | storage_main_trie_changes: Default::default(), | 500 | 126 | calculate_trie_changes: false, | 501 | 126 | }); | 502 | | | 503 | 126 | let vm = match vm_start_result { | 504 | 126 | Ok(vm) => vm, | 505 | 0 | Err((error, virtual_machine)) => { | 506 | 0 | return ChainInformationBuild::Finished { | 507 | 0 | result: Err(Error::WasmStart { call, error }), | 508 | 0 | virtual_machine, | 509 | 0 | } | 510 | | } | 511 | | }; | 512 | | | 513 | 126 | inner.call_in_progress = Some(call); | 514 | 126 | ChainInformationBuild::from_call_in_progress(vm, inner) | 515 | | } else { | 516 | | // If the logic of this module is correct, all the information that we need has been | 517 | | // retrieved at this point. | 518 | | | 519 | 42 | let consensus = match ( | 520 | 42 | inner.runtime_has_aura, | 521 | 42 | inner.runtime_babeapi_is_v1, | 522 | 42 | &inner.finalized_block_header, | 523 | | ) { | 524 | | (true, Some(_), _) => { | 525 | 0 | return ChainInformationBuild::Finished { | 526 | 0 | result: Err(Error::MultipleConsensusAlgorithms), | 527 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 528 | 0 | } | 529 | | } | 530 | 0 | (false, None, _) => chain_information::ChainInformationConsensus::Unknown, | 531 | | ( | 532 | | false, | 533 | | Some(_), | 534 | | ConfigFinalizedBlockHeader::Any { | 535 | 0 | scale_encoded_header, | 536 | 0 | .. | 537 | 0 | }, | 538 | 0 | ) if header::decode(scale_encoded_header, inner.block_number_bytes) | 539 | 0 | .unwrap() | 540 | 0 | .number | 541 | 0 | != 0 => | 542 | 0 | { | 543 | 0 | chain_information::ChainInformationConsensus::Babe { | 544 | 0 | finalized_block_epoch_information: Some(Box::new( | 545 | 0 | inner.babe_current_epoch_call_output.take().unwrap(), | 546 | 0 | )), | 547 | 0 | finalized_next_epoch_transition: Box::new( | 548 | 0 | inner.babe_next_epoch_call_output.take().unwrap(), | 549 | 0 | ), | 550 | 0 | slots_per_epoch: inner | 551 | 0 | .babe_configuration_call_output | 552 | 0 | .take() | 553 | 0 | .unwrap() | 554 | 0 | .slots_per_epoch, | 555 | 0 | } | 556 | | } | 557 | | (false, Some(_), _) => { | 558 | 0 | let config = inner.babe_configuration_call_output.take().unwrap(); | 559 | 0 | chain_information::ChainInformationConsensus::Babe { | 560 | 0 | slots_per_epoch: config.slots_per_epoch, | 561 | 0 | finalized_block_epoch_information: None, | 562 | 0 | finalized_next_epoch_transition: Box::new( | 563 | 0 | chain_information::BabeEpochInformation { | 564 | 0 | epoch_index: 0, | 565 | 0 | start_slot_number: None, | 566 | 0 | authorities: config.epoch0_information.authorities, | 567 | 0 | randomness: config.epoch0_information.randomness, | 568 | 0 | c: config.epoch0_configuration.c, | 569 | 0 | allowed_slots: config.epoch0_configuration.allowed_slots, | 570 | 0 | }, | 571 | 0 | ), | 572 | 0 | } | 573 | | } | 574 | 42 | (true, None, _) => chain_information::ChainInformationConsensus::Aura { | 575 | 42 | finalized_authorities_list: inner.aura_autorities_call_output.take().unwrap(), | 576 | 42 | slot_duration: inner.aura_slot_duration_call_output.take().unwrap(), | 577 | 42 | }, | 578 | | }; | 579 | | | 580 | | // Build the finalized block header, and extract the information about finality if it | 581 | | // was already provided by the API user. | 582 | 42 | let (finalized_block_header, known_finality) = match inner.finalized_block_header { | 583 | | ConfigFinalizedBlockHeader::Genesis { | 584 | 21 | state_trie_root_hash, | 585 | 21 | } => { | 586 | 21 | let header = header::HeaderRef { | 587 | 21 | parent_hash: &[0; 32], | 588 | 21 | number: 0, | 589 | 21 | state_root: &state_trie_root_hash, | 590 | 21 | extrinsics_root: &trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE, | 591 | 21 | digest: header::DigestRef::empty(), | 592 | 21 | } | 593 | 21 | .scale_encoding_vec(inner.block_number_bytes); | 594 | 21 | | 595 | 21 | (header, None) | 596 | | } | 597 | | ConfigFinalizedBlockHeader::Any { | 598 | 21 | scale_encoded_header: header, | 599 | 21 | known_finality, | 600 | 21 | } => (header, known_finality), | 601 | | }; | 602 | | | 603 | | // Build the finality information if not known yet. | 604 | 42 | let finality = if let Some(known_finality0 ) = known_finality { | 605 | 0 | known_finality | 606 | 42 | } else if inner.runtime_grandpa_supports_currentsetid.is_some() { | 607 | | chain_information::ChainInformationFinality::Grandpa { | 608 | 42 | after_finalized_block_authorities_set_id: if header::decode( | 609 | 42 | &finalized_block_header, | 610 | 42 | inner.block_number_bytes, | 611 | 42 | ) | 612 | 42 | .unwrap() | 613 | 42 | .number | 614 | 42 | == 0 | 615 | | { | 616 | 42 | 0 | 617 | | } else { | 618 | | // If the GrandPa runtime API version is too old, it is not possible to | 619 | | // determine the current set ID. | 620 | 0 | let Some(grandpa_current_set_id_call_output) = | 621 | 0 | inner.grandpa_current_set_id_call_output.take() | 622 | | else { | 623 | 0 | debug_assert_eq!( | 624 | 0 | inner.runtime_grandpa_supports_currentsetid, | 625 | 0 | Some(false) | 626 | 0 | ); | 627 | 0 | return ChainInformationBuild::Finished { | 628 | 0 | result: Err(Error::GrandpaApiTooOld), | 629 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 630 | 0 | }; | 631 | | }; | 632 | | | 633 | 0 | grandpa_current_set_id_call_output | 634 | | }, | 635 | | // TODO: The runtime doesn't give us a way to know the current scheduled change. At the moment the runtime it never schedules changes with a delay of more than 0. So in practice this `None` is correct, but it relies on implementation details | 636 | 42 | finalized_scheduled_change: None, | 637 | 42 | finalized_triggered_authorities: inner | 638 | 42 | .grandpa_autorities_call_output | 639 | 42 | .take() | 640 | 42 | .unwrap(), | 641 | | } | 642 | | } else { | 643 | 0 | chain_information::ChainInformationFinality::Outsourced | 644 | | }; | 645 | | | 646 | | // Build a `ChainInformation` using the parameters found in the runtime. | 647 | | // It is possible, however, that the runtime produces parameters that aren't | 648 | | // coherent. For example the runtime could give "current" and "next" Babe | 649 | | // epochs that don't follow each other. | 650 | 42 | let chain_information = match chain_information::ValidChainInformation::try_from( | 651 | 42 | chain_information::ChainInformation { | 652 | 42 | finalized_block_header: Box::new( | 653 | 42 | header::decode(&finalized_block_header, inner.block_number_bytes) | 654 | 42 | .unwrap() | 655 | 42 | .into(), | 656 | 42 | ), | 657 | 42 | finality, | 658 | 42 | consensus, | 659 | 42 | }, | 660 | 42 | ) { | 661 | 42 | Ok(ci) => ci, | 662 | 0 | Err(err) => { | 663 | 0 | return ChainInformationBuild::Finished { | 664 | 0 | result: Err(Error::InvalidChainInformation(err)), | 665 | 0 | virtual_machine: inner.virtual_machine.take().unwrap(), | 666 | 0 | } | 667 | | } | 668 | | }; | 669 | | | 670 | 42 | ChainInformationBuild::Finished { | 671 | 42 | result: Ok(chain_information), | 672 | 42 | virtual_machine: inner.virtual_machine.take().unwrap(), | 673 | 42 | } | 674 | | } | 675 | 168 | } |
|
676 | | |
677 | 215 | fn from_call_in_progress( |
678 | 215 | mut call: runtime_call::RuntimeCall, |
679 | 215 | mut inner: ChainInformationBuildInner, |
680 | 215 | ) -> Self { |
681 | 215 | loop { |
682 | 215 | debug_assert!(inner.call_in_progress.is_some()); |
683 | | |
684 | 128 | match call { |
685 | 128 | runtime_call::RuntimeCall::Finished(Ok(success)) => { |
686 | 128 | inner.virtual_machine = Some(match inner.call_in_progress.take() { |
687 | 0 | None => unreachable!(), |
688 | | Some(RuntimeCall::AuraApiSlotDuration) => { |
689 | 42 | let result = decode_aura_slot_duration_output( |
690 | 42 | success.virtual_machine.value().as_ref(), |
691 | 42 | ); |
692 | 42 | let virtual_machine = success.virtual_machine.into_prototype(); |
693 | 42 | match result { |
694 | 42 | Ok(output) => inner.aura_slot_duration_call_output = Some(output), |
695 | 0 | Err(err) => { |
696 | 0 | return ChainInformationBuild::Finished { |
697 | 0 | result: Err(err), |
698 | 0 | virtual_machine, |
699 | 0 | }; |
700 | | } |
701 | | } |
702 | 42 | virtual_machine |
703 | | } |
704 | | Some(RuntimeCall::AuraApiAuthorities) => { |
705 | 42 | let result = decode_aura_authorities_output( |
706 | 42 | success.virtual_machine.value().as_ref(), |
707 | 42 | ); |
708 | 42 | let virtual_machine = success.virtual_machine.into_prototype(); |
709 | 42 | match result { |
710 | 42 | Ok(output) => inner.aura_autorities_call_output = Some(output), |
711 | 0 | Err(err) => { |
712 | 0 | return ChainInformationBuild::Finished { |
713 | 0 | result: Err(err), |
714 | 0 | virtual_machine, |
715 | 0 | }; |
716 | | } |
717 | | } |
718 | 42 | virtual_machine |
719 | | } |
720 | | Some(RuntimeCall::BabeApiCurrentEpoch) => { |
721 | 0 | let result = decode_babe_epoch_output( |
722 | 0 | success.virtual_machine.value().as_ref(), |
723 | 0 | false, |
724 | 0 | ); |
725 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); |
726 | 0 | match result { |
727 | 0 | Ok(output) => inner.babe_current_epoch_call_output = Some(output), |
728 | 0 | Err(err) => { |
729 | 0 | return ChainInformationBuild::Finished { |
730 | 0 | result: Err(err), |
731 | 0 | virtual_machine, |
732 | 0 | }; |
733 | | } |
734 | | } |
735 | 0 | virtual_machine |
736 | | } |
737 | | Some(RuntimeCall::BabeApiNextEpoch) => { |
738 | 0 | let result = decode_babe_epoch_output( |
739 | 0 | success.virtual_machine.value().as_ref(), |
740 | 0 | true, |
741 | 0 | ); |
742 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); |
743 | 0 | match result { |
744 | 0 | Ok(output) => inner.babe_next_epoch_call_output = Some(output), |
745 | 0 | Err(err) => { |
746 | 0 | return ChainInformationBuild::Finished { |
747 | 0 | result: Err(err), |
748 | 0 | virtual_machine, |
749 | 0 | }; |
750 | | } |
751 | | } |
752 | 0 | virtual_machine |
753 | | } |
754 | | Some(RuntimeCall::BabeApiConfiguration) => { |
755 | 1 | let result = decode_babe_configuration_output( |
756 | 1 | success.virtual_machine.value().as_ref(), |
757 | 1 | inner.runtime_babeapi_is_v1.unwrap(), |
758 | 1 | ); |
759 | 1 | let virtual_machine = success.virtual_machine.into_prototype(); |
760 | 1 | match result { |
761 | 1 | Ok(output) => inner.babe_configuration_call_output = Some(output), |
762 | 0 | Err(err) => { |
763 | 0 | return ChainInformationBuild::Finished { |
764 | 0 | result: Err(err), |
765 | 0 | virtual_machine, |
766 | 0 | }; |
767 | | } |
768 | | } |
769 | 1 | virtual_machine |
770 | | } |
771 | | Some(RuntimeCall::GrandpaApiAuthorities) => { |
772 | 43 | let result = decode_grandpa_authorities_output( |
773 | 43 | success.virtual_machine.value().as_ref(), |
774 | 43 | ); |
775 | 43 | let virtual_machine = success.virtual_machine.into_prototype(); |
776 | 43 | match result { |
777 | 43 | Ok(output) => inner.grandpa_autorities_call_output = Some(output), |
778 | 0 | Err(err) => { |
779 | 0 | return ChainInformationBuild::Finished { |
780 | 0 | result: Err(err), |
781 | 0 | virtual_machine, |
782 | 0 | }; |
783 | | } |
784 | | } |
785 | 43 | virtual_machine |
786 | | } |
787 | | Some(RuntimeCall::GrandpaApiCurrentSetId) => { |
788 | 0 | let result = decode_grandpa_current_set_id_output( |
789 | 0 | success.virtual_machine.value().as_ref(), |
790 | 0 | ); |
791 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); |
792 | 0 | match result { |
793 | 0 | Ok(output) => { |
794 | 0 | inner.grandpa_current_set_id_call_output = Some(output) |
795 | | } |
796 | 0 | Err(err) => { |
797 | 0 | return ChainInformationBuild::Finished { |
798 | 0 | result: Err(err), |
799 | 0 | virtual_machine, |
800 | 0 | }; |
801 | | } |
802 | | } |
803 | 0 | virtual_machine |
804 | | } |
805 | | }); |
806 | | |
807 | 128 | break ChainInformationBuild::start_next_call(inner); |
808 | | } |
809 | 0 | runtime_call::RuntimeCall::Finished(Err(err)) => { |
810 | 0 | break ChainInformationBuild::Finished { |
811 | 0 | result: Err(Error::WasmVm { |
812 | 0 | call: inner.call_in_progress.unwrap(), |
813 | 0 | error: err.detail, |
814 | 0 | }), |
815 | 0 | virtual_machine: err.prototype, |
816 | 0 | } |
817 | | } |
818 | 87 | runtime_call::RuntimeCall::StorageGet(call) => { |
819 | 87 | break ChainInformationBuild::InProgress(InProgress::StorageGet(StorageGet( |
820 | 87 | call, inner, |
821 | 87 | ))) |
822 | | } |
823 | 0 | runtime_call::RuntimeCall::NextKey(call) => { |
824 | 0 | break ChainInformationBuild::InProgress(InProgress::NextKey(NextKey( |
825 | 0 | call, inner, |
826 | 0 | ))) |
827 | | } |
828 | 0 | runtime_call::RuntimeCall::ClosestDescendantMerkleValue(call) => { |
829 | 0 | break ChainInformationBuild::InProgress( |
830 | 0 | InProgress::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue( |
831 | 0 | call, inner, |
832 | 0 | )), |
833 | 0 | ) |
834 | | } |
835 | 0 | runtime_call::RuntimeCall::SignatureVerification(sig) => { |
836 | 0 | call = sig.verify_and_resume(); |
837 | 0 | } |
838 | 0 | runtime_call::RuntimeCall::OffchainStorageSet(req) => { |
839 | 0 | // Do nothing. |
840 | 0 | call = req.resume(); |
841 | 0 | } |
842 | 0 | runtime_call::RuntimeCall::Offchain(req) => { |
843 | 0 | let virtual_machine = runtime_call::RuntimeCall::Offchain(req).into_prototype(); |
844 | 0 | break ChainInformationBuild::Finished { |
845 | 0 | result: Err(Error::OffchainWorkerHostFunction), |
846 | 0 | virtual_machine, |
847 | 0 | }; |
848 | | } |
849 | 0 | runtime_call::RuntimeCall::LogEmit(req) => { |
850 | 0 | // Generated logs are ignored. |
851 | 0 | call = req.resume(); |
852 | 0 | } |
853 | | } |
854 | | } |
855 | 215 | } _RNvMs5_NtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild21from_call_in_progress Line | Count | Source | 677 | 5 | fn from_call_in_progress( | 678 | 5 | mut call: runtime_call::RuntimeCall, | 679 | 5 | mut inner: ChainInformationBuildInner, | 680 | 5 | ) -> Self { | 681 | 5 | loop { | 682 | 5 | debug_assert!(inner.call_in_progress.is_some()); | 683 | | | 684 | 2 | match call { | 685 | 2 | runtime_call::RuntimeCall::Finished(Ok(success)) => { | 686 | 2 | inner.virtual_machine = Some(match inner.call_in_progress.take() { | 687 | 0 | None => unreachable!(), | 688 | | Some(RuntimeCall::AuraApiSlotDuration) => { | 689 | 0 | let result = decode_aura_slot_duration_output( | 690 | 0 | success.virtual_machine.value().as_ref(), | 691 | 0 | ); | 692 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 693 | 0 | match result { | 694 | 0 | Ok(output) => inner.aura_slot_duration_call_output = Some(output), | 695 | 0 | Err(err) => { | 696 | 0 | return ChainInformationBuild::Finished { | 697 | 0 | result: Err(err), | 698 | 0 | virtual_machine, | 699 | 0 | }; | 700 | | } | 701 | | } | 702 | 0 | virtual_machine | 703 | | } | 704 | | Some(RuntimeCall::AuraApiAuthorities) => { | 705 | 0 | let result = decode_aura_authorities_output( | 706 | 0 | success.virtual_machine.value().as_ref(), | 707 | 0 | ); | 708 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 709 | 0 | match result { | 710 | 0 | Ok(output) => inner.aura_autorities_call_output = Some(output), | 711 | 0 | Err(err) => { | 712 | 0 | return ChainInformationBuild::Finished { | 713 | 0 | result: Err(err), | 714 | 0 | virtual_machine, | 715 | 0 | }; | 716 | | } | 717 | | } | 718 | 0 | virtual_machine | 719 | | } | 720 | | Some(RuntimeCall::BabeApiCurrentEpoch) => { | 721 | 0 | let result = decode_babe_epoch_output( | 722 | 0 | success.virtual_machine.value().as_ref(), | 723 | 0 | false, | 724 | 0 | ); | 725 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 726 | 0 | match result { | 727 | 0 | Ok(output) => inner.babe_current_epoch_call_output = Some(output), | 728 | 0 | Err(err) => { | 729 | 0 | return ChainInformationBuild::Finished { | 730 | 0 | result: Err(err), | 731 | 0 | virtual_machine, | 732 | 0 | }; | 733 | | } | 734 | | } | 735 | 0 | virtual_machine | 736 | | } | 737 | | Some(RuntimeCall::BabeApiNextEpoch) => { | 738 | 0 | let result = decode_babe_epoch_output( | 739 | 0 | success.virtual_machine.value().as_ref(), | 740 | 0 | true, | 741 | 0 | ); | 742 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 743 | 0 | match result { | 744 | 0 | Ok(output) => inner.babe_next_epoch_call_output = Some(output), | 745 | 0 | Err(err) => { | 746 | 0 | return ChainInformationBuild::Finished { | 747 | 0 | result: Err(err), | 748 | 0 | virtual_machine, | 749 | 0 | }; | 750 | | } | 751 | | } | 752 | 0 | virtual_machine | 753 | | } | 754 | | Some(RuntimeCall::BabeApiConfiguration) => { | 755 | 1 | let result = decode_babe_configuration_output( | 756 | 1 | success.virtual_machine.value().as_ref(), | 757 | 1 | inner.runtime_babeapi_is_v1.unwrap(), | 758 | 1 | ); | 759 | 1 | let virtual_machine = success.virtual_machine.into_prototype(); | 760 | 1 | match result { | 761 | 1 | Ok(output) => inner.babe_configuration_call_output = Some(output), | 762 | 0 | Err(err) => { | 763 | 0 | return ChainInformationBuild::Finished { | 764 | 0 | result: Err(err), | 765 | 0 | virtual_machine, | 766 | 0 | }; | 767 | | } | 768 | | } | 769 | 1 | virtual_machine | 770 | | } | 771 | | Some(RuntimeCall::GrandpaApiAuthorities) => { | 772 | 1 | let result = decode_grandpa_authorities_output( | 773 | 1 | success.virtual_machine.value().as_ref(), | 774 | 1 | ); | 775 | 1 | let virtual_machine = success.virtual_machine.into_prototype(); | 776 | 1 | match result { | 777 | 1 | Ok(output) => inner.grandpa_autorities_call_output = Some(output), | 778 | 0 | Err(err) => { | 779 | 0 | return ChainInformationBuild::Finished { | 780 | 0 | result: Err(err), | 781 | 0 | virtual_machine, | 782 | 0 | }; | 783 | | } | 784 | | } | 785 | 1 | virtual_machine | 786 | | } | 787 | | Some(RuntimeCall::GrandpaApiCurrentSetId) => { | 788 | 0 | let result = decode_grandpa_current_set_id_output( | 789 | 0 | success.virtual_machine.value().as_ref(), | 790 | 0 | ); | 791 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 792 | 0 | match result { | 793 | 0 | Ok(output) => { | 794 | 0 | inner.grandpa_current_set_id_call_output = Some(output) | 795 | | } | 796 | 0 | Err(err) => { | 797 | 0 | return ChainInformationBuild::Finished { | 798 | 0 | result: Err(err), | 799 | 0 | virtual_machine, | 800 | 0 | }; | 801 | | } | 802 | | } | 803 | 0 | virtual_machine | 804 | | } | 805 | | }); | 806 | | | 807 | 2 | break ChainInformationBuild::start_next_call(inner); | 808 | | } | 809 | 0 | runtime_call::RuntimeCall::Finished(Err(err)) => { | 810 | 0 | break ChainInformationBuild::Finished { | 811 | 0 | result: Err(Error::WasmVm { | 812 | 0 | call: inner.call_in_progress.unwrap(), | 813 | 0 | error: err.detail, | 814 | 0 | }), | 815 | 0 | virtual_machine: err.prototype, | 816 | 0 | } | 817 | | } | 818 | 3 | runtime_call::RuntimeCall::StorageGet(call) => { | 819 | 3 | break ChainInformationBuild::InProgress(InProgress::StorageGet(StorageGet( | 820 | 3 | call, inner, | 821 | 3 | ))) | 822 | | } | 823 | 0 | runtime_call::RuntimeCall::NextKey(call) => { | 824 | 0 | break ChainInformationBuild::InProgress(InProgress::NextKey(NextKey( | 825 | 0 | call, inner, | 826 | 0 | ))) | 827 | | } | 828 | 0 | runtime_call::RuntimeCall::ClosestDescendantMerkleValue(call) => { | 829 | 0 | break ChainInformationBuild::InProgress( | 830 | 0 | InProgress::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue( | 831 | 0 | call, inner, | 832 | 0 | )), | 833 | 0 | ) | 834 | | } | 835 | 0 | runtime_call::RuntimeCall::SignatureVerification(sig) => { | 836 | 0 | call = sig.verify_and_resume(); | 837 | 0 | } | 838 | 0 | runtime_call::RuntimeCall::OffchainStorageSet(req) => { | 839 | 0 | // Do nothing. | 840 | 0 | call = req.resume(); | 841 | 0 | } | 842 | 0 | runtime_call::RuntimeCall::Offchain(req) => { | 843 | 0 | let virtual_machine = runtime_call::RuntimeCall::Offchain(req).into_prototype(); | 844 | 0 | break ChainInformationBuild::Finished { | 845 | 0 | result: Err(Error::OffchainWorkerHostFunction), | 846 | 0 | virtual_machine, | 847 | 0 | }; | 848 | | } | 849 | 0 | runtime_call::RuntimeCall::LogEmit(req) => { | 850 | 0 | // Generated logs are ignored. | 851 | 0 | call = req.resume(); | 852 | 0 | } | 853 | | } | 854 | | } | 855 | 5 | } |
_RNvMs5_NtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5buildNtB5_21ChainInformationBuild21from_call_in_progress Line | Count | Source | 677 | 210 | fn from_call_in_progress( | 678 | 210 | mut call: runtime_call::RuntimeCall, | 679 | 210 | mut inner: ChainInformationBuildInner, | 680 | 210 | ) -> Self { | 681 | 210 | loop { | 682 | 210 | debug_assert!(inner.call_in_progress.is_some()); | 683 | | | 684 | 126 | match call { | 685 | 126 | runtime_call::RuntimeCall::Finished(Ok(success)) => { | 686 | 126 | inner.virtual_machine = Some(match inner.call_in_progress.take() { | 687 | 0 | None => unreachable!(), | 688 | | Some(RuntimeCall::AuraApiSlotDuration) => { | 689 | 42 | let result = decode_aura_slot_duration_output( | 690 | 42 | success.virtual_machine.value().as_ref(), | 691 | 42 | ); | 692 | 42 | let virtual_machine = success.virtual_machine.into_prototype(); | 693 | 42 | match result { | 694 | 42 | Ok(output) => inner.aura_slot_duration_call_output = Some(output), | 695 | 0 | Err(err) => { | 696 | 0 | return ChainInformationBuild::Finished { | 697 | 0 | result: Err(err), | 698 | 0 | virtual_machine, | 699 | 0 | }; | 700 | | } | 701 | | } | 702 | 42 | virtual_machine | 703 | | } | 704 | | Some(RuntimeCall::AuraApiAuthorities) => { | 705 | 42 | let result = decode_aura_authorities_output( | 706 | 42 | success.virtual_machine.value().as_ref(), | 707 | 42 | ); | 708 | 42 | let virtual_machine = success.virtual_machine.into_prototype(); | 709 | 42 | match result { | 710 | 42 | Ok(output) => inner.aura_autorities_call_output = Some(output), | 711 | 0 | Err(err) => { | 712 | 0 | return ChainInformationBuild::Finished { | 713 | 0 | result: Err(err), | 714 | 0 | virtual_machine, | 715 | 0 | }; | 716 | | } | 717 | | } | 718 | 42 | virtual_machine | 719 | | } | 720 | | Some(RuntimeCall::BabeApiCurrentEpoch) => { | 721 | 0 | let result = decode_babe_epoch_output( | 722 | 0 | success.virtual_machine.value().as_ref(), | 723 | 0 | false, | 724 | 0 | ); | 725 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 726 | 0 | match result { | 727 | 0 | Ok(output) => inner.babe_current_epoch_call_output = Some(output), | 728 | 0 | Err(err) => { | 729 | 0 | return ChainInformationBuild::Finished { | 730 | 0 | result: Err(err), | 731 | 0 | virtual_machine, | 732 | 0 | }; | 733 | | } | 734 | | } | 735 | 0 | virtual_machine | 736 | | } | 737 | | Some(RuntimeCall::BabeApiNextEpoch) => { | 738 | 0 | let result = decode_babe_epoch_output( | 739 | 0 | success.virtual_machine.value().as_ref(), | 740 | 0 | true, | 741 | 0 | ); | 742 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 743 | 0 | match result { | 744 | 0 | Ok(output) => inner.babe_next_epoch_call_output = Some(output), | 745 | 0 | Err(err) => { | 746 | 0 | return ChainInformationBuild::Finished { | 747 | 0 | result: Err(err), | 748 | 0 | virtual_machine, | 749 | 0 | }; | 750 | | } | 751 | | } | 752 | 0 | virtual_machine | 753 | | } | 754 | | Some(RuntimeCall::BabeApiConfiguration) => { | 755 | 0 | let result = decode_babe_configuration_output( | 756 | 0 | success.virtual_machine.value().as_ref(), | 757 | 0 | inner.runtime_babeapi_is_v1.unwrap(), | 758 | 0 | ); | 759 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 760 | 0 | match result { | 761 | 0 | Ok(output) => inner.babe_configuration_call_output = Some(output), | 762 | 0 | Err(err) => { | 763 | 0 | return ChainInformationBuild::Finished { | 764 | 0 | result: Err(err), | 765 | 0 | virtual_machine, | 766 | 0 | }; | 767 | | } | 768 | | } | 769 | 0 | virtual_machine | 770 | | } | 771 | | Some(RuntimeCall::GrandpaApiAuthorities) => { | 772 | 42 | let result = decode_grandpa_authorities_output( | 773 | 42 | success.virtual_machine.value().as_ref(), | 774 | 42 | ); | 775 | 42 | let virtual_machine = success.virtual_machine.into_prototype(); | 776 | 42 | match result { | 777 | 42 | Ok(output) => inner.grandpa_autorities_call_output = Some(output), | 778 | 0 | Err(err) => { | 779 | 0 | return ChainInformationBuild::Finished { | 780 | 0 | result: Err(err), | 781 | 0 | virtual_machine, | 782 | 0 | }; | 783 | | } | 784 | | } | 785 | 42 | virtual_machine | 786 | | } | 787 | | Some(RuntimeCall::GrandpaApiCurrentSetId) => { | 788 | 0 | let result = decode_grandpa_current_set_id_output( | 789 | 0 | success.virtual_machine.value().as_ref(), | 790 | 0 | ); | 791 | 0 | let virtual_machine = success.virtual_machine.into_prototype(); | 792 | 0 | match result { | 793 | 0 | Ok(output) => { | 794 | 0 | inner.grandpa_current_set_id_call_output = Some(output) | 795 | | } | 796 | 0 | Err(err) => { | 797 | 0 | return ChainInformationBuild::Finished { | 798 | 0 | result: Err(err), | 799 | 0 | virtual_machine, | 800 | 0 | }; | 801 | | } | 802 | | } | 803 | 0 | virtual_machine | 804 | | } | 805 | | }); | 806 | | | 807 | 126 | break ChainInformationBuild::start_next_call(inner); | 808 | | } | 809 | 0 | runtime_call::RuntimeCall::Finished(Err(err)) => { | 810 | 0 | break ChainInformationBuild::Finished { | 811 | 0 | result: Err(Error::WasmVm { | 812 | 0 | call: inner.call_in_progress.unwrap(), | 813 | 0 | error: err.detail, | 814 | 0 | }), | 815 | 0 | virtual_machine: err.prototype, | 816 | 0 | } | 817 | | } | 818 | 84 | runtime_call::RuntimeCall::StorageGet(call) => { | 819 | 84 | break ChainInformationBuild::InProgress(InProgress::StorageGet(StorageGet( | 820 | 84 | call, inner, | 821 | 84 | ))) | 822 | | } | 823 | 0 | runtime_call::RuntimeCall::NextKey(call) => { | 824 | 0 | break ChainInformationBuild::InProgress(InProgress::NextKey(NextKey( | 825 | 0 | call, inner, | 826 | 0 | ))) | 827 | | } | 828 | 0 | runtime_call::RuntimeCall::ClosestDescendantMerkleValue(call) => { | 829 | 0 | break ChainInformationBuild::InProgress( | 830 | 0 | InProgress::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue( | 831 | 0 | call, inner, | 832 | 0 | )), | 833 | 0 | ) | 834 | | } | 835 | 0 | runtime_call::RuntimeCall::SignatureVerification(sig) => { | 836 | 0 | call = sig.verify_and_resume(); | 837 | 0 | } | 838 | 0 | runtime_call::RuntimeCall::OffchainStorageSet(req) => { | 839 | 0 | // Do nothing. | 840 | 0 | call = req.resume(); | 841 | 0 | } | 842 | 0 | runtime_call::RuntimeCall::Offchain(req) => { | 843 | 0 | let virtual_machine = runtime_call::RuntimeCall::Offchain(req).into_prototype(); | 844 | 0 | break ChainInformationBuild::Finished { | 845 | 0 | result: Err(Error::OffchainWorkerHostFunction), | 846 | 0 | virtual_machine, | 847 | 0 | }; | 848 | | } | 849 | 0 | runtime_call::RuntimeCall::LogEmit(req) => { | 850 | 0 | // Generated logs are ignored. | 851 | 0 | call = req.resume(); | 852 | 0 | } | 853 | | } | 854 | | } | 855 | 210 | } |
|
856 | | } |
857 | | |
858 | | /// Struct shared by all the variants of the [`ChainInformationBuild`] enum. Contains the actual |
859 | | /// progress of the building. |
860 | | struct ChainInformationBuildInner { |
861 | | /// See [`Config::finalized_block_header`]. |
862 | | finalized_block_header: ConfigFinalizedBlockHeader, |
863 | | /// See [`Config::block_number_bytes`]. |
864 | | block_number_bytes: usize, |
865 | | |
866 | | /// Which call is currently in progress, if any. |
867 | | call_in_progress: Option<RuntimeCall>, |
868 | | /// Runtime to use to start the calls. |
869 | | /// |
870 | | /// [`ChainInformationBuildInner::call_in_progress`] and |
871 | | /// [`ChainInformationBuildInner::virtual_machine`] are never `Some` at the same time. However, |
872 | | /// using an enum wouldn't make the code cleaner because we need to be able to extract the |
873 | | /// values temporarily. |
874 | | virtual_machine: Option<host::HostVmPrototype>, |
875 | | |
876 | | /// If `true`, the runtime supports `AuraApi` functions. |
877 | | runtime_has_aura: bool, |
878 | | /// If `Some`, the runtime supports `BabeApi` functions. If `true`, the version is 1 (the old |
879 | | /// version). If `false`, the version is 2. |
880 | | runtime_babeapi_is_v1: Option<bool>, |
881 | | /// If `Some`, the runtime supports `GrandpaApi` functions. If `true`, the API supports the |
882 | | /// `GrandpaApi_current_set_id` runtime call. |
883 | | runtime_grandpa_supports_currentsetid: Option<bool>, |
884 | | |
885 | | /// Output of the call to `AuraApi_slot_duration`, if it was already made. |
886 | | aura_slot_duration_call_output: Option<NonZeroU64>, |
887 | | /// Output of the call to `AuraApi_authorities`, if it was already made. |
888 | | aura_autorities_call_output: Option<Vec<header::AuraAuthority>>, |
889 | | /// Output of the call to `BabeApi_current_epoch`, if it was already made. |
890 | | babe_current_epoch_call_output: Option<chain_information::BabeEpochInformation>, |
891 | | /// Output of the call to `BabeApi_next_epoch`, if it was already made. |
892 | | babe_next_epoch_call_output: Option<chain_information::BabeEpochInformation>, |
893 | | /// Output of the call to `BabeApi_configuration`, if it was already made. |
894 | | babe_configuration_call_output: Option<BabeGenesisConfiguration>, |
895 | | /// Output of the call to `GrandpaApi_grandpa_authorities`, if it was already made. |
896 | | grandpa_autorities_call_output: Option<Vec<header::GrandpaAuthority>>, |
897 | | /// Output of the call to `GrandpaApi_current_set_id`, if it was already made. |
898 | | grandpa_current_set_id_call_output: Option<u64>, |
899 | | } |
900 | | |
901 | | /// Decodes the output of a call to `AuraApi_slot_duration`. |
902 | 42 | fn decode_aura_slot_duration_output(bytes: &[u8]) -> Result<NonZeroU64, Error> { |
903 | 42 | <[u8; 8]>::try_from(bytes) |
904 | 42 | .ok() |
905 | 42 | .and_then(|b| NonZeroU64::new(u64::from_le_bytes(b))) Unexecuted instantiation: _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_aura_slot_duration_output0B9_ _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_aura_slot_duration_output0B9_ Line | Count | Source | 905 | 42 | .and_then(|b| NonZeroU64::new(u64::from_le_bytes(b))) |
|
906 | 42 | .ok_or(Error::AuraSlotDurationOutputDecode) |
907 | 42 | } Unexecuted instantiation: _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_aura_slot_duration_output _RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_aura_slot_duration_output Line | Count | Source | 902 | 42 | fn decode_aura_slot_duration_output(bytes: &[u8]) -> Result<NonZeroU64, Error> { | 903 | 42 | <[u8; 8]>::try_from(bytes) | 904 | 42 | .ok() | 905 | 42 | .and_then(|b| NonZeroU64::new(u64::from_le_bytes(b))) | 906 | 42 | .ok_or(Error::AuraSlotDurationOutputDecode) | 907 | 42 | } |
|
908 | | |
909 | | /// Decodes the output of a call to `AuraApi_authorities`. |
910 | 42 | fn decode_aura_authorities_output( |
911 | 42 | scale_encoded: &[u8], |
912 | 42 | ) -> Result<Vec<header::AuraAuthority>, Error> { |
913 | 42 | match header::AuraAuthoritiesIter::decode(scale_encoded) { |
914 | 42 | Ok(iter) => Ok(iter.map(header::AuraAuthority::from).collect::<Vec<_>>()), |
915 | 0 | Err(_) => Err(Error::AuraSlotDurationOutputDecode), |
916 | | } |
917 | 42 | } Unexecuted instantiation: _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build30decode_aura_authorities_output _RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build30decode_aura_authorities_output Line | Count | Source | 910 | 42 | fn decode_aura_authorities_output( | 911 | 42 | scale_encoded: &[u8], | 912 | 42 | ) -> Result<Vec<header::AuraAuthority>, Error> { | 913 | 42 | match header::AuraAuthoritiesIter::decode(scale_encoded) { | 914 | 42 | Ok(iter) => Ok(iter.map(header::AuraAuthority::from).collect::<Vec<_>>()), | 915 | 0 | Err(_) => Err(Error::AuraSlotDurationOutputDecode), | 916 | | } | 917 | 42 | } |
|
918 | | |
919 | | #[derive(Debug, Clone, PartialEq, Eq)] |
920 | | struct BabeGenesisConfiguration { |
921 | | slots_per_epoch: NonZeroU64, |
922 | | epoch0_configuration: header::BabeNextConfig, |
923 | | epoch0_information: header::BabeNextEpoch, |
924 | | } |
925 | | |
926 | | /// Decodes the output of a call to `BabeApi_configuration`. |
927 | 2 | fn decode_babe_configuration_output( |
928 | 2 | bytes: &[u8], |
929 | 2 | is_babe_api_v1: bool, |
930 | 2 | ) -> Result<BabeGenesisConfiguration, Error> { |
931 | 2 | let result: nom::IResult<_, _> = |
932 | 2 | nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map( |
933 | 2 | nom::sequence::tuple(( |
934 | 2 | nom::number::streaming::le_u64, |
935 | 2 | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), |
936 | 2 | nom::number::streaming::le_u64, |
937 | 2 | nom::number::streaming::le_u64, |
938 | 2 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { |
939 | 2 | nom::multi::many_m_n( |
940 | 2 | num_elems, |
941 | 2 | num_elems, |
942 | 2 | nom::combinator::map( |
943 | 2 | nom::sequence::tuple(( |
944 | 2 | nom::bytes::streaming::take(32u32), |
945 | 2 | nom::number::streaming::le_u64, |
946 | 2 | )), |
947 | 7 | move |(public_key, weight)| header::BabeAuthority { |
948 | 7 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), |
949 | 7 | weight, |
950 | 7 | }, _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_output00Bb_ Line | Count | Source | 947 | 7 | move |(public_key, weight)| header::BabeAuthority { | 948 | 7 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 949 | 7 | weight, | 950 | 7 | }, |
Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_output00Bb_ |
951 | 2 | ), |
952 | 2 | ) |
953 | 2 | }), _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_output0B9_ Line | Count | Source | 938 | 2 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 939 | 2 | nom::multi::many_m_n( | 940 | 2 | num_elems, | 941 | 2 | num_elems, | 942 | 2 | nom::combinator::map( | 943 | 2 | nom::sequence::tuple(( | 944 | 2 | nom::bytes::streaming::take(32u32), | 945 | 2 | nom::number::streaming::le_u64, | 946 | 2 | )), | 947 | 2 | move |(public_key, weight)| header::BabeAuthority { | 948 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 949 | | weight, | 950 | 2 | }, | 951 | 2 | ), | 952 | 2 | ) | 953 | 2 | }), |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_output0B9_ |
954 | 2 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { |
955 | 2 | <[u8; 32]>::try_from(b).unwrap() |
956 | 2 | }), _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs_0B9_ Line | Count | Source | 954 | 2 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { | 955 | 2 | <[u8; 32]>::try_from(b).unwrap() | 956 | 2 | }), |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs_0B9_ |
957 | 2 | |b| { |
958 | 2 | if is_babe_api_v1 { |
959 | 1 | nom::branch::alt(( |
960 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { |
961 | 0 | header::BabeAllowedSlots::PrimarySlots |
962 | 1 | }), Unexecuted instantiation: _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_00Bb_ Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_00Bb_ |
963 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { |
964 | 1 | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots |
965 | 1 | }), _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s_0Bb_ Line | Count | Source | 963 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 964 | 1 | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 965 | 1 | }), |
Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s_0Bb_ |
966 | 1 | ))(b) |
967 | | } else { |
968 | 1 | nom::branch::alt(( |
969 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { |
970 | 0 | header::BabeAllowedSlots::PrimarySlots |
971 | 1 | }), Unexecuted instantiation: _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s0_0Bb_ Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s0_0Bb_ |
972 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { |
973 | 1 | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots |
974 | 1 | }), _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s1_0Bb_ Line | Count | Source | 972 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 973 | 1 | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 974 | 1 | }), |
Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s1_0Bb_ |
975 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[2]), |_| { |
976 | 0 | header::BabeAllowedSlots::PrimaryAndSecondaryVrfSlots |
977 | 1 | }), Unexecuted instantiation: _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s2_0Bb_ Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0s2_0Bb_ |
978 | 1 | ))(b) |
979 | | } |
980 | 2 | }, _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0B9_ Line | Count | Source | 957 | 2 | |b| { | 958 | 2 | if is_babe_api_v1 { | 959 | 1 | nom::branch::alt(( | 960 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { | 961 | | header::BabeAllowedSlots::PrimarySlots | 962 | 1 | }), | 963 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 964 | | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 965 | 1 | }), | 966 | 1 | ))(b) | 967 | | } else { | 968 | 1 | nom::branch::alt(( | 969 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { | 970 | | header::BabeAllowedSlots::PrimarySlots | 971 | 1 | }), | 972 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 973 | | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 974 | 1 | }), | 975 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[2]), |_| { | 976 | | header::BabeAllowedSlots::PrimaryAndSecondaryVrfSlots | 977 | 1 | }), | 978 | 1 | ))(b) | 979 | | } | 980 | 2 | }, |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs0_0B9_ |
981 | 2 | )), |
982 | 2 | |(_slot_duration, slots_per_epoch, c0, c1, authorities, randomness, allowed_slots)| { |
983 | 2 | // Note that the slot duration is unused as it is not modifiable anyway. |
984 | 2 | BabeGenesisConfiguration { |
985 | 2 | slots_per_epoch, |
986 | 2 | epoch0_configuration: header::BabeNextConfig { |
987 | 2 | c: (c0, c1), |
988 | 2 | allowed_slots, |
989 | 2 | }, |
990 | 2 | epoch0_information: header::BabeNextEpoch { |
991 | 2 | randomness, |
992 | 2 | authorities, |
993 | 2 | }, |
994 | 2 | } |
995 | 2 | }, _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs1_0B9_ Line | Count | Source | 982 | 2 | |(_slot_duration, slots_per_epoch, c0, c1, authorities, randomness, allowed_slots)| { | 983 | 2 | // Note that the slot duration is unused as it is not modifiable anyway. | 984 | 2 | BabeGenesisConfiguration { | 985 | 2 | slots_per_epoch, | 986 | 2 | epoch0_configuration: header::BabeNextConfig { | 987 | 2 | c: (c0, c1), | 988 | 2 | allowed_slots, | 989 | 2 | }, | 990 | 2 | epoch0_information: header::BabeNextEpoch { | 991 | 2 | randomness, | 992 | 2 | authorities, | 993 | 2 | }, | 994 | 2 | } | 995 | 2 | }, |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_outputs1_0B9_ |
996 | 2 | )))(bytes); |
997 | | |
998 | 0 | match result { |
999 | 2 | Ok((_, out)) => Ok(out), |
1000 | 0 | Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(Error::BabeConfigurationOutputDecode), |
1001 | 0 | Err(_) => unreachable!(), |
1002 | | } |
1003 | 2 | } _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build32decode_babe_configuration_output Line | Count | Source | 927 | 2 | fn decode_babe_configuration_output( | 928 | 2 | bytes: &[u8], | 929 | 2 | is_babe_api_v1: bool, | 930 | 2 | ) -> Result<BabeGenesisConfiguration, Error> { | 931 | 2 | let result: nom::IResult<_, _> = | 932 | 2 | nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map( | 933 | 2 | nom::sequence::tuple(( | 934 | 2 | nom::number::streaming::le_u64, | 935 | 2 | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), | 936 | 2 | nom::number::streaming::le_u64, | 937 | 2 | nom::number::streaming::le_u64, | 938 | 2 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 939 | | nom::multi::many_m_n( | 940 | | num_elems, | 941 | | num_elems, | 942 | | nom::combinator::map( | 943 | | nom::sequence::tuple(( | 944 | | nom::bytes::streaming::take(32u32), | 945 | | nom::number::streaming::le_u64, | 946 | | )), | 947 | | move |(public_key, weight)| header::BabeAuthority { | 948 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 949 | | weight, | 950 | | }, | 951 | | ), | 952 | | ) | 953 | 2 | }), | 954 | 2 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { | 955 | | <[u8; 32]>::try_from(b).unwrap() | 956 | 2 | }), | 957 | 2 | |b| { | 958 | | if is_babe_api_v1 { | 959 | | nom::branch::alt(( | 960 | | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { | 961 | | header::BabeAllowedSlots::PrimarySlots | 962 | | }), | 963 | | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 964 | | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 965 | | }), | 966 | | ))(b) | 967 | | } else { | 968 | | nom::branch::alt(( | 969 | | nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| { | 970 | | header::BabeAllowedSlots::PrimarySlots | 971 | | }), | 972 | | nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| { | 973 | | header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots | 974 | | }), | 975 | | nom::combinator::map(nom::bytes::streaming::tag(&[2]), |_| { | 976 | | header::BabeAllowedSlots::PrimaryAndSecondaryVrfSlots | 977 | | }), | 978 | | ))(b) | 979 | | } | 980 | 2 | }, | 981 | 2 | )), | 982 | 2 | |(_slot_duration, slots_per_epoch, c0, c1, authorities, randomness, allowed_slots)| { | 983 | | // Note that the slot duration is unused as it is not modifiable anyway. | 984 | | BabeGenesisConfiguration { | 985 | | slots_per_epoch, | 986 | | epoch0_configuration: header::BabeNextConfig { | 987 | | c: (c0, c1), | 988 | | allowed_slots, | 989 | | }, | 990 | | epoch0_information: header::BabeNextEpoch { | 991 | | randomness, | 992 | | authorities, | 993 | | }, | 994 | | } | 995 | 2 | }, | 996 | 2 | )))(bytes); | 997 | | | 998 | 0 | match result { | 999 | 2 | Ok((_, out)) => Ok(out), | 1000 | 0 | Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(Error::BabeConfigurationOutputDecode), | 1001 | 0 | Err(_) => unreachable!(), | 1002 | | } | 1003 | 2 | } |
Unexecuted instantiation: _RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build32decode_babe_configuration_output |
1004 | | |
1005 | | /// Decodes the output of a call to `BabeApi_current_epoch` (`is_next_epoch` is `false`) or |
1006 | | /// `BabeApi_next_epoch` (`is_next_epoch` is `true`). |
1007 | 1 | fn decode_babe_epoch_output( |
1008 | 1 | scale_encoded: &'_ [u8], |
1009 | 1 | is_next_epoch: bool, |
1010 | 1 | ) -> Result<chain_information::BabeEpochInformation, Error> { |
1011 | 1 | let mut combinator = nom::combinator::all_consuming(nom::combinator::map( |
1012 | 1 | nom::sequence::tuple(( |
1013 | 1 | nom::number::streaming::le_u64, |
1014 | 1 | nom::number::streaming::le_u64, |
1015 | 1 | nom::number::streaming::le_u64, |
1016 | 1 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { |
1017 | 1 | nom::multi::many_m_n( |
1018 | 1 | num_elems, |
1019 | 1 | num_elems, |
1020 | 1 | nom::combinator::map( |
1021 | 1 | nom::sequence::tuple(( |
1022 | 1 | nom::bytes::streaming::take(32u32), |
1023 | 1 | nom::number::streaming::le_u64, |
1024 | 1 | )), |
1025 | 4 | move |(public_key, weight)| header::BabeAuthority { |
1026 | 4 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), |
1027 | 4 | weight, |
1028 | 4 | }, _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_output00Bb_ Line | Count | Source | 1025 | 4 | move |(public_key, weight)| header::BabeAuthority { | 1026 | 4 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1027 | 4 | weight, | 1028 | 4 | }, |
Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_output00Bb_ |
1029 | 1 | ), |
1030 | 1 | ) |
1031 | 1 | }), _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_output0B9_ Line | Count | Source | 1016 | 1 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1017 | 1 | nom::multi::many_m_n( | 1018 | 1 | num_elems, | 1019 | 1 | num_elems, | 1020 | 1 | nom::combinator::map( | 1021 | 1 | nom::sequence::tuple(( | 1022 | 1 | nom::bytes::streaming::take(32u32), | 1023 | 1 | nom::number::streaming::le_u64, | 1024 | 1 | )), | 1025 | 1 | move |(public_key, weight)| header::BabeAuthority { | 1026 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1027 | | weight, | 1028 | 1 | }, | 1029 | 1 | ), | 1030 | 1 | ) | 1031 | 1 | }), |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_output0B9_ |
1032 | 1 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { |
1033 | 1 | <[u8; 32]>::try_from(b).unwrap() |
1034 | 1 | }), _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs_0B9_ Line | Count | Source | 1032 | 1 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { | 1033 | 1 | <[u8; 32]>::try_from(b).unwrap() | 1034 | 1 | }), |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs_0B9_ |
1035 | 1 | nom::number::streaming::le_u64, |
1036 | 1 | nom::number::streaming::le_u64, |
1037 | 1 | |b| { |
1038 | 1 | header::BabeAllowedSlots::from_slice(b) |
1039 | 1 | .map(|v| (&[][..], v)) _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_00Bb_ Line | Count | Source | 1039 | 1 | .map(|v| (&[][..], v)) |
Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_00Bb_ |
1040 | 1 | .map_err(|_| { |
1041 | 0 | nom::Err::Error(nom::error::make_error(b, nom::error::ErrorKind::Verify)) |
1042 | 1 | }) Unexecuted instantiation: _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_0s_0Bb_ Unexecuted instantiation: _RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_0s_0Bb_ |
1043 | 1 | }, _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_0B9_ Line | Count | Source | 1037 | 1 | |b| { | 1038 | 1 | header::BabeAllowedSlots::from_slice(b) | 1039 | 1 | .map(|v| (&[][..], v)) | 1040 | 1 | .map_err(|_| { | 1041 | | nom::Err::Error(nom::error::make_error(b, nom::error::ErrorKind::Verify)) | 1042 | 1 | }) | 1043 | 1 | }, |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs0_0B9_ |
1044 | 1 | )), |
1045 | 1 | |( |
1046 | | epoch_index, |
1047 | | start_slot_number, |
1048 | | _duration, |
1049 | | authorities, |
1050 | | randomness, |
1051 | | c0, |
1052 | | c1, |
1053 | | allowed_slots, |
1054 | 1 | )| { |
1055 | 1 | chain_information::BabeEpochInformation { |
1056 | 1 | epoch_index, |
1057 | 1 | // Smoldot requires `start_slot_number` to be `None` in the context of next |
1058 | 1 | // epoch #0, because its start slot number can't be known. The runtime function, |
1059 | 1 | // however, as it doesn't have a way to represent `None`, instead returns an |
1060 | 1 | // unspecified value (typically `0`). |
1061 | 1 | start_slot_number: if !is_next_epoch || epoch_index != 0 { |
1062 | 1 | Some(start_slot_number) |
1063 | | } else { |
1064 | 0 | None |
1065 | | }, |
1066 | 1 | authorities, |
1067 | 1 | randomness, |
1068 | 1 | c: (c0, c1), |
1069 | 1 | allowed_slots, |
1070 | 1 | } |
1071 | 1 | }, _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs1_0B9_ Line | Count | Source | 1054 | 1 | )| { | 1055 | 1 | chain_information::BabeEpochInformation { | 1056 | 1 | epoch_index, | 1057 | 1 | // Smoldot requires `start_slot_number` to be `None` in the context of next | 1058 | 1 | // epoch #0, because its start slot number can't be known. The runtime function, | 1059 | 1 | // however, as it doesn't have a way to represent `None`, instead returns an | 1060 | 1 | // unspecified value (typically `0`). | 1061 | 1 | start_slot_number: if !is_next_epoch || epoch_index != 0 { | 1062 | 1 | Some(start_slot_number) | 1063 | | } else { | 1064 | 0 | None | 1065 | | }, | 1066 | 1 | authorities, | 1067 | 1 | randomness, | 1068 | 1 | c: (c0, c1), | 1069 | 1 | allowed_slots, | 1070 | 1 | } | 1071 | 1 | }, |
Unexecuted instantiation: _RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_outputs1_0B9_ |
1072 | 1 | )); |
1073 | 1 | |
1074 | 1 | let result: Result<_, nom::Err<nom::error::Error<&'_ [u8]>>> = combinator(scale_encoded); |
1075 | 1 | match result { |
1076 | 1 | Ok((_, info)) => Ok(info), |
1077 | 0 | Err(_) => Err(if is_next_epoch { |
1078 | 0 | Error::BabeNextEpochOutputDecode |
1079 | | } else { |
1080 | 0 | Error::BabeCurrentEpochOutputDecode |
1081 | | }), |
1082 | | } |
1083 | 1 | } _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build24decode_babe_epoch_output Line | Count | Source | 1007 | 1 | fn decode_babe_epoch_output( | 1008 | 1 | scale_encoded: &'_ [u8], | 1009 | 1 | is_next_epoch: bool, | 1010 | 1 | ) -> Result<chain_information::BabeEpochInformation, Error> { | 1011 | 1 | let mut combinator = nom::combinator::all_consuming(nom::combinator::map( | 1012 | 1 | nom::sequence::tuple(( | 1013 | 1 | nom::number::streaming::le_u64, | 1014 | 1 | nom::number::streaming::le_u64, | 1015 | 1 | nom::number::streaming::le_u64, | 1016 | 1 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1017 | | nom::multi::many_m_n( | 1018 | | num_elems, | 1019 | | num_elems, | 1020 | | nom::combinator::map( | 1021 | | nom::sequence::tuple(( | 1022 | | nom::bytes::streaming::take(32u32), | 1023 | | nom::number::streaming::le_u64, | 1024 | | )), | 1025 | | move |(public_key, weight)| header::BabeAuthority { | 1026 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1027 | | weight, | 1028 | | }, | 1029 | | ), | 1030 | | ) | 1031 | 1 | }), | 1032 | 1 | nom::combinator::map(nom::bytes::streaming::take(32u32), |b| { | 1033 | | <[u8; 32]>::try_from(b).unwrap() | 1034 | 1 | }), | 1035 | 1 | nom::number::streaming::le_u64, | 1036 | 1 | nom::number::streaming::le_u64, | 1037 | 1 | |b| { | 1038 | | header::BabeAllowedSlots::from_slice(b) | 1039 | | .map(|v| (&[][..], v)) | 1040 | | .map_err(|_| { | 1041 | | nom::Err::Error(nom::error::make_error(b, nom::error::ErrorKind::Verify)) | 1042 | | }) | 1043 | 1 | }, | 1044 | 1 | )), | 1045 | 1 | |( | 1046 | | epoch_index, | 1047 | | start_slot_number, | 1048 | | _duration, | 1049 | | authorities, | 1050 | | randomness, | 1051 | | c0, | 1052 | | c1, | 1053 | | allowed_slots, | 1054 | | )| { | 1055 | | chain_information::BabeEpochInformation { | 1056 | | epoch_index, | 1057 | | // Smoldot requires `start_slot_number` to be `None` in the context of next | 1058 | | // epoch #0, because its start slot number can't be known. The runtime function, | 1059 | | // however, as it doesn't have a way to represent `None`, instead returns an | 1060 | | // unspecified value (typically `0`). | 1061 | | start_slot_number: if !is_next_epoch || epoch_index != 0 { | 1062 | | Some(start_slot_number) | 1063 | | } else { | 1064 | | None | 1065 | | }, | 1066 | | authorities, | 1067 | | randomness, | 1068 | | c: (c0, c1), | 1069 | | allowed_slots, | 1070 | | } | 1071 | 1 | }, | 1072 | 1 | )); | 1073 | 1 | | 1074 | 1 | let result: Result<_, nom::Err<nom::error::Error<&'_ [u8]>>> = combinator(scale_encoded); | 1075 | 1 | match result { | 1076 | 1 | Ok((_, info)) => Ok(info), | 1077 | 0 | Err(_) => Err(if is_next_epoch { | 1078 | 0 | Error::BabeNextEpochOutputDecode | 1079 | | } else { | 1080 | 0 | Error::BabeCurrentEpochOutputDecode | 1081 | | }), | 1082 | | } | 1083 | 1 | } |
Unexecuted instantiation: _RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build24decode_babe_epoch_output |
1084 | | |
1085 | | /// Decodes the output of a call to `GrandpaApi_grandpa_authorities`, or the content of the |
1086 | | /// `:grandpa_authorities` storage item. |
1087 | 43 | fn decode_grandpa_authorities_output( |
1088 | 43 | scale_encoded: &[u8], |
1089 | 43 | ) -> Result<Vec<header::GrandpaAuthority>, Error> { |
1090 | 43 | let result: nom::IResult<_, _> = nom::combinator::all_consuming(nom::combinator::complete( |
1091 | 43 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { |
1092 | 43 | nom::multi::fold_many_m_n( |
1093 | 43 | num_elems, |
1094 | 43 | num_elems, |
1095 | 43 | nom::sequence::tuple(( |
1096 | 43 | nom::bytes::streaming::take(32u32), |
1097 | 43 | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), |
1098 | 43 | )), |
1099 | 43 | move || Vec::with_capacity(num_elems), _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output00Bb_ Line | Count | Source | 1099 | 1 | move || Vec::with_capacity(num_elems), |
_RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output00Bb_ Line | Count | Source | 1099 | 42 | move || Vec::with_capacity(num_elems), |
|
1100 | 85 | |mut acc, (public_key, weight)| { |
1101 | 85 | acc.push(header::GrandpaAuthority { |
1102 | 85 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), |
1103 | 85 | weight, |
1104 | 85 | }); |
1105 | 85 | acc |
1106 | 85 | }, _RNCNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output0s_0Bb_ Line | Count | Source | 1100 | 1 | |mut acc, (public_key, weight)| { | 1101 | 1 | acc.push(header::GrandpaAuthority { | 1102 | 1 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | 1 | weight, | 1104 | 1 | }); | 1105 | 1 | acc | 1106 | 1 | }, |
_RNCNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output0s_0Bb_ Line | Count | Source | 1100 | 84 | |mut acc, (public_key, weight)| { | 1101 | 84 | acc.push(header::GrandpaAuthority { | 1102 | 84 | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | 84 | weight, | 1104 | 84 | }); | 1105 | 84 | acc | 1106 | 84 | }, |
|
1107 | 43 | ) |
1108 | 43 | }), _RNCNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output0B9_ Line | Count | Source | 1091 | 1 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1092 | 1 | nom::multi::fold_many_m_n( | 1093 | 1 | num_elems, | 1094 | 1 | num_elems, | 1095 | 1 | nom::sequence::tuple(( | 1096 | 1 | nom::bytes::streaming::take(32u32), | 1097 | 1 | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), | 1098 | 1 | )), | 1099 | 1 | move || Vec::with_capacity(num_elems), | 1100 | 1 | |mut acc, (public_key, weight)| { | 1101 | | acc.push(header::GrandpaAuthority { | 1102 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | | weight, | 1104 | | }); | 1105 | | acc | 1106 | 1 | }, | 1107 | 1 | ) | 1108 | 1 | }), |
_RNCNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output0B9_ Line | Count | Source | 1091 | 42 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1092 | 42 | nom::multi::fold_many_m_n( | 1093 | 42 | num_elems, | 1094 | 42 | num_elems, | 1095 | 42 | nom::sequence::tuple(( | 1096 | 42 | nom::bytes::streaming::take(32u32), | 1097 | 42 | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), | 1098 | 42 | )), | 1099 | 42 | move || Vec::with_capacity(num_elems), | 1100 | 42 | |mut acc, (public_key, weight)| { | 1101 | | acc.push(header::GrandpaAuthority { | 1102 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | | weight, | 1104 | | }); | 1105 | | acc | 1106 | 42 | }, | 1107 | 42 | ) | 1108 | 42 | }), |
|
1109 | 43 | ))(scale_encoded); |
1110 | | |
1111 | 0 | match result { |
1112 | 43 | Ok((_, out)) => Ok(out), |
1113 | | Err(nom::Err::Error(_) | nom::Err::Failure(_)) => { |
1114 | 0 | Err(Error::GrandpaAuthoritiesOutputDecode) |
1115 | | } |
1116 | 0 | Err(_) => unreachable!(), |
1117 | | } |
1118 | 43 | } _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output Line | Count | Source | 1087 | 1 | fn decode_grandpa_authorities_output( | 1088 | 1 | scale_encoded: &[u8], | 1089 | 1 | ) -> Result<Vec<header::GrandpaAuthority>, Error> { | 1090 | 1 | let result: nom::IResult<_, _> = nom::combinator::all_consuming(nom::combinator::complete( | 1091 | 1 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1092 | | nom::multi::fold_many_m_n( | 1093 | | num_elems, | 1094 | | num_elems, | 1095 | | nom::sequence::tuple(( | 1096 | | nom::bytes::streaming::take(32u32), | 1097 | | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), | 1098 | | )), | 1099 | | move || Vec::with_capacity(num_elems), | 1100 | | |mut acc, (public_key, weight)| { | 1101 | | acc.push(header::GrandpaAuthority { | 1102 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | | weight, | 1104 | | }); | 1105 | | acc | 1106 | | }, | 1107 | | ) | 1108 | 1 | }), | 1109 | 1 | ))(scale_encoded); | 1110 | | | 1111 | 0 | match result { | 1112 | 1 | Ok((_, out)) => Ok(out), | 1113 | | Err(nom::Err::Error(_) | nom::Err::Failure(_)) => { | 1114 | 0 | Err(Error::GrandpaAuthoritiesOutputDecode) | 1115 | | } | 1116 | 0 | Err(_) => unreachable!(), | 1117 | | } | 1118 | 1 | } |
_RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build33decode_grandpa_authorities_output Line | Count | Source | 1087 | 42 | fn decode_grandpa_authorities_output( | 1088 | 42 | scale_encoded: &[u8], | 1089 | 42 | ) -> Result<Vec<header::GrandpaAuthority>, Error> { | 1090 | 42 | let result: nom::IResult<_, _> = nom::combinator::all_consuming(nom::combinator::complete( | 1091 | 42 | nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| { | 1092 | | nom::multi::fold_many_m_n( | 1093 | | num_elems, | 1094 | | num_elems, | 1095 | | nom::sequence::tuple(( | 1096 | | nom::bytes::streaming::take(32u32), | 1097 | | nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new), | 1098 | | )), | 1099 | | move || Vec::with_capacity(num_elems), | 1100 | | |mut acc, (public_key, weight)| { | 1101 | | acc.push(header::GrandpaAuthority { | 1102 | | public_key: <[u8; 32]>::try_from(public_key).unwrap(), | 1103 | | weight, | 1104 | | }); | 1105 | | acc | 1106 | | }, | 1107 | | ) | 1108 | 42 | }), | 1109 | 42 | ))(scale_encoded); | 1110 | | | 1111 | 0 | match result { | 1112 | 42 | Ok((_, out)) => Ok(out), | 1113 | | Err(nom::Err::Error(_) | nom::Err::Failure(_)) => { | 1114 | 0 | Err(Error::GrandpaAuthoritiesOutputDecode) | 1115 | | } | 1116 | 0 | Err(_) => unreachable!(), | 1117 | | } | 1118 | 42 | } |
|
1119 | | |
1120 | | /// Decodes the output of a call to `GrandpaApi_current_set_id`. |
1121 | 0 | fn decode_grandpa_current_set_id_output(bytes: &[u8]) -> Result<u64, Error> { |
1122 | 0 | <[u8; 8]>::try_from(bytes) |
1123 | 0 | .ok() |
1124 | 0 | .map(u64::from_le_bytes) |
1125 | 0 | .ok_or(Error::GrandpaCurrentSetIdOutputDecode) |
1126 | 0 | } Unexecuted instantiation: _RNvNtNtNtCsN16ciHI6Qf_7smoldot5chain17chain_information5build36decode_grandpa_current_set_id_output Unexecuted instantiation: _RNvNtNtNtCseuYC0Zibziv_7smoldot5chain17chain_information5build36decode_grandpa_current_set_id_output |
1127 | | |
1128 | | #[cfg(test)] |
1129 | | mod tests { |
1130 | | use crate::header; |
1131 | | use core::num::NonZeroU64; |
1132 | | |
1133 | | #[test] |
1134 | 1 | fn decode_babe_epoch_output_sample_decode() { |
1135 | 1 | // Sample taken from an actual Westend block. |
1136 | 1 | let sample_data = [ |
1137 | 1 | 100, 37, 0, 0, 0, 0, 0, 0, 215, 191, 25, 16, 0, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, 16, |
1138 | 1 | 102, 85, 132, 42, 246, 238, 38, 228, 88, 181, 254, 162, 211, 181, 190, 178, 221, 140, |
1139 | 1 | 249, 107, 36, 180, 72, 56, 145, 158, 26, 226, 150, 72, 223, 12, 1, 0, 0, 0, 0, 0, 0, 0, |
1140 | 1 | 92, 167, 131, 48, 94, 202, 168, 131, 131, 232, 44, 215, 20, 97, 44, 22, 227, 205, 24, |
1141 | 1 | 232, 243, 118, 34, 15, 45, 159, 187, 181, 132, 214, 138, 105, 1, 0, 0, 0, 0, 0, 0, 0, |
1142 | 1 | 212, 81, 34, 24, 150, 248, 208, 236, 69, 62, 90, 78, 252, 0, 125, 32, 86, 208, 73, 44, |
1143 | 1 | 151, 210, 88, 169, 187, 105, 170, 28, 165, 137, 126, 3, 1, 0, 0, 0, 0, 0, 0, 0, 236, |
1144 | 1 | 198, 169, 213, 112, 57, 219, 36, 157, 140, 107, 231, 182, 155, 98, 72, 224, 156, 194, |
1145 | 1 | 252, 107, 138, 97, 201, 177, 9, 13, 248, 167, 93, 218, 91, 1, 0, 0, 0, 0, 0, 0, 0, 150, |
1146 | 1 | 40, 172, 215, 156, 152, 22, 33, 79, 35, 203, 8, 40, 43, 0, 242, 126, 30, 241, 56, 206, |
1147 | 1 | 56, 36, 189, 60, 22, 121, 195, 168, 34, 207, 236, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, |
1148 | 1 | 0, 0, 0, 0, 2, |
1149 | 1 | ]; |
1150 | 1 | |
1151 | 1 | super::decode_babe_epoch_output(&sample_data, true).unwrap(); |
1152 | 1 | } |
1153 | | |
1154 | | #[test] |
1155 | 1 | fn decode_babe_configuration_output_v1() { |
1156 | 1 | let data = [ |
1157 | 1 | 112, 23, 0, 0, 0, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, |
1158 | 1 | 0, 0, 0, 0, 24, 202, 35, 147, 146, 150, 4, 115, 254, 27, 198, 95, 148, 238, 39, 216, |
1159 | 1 | 144, 164, 156, 27, 32, 12, 0, 111, 245, 220, 197, 37, 51, 14, 204, 22, 119, 1, 0, 0, 0, |
1160 | 1 | 0, 0, 0, 0, 180, 111, 1, 135, 76, 231, 171, 187, 82, 32, 232, 253, 137, 190, 222, 10, |
1161 | 1 | 218, 209, 76, 115, 3, 157, 145, 226, 142, 136, 24, 35, 67, 62, 114, 63, 1, 0, 0, 0, 0, |
1162 | 1 | 0, 0, 0, 214, 132, 217, 23, 109, 110, 182, 152, 135, 84, 12, 154, 137, 250, 96, 151, |
1163 | 1 | 173, 234, 130, 252, 75, 15, 242, 109, 16, 98, 180, 136, 243, 82, 225, 121, 1, 0, 0, 0, |
1164 | 1 | 0, 0, 0, 0, 104, 25, 90, 113, 189, 222, 73, 17, 122, 97, 100, 36, 189, 198, 10, 23, 51, |
1165 | 1 | 233, 106, 203, 29, 165, 174, 171, 93, 38, 140, 242, 165, 114, 233, 65, 1, 0, 0, 0, 0, |
1166 | 1 | 0, 0, 0, 26, 5, 117, 239, 74, 226, 75, 223, 211, 31, 76, 181, 189, 97, 35, 154, 230, |
1167 | 1 | 124, 18, 212, 230, 74, 229, 26, 199, 86, 4, 74, 166, 173, 130, 0, 1, 0, 0, 0, 0, 0, 0, |
1168 | 1 | 0, 24, 22, 143, 42, 173, 0, 129, 162, 87, 40, 150, 30, 224, 6, 39, 207, 227, 94, 57, |
1169 | 1 | 131, 60, 128, 80, 22, 99, 43, 247, 193, 77, 165, 128, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1170 | 1 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
1171 | 1 | 0, 1, |
1172 | 1 | ]; |
1173 | 1 | |
1174 | 1 | assert_eq!( |
1175 | 1 | super::decode_babe_configuration_output(&data, true).unwrap(), |
1176 | 1 | super::BabeGenesisConfiguration { |
1177 | 1 | slots_per_epoch: NonZeroU64::new(600).unwrap(), |
1178 | 1 | epoch0_configuration: header::BabeNextConfig { |
1179 | 1 | allowed_slots: header::BabeAllowedSlots::PrimaryAndSecondaryPlainSlots, |
1180 | 1 | c: (1, 4), |
1181 | 1 | }, |
1182 | 1 | epoch0_information: header::BabeNextEpoch { |
1183 | 1 | authorities: vec![ |
1184 | 1 | header::BabeAuthority { |
1185 | 1 | public_key: [ |
1186 | 1 | 202, 35, 147, 146, 150, 4, 115, 254, 27, 198, 95, 148, 238, 39, |
1187 | 1 | 216, 144, 164, 156, 27, 32, 12, 0, 111, 245, 220, 197, 37, 51, 14, |
1188 | 1 | 204, 22, 119 |
1189 | 1 | ], |
1190 | 1 | weight: 1 |
1191 | 1 | }, |
1192 | 1 | header::BabeAuthority { |
1193 | 1 | public_key: [ |
1194 | 1 | 180, 111, 1, 135, 76, 231, 171, 187, 82, 32, 232, 253, 137, 190, |
1195 | 1 | 222, 10, 218, 209, 76, 115, 3, 157, 145, 226, 142, 136, 24, 35, 67, |
1196 | 1 | 62, 114, 63 |
1197 | 1 | ], |
1198 | 1 | weight: 1 |
1199 | 1 | }, |
1200 | 1 | header::BabeAuthority { |
1201 | 1 | public_key: [ |
1202 | 1 | 214, 132, 217, 23, 109, 110, 182, 152, 135, 84, 12, 154, 137, 250, |
1203 | 1 | 96, 151, 173, 234, 130, 252, 75, 15, 242, 109, 16, 98, 180, 136, |
1204 | 1 | 243, 82, 225, 121 |
1205 | 1 | ], |
1206 | 1 | weight: 1 |
1207 | 1 | }, |
1208 | 1 | header::BabeAuthority { |
1209 | 1 | public_key: [ |
1210 | 1 | 104, 25, 90, 113, 189, 222, 73, 17, 122, 97, 100, 36, 189, 198, 10, |
1211 | 1 | 23, 51, 233, 106, 203, 29, 165, 174, 171, 93, 38, 140, 242, 165, |
1212 | 1 | 114, 233, 65 |
1213 | 1 | ], |
1214 | 1 | weight: 1 |
1215 | 1 | }, |
1216 | 1 | header::BabeAuthority { |
1217 | 1 | public_key: [ |
1218 | 1 | 26, 5, 117, 239, 74, 226, 75, 223, 211, 31, 76, 181, 189, 97, 35, |
1219 | 1 | 154, 230, 124, 18, 212, 230, 74, 229, 26, 199, 86, 4, 74, 166, 173, |
1220 | 1 | 130, 0 |
1221 | 1 | ], |
1222 | 1 | weight: 1 |
1223 | 1 | }, |
1224 | 1 | header::BabeAuthority { |
1225 | 1 | public_key: [ |
1226 | 1 | 24, 22, 143, 42, 173, 0, 129, 162, 87, 40, 150, 30, 224, 6, 39, |
1227 | 1 | 207, 227, 94, 57, 131, 60, 128, 80, 22, 99, 43, 247, 193, 77, 165, |
1228 | 1 | 128, 9 |
1229 | 1 | ], |
1230 | 1 | weight: 1 |
1231 | 1 | } |
1232 | 1 | ], |
1233 | 1 | randomness: [0; 32] |
1234 | 1 | }, |
1235 | 1 | } |
1236 | 1 | ); |
1237 | 1 | } |
1238 | | } |