/__w/smoldot/smoldot/repo/lib/src/author/runtime.rs
Line | Count | Source |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2020 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 | | //! Block generation system. |
19 | | //! |
20 | | //! This module provides the actual block generation code. The output is an unsealed header and |
21 | | //! body. |
22 | | //! |
23 | | //! After a block has been generated, it must still be sealed (in other words, signed by its |
24 | | //! author) by adding a corresponding entry to the log items in its header. This is out of scope |
25 | | //! of this module. |
26 | | //! |
27 | | //! # Detail |
28 | | //! |
29 | | //! Building a block consists in four steps: |
30 | | //! |
31 | | //! - A runtime call to `Core_initialize_block`, passing a header prototype as input. This call |
32 | | //! performs some initial storage writes. |
33 | | //! - A runtime call to `BlockBuilder_inherent_extrinsics`, passing as input a list of |
34 | | //! *intrinsics*. This pure call returns a list of extrinsics. |
35 | | //! - Zero or more runtime calls to `BlockBuilder_apply_extrinsic`, passing as input an extrinsic. |
36 | | //! This must be done once per extrinsic returned by the previous step, plus once for each |
37 | | //! transaction to push in the block. |
38 | | //! - A runtime call to `BlockBuilder_finalize_block`, which returns the newly-created unsealed |
39 | | //! block header. |
40 | | //! |
41 | | //! The body of the newly-generated block consists in the extrinsics pushed using |
42 | | //! `BlockBuilder_apply_extrinsic` (including the intrinsics). |
43 | | //! |
44 | | |
45 | | // TODO: expand docs |
46 | | // TODO: explain what an inherent extrinsic is |
47 | | |
48 | | mod tests; |
49 | | |
50 | | use crate::{ |
51 | | executor::{host, runtime_call}, |
52 | | header, util, |
53 | | verify::inherents, |
54 | | }; |
55 | | |
56 | | use alloc::{borrow::ToOwned as _, vec::Vec}; |
57 | | use core::{iter, mem, slice}; |
58 | | |
59 | | pub use runtime_call::{ |
60 | | Nibble, StorageChanges, TrieChange, TrieChangeStorageValue, TrieEntryVersion, |
61 | | }; |
62 | | |
63 | | /// Configuration for a block generation. |
64 | | pub struct Config<'a> { |
65 | | /// Number of bytes used to encode block numbers in the header. |
66 | | pub block_number_bytes: usize, |
67 | | |
68 | | /// Hash of the parent of the block to generate. |
69 | | /// |
70 | | /// Used to populate the header of the new block. |
71 | | pub parent_hash: &'a [u8; 32], |
72 | | |
73 | | /// Height of the parent of the block to generate. |
74 | | /// |
75 | | /// Used to populate the header of the new block. |
76 | | pub parent_number: u64, |
77 | | |
78 | | /// Runtime used to check the new block. Must be built using the Wasm code found at the |
79 | | /// `:code` key of the parent block storage. |
80 | | pub parent_runtime: host::HostVmPrototype, |
81 | | |
82 | | /// Consensus-specific item to put in the digest of the header prototype. |
83 | | /// |
84 | | /// > **Note**: In the case of Aura and Babe, contains the slot being claimed. |
85 | | pub consensus_digest_log_item: ConfigPreRuntime<'a>, |
86 | | |
87 | | /// Capacity to reserve for the number of extrinsics. Should be higher than the approximate |
88 | | /// number of extrinsics that are going to be applied. |
89 | | pub block_body_capacity: usize, |
90 | | |
91 | | /// Maximum log level of the runtime. |
92 | | /// |
93 | | /// > **Note**: This value is opaque from the point of the view of the client, and the runtime |
94 | | /// > is free to interpret it the way it wants. However, usually values are: `0` for |
95 | | /// > "off", `1` for "error", `2` for "warn", `3` for "info", `4` for "debug", |
96 | | /// > and `5` for "trace". |
97 | | pub max_log_level: u32, |
98 | | |
99 | | /// If `true`, then [`StorageChanges::trie_changes_iter_ordered`] will return `Some`. |
100 | | /// Passing `None` requires fewer calculation and fewer storage accesses. |
101 | | pub calculate_trie_changes: bool, |
102 | | } |
103 | | |
104 | | /// Extra configuration depending on the consensus algorithm. |
105 | | // TODO: consider not exposing `header` in the API |
106 | | pub enum ConfigPreRuntime<'a> { |
107 | | /// Chain uses the Aura consensus algorithm. |
108 | | Aura(header::AuraPreDigest), |
109 | | /// Chain uses the Babe consensus algorithm. |
110 | | Babe(header::BabePreDigestRef<'a>), |
111 | | } |
112 | | |
113 | | /// Block successfully verified. |
114 | | pub struct Success { |
115 | | /// SCALE-encoded header of the produced block. |
116 | | pub scale_encoded_header: Vec<u8>, |
117 | | /// Body of the produced block. |
118 | | pub body: Vec<Vec<u8>>, |
119 | | /// Runtime that was passed by [`Config`]. |
120 | | pub parent_runtime: host::HostVmPrototype, |
121 | | /// List of changes to the storage main trie that the block performs. |
122 | | pub storage_changes: StorageChanges, |
123 | | /// State trie version indicated by the runtime. All the storage changes indicated by |
124 | | /// [`Success::storage_changes`] should store this version alongside with them. |
125 | | pub state_trie_version: TrieEntryVersion, |
126 | | } |
127 | | |
128 | | /// Error that can happen during the block production. |
129 | | #[derive(Debug, derive_more::Display, derive_more::Error)] |
130 | | pub enum Error { |
131 | | /// Error while executing the Wasm virtual machine. |
132 | | #[display("{_0}")] |
133 | | WasmVm(runtime_call::ErrorDetail), |
134 | | /// Error while initializing the Wasm virtual machine. |
135 | | #[display("{_0}")] |
136 | | VmInit(host::StartErr), |
137 | | /// Overflow when incrementing block height. |
138 | | BlockHeightOverflow, |
139 | | /// `Core_initialize_block` has returned a non-empty output. |
140 | | InitializeBlockNonEmptyOutput, |
141 | | /// Error while parsing output of `BlockBuilder_inherent_extrinsics`. |
142 | | BadInherentExtrinsicsOutput, |
143 | | /// Error while parsing output of `BlockBuilder_apply_extrinsic`. |
144 | | BadApplyExtrinsicOutput, |
145 | | /// Applying an inherent extrinsic has returned a [`DispatchError`]. |
146 | | #[display("Error while applying inherent extrinsic: {error}\nExtrinsic: {extrinsic:?}")] |
147 | | InherentExtrinsicDispatchError { |
148 | | /// Extrinsic that triggered the problem. |
149 | | extrinsic: Vec<u8>, |
150 | | /// Error returned by the runtime. |
151 | | #[error(source)] |
152 | | error: DispatchError, |
153 | | }, |
154 | | /// Applying an inherent extrinsic has returned a [`TransactionValidityError`]. |
155 | | #[display("Error while applying inherent extrinsic: {error}\nExtrinsic: {extrinsic:?}")] |
156 | | InherentExtrinsicTransactionValidityError { |
157 | | /// Extrinsic that triggered the problem. |
158 | | extrinsic: Vec<u8>, |
159 | | /// Error returned by the runtime. |
160 | | #[error(source)] |
161 | | error: TransactionValidityError, |
162 | | }, |
163 | | } |
164 | | |
165 | | /// Start a block building process. |
166 | 1 | pub fn build_block(config: Config) -> BlockBuild { |
167 | 1 | let consensus_digest = match config.consensus_digest_log_item { |
168 | 1 | ConfigPreRuntime::Aura(item) => header::DigestItem::AuraPreDigest(item), |
169 | 0 | ConfigPreRuntime::Babe(item) => header::DigestItem::BabePreDigest(item.into()), |
170 | | }; |
171 | | |
172 | 1 | let init_result = runtime_call::run(runtime_call::Config { |
173 | 1 | function_to_call: "Core_initialize_block", |
174 | | parameter: { |
175 | | // The `Core_initialize_block` function expects a SCALE-encoded partially-initialized |
176 | | // header. |
177 | | header::HeaderRef { |
178 | 1 | parent_hash: config.parent_hash, |
179 | 1 | number: match config.parent_number.checked_add(1) { |
180 | 1 | Some(n) => n, |
181 | | None => { |
182 | 0 | return BlockBuild::Finished(Err(( |
183 | 0 | Error::BlockHeightOverflow, |
184 | 0 | config.parent_runtime, |
185 | 0 | ))); |
186 | | } |
187 | | }, |
188 | 1 | extrinsics_root: &[0; 32], |
189 | 1 | state_root: &[0; 32], |
190 | 1 | digest: header::DigestRef::from_slice(slice::from_ref(&consensus_digest)).unwrap(), |
191 | | } |
192 | 1 | .scale_encoding(config.block_number_bytes) |
193 | | }, |
194 | 1 | virtual_machine: config.parent_runtime, |
195 | 1 | storage_main_trie_changes: Default::default(), |
196 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, |
197 | 1 | max_log_level: config.max_log_level, |
198 | 1 | calculate_trie_changes: config.calculate_trie_changes, |
199 | | }); |
200 | | |
201 | 1 | let vm = match init_result { |
202 | 1 | Ok(vm) => vm, |
203 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), |
204 | | }; |
205 | | |
206 | 1 | let shared = Shared { |
207 | 1 | stage: Stage::InitializeBlock, |
208 | 1 | block_body: Vec::with_capacity(config.block_body_capacity), |
209 | 1 | max_log_level: config.max_log_level, |
210 | 1 | calculate_trie_changes: config.calculate_trie_changes, |
211 | 1 | }; |
212 | | |
213 | 1 | BlockBuild::from_inner(vm, shared) |
214 | 1 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime11build_block Line | Count | Source | 166 | 1 | pub fn build_block(config: Config) -> BlockBuild { | 167 | 1 | let consensus_digest = match config.consensus_digest_log_item { | 168 | 1 | ConfigPreRuntime::Aura(item) => header::DigestItem::AuraPreDigest(item), | 169 | 0 | ConfigPreRuntime::Babe(item) => header::DigestItem::BabePreDigest(item.into()), | 170 | | }; | 171 | | | 172 | 1 | let init_result = runtime_call::run(runtime_call::Config { | 173 | 1 | function_to_call: "Core_initialize_block", | 174 | | parameter: { | 175 | | // The `Core_initialize_block` function expects a SCALE-encoded partially-initialized | 176 | | // header. | 177 | | header::HeaderRef { | 178 | 1 | parent_hash: config.parent_hash, | 179 | 1 | number: match config.parent_number.checked_add(1) { | 180 | 1 | Some(n) => n, | 181 | | None => { | 182 | 0 | return BlockBuild::Finished(Err(( | 183 | 0 | Error::BlockHeightOverflow, | 184 | 0 | config.parent_runtime, | 185 | 0 | ))); | 186 | | } | 187 | | }, | 188 | 1 | extrinsics_root: &[0; 32], | 189 | 1 | state_root: &[0; 32], | 190 | 1 | digest: header::DigestRef::from_slice(slice::from_ref(&consensus_digest)).unwrap(), | 191 | | } | 192 | 1 | .scale_encoding(config.block_number_bytes) | 193 | | }, | 194 | 1 | virtual_machine: config.parent_runtime, | 195 | 1 | storage_main_trie_changes: Default::default(), | 196 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, | 197 | 1 | max_log_level: config.max_log_level, | 198 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 199 | | }); | 200 | | | 201 | 1 | let vm = match init_result { | 202 | 1 | Ok(vm) => vm, | 203 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), | 204 | | }; | 205 | | | 206 | 1 | let shared = Shared { | 207 | 1 | stage: Stage::InitializeBlock, | 208 | 1 | block_body: Vec::with_capacity(config.block_body_capacity), | 209 | 1 | max_log_level: config.max_log_level, | 210 | 1 | calculate_trie_changes: config.calculate_trie_changes, | 211 | 1 | }; | 212 | | | 213 | 1 | BlockBuild::from_inner(vm, shared) | 214 | 1 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime11build_block |
215 | | |
216 | | /// Current state of the block building process. |
217 | | #[must_use] |
218 | | pub enum BlockBuild { |
219 | | /// Block generation is over. |
220 | | Finished(Result<Success, (Error, host::HostVmPrototype)>), |
221 | | |
222 | | /// The inherent extrinsics are required in order to continue. |
223 | | /// |
224 | | /// [`BlockBuild::InherentExtrinsics`] is guaranteed to only be emitted once per block |
225 | | /// building process. |
226 | | /// |
227 | | /// The extrinsics returned by the call to `BlockBuilder_inherent_extrinsics` are |
228 | | /// automatically pushed to the runtime. |
229 | | InherentExtrinsics(InherentExtrinsics), |
230 | | |
231 | | /// Block building is ready to accept extrinsics. |
232 | | /// |
233 | | /// If [`ApplyExtrinsic::add_extrinsic`] is used, then a [`BlockBuild::ApplyExtrinsicResult`] |
234 | | /// stage will be emitted later. |
235 | | /// |
236 | | /// > **Note**: These extrinsics are generally coming from a transactions pool, but this is |
237 | | /// > out of scope of this module. |
238 | | ApplyExtrinsic(ApplyExtrinsic), |
239 | | |
240 | | /// Result of the previous call to [`ApplyExtrinsic::add_extrinsic`]. |
241 | | /// |
242 | | /// An [`ApplyExtrinsic`] object is provided in order to continue the operation. |
243 | | ApplyExtrinsicResult { |
244 | | /// Result of the previous call to [`ApplyExtrinsic::add_extrinsic`]. |
245 | | result: Result<Result<(), DispatchError>, TransactionValidityError>, |
246 | | /// Object to use to continue trying to push other transactions or finish the block. |
247 | | resume: ApplyExtrinsic, |
248 | | }, |
249 | | |
250 | | /// Loading a storage value from the parent storage is required in order to continue. |
251 | | StorageGet(StorageGet), |
252 | | |
253 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
254 | | /// to continue. |
255 | | ClosestDescendantMerkleValue(ClosestDescendantMerkleValue), |
256 | | |
257 | | /// Fetching the key that follows a given one in the parent storage is required in order to |
258 | | /// continue. |
259 | | NextKey(NextKey), |
260 | | |
261 | | /// Setting an offchain storage value is required in order to continue. |
262 | | OffchainStorageSet(OffchainStorageSet), |
263 | | } |
264 | | |
265 | | impl BlockBuild { |
266 | 4.20k | fn from_inner(inner: runtime_call::RuntimeCall, mut shared: Shared) -> Self { |
267 | | enum Inner { |
268 | | Runtime(runtime_call::RuntimeCall), |
269 | | Transition(runtime_call::Success), |
270 | | } |
271 | | |
272 | 4.20k | let mut inner = Inner::Runtime(inner); |
273 | | |
274 | | loop { |
275 | 4.20k | match (inner, &mut shared.stage) { |
276 | 0 | (Inner::Runtime(runtime_call::RuntimeCall::Finished(Err(err))), _) => { |
277 | 0 | return BlockBuild::Finished(Err((Error::WasmVm(err.detail), err.prototype))); |
278 | | } |
279 | 146 | (Inner::Runtime(runtime_call::RuntimeCall::StorageGet(inner)), _) => { |
280 | 146 | return BlockBuild::StorageGet(StorageGet(inner, shared)); |
281 | | } |
282 | | ( |
283 | 1.86k | Inner::Runtime(runtime_call::RuntimeCall::ClosestDescendantMerkleValue(inner)), |
284 | | _, |
285 | | ) => { |
286 | 1.86k | return BlockBuild::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue( |
287 | 1.86k | inner, shared, |
288 | 1.86k | )); |
289 | | } |
290 | 2.19k | (Inner::Runtime(runtime_call::RuntimeCall::NextKey(inner)), _) => { |
291 | 2.19k | return BlockBuild::NextKey(NextKey(inner, shared)); |
292 | | } |
293 | 0 | (Inner::Runtime(runtime_call::RuntimeCall::OffchainStorageSet(inner)), _) => { |
294 | 0 | return BlockBuild::OffchainStorageSet(OffchainStorageSet(inner, shared)); |
295 | | } |
296 | | |
297 | | ( |
298 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), |
299 | | Stage::InitializeBlock, |
300 | | ) => { |
301 | 1 | if !success.virtual_machine.value().as_ref().is_empty() { |
302 | 0 | return BlockBuild::Finished(Err(( |
303 | 0 | Error::InitializeBlockNonEmptyOutput, |
304 | 0 | success.virtual_machine.into_prototype(), |
305 | 0 | ))); |
306 | 1 | } |
307 | | |
308 | 1 | shared.stage = Stage::InherentExtrinsics; |
309 | | |
310 | 1 | return BlockBuild::InherentExtrinsics(InherentExtrinsics { |
311 | 1 | shared, |
312 | 1 | parent_runtime: success.virtual_machine.into_prototype(), |
313 | 1 | storage_changes: success.storage_changes, |
314 | 1 | }); |
315 | | } |
316 | | |
317 | | ( |
318 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), |
319 | | Stage::InherentExtrinsics, |
320 | | ) => { |
321 | 1 | let parse_result = |
322 | 1 | parse_inherent_extrinsics_output(success.virtual_machine.value().as_ref()); |
323 | 1 | let extrinsics = match parse_result { |
324 | 1 | Ok(extrinsics) => extrinsics, |
325 | 0 | Err(err) => { |
326 | 0 | return BlockBuild::Finished(Err(( |
327 | 0 | err, |
328 | 0 | success.virtual_machine.into_prototype(), |
329 | 0 | ))); |
330 | | } |
331 | | }; |
332 | | |
333 | 1 | shared.block_body.reserve(extrinsics.len()); |
334 | 1 | shared.stage = Stage::ApplyInherentExtrinsic { extrinsics }; |
335 | 1 | inner = Inner::Transition(success); |
336 | | } |
337 | | |
338 | 2 | (Inner::Transition(success1 ), Stage::ApplyInherentExtrinsic { extrinsics }) |
339 | 2 | if !extrinsics.is_empty()1 => |
340 | | { |
341 | 1 | let extrinsic = &extrinsics[0]; |
342 | | |
343 | 1 | let init_result = runtime_call::run(runtime_call::Config { |
344 | 1 | virtual_machine: success.virtual_machine.into_prototype(), |
345 | 1 | function_to_call: "BlockBuilder_apply_extrinsic", |
346 | 1 | parameter: iter::once(extrinsic), |
347 | 1 | storage_main_trie_changes: success.storage_changes.into_main_trie_diff(), |
348 | 1 | storage_proof_size_behavior: |
349 | 1 | runtime_call::StorageProofSizeBehavior::Unimplemented, |
350 | 1 | max_log_level: shared.max_log_level, |
351 | 1 | calculate_trie_changes: shared.calculate_trie_changes, |
352 | 1 | }); |
353 | | |
354 | 1 | inner = Inner::Runtime(match init_result { |
355 | 1 | Ok(vm) => vm, |
356 | 0 | Err((err, proto)) => { |
357 | 0 | return BlockBuild::Finished(Err((Error::VmInit(err), proto))); |
358 | | } |
359 | | }); |
360 | | } |
361 | | |
362 | 1 | (Inner::Transition(success), Stage::ApplyInherentExtrinsic { .. }) => { |
363 | 1 | return BlockBuild::ApplyExtrinsic(ApplyExtrinsic { |
364 | 1 | shared, |
365 | 1 | parent_runtime: success.virtual_machine.into_prototype(), |
366 | 1 | storage_changes: success.storage_changes, |
367 | 1 | }); |
368 | | } |
369 | | |
370 | | ( |
371 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), |
372 | | Stage::ApplyInherentExtrinsic { .. }, |
373 | | ) => { |
374 | 1 | let (extrinsic, new_stage) = match shared.stage { |
375 | 1 | Stage::ApplyInherentExtrinsic { mut extrinsics } => { |
376 | 1 | let extrinsic = extrinsics.remove(0); |
377 | 1 | (extrinsic, Stage::ApplyInherentExtrinsic { extrinsics }) |
378 | | } |
379 | 0 | _ => unreachable!(), |
380 | | }; |
381 | | |
382 | 1 | shared.stage = new_stage; |
383 | | |
384 | 1 | let parse_result = |
385 | 1 | parse_apply_extrinsic_output(success.virtual_machine.value().as_ref()); |
386 | 1 | match parse_result { |
387 | 1 | Ok(Ok(Ok(()))) => {} |
388 | 0 | Ok(Ok(Err(error))) => { |
389 | 0 | return BlockBuild::Finished(Err(( |
390 | 0 | Error::InherentExtrinsicDispatchError { extrinsic, error }, |
391 | 0 | success.virtual_machine.into_prototype(), |
392 | 0 | ))); |
393 | | } |
394 | 0 | Ok(Err(error)) => { |
395 | 0 | return BlockBuild::Finished(Err(( |
396 | 0 | Error::InherentExtrinsicTransactionValidityError { |
397 | 0 | extrinsic, |
398 | 0 | error, |
399 | 0 | }, |
400 | 0 | success.virtual_machine.into_prototype(), |
401 | 0 | ))); |
402 | | } |
403 | 0 | Err(err) => { |
404 | 0 | return BlockBuild::Finished(Err(( |
405 | 0 | err, |
406 | 0 | success.virtual_machine.into_prototype(), |
407 | 0 | ))); |
408 | | } |
409 | | } |
410 | | |
411 | 1 | shared.block_body.push(extrinsic); |
412 | | |
413 | 1 | inner = Inner::Transition(success); |
414 | | } |
415 | | |
416 | | ( |
417 | 0 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), |
418 | | Stage::ApplyExtrinsic(_), |
419 | | ) => { |
420 | 0 | let parse_result = |
421 | 0 | parse_apply_extrinsic_output(success.virtual_machine.value().as_ref()); |
422 | 0 | let result = match parse_result { |
423 | 0 | Ok(r) => r, |
424 | 0 | Err(err) => { |
425 | 0 | return BlockBuild::Finished(Err(( |
426 | 0 | err, |
427 | 0 | success.virtual_machine.into_prototype(), |
428 | 0 | ))); |
429 | | } |
430 | | }; |
431 | | |
432 | 0 | if result.is_ok() { |
433 | 0 | shared.block_body.push(match &mut shared.stage { |
434 | 0 | Stage::ApplyExtrinsic(ext) => mem::take(ext), |
435 | 0 | _ => unreachable!(), |
436 | | }); |
437 | 0 | } |
438 | | |
439 | | // TODO: consider giving back extrinsic to user in case of failure |
440 | | |
441 | | // TODO: IMPORTANT /!\ must throw away storage changes in case of error |
442 | | |
443 | 0 | return BlockBuild::ApplyExtrinsicResult { |
444 | 0 | result, |
445 | 0 | resume: ApplyExtrinsic { |
446 | 0 | shared, |
447 | 0 | parent_runtime: success.virtual_machine.into_prototype(), |
448 | 0 | storage_changes: success.storage_changes, |
449 | 0 | }, |
450 | 0 | }; |
451 | | } |
452 | | |
453 | | ( |
454 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), |
455 | | Stage::FinalizeBlock, |
456 | | ) => { |
457 | 1 | let scale_encoded_header = success.virtual_machine.value().as_ref().to_owned(); |
458 | 1 | return BlockBuild::Finished(Ok(Success { |
459 | 1 | scale_encoded_header, |
460 | 1 | body: shared.block_body, |
461 | 1 | parent_runtime: success.virtual_machine.into_prototype(), |
462 | 1 | storage_changes: success.storage_changes, |
463 | 1 | state_trie_version: success.state_trie_version, |
464 | 1 | })); |
465 | | } |
466 | | |
467 | | // TODO: what about SignatureVerification and EmitLog? at the time of writing of this comment, it's not worth fixing as this code would get removed by <https://github.com/smol-dot/smoldot/issues/1517> |
468 | 0 | (_, s) => unreachable!("{:?}", s), |
469 | | } |
470 | | } |
471 | 4.20k | } _RNvMNtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB2_10BlockBuild10from_inner Line | Count | Source | 266 | 4.20k | fn from_inner(inner: runtime_call::RuntimeCall, mut shared: Shared) -> Self { | 267 | | enum Inner { | 268 | | Runtime(runtime_call::RuntimeCall), | 269 | | Transition(runtime_call::Success), | 270 | | } | 271 | | | 272 | 4.20k | let mut inner = Inner::Runtime(inner); | 273 | | | 274 | | loop { | 275 | 4.20k | match (inner, &mut shared.stage) { | 276 | 0 | (Inner::Runtime(runtime_call::RuntimeCall::Finished(Err(err))), _) => { | 277 | 0 | return BlockBuild::Finished(Err((Error::WasmVm(err.detail), err.prototype))); | 278 | | } | 279 | 146 | (Inner::Runtime(runtime_call::RuntimeCall::StorageGet(inner)), _) => { | 280 | 146 | return BlockBuild::StorageGet(StorageGet(inner, shared)); | 281 | | } | 282 | | ( | 283 | 1.86k | Inner::Runtime(runtime_call::RuntimeCall::ClosestDescendantMerkleValue(inner)), | 284 | | _, | 285 | | ) => { | 286 | 1.86k | return BlockBuild::ClosestDescendantMerkleValue(ClosestDescendantMerkleValue( | 287 | 1.86k | inner, shared, | 288 | 1.86k | )); | 289 | | } | 290 | 2.19k | (Inner::Runtime(runtime_call::RuntimeCall::NextKey(inner)), _) => { | 291 | 2.19k | return BlockBuild::NextKey(NextKey(inner, shared)); | 292 | | } | 293 | 0 | (Inner::Runtime(runtime_call::RuntimeCall::OffchainStorageSet(inner)), _) => { | 294 | 0 | return BlockBuild::OffchainStorageSet(OffchainStorageSet(inner, shared)); | 295 | | } | 296 | | | 297 | | ( | 298 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), | 299 | | Stage::InitializeBlock, | 300 | | ) => { | 301 | 1 | if !success.virtual_machine.value().as_ref().is_empty() { | 302 | 0 | return BlockBuild::Finished(Err(( | 303 | 0 | Error::InitializeBlockNonEmptyOutput, | 304 | 0 | success.virtual_machine.into_prototype(), | 305 | 0 | ))); | 306 | 1 | } | 307 | | | 308 | 1 | shared.stage = Stage::InherentExtrinsics; | 309 | | | 310 | 1 | return BlockBuild::InherentExtrinsics(InherentExtrinsics { | 311 | 1 | shared, | 312 | 1 | parent_runtime: success.virtual_machine.into_prototype(), | 313 | 1 | storage_changes: success.storage_changes, | 314 | 1 | }); | 315 | | } | 316 | | | 317 | | ( | 318 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), | 319 | | Stage::InherentExtrinsics, | 320 | | ) => { | 321 | 1 | let parse_result = | 322 | 1 | parse_inherent_extrinsics_output(success.virtual_machine.value().as_ref()); | 323 | 1 | let extrinsics = match parse_result { | 324 | 1 | Ok(extrinsics) => extrinsics, | 325 | 0 | Err(err) => { | 326 | 0 | return BlockBuild::Finished(Err(( | 327 | 0 | err, | 328 | 0 | success.virtual_machine.into_prototype(), | 329 | 0 | ))); | 330 | | } | 331 | | }; | 332 | | | 333 | 1 | shared.block_body.reserve(extrinsics.len()); | 334 | 1 | shared.stage = Stage::ApplyInherentExtrinsic { extrinsics }; | 335 | 1 | inner = Inner::Transition(success); | 336 | | } | 337 | | | 338 | 2 | (Inner::Transition(success1 ), Stage::ApplyInherentExtrinsic { extrinsics }) | 339 | 2 | if !extrinsics.is_empty()1 => | 340 | | { | 341 | 1 | let extrinsic = &extrinsics[0]; | 342 | | | 343 | 1 | let init_result = runtime_call::run(runtime_call::Config { | 344 | 1 | virtual_machine: success.virtual_machine.into_prototype(), | 345 | 1 | function_to_call: "BlockBuilder_apply_extrinsic", | 346 | 1 | parameter: iter::once(extrinsic), | 347 | 1 | storage_main_trie_changes: success.storage_changes.into_main_trie_diff(), | 348 | 1 | storage_proof_size_behavior: | 349 | 1 | runtime_call::StorageProofSizeBehavior::Unimplemented, | 350 | 1 | max_log_level: shared.max_log_level, | 351 | 1 | calculate_trie_changes: shared.calculate_trie_changes, | 352 | 1 | }); | 353 | | | 354 | 1 | inner = Inner::Runtime(match init_result { | 355 | 1 | Ok(vm) => vm, | 356 | 0 | Err((err, proto)) => { | 357 | 0 | return BlockBuild::Finished(Err((Error::VmInit(err), proto))); | 358 | | } | 359 | | }); | 360 | | } | 361 | | | 362 | 1 | (Inner::Transition(success), Stage::ApplyInherentExtrinsic { .. }) => { | 363 | 1 | return BlockBuild::ApplyExtrinsic(ApplyExtrinsic { | 364 | 1 | shared, | 365 | 1 | parent_runtime: success.virtual_machine.into_prototype(), | 366 | 1 | storage_changes: success.storage_changes, | 367 | 1 | }); | 368 | | } | 369 | | | 370 | | ( | 371 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), | 372 | | Stage::ApplyInherentExtrinsic { .. }, | 373 | | ) => { | 374 | 1 | let (extrinsic, new_stage) = match shared.stage { | 375 | 1 | Stage::ApplyInherentExtrinsic { mut extrinsics } => { | 376 | 1 | let extrinsic = extrinsics.remove(0); | 377 | 1 | (extrinsic, Stage::ApplyInherentExtrinsic { extrinsics }) | 378 | | } | 379 | 0 | _ => unreachable!(), | 380 | | }; | 381 | | | 382 | 1 | shared.stage = new_stage; | 383 | | | 384 | 1 | let parse_result = | 385 | 1 | parse_apply_extrinsic_output(success.virtual_machine.value().as_ref()); | 386 | 1 | match parse_result { | 387 | 1 | Ok(Ok(Ok(()))) => {} | 388 | 0 | Ok(Ok(Err(error))) => { | 389 | 0 | return BlockBuild::Finished(Err(( | 390 | 0 | Error::InherentExtrinsicDispatchError { extrinsic, error }, | 391 | 0 | success.virtual_machine.into_prototype(), | 392 | 0 | ))); | 393 | | } | 394 | 0 | Ok(Err(error)) => { | 395 | 0 | return BlockBuild::Finished(Err(( | 396 | 0 | Error::InherentExtrinsicTransactionValidityError { | 397 | 0 | extrinsic, | 398 | 0 | error, | 399 | 0 | }, | 400 | 0 | success.virtual_machine.into_prototype(), | 401 | 0 | ))); | 402 | | } | 403 | 0 | Err(err) => { | 404 | 0 | return BlockBuild::Finished(Err(( | 405 | 0 | err, | 406 | 0 | success.virtual_machine.into_prototype(), | 407 | 0 | ))); | 408 | | } | 409 | | } | 410 | | | 411 | 1 | shared.block_body.push(extrinsic); | 412 | | | 413 | 1 | inner = Inner::Transition(success); | 414 | | } | 415 | | | 416 | | ( | 417 | 0 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), | 418 | | Stage::ApplyExtrinsic(_), | 419 | | ) => { | 420 | 0 | let parse_result = | 421 | 0 | parse_apply_extrinsic_output(success.virtual_machine.value().as_ref()); | 422 | 0 | let result = match parse_result { | 423 | 0 | Ok(r) => r, | 424 | 0 | Err(err) => { | 425 | 0 | return BlockBuild::Finished(Err(( | 426 | 0 | err, | 427 | 0 | success.virtual_machine.into_prototype(), | 428 | 0 | ))); | 429 | | } | 430 | | }; | 431 | | | 432 | 0 | if result.is_ok() { | 433 | 0 | shared.block_body.push(match &mut shared.stage { | 434 | 0 | Stage::ApplyExtrinsic(ext) => mem::take(ext), | 435 | 0 | _ => unreachable!(), | 436 | | }); | 437 | 0 | } | 438 | | | 439 | | // TODO: consider giving back extrinsic to user in case of failure | 440 | | | 441 | | // TODO: IMPORTANT /!\ must throw away storage changes in case of error | 442 | | | 443 | 0 | return BlockBuild::ApplyExtrinsicResult { | 444 | 0 | result, | 445 | 0 | resume: ApplyExtrinsic { | 446 | 0 | shared, | 447 | 0 | parent_runtime: success.virtual_machine.into_prototype(), | 448 | 0 | storage_changes: success.storage_changes, | 449 | 0 | }, | 450 | 0 | }; | 451 | | } | 452 | | | 453 | | ( | 454 | 1 | Inner::Runtime(runtime_call::RuntimeCall::Finished(Ok(success))), | 455 | | Stage::FinalizeBlock, | 456 | | ) => { | 457 | 1 | let scale_encoded_header = success.virtual_machine.value().as_ref().to_owned(); | 458 | 1 | return BlockBuild::Finished(Ok(Success { | 459 | 1 | scale_encoded_header, | 460 | 1 | body: shared.block_body, | 461 | 1 | parent_runtime: success.virtual_machine.into_prototype(), | 462 | 1 | storage_changes: success.storage_changes, | 463 | 1 | state_trie_version: success.state_trie_version, | 464 | 1 | })); | 465 | | } | 466 | | | 467 | | // TODO: what about SignatureVerification and EmitLog? at the time of writing of this comment, it's not worth fixing as this code would get removed by <https://github.com/smol-dot/smoldot/issues/1517> | 468 | 0 | (_, s) => unreachable!("{:?}", s), | 469 | | } | 470 | | } | 471 | 4.20k | } |
Unexecuted instantiation: _RNvMNtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB2_10BlockBuild10from_inner |
472 | | } |
473 | | |
474 | | /// Extra information maintained in parallel of the [`runtime_call::RuntimeCall`]. |
475 | | #[derive(Debug)] |
476 | | struct Shared { |
477 | | /// The block building process is separated into multiple stages. |
478 | | stage: Stage, |
479 | | /// Body of the block under construction. Items are added as construction progresses. |
480 | | block_body: Vec<Vec<u8>>, |
481 | | /// Value provided by [`Config::max_log_level`]. |
482 | | max_log_level: u32, |
483 | | /// Value provided by [`Config::calculate_trie_changes`]. |
484 | | calculate_trie_changes: bool, |
485 | | } |
486 | | |
487 | | /// The block building process is separated into multiple stages. |
488 | | #[derive(Debug, Clone)] |
489 | | enum Stage { |
490 | | InitializeBlock, |
491 | | InherentExtrinsics, |
492 | | ApplyInherentExtrinsic { |
493 | | /// List of inherent extrinsics being applied, including the one currently being applied. |
494 | | /// This list should thus never be empty. |
495 | | extrinsics: Vec<Vec<u8>>, |
496 | | }, |
497 | | ApplyExtrinsic(Vec<u8>), |
498 | | FinalizeBlock, |
499 | | } |
500 | | |
501 | | /// The list of inherent extrinsics are needed in order to continue. |
502 | | #[must_use] |
503 | | pub struct InherentExtrinsics { |
504 | | shared: Shared, |
505 | | parent_runtime: host::HostVmPrototype, |
506 | | storage_changes: StorageChanges, |
507 | | } |
508 | | |
509 | | impl InherentExtrinsics { |
510 | | /// Injects the inherents extrinsics and resumes execution. |
511 | | /// |
512 | | /// See the module-level documentation for more information. |
513 | 1 | pub fn inject_inherents(self, inherents: inherents::InherentData) -> BlockBuild { |
514 | 1 | self.inject_raw_inherents_list(inherents.as_raw_list()) |
515 | 1 | } _RNvMs_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB4_18InherentExtrinsics16inject_inherents Line | Count | Source | 513 | 1 | pub fn inject_inherents(self, inherents: inherents::InherentData) -> BlockBuild { | 514 | 1 | self.inject_raw_inherents_list(inherents.as_raw_list()) | 515 | 1 | } |
Unexecuted instantiation: _RNvMs_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB4_18InherentExtrinsics16inject_inherents |
516 | | |
517 | | /// Injects a raw list of inherents and resumes execution. |
518 | | /// |
519 | | /// This method is a more weakly-typed equivalent to [`InherentExtrinsics::inject_inherents`]. |
520 | | /// Only use this method if you know what you're doing. |
521 | 1 | pub fn inject_raw_inherents_list( |
522 | 1 | self, |
523 | 1 | list: impl ExactSizeIterator<Item = ([u8; 8], impl AsRef<[u8]> + Clone)> + Clone, |
524 | 1 | ) -> BlockBuild { |
525 | 1 | debug_assert!(matches!0 (self.shared.stage, Stage::InherentExtrinsics)); |
526 | | |
527 | 1 | let init_result = runtime_call::run(runtime_call::Config { |
528 | 1 | virtual_machine: self.parent_runtime, |
529 | 1 | function_to_call: "BlockBuilder_inherent_extrinsics", |
530 | | parameter: { |
531 | | // The `BlockBuilder_inherent_extrinsics` function expects a SCALE-encoded list of |
532 | | // tuples containing an "inherent identifier" (`[u8; 8]`) and a value (`Vec<u8>`). |
533 | 1 | let len = util::encode_scale_compact_usize(list.len()); |
534 | 2 | let encoded_list1 = list1 .flat_map1 (|(id, value)| { |
535 | 2 | let value_len = util::encode_scale_compact_usize(value.as_ref().len()); |
536 | 2 | let value_and_len = iter::once(value_len) |
537 | 2 | .map(either::Left) |
538 | 2 | .chain(iter::once(value).map(either::Right)); |
539 | 2 | iter::once(id) |
540 | 2 | .map(either::Left) |
541 | 2 | .chain(value_and_len.map(either::Right)) |
542 | 2 | }); _RNCINvMs_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB7_18InherentExtrinsics25inject_raw_inherents_listAhj8_INtNtNtCs1p5UDGgVI4d_4core5array4iter8IntoIterTB1C_B1C_EKj1_EE0Bb_ Line | Count | Source | 534 | 2 | let encoded_list = list.flat_map(|(id, value)| { | 535 | 2 | let value_len = util::encode_scale_compact_usize(value.as_ref().len()); | 536 | 2 | let value_and_len = iter::once(value_len) | 537 | 2 | .map(either::Left) | 538 | 2 | .chain(iter::once(value).map(either::Right)); | 539 | 2 | iter::once(id) | 540 | 2 | .map(either::Left) | 541 | 2 | .chain(value_and_len.map(either::Right)) | 542 | 2 | }); |
Unexecuted instantiation: _RNCINvMs_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB7_18InherentExtrinsics25inject_raw_inherents_listAhj8_INtNtNtCs1p5UDGgVI4d_4core5array4iter8IntoIterTB1C_B1C_EKj1_EE0Bb_ |
543 | | |
544 | 1 | iter::once(len) |
545 | 1 | .map(either::Left) |
546 | 1 | .chain(encoded_list.map(either::Right)) |
547 | | }, |
548 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, |
549 | 1 | storage_main_trie_changes: self.storage_changes.into_main_trie_diff(), |
550 | 1 | max_log_level: self.shared.max_log_level, |
551 | 1 | calculate_trie_changes: self.shared.calculate_trie_changes, |
552 | | }); |
553 | | |
554 | 1 | let vm = match init_result { |
555 | 1 | Ok(vm) => vm, |
556 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), |
557 | | }; |
558 | | |
559 | 1 | BlockBuild::from_inner(vm, self.shared) |
560 | 1 | } _RINvMs_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_18InherentExtrinsics25inject_raw_inherents_listAhj8_INtNtNtCs1p5UDGgVI4d_4core5array4iter8IntoIterTB1A_B1A_EKj1_EEB9_ Line | Count | Source | 521 | 1 | pub fn inject_raw_inherents_list( | 522 | 1 | self, | 523 | 1 | list: impl ExactSizeIterator<Item = ([u8; 8], impl AsRef<[u8]> + Clone)> + Clone, | 524 | 1 | ) -> BlockBuild { | 525 | 1 | debug_assert!(matches!0 (self.shared.stage, Stage::InherentExtrinsics)); | 526 | | | 527 | 1 | let init_result = runtime_call::run(runtime_call::Config { | 528 | 1 | virtual_machine: self.parent_runtime, | 529 | 1 | function_to_call: "BlockBuilder_inherent_extrinsics", | 530 | | parameter: { | 531 | | // The `BlockBuilder_inherent_extrinsics` function expects a SCALE-encoded list of | 532 | | // tuples containing an "inherent identifier" (`[u8; 8]`) and a value (`Vec<u8>`). | 533 | 1 | let len = util::encode_scale_compact_usize(list.len()); | 534 | 1 | let encoded_list = list.flat_map(|(id, value)| { | 535 | | let value_len = util::encode_scale_compact_usize(value.as_ref().len()); | 536 | | let value_and_len = iter::once(value_len) | 537 | | .map(either::Left) | 538 | | .chain(iter::once(value).map(either::Right)); | 539 | | iter::once(id) | 540 | | .map(either::Left) | 541 | | .chain(value_and_len.map(either::Right)) | 542 | | }); | 543 | | | 544 | 1 | iter::once(len) | 545 | 1 | .map(either::Left) | 546 | 1 | .chain(encoded_list.map(either::Right)) | 547 | | }, | 548 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, | 549 | 1 | storage_main_trie_changes: self.storage_changes.into_main_trie_diff(), | 550 | 1 | max_log_level: self.shared.max_log_level, | 551 | 1 | calculate_trie_changes: self.shared.calculate_trie_changes, | 552 | | }); | 553 | | | 554 | 1 | let vm = match init_result { | 555 | 1 | Ok(vm) => vm, | 556 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), | 557 | | }; | 558 | | | 559 | 1 | BlockBuild::from_inner(vm, self.shared) | 560 | 1 | } |
Unexecuted instantiation: _RINvMs_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_18InherentExtrinsics25inject_raw_inherents_listAhj8_INtNtNtCs1p5UDGgVI4d_4core5array4iter8IntoIterTB1A_B1A_EKj1_EEB9_ |
561 | | } |
562 | | |
563 | | /// More transactions can be added. |
564 | | #[must_use] |
565 | | pub struct ApplyExtrinsic { |
566 | | shared: Shared, |
567 | | parent_runtime: host::HostVmPrototype, |
568 | | storage_changes: StorageChanges, |
569 | | } |
570 | | |
571 | | impl ApplyExtrinsic { |
572 | | /// Adds a SCALE-encoded extrinsic and resumes execution. |
573 | | /// |
574 | | /// See the module-level documentation for more information. |
575 | 0 | pub fn add_extrinsic(mut self, extrinsic: Vec<u8>) -> BlockBuild { |
576 | 0 | let init_result = runtime_call::run(runtime_call::Config { |
577 | 0 | virtual_machine: self.parent_runtime, |
578 | 0 | function_to_call: "BlockBuilder_apply_extrinsic", |
579 | 0 | parameter: iter::once(&extrinsic), |
580 | 0 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, |
581 | 0 | storage_main_trie_changes: self.storage_changes.into_main_trie_diff(), |
582 | 0 | max_log_level: self.shared.max_log_level, |
583 | 0 | calculate_trie_changes: self.shared.calculate_trie_changes, |
584 | 0 | }); |
585 | | |
586 | 0 | self.shared.stage = Stage::ApplyExtrinsic(extrinsic); |
587 | | |
588 | 0 | let vm = match init_result { |
589 | 0 | Ok(vm) => vm, |
590 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), |
591 | | }; |
592 | | |
593 | 0 | BlockBuild::from_inner(vm, self.shared) |
594 | 0 | } Unexecuted instantiation: _RNvMs0_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_14ApplyExtrinsic13add_extrinsic Unexecuted instantiation: _RNvMs0_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_14ApplyExtrinsic13add_extrinsic |
595 | | |
596 | | /// Indicate that no more extrinsics will be added, and resume execution. |
597 | 1 | pub fn finish(mut self) -> BlockBuild { |
598 | 1 | self.shared.stage = Stage::FinalizeBlock; |
599 | | |
600 | 1 | let init_result = runtime_call::run(runtime_call::Config { |
601 | 1 | virtual_machine: self.parent_runtime, |
602 | 1 | function_to_call: "BlockBuilder_finalize_block", |
603 | 1 | parameter: iter::empty::<&[u8]>(), |
604 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, |
605 | 1 | storage_main_trie_changes: self.storage_changes.into_main_trie_diff(), |
606 | 1 | max_log_level: self.shared.max_log_level, |
607 | 1 | calculate_trie_changes: self.shared.calculate_trie_changes, |
608 | 1 | }); |
609 | | |
610 | 1 | let vm = match init_result { |
611 | 1 | Ok(vm) => vm, |
612 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), |
613 | | }; |
614 | | |
615 | 1 | BlockBuild::from_inner(vm, self.shared) |
616 | 1 | } _RNvMs0_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_14ApplyExtrinsic6finish Line | Count | Source | 597 | 1 | pub fn finish(mut self) -> BlockBuild { | 598 | 1 | self.shared.stage = Stage::FinalizeBlock; | 599 | | | 600 | 1 | let init_result = runtime_call::run(runtime_call::Config { | 601 | 1 | virtual_machine: self.parent_runtime, | 602 | 1 | function_to_call: "BlockBuilder_finalize_block", | 603 | 1 | parameter: iter::empty::<&[u8]>(), | 604 | 1 | storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented, | 605 | 1 | storage_main_trie_changes: self.storage_changes.into_main_trie_diff(), | 606 | 1 | max_log_level: self.shared.max_log_level, | 607 | 1 | calculate_trie_changes: self.shared.calculate_trie_changes, | 608 | 1 | }); | 609 | | | 610 | 1 | let vm = match init_result { | 611 | 1 | Ok(vm) => vm, | 612 | 0 | Err((err, proto)) => return BlockBuild::Finished(Err((Error::VmInit(err), proto))), | 613 | | }; | 614 | | | 615 | 1 | BlockBuild::from_inner(vm, self.shared) | 616 | 1 | } |
Unexecuted instantiation: _RNvMs0_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_14ApplyExtrinsic6finish |
617 | | } |
618 | | |
619 | | /// Loading a storage value from the parent storage is required in order to continue. |
620 | | #[must_use] |
621 | | pub struct StorageGet(runtime_call::StorageGet, Shared); |
622 | | |
623 | | impl StorageGet { |
624 | | /// Returns the key whose value must be passed to [`StorageGet::inject_value`]. |
625 | 8.72k | pub fn key(&self) -> impl AsRef<[u8]> { |
626 | 8.72k | self.0.key() |
627 | 8.72k | } _RNvMs1_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_10StorageGet3key Line | Count | Source | 625 | 8.72k | pub fn key(&self) -> impl AsRef<[u8]> { | 626 | 8.72k | self.0.key() | 627 | 8.72k | } |
Unexecuted instantiation: _RNvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_10StorageGet3key |
628 | | |
629 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
630 | 0 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
631 | 0 | self.0.child_trie() |
632 | 0 | } Unexecuted instantiation: _RNvMs1_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_10StorageGet10child_trie Unexecuted instantiation: _RNvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_10StorageGet10child_trie |
633 | | |
634 | | /// Injects the corresponding storage value. |
635 | 146 | pub fn inject_value( |
636 | 146 | self, |
637 | 146 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, |
638 | 146 | ) -> BlockBuild { |
639 | 146 | BlockBuild::from_inner(self.0.inject_value(value), self.1) |
640 | 146 | } _RINvMs1_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1g_EEBa_ Line | Count | Source | 635 | 146 | pub fn inject_value( | 636 | 146 | self, | 637 | 146 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>, | 638 | 146 | ) -> BlockBuild { | 639 | 146 | BlockBuild::from_inner(self.0.inject_value(value), self.1) | 640 | 146 | } |
Unexecuted instantiation: _RINvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1g_EECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_10StorageGet12inject_valueppEBa_ Unexecuted instantiation: _RINvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1g_EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs1_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_10StorageGet12inject_valueRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1g_EECs4VrkfB1pvQ3_25json_rpc_general_requests |
641 | | } |
642 | | |
643 | | /// Obtaining the Merkle value of the closest descendant of a trie node is required in order |
644 | | /// to continue. |
645 | | #[must_use] |
646 | | pub struct ClosestDescendantMerkleValue(runtime_call::ClosestDescendantMerkleValue, Shared); |
647 | | |
648 | | impl ClosestDescendantMerkleValue { |
649 | | /// Returns the key whose closest descendant Merkle value must be passed to |
650 | | /// [`ClosestDescendantMerkleValue::inject_merkle_value`]. |
651 | 0 | pub fn key(&self) -> impl Iterator<Item = Nibble> { |
652 | 0 | self.0.key() |
653 | 0 | } Unexecuted instantiation: _RNvMs2_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue3key Unexecuted instantiation: _RNvMs2_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue3key |
654 | | |
655 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
656 | 0 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
657 | 0 | self.0.child_trie() |
658 | 0 | } Unexecuted instantiation: _RNvMs2_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue10child_trie Unexecuted instantiation: _RNvMs2_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue10child_trie |
659 | | |
660 | | /// Indicate that the value is unknown and resume the calculation. |
661 | | /// |
662 | | /// This function be used if you are unaware of the Merkle value. The algorithm will perform |
663 | | /// the calculation of this Merkle value manually, which takes more time. |
664 | 1.86k | pub fn resume_unknown(self) -> BlockBuild { |
665 | 1.86k | BlockBuild::from_inner(self.0.resume_unknown(), self.1) |
666 | 1.86k | } _RNvMs2_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue14resume_unknown Line | Count | Source | 664 | 1.86k | pub fn resume_unknown(self) -> BlockBuild { | 665 | 1.86k | BlockBuild::from_inner(self.0.resume_unknown(), self.1) | 666 | 1.86k | } |
Unexecuted instantiation: _RNvMs2_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue14resume_unknown |
667 | | |
668 | | /// Injects the corresponding Merkle value. |
669 | | /// |
670 | | /// `None` can be passed if there is no descendant or, in the case of a child trie read, in |
671 | | /// order to indicate that the child trie does not exist. |
672 | 0 | pub fn inject_merkle_value(self, merkle_value: Option<&[u8]>) -> BlockBuild { |
673 | 0 | BlockBuild::from_inner(self.0.inject_merkle_value(merkle_value), self.1) |
674 | 0 | } Unexecuted instantiation: _RNvMs2_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue19inject_merkle_value Unexecuted instantiation: _RNvMs2_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_28ClosestDescendantMerkleValue19inject_merkle_value |
675 | | } |
676 | | |
677 | | /// Fetching the key that follows a given one in the parent storage is required in order to |
678 | | /// continue. |
679 | | #[must_use] |
680 | | pub struct NextKey(runtime_call::NextKey, Shared); |
681 | | |
682 | | impl NextKey { |
683 | | /// Returns the key whose next key must be passed back. |
684 | 2.19k | pub fn key(&self) -> impl Iterator<Item = Nibble> { |
685 | 2.19k | self.0.key() |
686 | 2.19k | } _RNvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_7NextKey3key Line | Count | Source | 684 | 2.19k | pub fn key(&self) -> impl Iterator<Item = Nibble> { | 685 | 2.19k | self.0.key() | 686 | 2.19k | } |
Unexecuted instantiation: _RNvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_7NextKey3key |
687 | | |
688 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
689 | 0 | pub fn child_trie(&self) -> Option<impl AsRef<[u8]>> { |
690 | 0 | self.0.child_trie() |
691 | 0 | } Unexecuted instantiation: _RNvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_7NextKey10child_trie Unexecuted instantiation: _RNvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_7NextKey10child_trie |
692 | | |
693 | | /// If `true`, then the provided value must the one superior or equal to the requested key. |
694 | | /// If `false`, then the provided value must be strictly superior to the requested key. |
695 | 2.19k | pub fn or_equal(&self) -> bool { |
696 | 2.19k | self.0.or_equal() |
697 | 2.19k | } _RNvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_7NextKey8or_equal Line | Count | Source | 695 | 2.19k | pub fn or_equal(&self) -> bool { | 696 | 2.19k | self.0.or_equal() | 697 | 2.19k | } |
Unexecuted instantiation: _RNvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_7NextKey8or_equal |
698 | | |
699 | | /// If `true`, then the search must include both branch nodes and storage nodes. If `false`, |
700 | | /// the search only covers storage nodes. |
701 | 2.19k | pub fn branch_nodes(&self) -> bool { |
702 | 2.19k | self.0.branch_nodes() |
703 | 2.19k | } _RNvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_7NextKey12branch_nodes Line | Count | Source | 701 | 2.19k | pub fn branch_nodes(&self) -> bool { | 702 | 2.19k | self.0.branch_nodes() | 703 | 2.19k | } |
Unexecuted instantiation: _RNvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_7NextKey12branch_nodes |
704 | | |
705 | | /// Returns the prefix the next key must start with. If the next key doesn't start with the |
706 | | /// given prefix, then `None` should be provided. |
707 | 2.19k | pub fn prefix(&self) -> impl Iterator<Item = Nibble> { |
708 | 2.19k | self.0.prefix() |
709 | 2.19k | } _RNvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_7NextKey6prefix Line | Count | Source | 707 | 2.19k | pub fn prefix(&self) -> impl Iterator<Item = Nibble> { | 708 | 2.19k | self.0.prefix() | 709 | 2.19k | } |
Unexecuted instantiation: _RNvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_7NextKey6prefix |
710 | | |
711 | | /// Injects the key. |
712 | | /// |
713 | | /// # Panic |
714 | | /// |
715 | | /// Panics if the key passed as parameter isn't strictly superior to the requested key. |
716 | | /// |
717 | 2.19k | pub fn inject_key(self, key: Option<impl Iterator<Item = Nibble>>) -> BlockBuild { |
718 | 2.19k | BlockBuild::from_inner(self.0.inject_key(key), self.1) |
719 | 2.19k | } _RINvMs3_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB6_7NextKey10inject_keyNtNtNtBa_4trie13branch_search21BranchTrieNodeKeyIterEBa_ Line | Count | Source | 717 | 2.19k | pub fn inject_key(self, key: Option<impl Iterator<Item = Nibble>>) -> BlockBuild { | 718 | 2.19k | BlockBuild::from_inner(self.0.inject_key(key), self.1) | 719 | 2.19k | } |
Unexecuted instantiation: _RINvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB2Z_14SyncBackground12author_block0s6_00EECscoAnRPySggw_6author Unexecuted instantiation: _RINvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_7NextKey10inject_keypEBa_ Unexecuted instantiation: _RINvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB2Z_14SyncBackground12author_block0s6_00EECsjyNE3yDMkgA_14json_rpc_basic Unexecuted instantiation: _RINvMs3_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB6_7NextKey10inject_keyINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters3map3MapINtNtNtCsaFPxhswmqCN_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsfFWJyR6nd6r_17smoldot_full_node17consensus_serviceNtB2Z_14SyncBackground12author_block0s6_00EECs4VrkfB1pvQ3_25json_rpc_general_requests |
720 | | } |
721 | | |
722 | | /// Setting the value of an offchain storage value is required. |
723 | | #[must_use] |
724 | | pub struct OffchainStorageSet(runtime_call::OffchainStorageSet, Shared); |
725 | | |
726 | | impl OffchainStorageSet { |
727 | | /// Returns the key whose value must be set. |
728 | 0 | pub fn key(&self) -> impl AsRef<[u8]> { |
729 | 0 | self.0.key() |
730 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_18OffchainStorageSet3key Unexecuted instantiation: _RNvMs4_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_18OffchainStorageSet3key |
731 | | |
732 | | /// Returns the value to set. |
733 | | /// |
734 | | /// If `None` is returned, the key should be removed from the storage entirely. |
735 | 0 | pub fn value(&self) -> Option<impl AsRef<[u8]>> { |
736 | 0 | self.0.value() |
737 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_18OffchainStorageSet5value Unexecuted instantiation: _RNvMs4_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_18OffchainStorageSet5value |
738 | | |
739 | | /// Resumes execution after having set the value. |
740 | 0 | pub fn resume(self) -> BlockBuild { |
741 | 0 | BlockBuild::from_inner(self.0.resume(), self.1) |
742 | 0 | } Unexecuted instantiation: _RNvMs4_NtNtCsjlkOsLH0Zfj_7smoldot6author7runtimeNtB5_18OffchainStorageSet6resume Unexecuted instantiation: _RNvMs4_NtNtCsc1ywvx6YAnK_7smoldot6author7runtimeNtB5_18OffchainStorageSet6resume |
743 | | } |
744 | | |
745 | | /// Analyzes the output of a call to `BlockBuilder_inherent_extrinsics`, and returns the resulting |
746 | | /// extrinsics. |
747 | | // TODO: this method implementation is hacky ; the `BlockBuilder_inherent_extrinsics` function |
748 | | // returns a `Vec<Extrinsic>`, where `Extrinsic` is opaque and depends on the chain. Because |
749 | | // we don't know the type of `Extrinsic`, a `Vec<Extrinsic>` is undecodable. However, most |
750 | | // Substrate chains use `type Extrinsic = OpaqueExtrinsic;` where |
751 | | // `type OpaqueExtrinsic = Vec<u8>;` here, which happens to start with a length prefix |
752 | | // containing its remaining size; this length prefix is fully part of the `Extrinsic` though. |
753 | | // In other words, this function might succeed or fail depending on the Substrate chain. |
754 | 1 | fn parse_inherent_extrinsics_output(output: &[u8]) -> Result<Vec<Vec<u8>>, Error> { |
755 | 1 | nom::Parser::parse( |
756 | 1 | &mut nom::combinator::all_consuming(nom::combinator::flat_map( |
757 | | crate::util::nom_scale_compact_usize, |
758 | 1 | |num_elems| { |
759 | 1 | nom::multi::many_m_n( |
760 | 1 | num_elems, |
761 | 1 | num_elems, |
762 | 1 | nom::combinator::map( |
763 | 1 | nom::combinator::recognize(nom::combinator::flat_map( |
764 | | crate::util::nom_scale_compact_usize, |
765 | | nom::bytes::streaming::take, |
766 | | )), |
767 | 1 | |v: &[u8]| v.to_vec(), _RNCNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime32parse_inherent_extrinsics_output00B9_ Line | Count | Source | 767 | 1 | |v: &[u8]| v.to_vec(), |
Unexecuted instantiation: _RNCNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime32parse_inherent_extrinsics_output00B9_ |
768 | | ), |
769 | | ) |
770 | 1 | }, _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime32parse_inherent_extrinsics_output0B7_ Line | Count | Source | 758 | 1 | |num_elems| { | 759 | 1 | nom::multi::many_m_n( | 760 | 1 | num_elems, | 761 | 1 | num_elems, | 762 | 1 | nom::combinator::map( | 763 | 1 | nom::combinator::recognize(nom::combinator::flat_map( | 764 | | crate::util::nom_scale_compact_usize, | 765 | | nom::bytes::streaming::take, | 766 | | )), | 767 | | |v: &[u8]| v.to_vec(), | 768 | | ), | 769 | | ) | 770 | 1 | }, |
Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime32parse_inherent_extrinsics_output0B7_ |
771 | | )), |
772 | 1 | output, |
773 | | ) |
774 | 1 | .map(|(_, parse_result)| parse_result) |
775 | 1 | .map_err(|_: nom::Err<(&[u8], nom::error::ErrorKind)>| Error::BadInherentExtrinsicsOutput) |
776 | 1 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime32parse_inherent_extrinsics_output Line | Count | Source | 754 | 1 | fn parse_inherent_extrinsics_output(output: &[u8]) -> Result<Vec<Vec<u8>>, Error> { | 755 | 1 | nom::Parser::parse( | 756 | 1 | &mut nom::combinator::all_consuming(nom::combinator::flat_map( | 757 | | crate::util::nom_scale_compact_usize, | 758 | | |num_elems| { | 759 | | nom::multi::many_m_n( | 760 | | num_elems, | 761 | | num_elems, | 762 | | nom::combinator::map( | 763 | | nom::combinator::recognize(nom::combinator::flat_map( | 764 | | crate::util::nom_scale_compact_usize, | 765 | | nom::bytes::streaming::take, | 766 | | )), | 767 | | |v: &[u8]| v.to_vec(), | 768 | | ), | 769 | | ) | 770 | | }, | 771 | | )), | 772 | 1 | output, | 773 | | ) | 774 | 1 | .map(|(_, parse_result)| parse_result) | 775 | 1 | .map_err(|_: nom::Err<(&[u8], nom::error::ErrorKind)>| Error::BadInherentExtrinsicsOutput) | 776 | 1 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime32parse_inherent_extrinsics_output |
777 | | |
778 | | /// Analyzes the output of a call to `BlockBuilder_apply_extrinsic`. |
779 | 1 | fn parse_apply_extrinsic_output( |
780 | 1 | output: &[u8], |
781 | 1 | ) -> Result<Result<Result<(), DispatchError>, TransactionValidityError>, Error> { |
782 | 1 | nom::Parser::parse( |
783 | 1 | &mut nom::combinator::all_consuming(apply_extrinsic_result), |
784 | 1 | output, |
785 | | ) |
786 | 1 | .map(|(_, parse_result)| parse_result) |
787 | 1 | .map_err(|_: nom::Err<nom::error::Error<&[u8]>>| Error::BadApplyExtrinsicOutput) |
788 | 1 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime28parse_apply_extrinsic_output Line | Count | Source | 779 | 1 | fn parse_apply_extrinsic_output( | 780 | 1 | output: &[u8], | 781 | 1 | ) -> Result<Result<Result<(), DispatchError>, TransactionValidityError>, Error> { | 782 | 1 | nom::Parser::parse( | 783 | 1 | &mut nom::combinator::all_consuming(apply_extrinsic_result), | 784 | 1 | output, | 785 | | ) | 786 | 1 | .map(|(_, parse_result)| parse_result) | 787 | 1 | .map_err(|_: nom::Err<nom::error::Error<&[u8]>>| Error::BadApplyExtrinsicOutput) | 788 | 1 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime28parse_apply_extrinsic_output |
789 | | |
790 | | // TODO: some parsers below are common with the tx-pool ; figure out how/whether they should be merged |
791 | | |
792 | | /// Errors that can occur while checking the validity of a transaction. |
793 | | #[derive(Debug, derive_more::Display, derive_more::Error, Clone, PartialEq, Eq)] |
794 | | pub enum TransactionValidityError { |
795 | | /// The transaction is invalid. |
796 | | #[display("Transaction is invalid: {_0}")] |
797 | | Invalid(InvalidTransaction), |
798 | | /// Transaction validity can't be determined. |
799 | | #[display("Transaction validity couldn't be determined: {_0}")] |
800 | | Unknown(UnknownTransaction), |
801 | | } |
802 | | |
803 | | /// An invalid transaction validity. |
804 | | #[derive(Debug, derive_more::Display, derive_more::Error, Clone, PartialEq, Eq)] |
805 | | pub enum InvalidTransaction { |
806 | | /// The call of the transaction is not expected. |
807 | | Call, |
808 | | /// General error to do with the inability to pay some fees (e.g. account balance too low). |
809 | | Payment, |
810 | | /// General error to do with the transaction not yet being valid (e.g. nonce too high). |
811 | | Future, |
812 | | /// General error to do with the transaction being outdated (e.g. nonce too low). |
813 | | Stale, |
814 | | /// General error to do with the transaction's proofs (e.g. signature). |
815 | | /// |
816 | | /// # Possible causes |
817 | | /// |
818 | | /// When using a signed extension that provides additional data for signing, it is required |
819 | | /// that the signing and the verifying side use the same additional data. Additional |
820 | | /// data will only be used to generate the signature, but will not be part of the transaction |
821 | | /// itself. As the verifying side does not know which additional data was used while signing |
822 | | /// it will only be able to assume a bad signature and cannot express a more meaningful error. |
823 | | BadProof, |
824 | | /// The transaction birth block is ancient. |
825 | | AncientBirthBlock, |
826 | | /// The transaction would exhaust the resources of current block. |
827 | | /// |
828 | | /// The transaction might be valid, but there are not enough resources |
829 | | /// left in the current block. |
830 | | ExhaustsResources, |
831 | | /// Any other custom invalid validity that is not covered by this enum. |
832 | | #[display("Other reason (code: {_0})")] |
833 | | Custom(#[error(not(source))] u8), |
834 | | /// An extrinsic with a Mandatory dispatch resulted in Error. This is indicative of either a |
835 | | /// malicious validator or a buggy `provide_inherent`. In any case, it can result in dangerously |
836 | | /// overweight blocks and therefore if found, invalidates the block. |
837 | | BadMandatory, |
838 | | /// A transaction with a mandatory dispatch. This is invalid; only inherent extrinsics are |
839 | | /// allowed to have mandatory dispatches. |
840 | | MandatoryDispatch, |
841 | | } |
842 | | |
843 | | /// An unknown transaction validity. |
844 | | #[derive(Debug, derive_more::Display, derive_more::Error, Clone, PartialEq, Eq)] |
845 | | pub enum UnknownTransaction { |
846 | | /// Could not lookup some information that is required to validate the transaction. |
847 | | CannotLookup, |
848 | | /// No validator found for the given unsigned transaction. |
849 | | NoUnsignedValidator, |
850 | | /// Any other custom unknown validity that is not covered by this enum. |
851 | | #[display("Other reason (code: {_0})")] |
852 | | Custom(#[error(not(source))] u8), |
853 | | } |
854 | | |
855 | | /// Reason why a dispatch call failed. |
856 | | #[derive(Debug, derive_more::Display, derive_more::Error, Clone, PartialEq, Eq)] |
857 | | pub enum DispatchError { |
858 | | /// Failed to lookup some data. |
859 | | CannotLookup, |
860 | | /// A bad origin. |
861 | | BadOrigin, |
862 | | /// A custom error in a module. |
863 | | #[display("Error in module #{index}, error number #{error}")] |
864 | | Module { |
865 | | /// Module index, matching the metadata module index. |
866 | | index: u8, |
867 | | /// Module specific error value. |
868 | | error: u8, |
869 | | }, |
870 | | } |
871 | | |
872 | 1 | fn apply_extrinsic_result( |
873 | 1 | bytes: &[u8], |
874 | 1 | ) -> nom::IResult<&[u8], Result<Result<(), DispatchError>, TransactionValidityError>> { |
875 | 1 | nom::Parser::parse( |
876 | 1 | &mut nom::error::context( |
877 | 1 | "apply extrinsic result", |
878 | 1 | nom::branch::alt(( |
879 | 1 | nom::combinator::map( |
880 | 1 | nom::sequence::preceded(nom::bytes::streaming::tag(&[0][..]), dispatch_outcome), |
881 | 1 | Ok, |
882 | 1 | ), |
883 | 1 | nom::combinator::map( |
884 | 1 | nom::sequence::preceded( |
885 | 1 | nom::bytes::streaming::tag(&[1][..]), |
886 | 1 | transaction_validity_error, |
887 | 1 | ), |
888 | 1 | Err, |
889 | 1 | ), |
890 | 1 | )), |
891 | 1 | ), |
892 | 1 | bytes, |
893 | | ) |
894 | 1 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime22apply_extrinsic_result Line | Count | Source | 872 | 1 | fn apply_extrinsic_result( | 873 | 1 | bytes: &[u8], | 874 | 1 | ) -> nom::IResult<&[u8], Result<Result<(), DispatchError>, TransactionValidityError>> { | 875 | 1 | nom::Parser::parse( | 876 | 1 | &mut nom::error::context( | 877 | 1 | "apply extrinsic result", | 878 | 1 | nom::branch::alt(( | 879 | 1 | nom::combinator::map( | 880 | 1 | nom::sequence::preceded(nom::bytes::streaming::tag(&[0][..]), dispatch_outcome), | 881 | 1 | Ok, | 882 | 1 | ), | 883 | 1 | nom::combinator::map( | 884 | 1 | nom::sequence::preceded( | 885 | 1 | nom::bytes::streaming::tag(&[1][..]), | 886 | 1 | transaction_validity_error, | 887 | 1 | ), | 888 | 1 | Err, | 889 | 1 | ), | 890 | 1 | )), | 891 | 1 | ), | 892 | 1 | bytes, | 893 | | ) | 894 | 1 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime22apply_extrinsic_result |
895 | | |
896 | 1 | fn dispatch_outcome(bytes: &[u8]) -> nom::IResult<&[u8], Result<(), DispatchError>> { |
897 | 1 | nom::Parser::parse( |
898 | 1 | &mut nom::error::context( |
899 | | "dispatch outcome", |
900 | 1 | nom::branch::alt(( |
901 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| Ok(())), _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime16dispatch_outcome0B7_ Line | Count | Source | 901 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| Ok(())), |
Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime16dispatch_outcome0B7_ |
902 | 1 | nom::combinator::map( |
903 | 1 | nom::sequence::preceded(nom::bytes::streaming::tag(&[1][..]), dispatch_error), |
904 | | Err, |
905 | | ), |
906 | | )), |
907 | | ), |
908 | 1 | bytes, |
909 | | ) |
910 | 1 | } _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime16dispatch_outcome Line | Count | Source | 896 | 1 | fn dispatch_outcome(bytes: &[u8]) -> nom::IResult<&[u8], Result<(), DispatchError>> { | 897 | 1 | nom::Parser::parse( | 898 | 1 | &mut nom::error::context( | 899 | | "dispatch outcome", | 900 | 1 | nom::branch::alt(( | 901 | 1 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| Ok(())), | 902 | 1 | nom::combinator::map( | 903 | 1 | nom::sequence::preceded(nom::bytes::streaming::tag(&[1][..]), dispatch_error), | 904 | | Err, | 905 | | ), | 906 | | )), | 907 | | ), | 908 | 1 | bytes, | 909 | | ) | 910 | 1 | } |
Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime16dispatch_outcome |
911 | | |
912 | 0 | fn dispatch_error(bytes: &[u8]) -> nom::IResult<&[u8], DispatchError> { |
913 | 0 | nom::Parser::parse( |
914 | 0 | &mut nom::error::context( |
915 | | "dispatch error", |
916 | 0 | nom::branch::alt(( |
917 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| { |
918 | 0 | DispatchError::CannotLookup |
919 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime14dispatch_error0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime14dispatch_error0B7_ |
920 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[1][..]), |_| { |
921 | 0 | DispatchError::BadOrigin |
922 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime14dispatch_errors_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime14dispatch_errors_0B7_ |
923 | 0 | nom::combinator::map( |
924 | 0 | nom::sequence::preceded( |
925 | 0 | nom::bytes::streaming::tag(&[2][..]), |
926 | 0 | (nom::number::streaming::u8, nom::number::streaming::u8), |
927 | | ), |
928 | 0 | |(index, error)| DispatchError::Module { index, error }, Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime14dispatch_errors0_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime14dispatch_errors0_0B7_ |
929 | | ), |
930 | | )), |
931 | | ), |
932 | 0 | bytes, |
933 | | ) |
934 | 0 | } Unexecuted instantiation: _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime14dispatch_error Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime14dispatch_error |
935 | | |
936 | 0 | fn transaction_validity_error(bytes: &[u8]) -> nom::IResult<&[u8], TransactionValidityError> { |
937 | 0 | nom::Parser::parse( |
938 | 0 | &mut nom::error::context( |
939 | 0 | "transaction validity error", |
940 | 0 | nom::branch::alt(( |
941 | 0 | nom::combinator::map( |
942 | 0 | nom::sequence::preceded( |
943 | 0 | nom::bytes::streaming::tag(&[0][..]), |
944 | 0 | invalid_transaction, |
945 | 0 | ), |
946 | 0 | TransactionValidityError::Invalid, |
947 | 0 | ), |
948 | 0 | nom::combinator::map( |
949 | 0 | nom::sequence::preceded( |
950 | 0 | nom::bytes::streaming::tag(&[1][..]), |
951 | 0 | unknown_transaction, |
952 | 0 | ), |
953 | 0 | TransactionValidityError::Unknown, |
954 | 0 | ), |
955 | 0 | )), |
956 | 0 | ), |
957 | 0 | bytes, |
958 | | ) |
959 | 0 | } Unexecuted instantiation: _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime26transaction_validity_error Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime26transaction_validity_error |
960 | | |
961 | 0 | fn invalid_transaction(bytes: &[u8]) -> nom::IResult<&[u8], InvalidTransaction> { |
962 | 0 | nom::Parser::parse( |
963 | 0 | &mut nom::error::context( |
964 | | "invalid transaction", |
965 | 0 | nom::branch::alt(( |
966 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| { |
967 | 0 | InvalidTransaction::Call |
968 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transaction0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transaction0B7_ |
969 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[1][..]), |_| { |
970 | 0 | InvalidTransaction::Payment |
971 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions_0B7_ |
972 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[2][..]), |_| { |
973 | 0 | InvalidTransaction::Future |
974 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions0_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions0_0B7_ |
975 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[3][..]), |_| { |
976 | 0 | InvalidTransaction::Stale |
977 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions1_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions1_0B7_ |
978 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[4][..]), |_| { |
979 | 0 | InvalidTransaction::BadProof |
980 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions2_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions2_0B7_ |
981 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[5][..]), |_| { |
982 | 0 | InvalidTransaction::AncientBirthBlock |
983 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions3_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions3_0B7_ |
984 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[6][..]), |_| { |
985 | 0 | InvalidTransaction::ExhaustsResources |
986 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions4_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions4_0B7_ |
987 | 0 | nom::combinator::map( |
988 | 0 | nom::sequence::preceded( |
989 | 0 | nom::bytes::streaming::tag(&[7][..]), |
990 | 0 | nom::bytes::streaming::take(1u32), |
991 | | ), |
992 | 0 | |n: &[u8]| InvalidTransaction::Custom(n[0]), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions5_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions5_0B7_ |
993 | | ), |
994 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[8][..]), |_| { |
995 | 0 | InvalidTransaction::BadMandatory |
996 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions6_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions6_0B7_ |
997 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[9][..]), |_| { |
998 | 0 | InvalidTransaction::MandatoryDispatch |
999 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transactions7_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transactions7_0B7_ |
1000 | | )), |
1001 | | ), |
1002 | 0 | bytes, |
1003 | | ) |
1004 | 0 | } Unexecuted instantiation: _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19invalid_transaction Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19invalid_transaction |
1005 | | |
1006 | 0 | fn unknown_transaction(bytes: &[u8]) -> nom::IResult<&[u8], UnknownTransaction> { |
1007 | 0 | nom::Parser::parse( |
1008 | 0 | &mut nom::error::context( |
1009 | | "unknown transaction", |
1010 | 0 | nom::branch::alt(( |
1011 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[0][..]), |_| { |
1012 | 0 | UnknownTransaction::CannotLookup |
1013 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19unknown_transaction0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19unknown_transaction0B7_ |
1014 | 0 | nom::combinator::map(nom::bytes::streaming::tag(&[1][..]), |_| { |
1015 | 0 | UnknownTransaction::NoUnsignedValidator |
1016 | 0 | }), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19unknown_transactions_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19unknown_transactions_0B7_ |
1017 | 0 | nom::combinator::map( |
1018 | 0 | nom::sequence::preceded( |
1019 | 0 | nom::bytes::streaming::tag(&[2][..]), |
1020 | 0 | nom::bytes::streaming::take(1u32), |
1021 | | ), |
1022 | 0 | |n: &[u8]| UnknownTransaction::Custom(n[0]), Unexecuted instantiation: _RNCNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19unknown_transactions0_0B7_ Unexecuted instantiation: _RNCNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19unknown_transactions0_0B7_ |
1023 | | ), |
1024 | | )), |
1025 | | ), |
1026 | 0 | bytes, |
1027 | | ) |
1028 | 0 | } Unexecuted instantiation: _RNvNtNtCsjlkOsLH0Zfj_7smoldot6author7runtime19unknown_transaction Unexecuted instantiation: _RNvNtNtCsc1ywvx6YAnK_7smoldot6author7runtime19unknown_transaction |