Coverage Report

Created: 2025-07-01 09:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/__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