Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/author/build.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
// TODO: docs
19
20
use crate::{
21
    author::{aura, runtime},
22
    executor::host,
23
    header,
24
    verify::inherents,
25
};
26
27
use alloc::vec::Vec;
28
use core::{num::NonZeroU64, time::Duration};
29
30
pub use runtime::{Nibble, StorageChanges, TrieEntryVersion};
31
32
/// Configuration for a block generation.
33
pub struct Config<'a, TLocAuth> {
34
    /// Consensus-specific configuration.
35
    pub consensus: ConfigConsensus<'a, TLocAuth>,
36
}
37
38
/// Extension to [`Config`].
39
pub enum ConfigConsensus<'a, TLocAuth> {
40
    /// Chain is using the Aura consensus algorithm.
41
    Aura {
42
        /// Time elapsed since [the Unix Epoch](https://en.wikipedia.org/wiki/Unix_time) (i.e.
43
        /// 00:00:00 UTC on 1 January 1970), ignoring leap seconds.
44
        now_from_unix_epoch: Duration,
45
46
        /// Duration, in milliseconds, of an Aura slot.
47
        slot_duration: NonZeroU64,
48
49
        /// List of the Aura authorities allowed to produce a block. This is either the same as
50
        /// the ones of the current best block, or a new list if the current best block contains
51
        /// an authorities list change digest item.
52
        current_authorities: header::AuraAuthoritiesIter<'a>,
53
54
        /// Iterator to the list of Sr25519 public keys available locally.
55
        ///
56
        /// Must implement `Iterator<Item = &[u8; 32]>`.
57
        local_authorities: TLocAuth,
58
    },
59
    // TODO: Babe isn't supported yet
60
}
61
62
/// Current state of the block building process.
63
#[must_use]
64
pub enum Builder {
65
    /// None of the authorities available locally are allowed to produce a block.
66
    Idle,
67
68
    /// Block production is idle, waiting for a slot.
69
    WaitSlot(WaitSlot),
70
71
    /// Block production is ready to start.
72
    Ready(AuthoringStart),
73
}
74
75
impl Builder {
76
    /// Initializes a new builder.
77
    ///
78
    /// Returns `None` if none of the local authorities are allowed to produce blocks.
79
    ///
80
    /// Keep in mind that the builder should be reconstructed every time the best block changes.
81
0
    pub fn new<'a>(config: Config<'a, impl Iterator<Item = &'a [u8; 32]>>) -> Self {
82
0
        let (slot, ready): (WaitSlotConsensus, bool) = match config.consensus {
83
0
            ConfigConsensus::Aura {
84
0
                current_authorities,
85
0
                local_authorities,
86
0
                now_from_unix_epoch,
87
0
                slot_duration,
88
            } => {
89
0
                let consensus = match aura::next_slot_claim(aura::Config {
90
0
                    now_from_unix_epoch,
91
0
                    slot_duration,
92
0
                    current_authorities,
93
0
                    local_authorities,
94
0
                }) {
95
0
                    Some(c) => c,
96
0
                    None => return Builder::Idle,
97
                };
98
99
0
                debug_assert!(now_from_unix_epoch < consensus.slot_end_from_unix_epoch);
100
0
                let ready = now_from_unix_epoch >= consensus.slot_start_from_unix_epoch;
101
0
102
0
                (WaitSlotConsensus::Aura(consensus), ready)
103
0
            }
104
0
        };
105
0
106
0
        if ready {
107
0
            Builder::Ready(AuthoringStart { consensus: slot })
108
        } else {
109
0
            Builder::WaitSlot(WaitSlot { consensus: slot })
110
        }
111
0
    }
Unexecuted instantiation: _RINvMNtNtCsN16ciHI6Qf_7smoldot6author5buildNtB3_7Builder3newpEB7_
Unexecuted instantiation: _RINvMNtNtCseuYC0Zibziv_7smoldot6author5buildNtB3_7Builder3newpEB7_
112
}
113
114
/// Current state of the block building process.
115
#[must_use]
116
pub enum BuilderAuthoring {
117
    /// Error happened during the generation.
118
    Error {
119
        /// Runtime of the parent block, as provided at initialization.
120
        parent_runtime: host::HostVmPrototype,
121
        /// The error in question.
122
        error: Error,
123
    },
124
125
    /// Block building is ready to accept extrinsics.
126
    ///
127
    /// If [`ApplyExtrinsic::add_extrinsic`] is used, then a
128
    /// [`BuilderAuthoring::ApplyExtrinsicResult`] stage will be emitted later.
129
    ///
130
    /// > **Note**: These extrinsics are generally coming from a transactions pool, but this is
131
    /// >           out of scope of this module.
132
    ApplyExtrinsic(ApplyExtrinsic),
133
134
    /// Result of the previous call to [`ApplyExtrinsic::add_extrinsic`].
135
    ///
136
    /// An [`ApplyExtrinsic`] object is provided in order to continue the operation.
137
    ApplyExtrinsicResult {
138
        /// Result of the previous call to [`ApplyExtrinsic::add_extrinsic`].
139
        result: Result<Result<(), runtime::DispatchError>, runtime::TransactionValidityError>,
140
        /// Object to use to continue trying to push other transactions or finish the block.
141
        resume: ApplyExtrinsic,
142
    },
143
144
    /// Loading a storage value from the parent storage is required in order to continue.
145
    StorageGet(StorageGet),
146
147
    /// Obtaining the Merkle value of the closest descendant of a trie node is required in order
148
    /// to continue.
149
    ClosestDescendantMerkleValue(ClosestDescendantMerkleValue),
150
151
    /// Fetching the key that follows a given one in the parent storage is required in order to
152
    /// continue.
153
    NextKey(NextKey),
154
155
    /// Setting the value of an offchain storage value is required.
156
    OffchainStorageSet(OffchainStorageSet),
157
158
    /// Block has been produced by the runtime and must now be sealed.
159
    Seal(Seal),
160
}
161
162
/// Block production is idle, waiting for a slot.
163
#[must_use]
164
#[derive(Debug)]
165
pub struct WaitSlot {
166
    consensus: WaitSlotConsensus,
167
}
168
169
#[derive(Debug)]
170
enum WaitSlotConsensus {
171
    Aura(aura::SlotClaim),
172
}
173
174
impl WaitSlot {
175
    /// Returns when block production can begin, as a UNIX timestamp (i.e. number of seconds since
176
    /// the UNIX epoch, ignoring leap seconds).
177
0
    pub fn when(&self) -> Duration {
178
0
        // TODO: we can actually start building the block before our slot in some situations?
179
0
        match self.consensus {
180
0
            WaitSlotConsensus::Aura(claim) => claim.slot_start_from_unix_epoch,
181
0
        }
182
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB4_8WaitSlot4when
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB4_8WaitSlot4when
183
184
    /// Start the block production.
185
    ///
186
    /// Shouldn't be called before the timestamp returned by [`WaitSlot::when`]. Blocks that are
187
    /// authored and sent to other nodes before the proper timestamp will be considered as
188
    /// invalid.
189
0
    pub fn start(self) -> AuthoringStart {
190
0
        AuthoringStart {
191
0
            consensus: self.consensus,
192
0
        }
193
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB4_8WaitSlot5start
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB4_8WaitSlot5start
194
}
195
196
/// Ready to start producing blocks.
197
pub struct AuthoringStart {
198
    consensus: WaitSlotConsensus,
199
}
200
201
impl AuthoringStart {
202
    /// Returns when the authoring slot start, as a UNIX timestamp (i.e. number of seconds since
203
    /// the UNIX epoch, ignoring leap seconds).
204
0
    pub fn slot_start_from_unix_epoch(&self) -> Duration {
205
0
        match self.consensus {
206
0
            WaitSlotConsensus::Aura(claim) => claim.slot_start_from_unix_epoch,
207
0
        }
208
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_14AuthoringStart26slot_start_from_unix_epoch
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_14AuthoringStart26slot_start_from_unix_epoch
209
210
    /// Returns when the authoring slot ends, as a UNIX timestamp (i.e. number of seconds since
211
    /// the UNIX epoch, ignoring leap seconds).
212
    ///
213
    /// The block should finish being authored before the slot ends.
214
    /// However, in order for the network to perform smoothly, the block should have been
215
    /// authored **and** propagated throughout the entire peer-to-peer network before the slot
216
    /// ends.
217
0
    pub fn slot_end_from_unix_epoch(&self) -> Duration {
218
0
        match self.consensus {
219
0
            WaitSlotConsensus::Aura(claim) => claim.slot_end_from_unix_epoch,
220
0
        }
221
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_14AuthoringStart24slot_end_from_unix_epoch
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_14AuthoringStart24slot_end_from_unix_epoch
222
223
    /// Start producing the block.
224
0
    pub fn start(self, config: AuthoringStartConfig) -> BuilderAuthoring {
225
0
        let inner_block_build = runtime::build_block(runtime::Config {
226
0
            block_number_bytes: config.block_number_bytes,
227
0
            parent_hash: config.parent_hash,
228
0
            parent_number: config.parent_number,
229
0
            parent_runtime: config.parent_runtime,
230
0
            block_body_capacity: config.block_body_capacity,
231
0
            consensus_digest_log_item: match self.consensus {
232
0
                WaitSlotConsensus::Aura(slot) => {
233
0
                    runtime::ConfigPreRuntime::Aura(header::AuraPreDigest {
234
0
                        slot_number: slot.slot_number,
235
0
                    })
236
0
                }
237
0
            },
238
0
            max_log_level: config.max_log_level,
239
0
            calculate_trie_changes: config.calculate_trie_changes,
240
0
        });
241
0
242
0
        let inherent_data = inherents::InherentData {
243
0
            timestamp: u64::try_from(config.now_from_unix_epoch.as_millis()).unwrap_or(u64::MAX),
244
0
        };
245
0
246
0
        (Shared {
247
0
            inherent_data: Some(inherent_data),
248
0
            slot_claim: self.consensus,
249
0
            block_number_bytes: config.block_number_bytes,
250
0
        })
251
0
        .with_runtime_inner(inner_block_build)
252
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_14AuthoringStart5start
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_14AuthoringStart5start
253
}
254
255
/// Configuration to pass when the actual block authoring is started.
256
pub struct AuthoringStartConfig<'a> {
257
    /// Number of bytes used to encode block numbers in the header.
258
    pub block_number_bytes: usize,
259
260
    /// Hash of the parent of the block to generate.
261
    ///
262
    /// Used to populate the header of the new block.
263
    pub parent_hash: &'a [u8; 32],
264
265
    /// Height of the parent of the block to generate.
266
    ///
267
    /// Used to populate the header of the new block.
268
    pub parent_number: u64,
269
270
    /// Time elapsed since [the Unix Epoch](https://en.wikipedia.org/wiki/Unix_time) (i.e.
271
    /// 00:00:00 UTC on 1 January 1970), ignoring leap seconds.
272
    pub now_from_unix_epoch: Duration,
273
274
    /// Runtime used to check the new block. Must be built using the Wasm code found at the
275
    /// `:code` key of the parent block storage.
276
    pub parent_runtime: host::HostVmPrototype,
277
278
    /// Capacity to reserve for the number of extrinsics. Should be higher than the approximate
279
    /// number of extrinsics that are going to be applied.
280
    pub block_body_capacity: usize,
281
282
    /// Maximum log level of the runtime.
283
    ///
284
    /// > **Note**: This value is opaque from the point of the view of the client, and the runtime
285
    /// >           is free to interpret it the way it wants. However, usually values are: `0` for
286
    /// >           "off", `1` for "error", `2` for "warn", `3` for "info", `4` for "debug",
287
    /// >           and `5` for "trace".
288
    pub max_log_level: u32,
289
290
    /// If `true`, then [`StorageChanges::trie_changes_iter_ordered`] will return `Some`.
291
    /// Passing `None` requires fewer calculation and fewer storage accesses.
292
    pub calculate_trie_changes: bool,
293
}
294
295
/// More transactions can be added.
296
#[must_use]
297
pub struct ApplyExtrinsic {
298
    inner: runtime::ApplyExtrinsic,
299
    shared: Shared,
300
}
301
302
impl ApplyExtrinsic {
303
    /// Adds a SCALE-encoded extrinsic and resumes execution.
304
    ///
305
    /// See the module-level documentation for more information.
306
0
    pub fn add_extrinsic(self, extrinsic: Vec<u8>) -> BuilderAuthoring {
307
0
        self.shared
308
0
            .with_runtime_inner(self.inner.add_extrinsic(extrinsic))
309
0
    }
Unexecuted instantiation: _RNvMs1_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_14ApplyExtrinsic13add_extrinsic
Unexecuted instantiation: _RNvMs1_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_14ApplyExtrinsic13add_extrinsic
310
311
    /// Indicate that no more extrinsics will be added, and resume execution.
312
0
    pub fn finish(self) -> BuilderAuthoring {
313
0
        self.shared.with_runtime_inner(self.inner.finish())
314
0
    }
Unexecuted instantiation: _RNvMs1_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_14ApplyExtrinsic6finish
Unexecuted instantiation: _RNvMs1_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_14ApplyExtrinsic6finish
315
}
316
317
/// Loading a storage value from the parent storage is required in order to continue.
318
#[must_use]
319
pub struct StorageGet(runtime::StorageGet, Shared);
320
321
impl StorageGet {
322
    /// Returns the key whose value must be passed to [`StorageGet::inject_value`].
323
0
    pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ {
324
0
        self.0.key()
325
0
    }
Unexecuted instantiation: _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_10StorageGet3key
Unexecuted instantiation: _RNvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_10StorageGet3key
326
327
    /// If `Some`, read from the given child trie. If `None`, read from the main trie.
328
0
    pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> {
329
0
        self.0.child_trie()
330
0
    }
Unexecuted instantiation: _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_10StorageGet10child_trie
Unexecuted instantiation: _RNvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_10StorageGet10child_trie
331
332
    /// Injects the corresponding storage value.
333
0
    pub fn inject_value(
334
0
        self,
335
0
        value: Option<(impl Iterator<Item = impl AsRef<[u8]>>, TrieEntryVersion)>,
336
0
    ) -> BuilderAuthoring {
337
0
        self.1.with_runtime_inner(self.0.inject_value(value))
338
0
    }
Unexecuted instantiation: _RINvMs2_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB6_10StorageGet12inject_valueppEBa_
Unexecuted instantiation: _RINvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_10StorageGet12inject_valueppEBa_
Unexecuted instantiation: _RINvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1e_EECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1e_EECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvMs2_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_10StorageGet12inject_valueRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1e_EECsibGXYHQB8Ea_25json_rpc_general_requests
339
}
340
341
/// Obtaining the Merkle value of the closest descendant of a trie node is required in order
342
/// to continue.
343
#[must_use]
344
pub struct ClosestDescendantMerkleValue(runtime::ClosestDescendantMerkleValue, Shared);
345
346
impl ClosestDescendantMerkleValue {
347
    /// Returns the key whose closest descendant Merkle value must be passed to
348
    /// [`ClosestDescendantMerkleValue::inject_merkle_value`].
349
0
    pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ {
350
0
        self.0.key()
351
0
    }
Unexecuted instantiation: _RNvMs3_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue3key
Unexecuted instantiation: _RNvMs3_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue3key
352
353
    /// If `Some`, read from the given child trie. If `None`, read from the main trie.
354
0
    pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> {
355
0
        self.0.child_trie()
356
0
    }
Unexecuted instantiation: _RNvMs3_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue10child_trie
Unexecuted instantiation: _RNvMs3_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue10child_trie
357
358
    /// Indicate that the value is unknown and resume the calculation.
359
    ///
360
    /// This function be used if you are unaware of the Merkle value. The algorithm will perform
361
    /// the calculation of this Merkle value manually, which takes more time.
362
0
    pub fn resume_unknown(self) -> BuilderAuthoring {
363
0
        self.1.with_runtime_inner(self.0.resume_unknown())
364
0
    }
Unexecuted instantiation: _RNvMs3_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue14resume_unknown
Unexecuted instantiation: _RNvMs3_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue14resume_unknown
365
366
    /// Injects the corresponding Merkle value.
367
    ///
368
    /// `None` can be passed if there is no descendant or, in the case of a child trie read, in
369
    /// order to indicate that the child trie does not exist.
370
0
    pub fn inject_merkle_value(self, merkle_value: Option<&[u8]>) -> BuilderAuthoring {
371
0
        self.1
372
0
            .with_runtime_inner(self.0.inject_merkle_value(merkle_value))
373
0
    }
Unexecuted instantiation: _RNvMs3_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue19inject_merkle_value
Unexecuted instantiation: _RNvMs3_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_28ClosestDescendantMerkleValue19inject_merkle_value
374
}
375
376
/// Fetching the key that follows a given one in the parent storage is required in order to
377
/// continue.
378
#[must_use]
379
pub struct NextKey(runtime::NextKey, Shared);
380
381
impl NextKey {
382
    /// Returns the key whose next key must be passed back.
383
0
    pub fn key(&'_ self) -> impl Iterator<Item = Nibble> + '_ {
384
0
        self.0.key()
385
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_7NextKey3key
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_7NextKey3key
386
387
    /// If `Some`, read from the given child trie. If `None`, read from the main trie.
388
0
    pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> {
389
0
        self.0.child_trie()
390
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_7NextKey10child_trie
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_7NextKey10child_trie
391
392
    /// If `true`, then the provided value must the one superior or equal to the requested key.
393
    /// If `false`, then the provided value must be strictly superior to the requested key.
394
0
    pub fn or_equal(&self) -> bool {
395
0
        self.0.or_equal()
396
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_7NextKey8or_equal
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_7NextKey8or_equal
397
398
    /// If `true`, then the search must include both branch nodes and storage nodes. If `false`,
399
    /// the search only covers storage nodes.
400
0
    pub fn branch_nodes(&self) -> bool {
401
0
        self.0.branch_nodes()
402
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_7NextKey12branch_nodes
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_7NextKey12branch_nodes
403
404
    /// Returns the prefix the next key must start with. If the next key doesn't start with the
405
    /// given prefix, then `None` should be provided.
406
0
    pub fn prefix(&'_ self) -> impl Iterator<Item = Nibble> + '_ {
407
0
        self.0.prefix()
408
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_7NextKey6prefix
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_7NextKey6prefix
409
410
    /// Injects the key.
411
    ///
412
    /// # Panic
413
    ///
414
    /// Panics if the key passed as parameter isn't strictly superior to the requested key.
415
    ///
416
0
    pub fn inject_key(self, key: Option<impl Iterator<Item = Nibble>>) -> BuilderAuthoring {
417
0
        self.1.with_runtime_inner(self.0.inject_key(key))
418
0
    }
Unexecuted instantiation: _RINvMs4_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB6_7NextKey10inject_keypEBa_
Unexecuted instantiation: _RINvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_7NextKey10inject_keypEBa_
Unexecuted instantiation: _RINvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB2X_14SyncBackground12author_block0s6_00EECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB2X_14SyncBackground12author_block0s6_00EECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvMs4_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB6_7NextKey10inject_keyINtNtNtNtCsaYZPK01V26L_4core4iter8adapters3map3MapINtNtNtCsdZExvAaxgia_5alloc3vec9into_iter8IntoIterhENCNCNCNvMs_NtCsiUjFBJteJ7x_17smoldot_full_node17consensus_serviceNtB2X_14SyncBackground12author_block0s6_00EECsibGXYHQB8Ea_25json_rpc_general_requests
419
}
420
421
/// Setting the value of an offchain storage value is required.
422
#[must_use]
423
pub struct OffchainStorageSet(runtime::OffchainStorageSet, Shared);
424
425
impl OffchainStorageSet {
426
    /// Returns the key whose value must be set.
427
0
    pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ {
428
0
        self.0.key()
429
0
    }
Unexecuted instantiation: _RNvMs5_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_18OffchainStorageSet3key
Unexecuted instantiation: _RNvMs5_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_18OffchainStorageSet3key
430
431
    /// Returns the value to set.
432
    ///
433
    /// If `None` is returned, the key should be removed from the storage entirely.
434
0
    pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> {
435
0
        self.0.value()
436
0
    }
Unexecuted instantiation: _RNvMs5_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_18OffchainStorageSet5value
Unexecuted instantiation: _RNvMs5_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_18OffchainStorageSet5value
437
438
    /// Resumes execution after having set the value.
439
0
    pub fn resume(self) -> BuilderAuthoring {
440
0
        self.1.with_runtime_inner(self.0.resume())
441
0
    }
Unexecuted instantiation: _RNvMs5_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_18OffchainStorageSet6resume
Unexecuted instantiation: _RNvMs5_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_18OffchainStorageSet6resume
442
}
443
444
/// Block has been produced and must now be sealed.
445
#[must_use]
446
pub struct Seal {
447
    shared: Shared,
448
    block: runtime::Success,
449
}
450
451
impl Seal {
452
    /// Returns the SCALE-encoded header whose hash must be signed.
453
0
    pub fn scale_encoded_header(&self) -> &[u8] {
454
0
        &self.block.scale_encoded_header
455
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_4Seal20scale_encoded_header
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_4Seal20scale_encoded_header
456
457
    /// Returns the data to sign. This is the hash of the SCALE-encoded header of the block.
458
0
    pub fn to_sign(&self) -> [u8; 32] {
459
0
        header::hash_from_scale_encoded_header(&self.block.scale_encoded_header)
460
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_4Seal7to_sign
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_4Seal7to_sign
461
462
    /// Returns the index within the list of authorities of the authority that must sign the
463
    /// block.
464
    ///
465
    /// See [`ConfigConsensus::Aura::local_authorities`].
466
0
    pub fn authority_index(&self) -> usize {
467
0
        match self.shared.slot_claim {
468
0
            WaitSlotConsensus::Aura(slot) => slot.local_authorities_index,
469
0
        }
470
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_4Seal15authority_index
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_4Seal15authority_index
471
472
    /// Injects the Sr25519 signature of the hash of the SCALE-encoded header from the given
473
    /// authority.
474
    ///
475
    /// The method then returns the finished block.
476
0
    pub fn inject_sr25519_signature(mut self, signature: [u8; 64]) -> runtime::Success {
477
0
        let header = header::decode(
478
0
            &self.block.scale_encoded_header,
479
0
            self.shared.block_number_bytes,
480
0
        )
481
0
        .unwrap();
482
0
483
0
        self.block.scale_encoded_header = header
484
0
            .scale_encoding_with_extra_digest_item(
485
0
                self.shared.block_number_bytes,
486
0
                header::DigestItemRef::AuraSeal(&signature),
487
0
            )
488
0
            .fold(Vec::with_capacity(8192), |mut a, b| {
489
0
                a.extend_from_slice(b.as_ref());
490
0
                a
491
0
            });
Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB7_4Seal24inject_sr25519_signature0Bb_
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB7_4Seal24inject_sr25519_signature0Bb_
492
0
493
0
        self.block
494
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_4Seal24inject_sr25519_signature
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_4Seal24inject_sr25519_signature
495
}
496
497
/// Error that can happen during the block production.
498
0
#[derive(Debug, derive_more::Display, derive_more::From)]
Unexecuted instantiation: _RNvXsb_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsb_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
499
pub enum Error {
500
    /// Error while producing the block in the runtime.
501
    #[display(fmt = "{_0}")]
502
    Runtime(runtime::Error),
503
    /// Runtime has generated an invalid block header.
504
    #[from(ignore)]
505
    InvalidHeaderGenerated,
506
}
507
508
/// Extra information maintained in all variants of the [`Builder`].
509
#[derive(Debug)]
510
struct Shared {
511
    /// Inherent data waiting to be injected. Will be extracted from its `Option` when the inner
512
    /// block builder requests it.
513
    inherent_data: Option<inherents::InherentData>,
514
515
    /// Number of bytes used to encode the block number in the header.
516
    block_number_bytes: usize,
517
518
    /// Slot that has been claimed.
519
    slot_claim: WaitSlotConsensus,
520
}
521
522
impl Shared {
523
0
    fn with_runtime_inner(mut self, mut inner: runtime::BlockBuild) -> BuilderAuthoring {
524
        loop {
525
0
            match inner {
526
0
                runtime::BlockBuild::Finished(Ok(block)) => {
527
                    // After the runtime has produced a block, the last step is to seal it.
528
529
                    // Verify the correctness of the header. If not, the runtime is misbehaving.
530
0
                    let decoded_header = match header::decode(
531
0
                        &block.scale_encoded_header,
532
0
                        self.block_number_bytes,
533
0
                    ) {
534
0
                        Ok(h) => h,
535
                        Err(_) => {
536
0
                            break BuilderAuthoring::Error {
537
0
                                parent_runtime: block.parent_runtime,
538
0
                                error: Error::InvalidHeaderGenerated,
539
0
                            }
540
                        }
541
                    };
542
543
                    // The `Seal` object created below assumes that there is no existing seal.
544
0
                    if decoded_header.digest.aura_seal().is_some()
545
0
                        || decoded_header.digest.babe_seal().is_some()
546
                    {
547
0
                        break BuilderAuthoring::Error {
548
0
                            parent_runtime: block.parent_runtime,
549
0
                            error: Error::InvalidHeaderGenerated,
550
0
                        };
551
0
                    }
552
0
553
0
                    break BuilderAuthoring::Seal(Seal {
554
0
                        shared: self,
555
0
                        block,
556
0
                    });
557
                }
558
0
                runtime::BlockBuild::Finished(Err((error, parent_runtime))) => {
559
0
                    break BuilderAuthoring::Error {
560
0
                        parent_runtime,
561
0
                        error: Error::Runtime(error),
562
0
                    }
563
                }
564
0
                runtime::BlockBuild::InherentExtrinsics(a) => {
565
0
                    // Injecting the inherent is guaranteed to be done only once per block.
566
0
                    inner = a.inject_inherents(self.inherent_data.take().unwrap());
567
0
                }
568
0
                runtime::BlockBuild::ApplyExtrinsic(a) => {
569
0
                    inner = a.finish();
570
0
                }
571
0
                runtime::BlockBuild::ApplyExtrinsicResult { result, resume } => {
572
0
                    break BuilderAuthoring::ApplyExtrinsicResult {
573
0
                        result,
574
0
                        resume: ApplyExtrinsic {
575
0
                            inner: resume,
576
0
                            shared: self,
577
0
                        },
578
0
                    }
579
                }
580
0
                runtime::BlockBuild::StorageGet(inner) => {
581
0
                    break BuilderAuthoring::StorageGet(StorageGet(inner, self))
582
                }
583
0
                runtime::BlockBuild::ClosestDescendantMerkleValue(inner) => {
584
0
                    break BuilderAuthoring::ClosestDescendantMerkleValue(
585
0
                        ClosestDescendantMerkleValue(inner, self),
586
0
                    )
587
                }
588
0
                runtime::BlockBuild::NextKey(inner) => {
589
0
                    break BuilderAuthoring::NextKey(NextKey(inner, self))
590
                }
591
0
                runtime::BlockBuild::OffchainStorageSet(inner) => {
592
0
                    break BuilderAuthoring::OffchainStorageSet(OffchainStorageSet(inner, self))
593
                }
594
            }
595
        }
596
0
    }
Unexecuted instantiation: _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot6author5buildNtB5_6Shared18with_runtime_inner
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot6author5buildNtB5_6Shared18with_runtime_inner
597
}