Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/sync/warp_sync.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
//! Warp syncing.
19
//!
20
//! Warp syncing makes it possible to very quickly reach the currently finalized block of a chain.
21
//! No attempt is made at verifying blocks. The algorithm assumes that the currently finalized
22
//! block is valid, as the chain is likely bricked if this is not the case.
23
//!
24
//! # Long range attack vulnerability
25
//!
26
//! Warp syncing is particularly vulnerable to what is called long range attacks.
27
//!
28
//! The authorities allowed to finalize blocks can generate multiple proofs of finality for
29
//! multiple different blocks of the same height. In other words, they can finalize more than one
30
//! chain at a time.
31
//!
32
//! Finalizing multiple chains at the same time is called an equivocation. Client implementations
33
//! detect equivocations and report them to the runtime. While this is out of scope of the client,
34
//! the runtime then typically provides a mechanism that punishes the validators that have
35
//! equivocated.
36
//! However, this defense mechanism is flawed in case when a long time passes between the
37
//! multiple finality proofs generated by the same validators. Clients cannot hold an unlimited
38
//! amount of information in memory, so they might not detect the equivocation, and even if it is
39
//! detected, the punishment might not be enforceable because validators have moved all their
40
//! funds.
41
//!
42
//! In other words, it is possible for two thirds of the validators that were active at a certain
43
//! past block N to collude and decide to finalize a different block N, even when N has been
44
//! finalized for the first time several weeks or months in the past. When a client then warp
45
//! syncs, it can be tricked to consider this alternative block N as the finalized one.
46
//!
47
//! There is no fool-proof defense against this attack. However, consider the extremely high
48
//! investment and high risk for the malicious validators, and the difficulty of pulling off this
49
//! attack, it is extremely unlikely to happen in reality.
50
//! The aforementioned punishment system is the only defense against this attack, and in order to
51
//! be effective, the starting point of the warp syncing shouldn't be too far in the past. How
52
//! far exactly depends on the logic of the runtime of the chain.
53
//!
54
//! # Overview
55
//!
56
//! The warp syncing algorithm works only if the chain uses Grandpa for its finality.
57
//! It consists in the following steps:
58
//!
59
//! - Downloading a warp sync proof from a source. This proof contains a list of *fragments*. Each
60
//! fragment represents a change in the list of Grandpa authorities, and a list of signatures of
61
//! the previous authorities that certify that this change is correct.
62
//! - Verifying the fragments. Each fragment that is successfully verified progresses towards
63
//! the head of the chain. Even if one fragment is invalid, all the previously-verified
64
//! fragments can still be kept, and the warp syncing can resume from there.
65
//! - Downloading from a source the runtime code of the final block of the proof.
66
//! - Performing some runtime calls in order to obtain the current consensus-related parameters
67
//! of the chain. This might require obtaining some storage items, in which case they must also
68
//! be downloaded from a source.
69
//!
70
//! At the end of the syncing, a [`ValidChainInformation`] corresponding to the head of the chain
71
//! is yielded.
72
//!
73
//! # Usage
74
//!
75
//! Use the [`start_warp_sync()`] function to start a Grandpa warp syncing state machine.
76
//!
77
//! At any given moment, this state machine holds a list of *sources* that it might use to
78
//! download the warp sync proof or the runtime code. Sources must be added and removed by the API
79
//! user by calling one of the various `add_source` and `remove_source` functions.
80
//!
81
//! Sources are identified through a [`SourceId`]. Each source has an opaque so-called "user data"
82
//! of type `TSrc` associated to it. The content of this "user data" is at the discretion of the
83
//! API user.
84
//!
85
//! Similarly, at any given moment, this state machine holds a list of requests that concern these
86
//! sources. Use [`WarpSync::desired_requests`] to determine which requests will be useful to the
87
//! progress of the warp syncing, then use [`WarpSync::add_request`] to update the state machine
88
//! with a newly-started request.
89
//!
90
//! Use [`WarpSync::process_one`] in order to run verifications of the payloads that have
91
//! previously been downloaded.
92
//!
93
94
use crate::{
95
    chain::chain_information::{
96
        self, ChainInformationConsensusRef, ChainInformationFinality, ChainInformationFinalityRef,
97
        ValidChainInformation, ValidChainInformationRef,
98
    },
99
    executor::{
100
        self,
101
        host::{self, HostVmPrototype},
102
        vm::ExecHint,
103
    },
104
    finality::{decode, verify},
105
    header,
106
    informant::HashDisplay,
107
    trie::{self, proof_decode},
108
};
109
110
use alloc::{
111
    borrow::{Cow, ToOwned as _},
112
    collections::{BTreeSet, VecDeque},
113
    vec,
114
    vec::Vec,
115
};
116
use core::{cmp, fmt, iter, mem, ops};
117
118
pub use trie::Nibble;
119
120
/// The configuration for [`start_warp_sync()`].
121
#[derive(Debug)]
122
pub struct Config {
123
    /// The chain information of the starting point of the warp syncing.
124
    pub start_chain_information: ValidChainInformation,
125
126
    /// Number of bytes used when encoding/decoding the block number. Influences how various data
127
    /// structures should be parsed.
128
    pub block_number_bytes: usize,
129
130
    /// The initial capacity of the list of sources.
131
    pub sources_capacity: usize,
132
133
    /// The initial capacity of the list of requests.
134
    pub requests_capacity: usize,
135
136
    /// Known valid Merkle value and storage value combination for the `:code` key.
137
    ///
138
    /// If provided, the warp syncing algorithm will first fetch the Merkle value of `:code`, and
139
    /// if it matches the Merkle value provided in the hint, use the storage value in the hint
140
    /// instead of downloading it. If the hint doesn't match, an extra round-trip will be needed,
141
    /// but if the hint matches it saves a big download.
142
    pub code_trie_node_hint: Option<ConfigCodeTrieNodeHint>,
143
144
    /// Number of warp sync fragments after which the state machine will pause downloading new
145
    /// ones until the ones that have been downloaded are verified.
146
    ///
147
    /// A too low value will cause stalls, while a high value will use more memory and runs the
148
    /// risk of wasting more bandwidth in case the downloaded fragments need to be thrown away.
149
    pub num_download_ahead_fragments: usize,
150
151
    /// If the height of the current local finalized block is `N`, the warp sync state machine
152
    /// will not attempt to warp sync to blocks whose height inferior or equal to `N + k` where
153
    /// `k` is the value in this field.
154
    ///
155
    /// Because warp syncing is a relatively expensive process, it is not worth performing it
156
    /// between two blocks that are too close to each other.
157
    ///
158
    /// The ideal value of this field depends on the block production rate and the time it takes
159
    /// to answer requests.
160
    pub warp_sync_minimum_gap: usize,
161
162
    /// If `true`, the body of the warp sync target will be downloaded before the warp sync
163
    /// finishes.
164
    /// Determines whether [`RuntimeInformation::finalized_body`] is `Some`.
165
    pub download_block_body: bool,
166
167
    /// If `true`, all the storage proofs and call proofs necessary in order to compute the chain
168
    /// information of the warp synced block will be downloaded. If `false`, the finality
169
    /// information of the warp synced block is inferred from the warp sync fragments instead.
170
    pub download_all_chain_information_storage_proofs: bool,
171
}
172
173
/// See [`Config::code_trie_node_hint`].
174
#[derive(Debug)]
175
pub struct ConfigCodeTrieNodeHint {
176
    /// Potential Merkle value of the `:code` key.
177
    pub merkle_value: Vec<u8>,
178
179
    /// Storage value corresponding to [`ConfigCodeTrieNodeHint::merkle_value`].
180
    pub storage_value: Vec<u8>,
181
182
    /// Closest ancestor of the `:code` key except for `:code` itself.
183
    pub closest_ancestor_excluding: Vec<Nibble>,
184
}
185
186
/// Initializes the warp sync state machine.
187
///
188
/// On error, returns the [`ValidChainInformation`] that was provided in the configuration.
189
21
pub fn start_warp_sync<TSrc, TRq>(
190
21
    config: Config,
191
21
) -> Result<WarpSync<TSrc, TRq>, (ValidChainInformation, WarpSyncInitError)> {
192
21
    match config.start_chain_information.as_ref().finality {
193
        // TODO: we make sure that `finalized_scheduled_change` is `None` because it seems complicated to support, but ideally it would be supported
194
        ChainInformationFinalityRef::Grandpa {
195
            finalized_scheduled_change: None,
196
            ..
197
21
        } => {}
198
        _ => {
199
0
            return Err((
200
0
                config.start_chain_information,
201
0
                WarpSyncInitError::NotGrandpa,
202
0
            ))
203
        }
204
    }
205
206
21
    match config.start_chain_information.as_ref().consensus {
207
21
        ChainInformationConsensusRef::Babe { .. } | ChainInformationConsensusRef::Aura { .. } => {}
208
        ChainInformationConsensusRef::Unknown => {
209
0
            return Err((
210
0
                config.start_chain_information,
211
0
                WarpSyncInitError::UnknownConsensus,
212
0
            ))
213
        }
214
    }
215
216
21
    let warped_header = config
217
21
        .start_chain_information
218
21
        .as_ref()
219
21
        .finalized_block_header
220
21
        .scale_encoding_vec(config.block_number_bytes);
221
21
222
21
    Ok(WarpSync {
223
21
        warped_header_number: config
224
21
            .start_chain_information
225
21
            .as_ref()
226
21
            .finalized_block_header
227
21
            .number,
228
21
        warped_header_state_root: *config
229
21
            .start_chain_information
230
21
            .as_ref()
231
21
            .finalized_block_header
232
21
            .state_root,
233
21
        warped_header_extrinsics_root: *config
234
21
            .start_chain_information
235
21
            .as_ref()
236
21
            .finalized_block_header
237
21
            .extrinsics_root,
238
21
        warped_header_hash: header::hash_from_scale_encoded_header(&warped_header),
239
21
        warped_header,
240
21
        warped_finality: config.start_chain_information.as_ref().finality.into(),
241
21
        warped_block_ty: WarpedBlockTy::AlreadyVerified,
242
21
        runtime_calls: runtime_calls_default_value(
243
21
            config.start_chain_information.as_ref().consensus,
244
21
        ),
245
21
        verified_chain_information: config.start_chain_information,
246
21
        code_trie_node_hint: config.code_trie_node_hint,
247
21
        num_download_ahead_fragments: config.num_download_ahead_fragments,
248
21
        warp_sync_minimum_gap: config.warp_sync_minimum_gap,
249
21
        block_number_bytes: config.block_number_bytes,
250
21
        download_all_chain_information_storage_proofs: config
251
21
            .download_all_chain_information_storage_proofs,
252
21
        sources: slab::Slab::with_capacity(config.sources_capacity),
253
21
        sources_by_finalized_height: BTreeSet::new(),
254
21
        in_progress_requests: slab::Slab::with_capacity(config.requests_capacity),
255
21
        in_progress_requests_by_source: BTreeSet::new(),
256
21
        warp_sync_fragments_download: None,
257
21
        verify_queue: VecDeque::new(),
258
21
        runtime_download: RuntimeDownload::NotStarted {
259
21
            hint_doesnt_match: false,
260
21
        },
261
21
        body_download: if config.download_block_body {
262
21
            BodyDownload::NotStarted
263
        } else {
264
0
            BodyDownload::NotNeeded
265
        },
266
    })
267
21
}
Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot4sync9warp_sync15start_warp_syncppEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync15start_warp_syncNtNtB4_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync15start_warp_syncppEB6_
_RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync15start_warp_syncNtNtB4_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraECsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
189
2
pub fn start_warp_sync<TSrc, TRq>(
190
2
    config: Config,
191
2
) -> Result<WarpSync<TSrc, TRq>, (ValidChainInformation, WarpSyncInitError)> {
192
2
    match config.start_chain_information.as_ref().finality {
193
        // TODO: we make sure that `finalized_scheduled_change` is `None` because it seems complicated to support, but ideally it would be supported
194
        ChainInformationFinalityRef::Grandpa {
195
            finalized_scheduled_change: None,
196
            ..
197
2
        } => {}
198
        _ => {
199
0
            return Err((
200
0
                config.start_chain_information,
201
0
                WarpSyncInitError::NotGrandpa,
202
0
            ))
203
        }
204
    }
205
206
2
    match config.start_chain_information.as_ref().consensus {
207
2
        ChainInformationConsensusRef::Babe { .. } | ChainInformationConsensusRef::Aura { .. } => {}
208
        ChainInformationConsensusRef::Unknown => {
209
0
            return Err((
210
0
                config.start_chain_information,
211
0
                WarpSyncInitError::UnknownConsensus,
212
0
            ))
213
        }
214
    }
215
216
2
    let warped_header = config
217
2
        .start_chain_information
218
2
        .as_ref()
219
2
        .finalized_block_header
220
2
        .scale_encoding_vec(config.block_number_bytes);
221
2
222
2
    Ok(WarpSync {
223
2
        warped_header_number: config
224
2
            .start_chain_information
225
2
            .as_ref()
226
2
            .finalized_block_header
227
2
            .number,
228
2
        warped_header_state_root: *config
229
2
            .start_chain_information
230
2
            .as_ref()
231
2
            .finalized_block_header
232
2
            .state_root,
233
2
        warped_header_extrinsics_root: *config
234
2
            .start_chain_information
235
2
            .as_ref()
236
2
            .finalized_block_header
237
2
            .extrinsics_root,
238
2
        warped_header_hash: header::hash_from_scale_encoded_header(&warped_header),
239
2
        warped_header,
240
2
        warped_finality: config.start_chain_information.as_ref().finality.into(),
241
2
        warped_block_ty: WarpedBlockTy::AlreadyVerified,
242
2
        runtime_calls: runtime_calls_default_value(
243
2
            config.start_chain_information.as_ref().consensus,
244
2
        ),
245
2
        verified_chain_information: config.start_chain_information,
246
2
        code_trie_node_hint: config.code_trie_node_hint,
247
2
        num_download_ahead_fragments: config.num_download_ahead_fragments,
248
2
        warp_sync_minimum_gap: config.warp_sync_minimum_gap,
249
2
        block_number_bytes: config.block_number_bytes,
250
2
        download_all_chain_information_storage_proofs: config
251
2
            .download_all_chain_information_storage_proofs,
252
2
        sources: slab::Slab::with_capacity(config.sources_capacity),
253
2
        sources_by_finalized_height: BTreeSet::new(),
254
2
        in_progress_requests: slab::Slab::with_capacity(config.requests_capacity),
255
2
        in_progress_requests_by_source: BTreeSet::new(),
256
2
        warp_sync_fragments_download: None,
257
2
        verify_queue: VecDeque::new(),
258
2
        runtime_download: RuntimeDownload::NotStarted {
259
2
            hint_doesnt_match: false,
260
2
        },
261
2
        body_download: if config.download_block_body {
262
2
            BodyDownload::NotStarted
263
        } else {
264
0
            BodyDownload::NotNeeded
265
        },
266
    })
267
2
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync15start_warp_syncNtNtB4_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraECscDgN54JpMGG_6author
_RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync15start_warp_syncNtNtB4_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraECsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
189
19
pub fn start_warp_sync<TSrc, TRq>(
190
19
    config: Config,
191
19
) -> Result<WarpSync<TSrc, TRq>, (ValidChainInformation, WarpSyncInitError)> {
192
19
    match config.start_chain_information.as_ref().finality {
193
        // TODO: we make sure that `finalized_scheduled_change` is `None` because it seems complicated to support, but ideally it would be supported
194
        ChainInformationFinalityRef::Grandpa {
195
            finalized_scheduled_change: None,
196
            ..
197
19
        } => {}
198
        _ => {
199
0
            return Err((
200
0
                config.start_chain_information,
201
0
                WarpSyncInitError::NotGrandpa,
202
0
            ))
203
        }
204
    }
205
206
19
    match config.start_chain_information.as_ref().consensus {
207
19
        ChainInformationConsensusRef::Babe { .. } | ChainInformationConsensusRef::Aura { .. } => {}
208
        ChainInformationConsensusRef::Unknown => {
209
0
            return Err((
210
0
                config.start_chain_information,
211
0
                WarpSyncInitError::UnknownConsensus,
212
0
            ))
213
        }
214
    }
215
216
19
    let warped_header = config
217
19
        .start_chain_information
218
19
        .as_ref()
219
19
        .finalized_block_header
220
19
        .scale_encoding_vec(config.block_number_bytes);
221
19
222
19
    Ok(WarpSync {
223
19
        warped_header_number: config
224
19
            .start_chain_information
225
19
            .as_ref()
226
19
            .finalized_block_header
227
19
            .number,
228
19
        warped_header_state_root: *config
229
19
            .start_chain_information
230
19
            .as_ref()
231
19
            .finalized_block_header
232
19
            .state_root,
233
19
        warped_header_extrinsics_root: *config
234
19
            .start_chain_information
235
19
            .as_ref()
236
19
            .finalized_block_header
237
19
            .extrinsics_root,
238
19
        warped_header_hash: header::hash_from_scale_encoded_header(&warped_header),
239
19
        warped_header,
240
19
        warped_finality: config.start_chain_information.as_ref().finality.into(),
241
19
        warped_block_ty: WarpedBlockTy::AlreadyVerified,
242
19
        runtime_calls: runtime_calls_default_value(
243
19
            config.start_chain_information.as_ref().consensus,
244
19
        ),
245
19
        verified_chain_information: config.start_chain_information,
246
19
        code_trie_node_hint: config.code_trie_node_hint,
247
19
        num_download_ahead_fragments: config.num_download_ahead_fragments,
248
19
        warp_sync_minimum_gap: config.warp_sync_minimum_gap,
249
19
        block_number_bytes: config.block_number_bytes,
250
19
        download_all_chain_information_storage_proofs: config
251
19
            .download_all_chain_information_storage_proofs,
252
19
        sources: slab::Slab::with_capacity(config.sources_capacity),
253
19
        sources_by_finalized_height: BTreeSet::new(),
254
19
        in_progress_requests: slab::Slab::with_capacity(config.requests_capacity),
255
19
        in_progress_requests_by_source: BTreeSet::new(),
256
19
        warp_sync_fragments_download: None,
257
19
        verify_queue: VecDeque::new(),
258
19
        runtime_download: RuntimeDownload::NotStarted {
259
19
            hint_doesnt_match: false,
260
19
        },
261
19
        body_download: if config.download_block_body {
262
19
            BodyDownload::NotStarted
263
        } else {
264
0
            BodyDownload::NotNeeded
265
        },
266
    })
267
19
}
268
269
/// Error potentially returned by [`start_warp_sync()`].
270
0
#[derive(Debug, derive_more::Display, Clone)]
Unexecuted instantiation: _RNvXsb_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_17WarpSyncInitErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsb_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_17WarpSyncInitErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
271
pub enum WarpSyncInitError {
272
    /// Chain doesn't use the Grandpa finality algorithm.
273
    NotGrandpa,
274
    /// Chain uses an unrecognized consensus mechanism.
275
    UnknownConsensus,
276
}
277
278
/// Identifier for a source in the [`WarpSync`].
279
//
280
// Implementation note: this represents the index within the `Slab` used for the list of sources.
281
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
282
pub struct SourceId(usize);
283
284
impl SourceId {
285
    /// Smallest possible [`SourceId`]. It is always inferior or equal to any other.
286
    pub const MIN: Self = SourceId(usize::MIN);
287
}
288
289
// TODO: consider removing this entirely
290
pub struct RuntimeInformation {
291
    /// The runtime constructed in `VirtualMachineParamsGet`. Corresponds to the runtime of the
292
    /// finalized block of [`WarpSync::as_chain_information`].
293
    pub finalized_runtime: HostVmPrototype,
294
295
    /// List of SCALE-encoded extrinsics of the body of the finalized block.
296
    /// `Some` if and only if [`Config::download_block_body`] was `true`.
297
    pub finalized_body: Option<Vec<Vec<u8>>>,
298
299
    /// Storage value at the `:code` key of the finalized block.
300
    pub finalized_storage_code: Option<Vec<u8>>,
301
302
    /// Storage value at the `:heappages` key of the finalized block.
303
    pub finalized_storage_heap_pages: Option<Vec<u8>>,
304
305
    /// Merkle value of the `:code` trie node of the finalized block.
306
    pub finalized_storage_code_merkle_value: Option<Vec<u8>>,
307
308
    /// Closest ancestor of the `:code` trie node of the finalized block excluding `:code` itself.
309
    pub finalized_storage_code_closest_ancestor_excluding: Option<Vec<Nibble>>,
310
}
311
312
/// Fragment to be verified.
313
#[derive(Debug)]
314
pub struct WarpSyncFragment {
315
    /// Header of a block in the chain.
316
    pub scale_encoded_header: Vec<u8>,
317
318
    /// Justification that proves the finality of [`WarpSyncFragment::scale_encoded_header`].
319
    pub scale_encoded_justification: Vec<u8>,
320
}
321
322
/// Warp syncing process state machine.
323
pub struct WarpSync<TSrc, TRq> {
324
    /// SCALE-encoded header of the finalized block of the chain we warp synced to. Initially
325
    /// identical to the value in [`WarpSync::verified_chain_information`].
326
    warped_header: Vec<u8>,
327
    /// Hash of the block in [`WarpSync::warped_header`].
328
    warped_header_hash: [u8; 32],
329
    /// State trie root hash of the block in [`WarpSync::warped_header`].
330
    warped_header_state_root: [u8; 32],
331
    /// Extrinsics trie root hash of the block in [`WarpSync::warped_header`].
332
    warped_header_extrinsics_root: [u8; 32],
333
    /// Number of the block in [`WarpSync::warped_header`].
334
    warped_header_number: u64,
335
    /// Information about the finality of the chain at the point where we warp synced to.
336
    /// Initially identical to the value in [`WarpSync::verified_chain_information`].
337
    warped_finality: ChainInformationFinality,
338
    /// Information about the block described by [`WarpSync::warped_header`] and
339
    /// [`WarpSync::warped_finality`].
340
    warped_block_ty: WarpedBlockTy,
341
    /// See [`Config::code_trie_node_hint`].
342
    code_trie_node_hint: Option<ConfigCodeTrieNodeHint>,
343
    /// Starting point of the warp syncing as provided to [`start_warp_sync`], or latest chain
344
    /// information that was warp synced to.
345
    verified_chain_information: ValidChainInformation,
346
    /// See [`Config::num_download_ahead_fragments`].
347
    num_download_ahead_fragments: usize,
348
    /// See [`Config::warp_sync_minimum_gap`].
349
    warp_sync_minimum_gap: usize,
350
    /// See [`Config::block_number_bytes`].
351
    block_number_bytes: usize,
352
    /// See [`Config::download_all_chain_information_storage_proofs`].
353
    download_all_chain_information_storage_proofs: bool,
354
    /// List of requests that have been added using [`WarpSync::add_source`].
355
    sources: slab::Slab<Source<TSrc>>,
356
    /// Subset of the entries as [`WarpSync::sources`] whose [`Source::finalized_block_height`]
357
    /// is `Ok`. Indexed by [`Source::finalized_block_height`].
358
    sources_by_finalized_height: BTreeSet<(u64, SourceId)>,
359
    /// List of requests that have been added using [`WarpSync::add_request`].
360
    in_progress_requests: slab::Slab<(SourceId, TRq, RequestDetail)>,
361
    /// Identical to [`WarpSync::in_progress_requests`], but indexed differently.
362
    in_progress_requests_by_source: BTreeSet<(SourceId, RequestId)>,
363
    /// Request that is downloading warp sync fragments, if any has been started yet.
364
    warp_sync_fragments_download: Option<RequestId>,
365
    /// Queue of fragments that have been downloaded and need to be verified.
366
    verify_queue: VecDeque<PendingVerify>,
367
    /// State of the download of the runtime and chain information call proofs.
368
    runtime_download: RuntimeDownload,
369
    /// State of the download of the body of the block.
370
    body_download: BodyDownload,
371
    /// For each call required by the chain information builder, whether it has been downloaded yet.
372
    runtime_calls:
373
        hashbrown::HashMap<chain_information::build::RuntimeCall, CallProof, fnv::FnvBuildHasher>,
374
}
375
376
/// See [`WarpSync::sources`].
377
#[derive(Debug, Copy, Clone)]
378
struct Source<TSrc> {
379
    /// User data chosen by the API user.
380
    user_data: TSrc,
381
    /// Height of the finalized block of the source, as reported by the source.
382
    finalized_block_height: u64,
383
}
384
385
/// See [`WarpSync::warped_block_ty`].
386
enum WarpedBlockTy {
387
    /// Block is equal to the finalized block in [`WarpSync::verified_chain_information`].
388
    AlreadyVerified,
389
    /// Block is known to not be warp-syncable due to an incompatibility between smoldot and
390
    /// the chain.
391
    KnownBad,
392
    /// Block is expected to be warp syncable.
393
    Normal,
394
}
395
396
/// See [`WarpSync::runtime_download`].
397
enum RuntimeDownload {
398
    NotStarted {
399
        hint_doesnt_match: bool,
400
    },
401
    Downloading {
402
        hint_doesnt_match: bool,
403
        request_id: RequestId,
404
    },
405
    NotVerified {
406
        /// Source the runtime has been obtained from. `None` if the source has been removed.
407
        downloaded_source: Option<SourceId>,
408
        hint_doesnt_match: bool,
409
        trie_proof: Vec<u8>,
410
    },
411
    Verified {
412
        downloaded_runtime: DownloadedRuntime,
413
        chain_info_builder: chain_information::build::ChainInformationBuild,
414
    },
415
}
416
417
/// See [`WarpSync::body_download`].
418
enum BodyDownload {
419
    NotNeeded,
420
    NotStarted,
421
    Downloading {
422
        request_id: RequestId,
423
    },
424
    Downloaded {
425
        /// Source the body has been obtained from. `None` if the source has been removed.
426
        downloaded_source: Option<SourceId>,
427
        body: Vec<Vec<u8>>,
428
    },
429
}
430
431
/// See [`WarpSync::verify_queue`].
432
struct PendingVerify {
433
    /// Source the fragments have been obtained from. `None` if the source has been removed.
434
    downloaded_source: Option<SourceId>,
435
    /// `true` if the source has indicated that there is no more fragment afterwards, in other
436
    /// words that the last fragment corresponds to the current finalized block of the chain.
437
    final_set_of_fragments: bool,
438
    /// List of fragments to verify. Can be empty.
439
    fragments: Vec<WarpSyncFragment>,
440
    /// Number of fragments at the start of [`PendingVerify::fragments`] that have already been
441
    /// verified. Must always be strictly inferior to `fragments.len()`, unless the list of
442
    /// fragments is empty.
443
    next_fragment_to_verify_index: usize,
444
}
445
446
/// See [`RuntimeDownload::Verified`].
447
struct DownloadedRuntime {
448
    /// Storage item at the `:code` key. `None` if there is no entry at that key.
449
    storage_code: Option<Vec<u8>>,
450
    /// Storage item at the `:heappages` key. `None` if there is no entry at that key.
451
    storage_heap_pages: Option<Vec<u8>>,
452
    /// Merkle value of the `:code` trie node. `None` if there is no entry at that key.
453
    code_merkle_value: Option<Vec<u8>>,
454
    /// Closest ancestor of the `:code` key except for `:code` itself.
455
    closest_ancestor_excluding: Option<Vec<Nibble>>,
456
}
457
458
/// See [`WarpSync::runtime_calls`].
459
enum CallProof {
460
    NotStarted,
461
    Downloading(RequestId),
462
    Downloaded {
463
        /// Source the proof has been obtained from. `None` if the source has been removed.
464
        downloaded_source: Option<SourceId>,
465
        proof: Vec<u8>,
466
    },
467
}
468
469
/// Returns the default value for [`WarpSync::runtime_calls`].
470
///
471
/// Contains the list of calls that we anticipate the chain information builder will make. This
472
/// assumes that the runtime is the latest version available.
473
21
fn runtime_calls_default_value(
474
21
    verified_chain_information_consensus: chain_information::ChainInformationConsensusRef,
475
21
) -> hashbrown::HashMap<chain_information::build::RuntimeCall, CallProof, fnv::FnvBuildHasher> {
476
21
    let mut list = hashbrown::HashMap::with_capacity_and_hasher(8, Default::default());
477
21
    match verified_chain_information_consensus {
478
21
        ChainInformationConsensusRef::Aura { .. } => {
479
21
            list.insert(
480
21
                chain_information::build::RuntimeCall::AuraApiAuthorities,
481
21
                CallProof::NotStarted,
482
21
            );
483
21
            list.insert(
484
21
                chain_information::build::RuntimeCall::AuraApiSlotDuration,
485
21
                CallProof::NotStarted,
486
21
            );
487
21
        }
488
0
        ChainInformationConsensusRef::Babe { .. } => {
489
0
            list.insert(
490
0
                chain_information::build::RuntimeCall::BabeApiCurrentEpoch,
491
0
                CallProof::NotStarted,
492
0
            );
493
0
            list.insert(
494
0
                chain_information::build::RuntimeCall::BabeApiNextEpoch,
495
0
                CallProof::NotStarted,
496
0
            );
497
0
            list.insert(
498
0
                chain_information::build::RuntimeCall::BabeApiConfiguration,
499
0
                CallProof::NotStarted,
500
0
            );
501
0
        }
502
0
        ChainInformationConsensusRef::Unknown => {}
503
    }
504
21
    list
505
21
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot4sync9warp_sync27runtime_calls_default_value
_RNvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync27runtime_calls_default_value
Line
Count
Source
473
21
fn runtime_calls_default_value(
474
21
    verified_chain_information_consensus: chain_information::ChainInformationConsensusRef,
475
21
) -> hashbrown::HashMap<chain_information::build::RuntimeCall, CallProof, fnv::FnvBuildHasher> {
476
21
    let mut list = hashbrown::HashMap::with_capacity_and_hasher(8, Default::default());
477
21
    match verified_chain_information_consensus {
478
21
        ChainInformationConsensusRef::Aura { .. } => {
479
21
            list.insert(
480
21
                chain_information::build::RuntimeCall::AuraApiAuthorities,
481
21
                CallProof::NotStarted,
482
21
            );
483
21
            list.insert(
484
21
                chain_information::build::RuntimeCall::AuraApiSlotDuration,
485
21
                CallProof::NotStarted,
486
21
            );
487
21
        }
488
0
        ChainInformationConsensusRef::Babe { .. } => {
489
0
            list.insert(
490
0
                chain_information::build::RuntimeCall::BabeApiCurrentEpoch,
491
0
                CallProof::NotStarted,
492
0
            );
493
0
            list.insert(
494
0
                chain_information::build::RuntimeCall::BabeApiNextEpoch,
495
0
                CallProof::NotStarted,
496
0
            );
497
0
            list.insert(
498
0
                chain_information::build::RuntimeCall::BabeApiConfiguration,
499
0
                CallProof::NotStarted,
500
0
            );
501
0
        }
502
0
        ChainInformationConsensusRef::Unknown => {}
503
    }
504
21
    list
505
21
}
506
507
/// See [`WarpSync::status`].
508
#[derive(Debug)]
509
pub enum Status<'a, TSrc> {
510
    /// Warp syncing algorithm is downloading Grandpa warp sync fragments containing a finality
511
    /// proof.
512
    Fragments {
513
        /// Source from which the fragments are currently being downloaded, if any.
514
        source: Option<(SourceId, &'a TSrc)>,
515
        /// Hash of the highest block that is proven to be finalized.
516
        ///
517
        /// This isn't necessarily the same block as returned by
518
        /// [`WarpSync::as_chain_information`], as this function first has to download
519
        /// extra information compared to just the finalized block.
520
        finalized_block_hash: [u8; 32],
521
        /// Height of the block indicated by [`Status::ChainInformation::finalized_block_hash`].
522
        finalized_block_number: u64,
523
    },
524
    /// Warp syncing algorithm has reached the head of the finalized chain and is downloading and
525
    /// building the chain information.
526
    ChainInformation {
527
        /// Hash of the highest block that is proven to be finalized.
528
        ///
529
        /// This isn't necessarily the same block as returned by
530
        /// [`WarpSync::as_chain_information`], as this function first has to download
531
        /// extra information compared to just the finalized block.
532
        finalized_block_hash: [u8; 32],
533
        /// Height of the block indicated by [`Status::ChainInformation::finalized_block_hash`].
534
        finalized_block_number: u64,
535
    },
536
}
537
538
impl<TSrc, TRq> WarpSync<TSrc, TRq> {
539
    /// Returns the value that was initially passed in [`Config::block_number_bytes`].
540
0
    pub fn block_number_bytes(&self) -> usize {
541
0
        self.block_number_bytes
542
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE18block_number_bytesB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE18block_number_bytesCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE18block_number_bytesB8_
543
544
    /// Returns the chain information that is considered verified.
545
0
    pub fn as_chain_information(&self) -> ValidChainInformationRef {
546
0
        // Note: after verifying a warp sync fragment, we are certain that the header targeted by
547
0
        // this fragment is indeed part of the chain. However, this is not enough in order to
548
0
        // produce a full chain information struct. Such struct can only be produced after the
549
0
        // entire warp syncing has succeeded. If if it still in progress, all we can return is
550
0
        // the starting point.
551
0
        (&self.verified_chain_information).into()
552
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE20as_chain_informationB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20as_chain_informationCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE20as_chain_informationB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20as_chain_informationCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20as_chain_informationCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20as_chain_informationCsibGXYHQB8Ea_25json_rpc_general_requests
553
554
    /// Modifies the chain information known to be valid.
555
0
    pub fn set_chain_information(&mut self, chain_information: ValidChainInformationRef) {
556
0
        // The implementation simply resets the state machine, apart from the fragment download
557
0
        // and verification queue.
558
0
        // TODO: what if the new chain doesn't support grandpa?
559
0
        if self.warped_header_number <= chain_information.as_ref().finalized_block_header.number {
560
0
            self.warped_header = chain_information
561
0
                .as_ref()
562
0
                .finalized_block_header
563
0
                .scale_encoding_vec(self.block_number_bytes);
564
0
            self.warped_header_hash = chain_information
565
0
                .as_ref()
566
0
                .finalized_block_header
567
0
                .hash(self.block_number_bytes);
568
0
            self.warped_header_state_root =
569
0
                *chain_information.as_ref().finalized_block_header.state_root;
570
0
            self.warped_header_extrinsics_root = *chain_information
571
0
                .as_ref()
572
0
                .finalized_block_header
573
0
                .extrinsics_root;
574
0
            self.warped_header_number = chain_information.as_ref().finalized_block_header.number;
575
0
            self.warped_finality = chain_information.as_ref().finality.into();
576
0
            self.warped_block_ty = WarpedBlockTy::AlreadyVerified;
577
0
578
0
            self.verified_chain_information = chain_information.into();
579
0
            self.runtime_calls =
580
0
                runtime_calls_default_value(self.verified_chain_information.as_ref().consensus);
581
0
582
0
            self.runtime_download = RuntimeDownload::NotStarted {
583
0
                hint_doesnt_match: false,
584
0
            };
585
586
0
            if !matches!(self.body_download, BodyDownload::NotNeeded) {
587
0
                self.body_download = BodyDownload::NotStarted;
588
0
            }
589
0
        }
590
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE21set_chain_informationB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21set_chain_informationCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE21set_chain_informationB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21set_chain_informationCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21set_chain_informationCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21set_chain_informationCsibGXYHQB8Ea_25json_rpc_general_requests
591
592
    /// Returns the current status of the warp syncing.
593
0
    pub fn status(&self) -> Status<TSrc> {
594
0
        match &self.runtime_download {
595
            RuntimeDownload::NotStarted { .. } => {
596
0
                let finalized_block_hash = self.warped_header_hash;
597
598
0
                let source_id =
599
0
                    if let Some(warp_sync_fragments_download) = self.warp_sync_fragments_download {
600
0
                        Some(
601
0
                            self.in_progress_requests
602
0
                                .get(warp_sync_fragments_download.0)
603
0
                                .unwrap()
604
0
                                .0,
605
0
                        )
606
                    } else {
607
0
                        self.verify_queue.back().and_then(|f| f.downloaded_source)
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE6status0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE6status0Ba_
608
                    };
609
610
0
                Status::Fragments {
611
0
                    source: source_id.map(|id| (id, &self.sources[id.0].user_data)),
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE6statuss_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE6statuss_0Ba_
612
0
                    finalized_block_hash,
613
0
                    finalized_block_number: self.warped_header_number,
614
0
                }
615
            }
616
0
            _ => Status::ChainInformation {
617
0
                finalized_block_hash: self.warped_header_hash,
618
0
                finalized_block_number: self.warped_header_number,
619
0
            },
620
        }
621
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE6statusB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE6statusB8_
622
623
    /// Returns a list of all known sources stored in the state machine.
624
0
    pub fn sources(&'_ self) -> impl Iterator<Item = SourceId> + '_ {
625
0
        self.sources.iter().map(|(id, _)| SourceId(id))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE7sources0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE7sources0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE7sources0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE7sources0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE7sources0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE7sources0CsibGXYHQB8Ea_25json_rpc_general_requests
626
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE7sourcesB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE7sourcesCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE7sourcesB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE7sourcesCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE7sourcesCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE7sourcesCsibGXYHQB8Ea_25json_rpc_general_requests
627
628
    /// Returns the number of ongoing requests that concern this source.
629
    ///
630
    /// # Panic
631
    ///
632
    /// Panics if the [`SourceId`] is invalid.
633
    ///
634
0
    pub fn source_num_ongoing_requests(&self, source_id: SourceId) -> usize {
635
0
        assert!(self.sources.contains(source_id.0));
636
0
        self.in_progress_requests_by_source
637
0
            .range((source_id, RequestId(usize::MIN))..=(source_id, RequestId(usize::MAX)))
638
0
            .count()
639
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE27source_num_ongoing_requestsB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE27source_num_ongoing_requestsB8_
640
641
    /// Add a source to the list of sources.
642
    ///
643
    /// The source has a finalized block height of 0, which should later be updated using
644
    /// [`WarpSync::set_source_finality_state`].
645
21
    pub fn add_source(&mut self, user_data: TSrc) -> SourceId {
646
21
        let source_id = SourceId(self.sources.insert(Source {
647
21
            user_data,
648
21
            finalized_block_height: 0,
649
21
        }));
650
21
651
21
        let _inserted = self.sources_by_finalized_height.insert((0, source_id));
652
21
        debug_assert!(_inserted);
653
21
        debug_assert!(self.sources.len() >= self.sources_by_finalized_height.len());
654
655
21
        source_id
656
21
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE10add_sourceB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE10add_sourceCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE10add_sourceB8_
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE10add_sourceCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
645
2
    pub fn add_source(&mut self, user_data: TSrc) -> SourceId {
646
2
        let source_id = SourceId(self.sources.insert(Source {
647
2
            user_data,
648
2
            finalized_block_height: 0,
649
2
        }));
650
2
651
2
        let _inserted = self.sources_by_finalized_height.insert((0, source_id));
652
2
        debug_assert!(_inserted);
653
2
        debug_assert!(self.sources.len() >= self.sources_by_finalized_height.len());
654
655
2
        source_id
656
2
    }
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE10add_sourceCscDgN54JpMGG_6author
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE10add_sourceCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
645
19
    pub fn add_source(&mut self, user_data: TSrc) -> SourceId {
646
19
        let source_id = SourceId(self.sources.insert(Source {
647
19
            user_data,
648
19
            finalized_block_height: 0,
649
19
        }));
650
19
651
19
        let _inserted = self.sources_by_finalized_height.insert((0, source_id));
652
19
        debug_assert!(_inserted);
653
19
        debug_assert!(self.sources.len() >= self.sources_by_finalized_height.len());
654
655
19
        source_id
656
19
    }
657
658
    /// Removes a source from the list of sources. In addition to the user data associated to this
659
    /// source, also returns a list of requests that were in progress concerning this source. These
660
    /// requests are now considered obsolete.
661
    ///
662
    /// # Panic
663
    ///
664
    /// Panics if the [`SourceId`] is invalid.
665
    ///
666
0
    pub fn remove_source(
667
0
        &'_ mut self,
668
0
        to_remove: SourceId,
669
0
    ) -> (TSrc, impl Iterator<Item = (RequestId, TRq)> + '_) {
670
0
        debug_assert!(self.sources.contains(to_remove.0));
671
0
        let removed = self.sources.remove(to_remove.0);
672
0
        let _was_in = self
673
0
            .sources_by_finalized_height
674
0
            .remove(&(removed.finalized_block_height, to_remove));
675
0
        debug_assert!(_was_in);
676
0
        debug_assert!(self.sources.len() >= self.sources_by_finalized_height.len());
677
678
        // We make sure to not leave invalid source IDs in the state of `self`.
679
        // TODO: O(n)
680
0
        for item in &mut self.verify_queue {
681
0
            if item.downloaded_source == Some(to_remove) {
682
0
                item.downloaded_source = None;
683
0
            }
684
        }
685
        if let RuntimeDownload::NotVerified {
686
0
            downloaded_source, ..
687
0
        } = &mut self.runtime_download
688
        {
689
0
            if *downloaded_source == Some(to_remove) {
690
0
                *downloaded_source = None;
691
0
            }
692
0
        }
693
        if let BodyDownload::Downloaded {
694
0
            downloaded_source, ..
695
0
        } = &mut self.body_download
696
        {
697
0
            if *downloaded_source == Some(to_remove) {
698
0
                *downloaded_source = None;
699
0
            }
700
0
        }
701
0
        for (_, call_proof) in &mut self.runtime_calls {
702
            if let CallProof::Downloaded {
703
0
                downloaded_source, ..
704
0
            } = call_proof
705
            {
706
0
                if *downloaded_source == Some(to_remove) {
707
0
                    *downloaded_source = None;
708
0
                }
709
0
            }
710
        }
711
712
0
        let obsolete_requests_indices = self
713
0
            .in_progress_requests_by_source
714
0
            .range((to_remove, RequestId(usize::MIN))..=(to_remove, RequestId(usize::MAX)))
715
0
            .map(|(_, rq_id)| rq_id.0)
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE13remove_source0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE13remove_source0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE13remove_source0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE13remove_source0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE13remove_source0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE13remove_source0CsibGXYHQB8Ea_25json_rpc_general_requests
716
0
            .collect::<Vec<_>>();
717
0
        let mut obsolete_requests = Vec::with_capacity(obsolete_requests_indices.len());
718
0
        for index in obsolete_requests_indices {
719
0
            let (_, user_data, _) = self.in_progress_requests.remove(index);
720
0
            self.in_progress_requests_by_source
721
0
                .remove(&(to_remove, RequestId(index)));
722
0
            if self.warp_sync_fragments_download == Some(RequestId(index)) {
723
0
                self.warp_sync_fragments_download = None;
724
0
            }
725
0
            for call in self.runtime_calls.values_mut() {
726
0
                if matches!(call, CallProof::Downloading(rq_id) if *rq_id == RequestId(index)) {
727
0
                    *call = CallProof::NotStarted;
728
0
                }
729
            }
730
            if let RuntimeDownload::Downloading {
731
0
                request_id,
732
0
                hint_doesnt_match,
733
0
            } = &mut self.runtime_download
734
            {
735
0
                if *request_id == RequestId(index) {
736
0
                    self.runtime_download = RuntimeDownload::NotStarted {
737
0
                        hint_doesnt_match: *hint_doesnt_match,
738
0
                    };
739
0
                }
740
0
            }
741
0
            if let BodyDownload::Downloading { request_id } = &mut self.body_download {
742
0
                if *request_id == RequestId(index) {
743
0
                    self.body_download = BodyDownload::NotStarted;
744
0
                }
745
0
            }
746
0
            obsolete_requests.push((RequestId(index), user_data));
747
        }
748
749
0
        (removed.user_data, obsolete_requests.into_iter())
750
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE13remove_sourceB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE13remove_sourceCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE13remove_sourceB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE13remove_sourceCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE13remove_sourceCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE13remove_sourceCsibGXYHQB8Ea_25json_rpc_general_requests
751
752
    /// Sets the finalized block height of the given source.
753
    ///
754
    /// # Panic
755
    ///
756
    /// Panics if `source_id` is invalid.
757
    ///
758
0
    pub fn set_source_finality_state(&mut self, source_id: SourceId, finalized_block_height: u64) {
759
0
        let stored_height = &mut self.sources[source_id.0].finalized_block_height;
760
0
761
0
        // Small optimization. No need to do anything more if the block doesn't actuall change.
762
0
        if *stored_height == finalized_block_height {
763
0
            return;
764
0
        }
765
0
766
0
        // Note that if the new finalized block is below the former one (which is not something
767
0
        // that is ever supposed to happen), we should in principle cancel the requests
768
0
        // targeting that source that require a specific block height. In practice, however,
769
0
        // we don't care as again this isn't supposed to ever happen. While ongoing requests
770
0
        // might fail as a result, this is handled the same way as a regular request failure.
771
0
772
0
        let _was_in = self
773
0
            .sources_by_finalized_height
774
0
            .remove(&(*stored_height, source_id));
775
0
        debug_assert!(_was_in);
776
0
        let _inserted = self
777
0
            .sources_by_finalized_height
778
0
            .insert((finalized_block_height, source_id));
779
0
        debug_assert!(_inserted);
780
781
0
        *stored_height = finalized_block_height;
782
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE25set_source_finality_stateB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE25set_source_finality_stateCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE25set_source_finality_stateB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE25set_source_finality_stateCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE25set_source_finality_stateCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE25set_source_finality_stateCsibGXYHQB8Ea_25json_rpc_general_requests
783
784
    /// Gets the finalized block height of the given source.
785
    ///
786
    /// Equal to 0 if [`WarpSync::set_source_finality_state`] hasn't been called.
787
    ///
788
    /// # Panic
789
    ///
790
    /// Panics if `source_id` is invalid.
791
    ///
792
0
    pub fn source_finality_state(&self, source_id: SourceId) -> u64 {
793
0
        self.sources[source_id.0].finalized_block_height
794
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE21source_finality_stateB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21source_finality_stateCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE21source_finality_stateB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21source_finality_stateCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21source_finality_stateCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE21source_finality_stateCsibGXYHQB8Ea_25json_rpc_general_requests
795
796
    /// Returns a list of requests that should be started in order to drive the warp syncing
797
    /// process to completion.
798
    ///
799
    /// Once a request that matches a desired request is added through
800
    /// [`WarpSync::add_request`], it is no longer returned by this function.
801
43
    pub fn desired_requests(
802
43
        &'_ self,
803
43
    ) -> impl Iterator<Item = (SourceId, &'_ TSrc, DesiredRequest)> + '_ {
804
        // If we are in the fragments download phase, return a fragments download request.
805
43
        let mut desired_warp_sync_request = if self.warp_sync_fragments_download.is_none() {
806
43
            if self.verify_queue.iter().fold(0, |sum, entry| {
807
0
                sum + entry.fragments.len() - entry.next_fragment_to_verify_index
808
43
            }) < self.num_download_ahead_fragments
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requests0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requests0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requests0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requests0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requests0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requests0CsibGXYHQB8Ea_25json_rpc_general_requests
809
            {
810
                // Block hash to request.
811
43
                let start_block_hash = self
812
43
                    .verify_queue
813
43
                    .back()
814
43
                    .and_then(|entry| 
entry.fragments.last()0
)
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss_0CsibGXYHQB8Ea_25json_rpc_general_requests
815
43
                    .map(|fragment| {
816
0
                        header::hash_from_scale_encoded_header(&fragment.scale_encoded_header)
817
43
                    })
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss0_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss0_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss0_0CsibGXYHQB8Ea_25json_rpc_general_requests
818
43
                    .unwrap_or(self.warped_header_hash);
819
43
820
43
                // Calculate the block number at the tail of the verify queue.
821
43
                // Contains `None` if the verify queue has a problem such as an indecodable header.
822
43
                // In that situation, we don't start any new request and wait for the verify
823
43
                // queue to empty itself.
824
43
                let verify_queue_tail_block_number = self
825
43
                    .verify_queue
826
43
                    .back()
827
43
                    .map(|entry| {
828
0
                        entry
829
0
                            .fragments
830
0
                            .last()
831
0
                            .and_then(|fragment| {
832
0
                                header::decode(
833
0
                                    &fragment.scale_encoded_header,
834
0
                                    self.block_number_bytes,
835
0
                                )
836
0
                                .ok()
837
0
                            })
Unexecuted instantiation: _RNCNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss1_00Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_00CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss1_00Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_00CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_00CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_00CsibGXYHQB8Ea_25json_rpc_general_requests
838
0
                            .map(|header| header.number)
Unexecuted instantiation: _RNCNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss1_0s_0Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_0s_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss1_0s_0Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_0s_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_0s_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss1_0s_0CsibGXYHQB8Ea_25json_rpc_general_requests
839
43
                    })
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss1_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss1_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss1_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss1_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss1_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss1_0CsibGXYHQB8Ea_25json_rpc_general_requests
840
43
                    .unwrap_or(Some(self.warped_header_number));
841
43
                let warp_sync_minimum_gap = self.warp_sync_minimum_gap;
842
843
43
                if let Some(verify_queue_tail_block_number) = verify_queue_tail_block_number {
844
                    // Combine the request with every single available source.
845
43
                    either::Left(self.sources.iter().filter_map(move |(src_id, src)| {
846
43
                        if src.finalized_block_height
847
43
                            <= verify_queue_tail_block_number.saturating_add(
848
43
                                u64::try_from(warp_sync_minimum_gap).unwrap_or(u64::MAX),
849
43
                            )
850
                        {
851
43
                            return None;
852
0
                        }
853
0
854
0
                        Some((
855
0
                            SourceId(src_id),
856
0
                            &src.user_data,
857
0
                            DesiredRequest::WarpSyncRequest {
858
0
                                block_hash: start_block_hash,
859
0
                            },
860
0
                        ))
861
43
                    }))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss2_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss2_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss2_0Ba_
_RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss2_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
845
4
                    either::Left(self.sources.iter().filter_map(move |(src_id, src)| {
846
4
                        if src.finalized_block_height
847
4
                            <= verify_queue_tail_block_number.saturating_add(
848
4
                                u64::try_from(warp_sync_minimum_gap).unwrap_or(u64::MAX),
849
4
                            )
850
                        {
851
4
                            return None;
852
0
                        }
853
0
854
0
                        Some((
855
0
                            SourceId(src_id),
856
0
                            &src.user_data,
857
0
                            DesiredRequest::WarpSyncRequest {
858
0
                                block_hash: start_block_hash,
859
0
                            },
860
0
                        ))
861
4
                    }))
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss2_0CscDgN54JpMGG_6author
_RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss2_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
845
39
                    either::Left(self.sources.iter().filter_map(move |(src_id, src)| {
846
39
                        if src.finalized_block_height
847
39
                            <= verify_queue_tail_block_number.saturating_add(
848
39
                                u64::try_from(warp_sync_minimum_gap).unwrap_or(u64::MAX),
849
39
                            )
850
                        {
851
39
                            return None;
852
0
                        }
853
0
854
0
                        Some((
855
0
                            SourceId(src_id),
856
0
                            &src.user_data,
857
0
                            DesiredRequest::WarpSyncRequest {
858
0
                                block_hash: start_block_hash,
859
0
                            },
860
0
                        ))
861
39
                    }))
862
                } else {
863
0
                    either::Right(iter::empty())
864
                }
865
            } else {
866
0
                either::Right(iter::empty())
867
            }
868
        } else {
869
0
            either::Right(iter::empty())
870
        }
871
43
        .peekable();
872
873
        // If we are in the appropriate phase, and we are not currently downloading the runtime,
874
        // return a runtime download request.
875
43
        let desired_runtime_parameters_get = if let (
876
            WarpedBlockTy::Normal,
877
0
            RuntimeDownload::NotStarted { hint_doesnt_match },
878
            None,
879
            true,
880
            None,
881
43
        ) = (
882
43
            &self.warped_block_ty,
883
43
            &self.runtime_download,
884
43
            self.warp_sync_fragments_download,
885
43
            self.verify_queue.is_empty(),
886
43
            desired_warp_sync_request.peek(),
887
43
        ) {
888
0
            let code_key_to_request = if let (false, Some(hint)) =
889
0
                (*hint_doesnt_match, self.code_trie_node_hint.as_ref())
890
            {
891
0
                Cow::Owned(
892
0
                    trie::nibbles_to_bytes_truncate(
893
0
                        hint.closest_ancestor_excluding.iter().copied(),
894
0
                    )
895
0
                    .collect::<Vec<_>>(),
896
0
                )
897
            } else {
898
0
                Cow::Borrowed(&b":code"[..])
899
            };
900
901
            // Sources are ordered by increasing finalized block height, in order to
902
            // have the highest chance for the block to not be pruned.
903
0
            let sources_with_block = self
904
0
                .sources_by_finalized_height
905
0
                .range((self.warped_header_number, SourceId(usize::MIN))..)
906
0
                .map(|(_, src_id)| src_id);
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss3_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss3_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss3_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss3_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss3_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss3_0CsibGXYHQB8Ea_25json_rpc_general_requests
907
0
908
0
            either::Left(sources_with_block.map(move |source_id| {
909
0
                (
910
0
                    *source_id,
911
0
                    &self.sources[source_id.0].user_data,
912
0
                    DesiredRequest::StorageGetMerkleProof {
913
0
                        block_hash: self.warped_header_hash,
914
0
                        state_trie_root: self.warped_header_state_root,
915
0
                        keys: vec![code_key_to_request.to_vec(), b":heappages".to_vec()],
916
0
                    },
917
0
                )
918
0
            }))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss4_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss4_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss4_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss4_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss4_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss4_0CsibGXYHQB8Ea_25json_rpc_general_requests
919
        } else {
920
43
            either::Right(iter::empty())
921
        };
922
923
        // If we are in the appropriate phase, and we are not currently downloading the body of
924
        // the block, return a runtime download request.
925
43
        let desired_body_download =
926
43
            if let 
(WarpedBlockTy::Normal, BodyDownload::NotStarted, None, true, None)0
= (
927
43
                &self.warped_block_ty,
928
43
                &self.body_download,
929
43
                self.warp_sync_fragments_download,
930
43
                self.verify_queue.is_empty(),
931
43
                desired_warp_sync_request.peek(),
932
43
            ) {
933
                // Sources are ordered by increasing finalized block height, in order to
934
                // have the highest chance for the block to not be pruned.
935
0
                let sources_with_block = self
936
0
                    .sources_by_finalized_height
937
0
                    .range((self.warped_header_number, SourceId(usize::MIN))..)
938
0
                    .map(|(_, src_id)| src_id);
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss5_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss5_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss5_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss5_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss5_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss5_0CsibGXYHQB8Ea_25json_rpc_general_requests
939
0
940
0
                either::Left(sources_with_block.map(move |source_id| {
941
0
                    (
942
0
                        *source_id,
943
0
                        &self.sources[source_id.0].user_data,
944
0
                        DesiredRequest::BlockBodyDownload {
945
0
                            block_hash: self.warped_header_hash,
946
0
                            block_number: self.warped_header_number,
947
0
                            extrinsics_root: self.warped_header_extrinsics_root,
948
0
                        },
949
0
                    )
950
0
                }))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss6_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss6_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss6_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss6_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss6_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss6_0CsibGXYHQB8Ea_25json_rpc_general_requests
951
            } else {
952
43
                either::Right(iter::empty())
953
            };
954
955
        // Return the list of runtime calls indicated by the chain information builder state
956
        // machine.
957
43
        let desired_call_proofs = if matches!(self.warped_block_ty, WarpedBlockTy::Normal)
958
0
            && self.warp_sync_fragments_download.is_none()
959
0
            && self.verify_queue.is_empty()
960
0
            && desired_warp_sync_request.peek().is_none()
961
        {
962
0
            either::Left(
963
0
                self.runtime_calls
964
0
                    .iter()
965
0
                    .filter(|(_, v)| matches!(v, CallProof::NotStarted))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss7_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss7_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss7_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss7_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss7_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss7_0CsibGXYHQB8Ea_25json_rpc_general_requests
966
0
                    .map(|(call, _)| DesiredRequest::RuntimeCallMerkleProof {
967
0
                        block_hash: self.warped_header_hash,
968
0
                        function_name: call.function_name().into(),
969
0
                        parameter_vectored: Cow::Owned(call.parameter_vectored_vec()),
970
0
                    })
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss8_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss8_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss8_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss8_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss8_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss8_0CsibGXYHQB8Ea_25json_rpc_general_requests
971
0
                    .flat_map(move |request_detail| {
972
0
                        // Sources are ordered by increasing finalized block height, in order to
973
0
                        // have the highest chance for the block to not be pruned.
974
0
                        let sources_with_block = self
975
0
                            .sources_by_finalized_height
976
0
                            .range((self.warped_header_number, SourceId(usize::MIN))..)
977
0
                            .map(|(_, src_id)| src_id);
Unexecuted instantiation: _RNCNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss9_00Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_00CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss9_00Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_00CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_00CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_00CsibGXYHQB8Ea_25json_rpc_general_requests
978
0
979
0
                        sources_with_block.map(move |source_id| {
980
0
                            (
981
0
                                *source_id,
982
0
                                &self.sources[source_id.0].user_data,
983
0
                                request_detail.clone(),
984
0
                            )
985
0
                        })
Unexecuted instantiation: _RNCNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss9_0s_0Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_0s_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncppE16desired_requestss9_0s_0Bc_
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_0s_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_0s_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB8_8WarpSyncNtNtBa_3all19WarpSyncSourceExtraNtB14_20WarpSyncRequestExtraE16desired_requestss9_0s_0CsibGXYHQB8Ea_25json_rpc_general_requests
986
0
                    }),
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss9_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss9_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE16desired_requestss9_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss9_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss9_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE16desired_requestss9_0CsibGXYHQB8Ea_25json_rpc_general_requests
987
0
            )
988
        } else {
989
43
            either::Right(iter::empty())
990
        };
991
992
        // Chain all these demanded requests together.
993
43
        desired_warp_sync_request
994
43
            .chain(desired_runtime_parameters_get)
995
43
            .chain(desired_body_download)
996
43
            .chain(desired_call_proofs)
997
43
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE16desired_requestsB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE16desired_requestsCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE16desired_requestsB8_
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE16desired_requestsCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
801
4
    pub fn desired_requests(
802
4
        &'_ self,
803
4
    ) -> impl Iterator<Item = (SourceId, &'_ TSrc, DesiredRequest)> + '_ {
804
        // If we are in the fragments download phase, return a fragments download request.
805
4
        let mut desired_warp_sync_request = if self.warp_sync_fragments_download.is_none() {
806
4
            if self.verify_queue.iter().fold(0, |sum, entry| {
807
                sum + entry.fragments.len() - entry.next_fragment_to_verify_index
808
4
            }) < self.num_download_ahead_fragments
809
            {
810
                // Block hash to request.
811
4
                let start_block_hash = self
812
4
                    .verify_queue
813
4
                    .back()
814
4
                    .and_then(|entry| entry.fragments.last())
815
4
                    .map(|fragment| {
816
                        header::hash_from_scale_encoded_header(&fragment.scale_encoded_header)
817
4
                    })
818
4
                    .unwrap_or(self.warped_header_hash);
819
4
820
4
                // Calculate the block number at the tail of the verify queue.
821
4
                // Contains `None` if the verify queue has a problem such as an indecodable header.
822
4
                // In that situation, we don't start any new request and wait for the verify
823
4
                // queue to empty itself.
824
4
                let verify_queue_tail_block_number = self
825
4
                    .verify_queue
826
4
                    .back()
827
4
                    .map(|entry| {
828
                        entry
829
                            .fragments
830
                            .last()
831
                            .and_then(|fragment| {
832
                                header::decode(
833
                                    &fragment.scale_encoded_header,
834
                                    self.block_number_bytes,
835
                                )
836
                                .ok()
837
                            })
838
                            .map(|header| header.number)
839
4
                    })
840
4
                    .unwrap_or(Some(self.warped_header_number));
841
4
                let warp_sync_minimum_gap = self.warp_sync_minimum_gap;
842
843
4
                if let Some(verify_queue_tail_block_number) = verify_queue_tail_block_number {
844
                    // Combine the request with every single available source.
845
4
                    either::Left(self.sources.iter().filter_map(move |(src_id, src)| {
846
                        if src.finalized_block_height
847
                            <= verify_queue_tail_block_number.saturating_add(
848
                                u64::try_from(warp_sync_minimum_gap).unwrap_or(u64::MAX),
849
                            )
850
                        {
851
                            return None;
852
                        }
853
854
                        Some((
855
                            SourceId(src_id),
856
                            &src.user_data,
857
                            DesiredRequest::WarpSyncRequest {
858
                                block_hash: start_block_hash,
859
                            },
860
                        ))
861
4
                    }))
862
                } else {
863
0
                    either::Right(iter::empty())
864
                }
865
            } else {
866
0
                either::Right(iter::empty())
867
            }
868
        } else {
869
0
            either::Right(iter::empty())
870
        }
871
4
        .peekable();
872
873
        // If we are in the appropriate phase, and we are not currently downloading the runtime,
874
        // return a runtime download request.
875
4
        let desired_runtime_parameters_get = if let (
876
            WarpedBlockTy::Normal,
877
0
            RuntimeDownload::NotStarted { hint_doesnt_match },
878
            None,
879
            true,
880
            None,
881
4
        ) = (
882
4
            &self.warped_block_ty,
883
4
            &self.runtime_download,
884
4
            self.warp_sync_fragments_download,
885
4
            self.verify_queue.is_empty(),
886
4
            desired_warp_sync_request.peek(),
887
4
        ) {
888
0
            let code_key_to_request = if let (false, Some(hint)) =
889
0
                (*hint_doesnt_match, self.code_trie_node_hint.as_ref())
890
            {
891
0
                Cow::Owned(
892
0
                    trie::nibbles_to_bytes_truncate(
893
0
                        hint.closest_ancestor_excluding.iter().copied(),
894
0
                    )
895
0
                    .collect::<Vec<_>>(),
896
0
                )
897
            } else {
898
0
                Cow::Borrowed(&b":code"[..])
899
            };
900
901
            // Sources are ordered by increasing finalized block height, in order to
902
            // have the highest chance for the block to not be pruned.
903
0
            let sources_with_block = self
904
0
                .sources_by_finalized_height
905
0
                .range((self.warped_header_number, SourceId(usize::MIN))..)
906
0
                .map(|(_, src_id)| src_id);
907
0
908
0
            either::Left(sources_with_block.map(move |source_id| {
909
                (
910
                    *source_id,
911
                    &self.sources[source_id.0].user_data,
912
                    DesiredRequest::StorageGetMerkleProof {
913
                        block_hash: self.warped_header_hash,
914
                        state_trie_root: self.warped_header_state_root,
915
                        keys: vec![code_key_to_request.to_vec(), b":heappages".to_vec()],
916
                    },
917
                )
918
0
            }))
919
        } else {
920
4
            either::Right(iter::empty())
921
        };
922
923
        // If we are in the appropriate phase, and we are not currently downloading the body of
924
        // the block, return a runtime download request.
925
4
        let desired_body_download =
926
4
            if let 
(WarpedBlockTy::Normal, BodyDownload::NotStarted, None, true, None)0
= (
927
4
                &self.warped_block_ty,
928
4
                &self.body_download,
929
4
                self.warp_sync_fragments_download,
930
4
                self.verify_queue.is_empty(),
931
4
                desired_warp_sync_request.peek(),
932
4
            ) {
933
                // Sources are ordered by increasing finalized block height, in order to
934
                // have the highest chance for the block to not be pruned.
935
0
                let sources_with_block = self
936
0
                    .sources_by_finalized_height
937
0
                    .range((self.warped_header_number, SourceId(usize::MIN))..)
938
0
                    .map(|(_, src_id)| src_id);
939
0
940
0
                either::Left(sources_with_block.map(move |source_id| {
941
                    (
942
                        *source_id,
943
                        &self.sources[source_id.0].user_data,
944
                        DesiredRequest::BlockBodyDownload {
945
                            block_hash: self.warped_header_hash,
946
                            block_number: self.warped_header_number,
947
                            extrinsics_root: self.warped_header_extrinsics_root,
948
                        },
949
                    )
950
0
                }))
951
            } else {
952
4
                either::Right(iter::empty())
953
            };
954
955
        // Return the list of runtime calls indicated by the chain information builder state
956
        // machine.
957
4
        let desired_call_proofs = if matches!(self.warped_block_ty, WarpedBlockTy::Normal)
958
0
            && self.warp_sync_fragments_download.is_none()
959
0
            && self.verify_queue.is_empty()
960
0
            && desired_warp_sync_request.peek().is_none()
961
        {
962
0
            either::Left(
963
0
                self.runtime_calls
964
0
                    .iter()
965
0
                    .filter(|(_, v)| matches!(v, CallProof::NotStarted))
966
0
                    .map(|(call, _)| DesiredRequest::RuntimeCallMerkleProof {
967
                        block_hash: self.warped_header_hash,
968
                        function_name: call.function_name().into(),
969
                        parameter_vectored: Cow::Owned(call.parameter_vectored_vec()),
970
0
                    })
971
0
                    .flat_map(move |request_detail| {
972
                        // Sources are ordered by increasing finalized block height, in order to
973
                        // have the highest chance for the block to not be pruned.
974
                        let sources_with_block = self
975
                            .sources_by_finalized_height
976
                            .range((self.warped_header_number, SourceId(usize::MIN))..)
977
                            .map(|(_, src_id)| src_id);
978
979
                        sources_with_block.map(move |source_id| {
980
                            (
981
                                *source_id,
982
                                &self.sources[source_id.0].user_data,
983
                                request_detail.clone(),
984
                            )
985
                        })
986
0
                    }),
987
0
            )
988
        } else {
989
4
            either::Right(iter::empty())
990
        };
991
992
        // Chain all these demanded requests together.
993
4
        desired_warp_sync_request
994
4
            .chain(desired_runtime_parameters_get)
995
4
            .chain(desired_body_download)
996
4
            .chain(desired_call_proofs)
997
4
    }
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE16desired_requestsCscDgN54JpMGG_6author
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE16desired_requestsCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
801
39
    pub fn desired_requests(
802
39
        &'_ self,
803
39
    ) -> impl Iterator<Item = (SourceId, &'_ TSrc, DesiredRequest)> + '_ {
804
        // If we are in the fragments download phase, return a fragments download request.
805
39
        let mut desired_warp_sync_request = if self.warp_sync_fragments_download.is_none() {
806
39
            if self.verify_queue.iter().fold(0, |sum, entry| {
807
                sum + entry.fragments.len() - entry.next_fragment_to_verify_index
808
39
            }) < self.num_download_ahead_fragments
809
            {
810
                // Block hash to request.
811
39
                let start_block_hash = self
812
39
                    .verify_queue
813
39
                    .back()
814
39
                    .and_then(|entry| entry.fragments.last())
815
39
                    .map(|fragment| {
816
                        header::hash_from_scale_encoded_header(&fragment.scale_encoded_header)
817
39
                    })
818
39
                    .unwrap_or(self.warped_header_hash);
819
39
820
39
                // Calculate the block number at the tail of the verify queue.
821
39
                // Contains `None` if the verify queue has a problem such as an indecodable header.
822
39
                // In that situation, we don't start any new request and wait for the verify
823
39
                // queue to empty itself.
824
39
                let verify_queue_tail_block_number = self
825
39
                    .verify_queue
826
39
                    .back()
827
39
                    .map(|entry| {
828
                        entry
829
                            .fragments
830
                            .last()
831
                            .and_then(|fragment| {
832
                                header::decode(
833
                                    &fragment.scale_encoded_header,
834
                                    self.block_number_bytes,
835
                                )
836
                                .ok()
837
                            })
838
                            .map(|header| header.number)
839
39
                    })
840
39
                    .unwrap_or(Some(self.warped_header_number));
841
39
                let warp_sync_minimum_gap = self.warp_sync_minimum_gap;
842
843
39
                if let Some(verify_queue_tail_block_number) = verify_queue_tail_block_number {
844
                    // Combine the request with every single available source.
845
39
                    either::Left(self.sources.iter().filter_map(move |(src_id, src)| {
846
                        if src.finalized_block_height
847
                            <= verify_queue_tail_block_number.saturating_add(
848
                                u64::try_from(warp_sync_minimum_gap).unwrap_or(u64::MAX),
849
                            )
850
                        {
851
                            return None;
852
                        }
853
854
                        Some((
855
                            SourceId(src_id),
856
                            &src.user_data,
857
                            DesiredRequest::WarpSyncRequest {
858
                                block_hash: start_block_hash,
859
                            },
860
                        ))
861
39
                    }))
862
                } else {
863
0
                    either::Right(iter::empty())
864
                }
865
            } else {
866
0
                either::Right(iter::empty())
867
            }
868
        } else {
869
0
            either::Right(iter::empty())
870
        }
871
39
        .peekable();
872
873
        // If we are in the appropriate phase, and we are not currently downloading the runtime,
874
        // return a runtime download request.
875
39
        let desired_runtime_parameters_get = if let (
876
            WarpedBlockTy::Normal,
877
0
            RuntimeDownload::NotStarted { hint_doesnt_match },
878
            None,
879
            true,
880
            None,
881
39
        ) = (
882
39
            &self.warped_block_ty,
883
39
            &self.runtime_download,
884
39
            self.warp_sync_fragments_download,
885
39
            self.verify_queue.is_empty(),
886
39
            desired_warp_sync_request.peek(),
887
39
        ) {
888
0
            let code_key_to_request = if let (false, Some(hint)) =
889
0
                (*hint_doesnt_match, self.code_trie_node_hint.as_ref())
890
            {
891
0
                Cow::Owned(
892
0
                    trie::nibbles_to_bytes_truncate(
893
0
                        hint.closest_ancestor_excluding.iter().copied(),
894
0
                    )
895
0
                    .collect::<Vec<_>>(),
896
0
                )
897
            } else {
898
0
                Cow::Borrowed(&b":code"[..])
899
            };
900
901
            // Sources are ordered by increasing finalized block height, in order to
902
            // have the highest chance for the block to not be pruned.
903
0
            let sources_with_block = self
904
0
                .sources_by_finalized_height
905
0
                .range((self.warped_header_number, SourceId(usize::MIN))..)
906
0
                .map(|(_, src_id)| src_id);
907
0
908
0
            either::Left(sources_with_block.map(move |source_id| {
909
                (
910
                    *source_id,
911
                    &self.sources[source_id.0].user_data,
912
                    DesiredRequest::StorageGetMerkleProof {
913
                        block_hash: self.warped_header_hash,
914
                        state_trie_root: self.warped_header_state_root,
915
                        keys: vec![code_key_to_request.to_vec(), b":heappages".to_vec()],
916
                    },
917
                )
918
0
            }))
919
        } else {
920
39
            either::Right(iter::empty())
921
        };
922
923
        // If we are in the appropriate phase, and we are not currently downloading the body of
924
        // the block, return a runtime download request.
925
39
        let desired_body_download =
926
39
            if let 
(WarpedBlockTy::Normal, BodyDownload::NotStarted, None, true, None)0
= (
927
39
                &self.warped_block_ty,
928
39
                &self.body_download,
929
39
                self.warp_sync_fragments_download,
930
39
                self.verify_queue.is_empty(),
931
39
                desired_warp_sync_request.peek(),
932
39
            ) {
933
                // Sources are ordered by increasing finalized block height, in order to
934
                // have the highest chance for the block to not be pruned.
935
0
                let sources_with_block = self
936
0
                    .sources_by_finalized_height
937
0
                    .range((self.warped_header_number, SourceId(usize::MIN))..)
938
0
                    .map(|(_, src_id)| src_id);
939
0
940
0
                either::Left(sources_with_block.map(move |source_id| {
941
                    (
942
                        *source_id,
943
                        &self.sources[source_id.0].user_data,
944
                        DesiredRequest::BlockBodyDownload {
945
                            block_hash: self.warped_header_hash,
946
                            block_number: self.warped_header_number,
947
                            extrinsics_root: self.warped_header_extrinsics_root,
948
                        },
949
                    )
950
0
                }))
951
            } else {
952
39
                either::Right(iter::empty())
953
            };
954
955
        // Return the list of runtime calls indicated by the chain information builder state
956
        // machine.
957
39
        let desired_call_proofs = if matches!(self.warped_block_ty, WarpedBlockTy::Normal)
958
0
            && self.warp_sync_fragments_download.is_none()
959
0
            && self.verify_queue.is_empty()
960
0
            && desired_warp_sync_request.peek().is_none()
961
        {
962
0
            either::Left(
963
0
                self.runtime_calls
964
0
                    .iter()
965
0
                    .filter(|(_, v)| matches!(v, CallProof::NotStarted))
966
0
                    .map(|(call, _)| DesiredRequest::RuntimeCallMerkleProof {
967
                        block_hash: self.warped_header_hash,
968
                        function_name: call.function_name().into(),
969
                        parameter_vectored: Cow::Owned(call.parameter_vectored_vec()),
970
0
                    })
971
0
                    .flat_map(move |request_detail| {
972
                        // Sources are ordered by increasing finalized block height, in order to
973
                        // have the highest chance for the block to not be pruned.
974
                        let sources_with_block = self
975
                            .sources_by_finalized_height
976
                            .range((self.warped_header_number, SourceId(usize::MIN))..)
977
                            .map(|(_, src_id)| src_id);
978
979
                        sources_with_block.map(move |source_id| {
980
                            (
981
                                *source_id,
982
                                &self.sources[source_id.0].user_data,
983
                                request_detail.clone(),
984
                            )
985
                        })
986
0
                    }),
987
0
            )
988
        } else {
989
39
            either::Right(iter::empty())
990
        };
991
992
        // Chain all these demanded requests together.
993
39
        desired_warp_sync_request
994
39
            .chain(desired_runtime_parameters_get)
995
39
            .chain(desired_body_download)
996
39
            .chain(desired_call_proofs)
997
39
    }
998
999
    /// Inserts a new request in the data structure.
1000
    ///
1001
    /// > **Note**: The request doesn't necessarily have to match a request returned by
1002
    /// >           [`WarpSync::desired_requests`].
1003
    ///
1004
    /// # Panic
1005
    ///
1006
    /// Panics if the [`SourceId`] is out of range.
1007
    ///
1008
0
    pub fn add_request(
1009
0
        &mut self,
1010
0
        source_id: SourceId,
1011
0
        user_data: TRq,
1012
0
        detail: RequestDetail,
1013
0
    ) -> RequestId {
1014
0
        assert!(self.sources.contains(source_id.0));
1015
1016
0
        let request_slot = self.in_progress_requests.vacant_entry();
1017
0
        let request_id = RequestId(request_slot.key());
1018
0
1019
0
        match (&detail, &mut self.runtime_download, &mut self.body_download) {
1020
0
            (RequestDetail::WarpSyncRequest { block_hash }, _, _)
1021
0
                if self.warp_sync_fragments_download.is_none()
1022
0
                    && *block_hash
1023
0
                        == self
1024
0
                            .verify_queue
1025
0
                            .back()
1026
0
                            .and_then(|entry| entry.fragments.last())
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_request0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_request0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_request0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_request0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_request0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_request0CsibGXYHQB8Ea_25json_rpc_general_requests
1027
0
                            .map(|fragment| {
1028
0
                                header::hash_from_scale_encoded_header(
1029
0
                                    &fragment.scale_encoded_header,
1030
0
                                )
1031
0
                            })
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests_0CsibGXYHQB8Ea_25json_rpc_general_requests
1032
0
                            .unwrap_or(self.warped_header_hash) =>
1033
0
            {
1034
0
                self.warp_sync_fragments_download = Some(request_id);
1035
0
            }
1036
            (
1037
                RequestDetail::BlockBodyDownload {
1038
0
                    block_hash,
1039
0
                    block_number,
1040
0
                },
1041
0
                _,
1042
0
                BodyDownload::NotStarted,
1043
0
            ) => {
1044
0
                if self.sources[source_id.0].finalized_block_height >= self.warped_header_number
1045
0
                    && *block_number == self.warped_header_number
1046
0
                    && *block_hash == self.warped_header_hash
1047
0
                {
1048
0
                    self.body_download = BodyDownload::Downloading { request_id };
1049
0
                }
1050
            }
1051
            (
1052
0
                RequestDetail::StorageGetMerkleProof { block_hash, keys },
1053
0
                RuntimeDownload::NotStarted { hint_doesnt_match },
1054
                _,
1055
            ) => {
1056
0
                let code_key_to_request = if let (false, Some(hint)) =
1057
0
                    (*hint_doesnt_match, self.code_trie_node_hint.as_ref())
1058
                {
1059
0
                    Cow::Owned(
1060
0
                        trie::nibbles_to_bytes_truncate(
1061
0
                            hint.closest_ancestor_excluding.iter().copied(),
1062
0
                        )
1063
0
                        .collect::<Vec<_>>(),
1064
0
                    )
1065
                } else {
1066
0
                    Cow::Borrowed(&b":code"[..])
1067
                };
1068
1069
0
                if self.sources[source_id.0].finalized_block_height >= self.warped_header_number
1070
0
                    && *block_hash == self.warped_header_hash
1071
0
                    && keys.iter().any(|k| *k == *code_key_to_request)
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests0_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests0_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests0_0CsibGXYHQB8Ea_25json_rpc_general_requests
1072
0
                    && keys.iter().any(|k| k == b":heappages")
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests1_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests1_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11add_requests1_0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests1_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests1_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11add_requests1_0CsibGXYHQB8Ea_25json_rpc_general_requests
1073
0
                {
1074
0
                    self.runtime_download = RuntimeDownload::Downloading {
1075
0
                        hint_doesnt_match: *hint_doesnt_match,
1076
0
                        request_id,
1077
0
                    };
1078
0
                }
1079
            }
1080
            (
1081
                RequestDetail::RuntimeCallMerkleProof {
1082
0
                    block_hash,
1083
0
                    function_name,
1084
0
                    parameter_vectored,
1085
                },
1086
                _,
1087
                _,
1088
            ) => {
1089
0
                for (info, status) in &mut self.runtime_calls {
1090
0
                    if matches!(status, CallProof::NotStarted)
1091
0
                        && self.sources[source_id.0].finalized_block_height
1092
0
                            >= self.warped_header_number
1093
0
                        && *block_hash == self.warped_header_hash
1094
0
                        && function_name == info.function_name()
1095
0
                        && parameters_equal(parameter_vectored, info.parameter_vectored())
1096
                    {
1097
0
                        *status = CallProof::Downloading(request_id);
1098
0
                        break;
1099
0
                    }
1100
                }
1101
            }
1102
0
            _ => {}
1103
        }
1104
1105
0
        request_slot.insert((source_id, user_data, detail));
1106
0
        let _was_inserted = self
1107
0
            .in_progress_requests_by_source
1108
0
            .insert((source_id, request_id));
1109
0
        debug_assert!(_was_inserted);
1110
0
        request_id
1111
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE11add_requestB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11add_requestCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE11add_requestB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11add_requestCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11add_requestCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11add_requestCsibGXYHQB8Ea_25json_rpc_general_requests
1112
1113
    /// Removes the given request from the state machine. Returns the user data that was associated
1114
    /// to it.
1115
    ///
1116
    /// > **Note**: The state machine might want to re-start the same request again. It is out of
1117
    /// >           the scope of this module to keep track of requests that don't succeed.
1118
    ///
1119
    /// # Panic
1120
    ///
1121
    /// Panics if the [`RequestId`] is invalid.
1122
    ///
1123
0
    pub fn remove_request(&mut self, id: RequestId) -> TRq {
1124
0
        if self.warp_sync_fragments_download == Some(id) {
1125
0
            self.warp_sync_fragments_download = None;
1126
0
        }
1127
1128
0
        for call in self.runtime_calls.values_mut() {
1129
0
            if matches!(call, CallProof::Downloading(rq_id) if *rq_id == id) {
1130
0
                *call = CallProof::NotStarted;
1131
0
            }
1132
        }
1133
1134
        if let RuntimeDownload::Downloading {
1135
0
            request_id,
1136
0
            hint_doesnt_match,
1137
0
        } = &mut self.runtime_download
1138
        {
1139
0
            if *request_id == id {
1140
0
                self.runtime_download = RuntimeDownload::NotStarted {
1141
0
                    hint_doesnt_match: *hint_doesnt_match,
1142
0
                }
1143
0
            }
1144
0
        }
1145
1146
0
        if let BodyDownload::Downloading { request_id } = &mut self.body_download {
1147
0
            if *request_id == id {
1148
0
                self.body_download = BodyDownload::NotStarted;
1149
0
            }
1150
0
        }
1151
1152
0
        let (source_id, user_data, _) = self.in_progress_requests.remove(id.0);
1153
0
        let _was_removed = self.in_progress_requests_by_source.remove(&(source_id, id));
1154
0
        debug_assert!(_was_removed);
1155
0
        user_data
1156
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE14remove_requestB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE14remove_requestCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE14remove_requestB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE14remove_requestCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE14remove_requestCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE14remove_requestCsibGXYHQB8Ea_25json_rpc_general_requests
1157
1158
    /// Returns the [`SourceId`] that is expected to fulfill the given request.
1159
    ///
1160
    /// # Panic
1161
    ///
1162
    /// Panics if the [`RequestId`] is invalid.
1163
    ///
1164
0
    pub fn request_source_id(&self, request_id: RequestId) -> SourceId {
1165
0
        self.in_progress_requests[request_id.0].0
1166
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE17request_source_idB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE17request_source_idB8_
1167
1168
    /// Injects a body download and removes the given request from the state machine.
1169
    /// Returns the user data that was associated to it.
1170
    ///
1171
    /// # Panic
1172
    ///
1173
    /// Panics if the [`RequestId`] is invalid.
1174
    /// Panics if the [`RequestId`] doesn't correspond to a body download request.
1175
    ///
1176
0
    pub fn body_download_response(&mut self, id: RequestId, body: Vec<Vec<u8>>) -> TRq {
1177
        // Remove the request from the list, obtaining its user data.
1178
        // If the request corresponds to the runtime parameters we're looking for, the function
1179
        // continues below, otherwise we return early.
1180
0
        let (source_id, user_data) =
1181
0
            match (self.in_progress_requests.remove(id.0), &self.body_download) {
1182
0
                ((source_id, user_data, _), BodyDownload::Downloading { request_id })
1183
0
                    if *request_id == id =>
1184
0
                {
1185
0
                    (source_id, user_data)
1186
                }
1187
0
                ((source_id, user_data, RequestDetail::BlockBodyDownload { .. }), _) => {
1188
0
                    let _was_removed = self.in_progress_requests_by_source.remove(&(source_id, id));
1189
0
                    debug_assert!(_was_removed);
1190
0
                    return user_data;
1191
                }
1192
                (
1193
                    (
1194
                        _,
1195
                        _,
1196
                        RequestDetail::RuntimeCallMerkleProof { .. }
1197
                        | RequestDetail::WarpSyncRequest { .. }
1198
                        | RequestDetail::StorageGetMerkleProof { .. },
1199
                    ),
1200
                    _,
1201
0
                ) => panic!(),
1202
            };
1203
1204
0
        self.body_download = BodyDownload::Downloaded {
1205
0
            downloaded_source: Some(source_id),
1206
0
            body,
1207
0
        };
1208
0
1209
0
        let _was_removed = self.in_progress_requests_by_source.remove(&(source_id, id));
1210
0
        debug_assert!(_was_removed);
1211
1212
0
        user_data
1213
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE22body_download_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE22body_download_responseCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE22body_download_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE22body_download_responseCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE22body_download_responseCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE22body_download_responseCsibGXYHQB8Ea_25json_rpc_general_requests
1214
1215
    /// Injects a Merkle proof and removes the given request from the state machine.
1216
    /// Returns the user data that was associated to it.
1217
    ///
1218
    /// # Panic
1219
    ///
1220
    /// Panics if the [`RequestId`] is invalid.
1221
    /// Panics if the [`RequestId`] doesn't correspond to a storage get request.
1222
    ///
1223
0
    pub fn storage_get_response(&mut self, id: RequestId, merkle_proof: Vec<u8>) -> TRq {
1224
        // Remove the request from the list, obtaining its user data.
1225
        // If the request corresponds to the runtime parameters we're looking for, the function
1226
        // continues below, otherwise we return early.
1227
0
        let (source_id, hint_doesnt_match, user_data) = match (
1228
0
            self.in_progress_requests.remove(id.0),
1229
0
            &self.runtime_download,
1230
        ) {
1231
            (
1232
0
                (source_id, user_data, _),
1233
                RuntimeDownload::Downloading {
1234
0
                    request_id,
1235
0
                    hint_doesnt_match,
1236
0
                },
1237
0
            ) if *request_id == id => (source_id, *hint_doesnt_match, user_data),
1238
0
            ((source_id, user_data, RequestDetail::StorageGetMerkleProof { .. }), _) => {
1239
0
                let _was_removed = self.in_progress_requests_by_source.remove(&(source_id, id));
1240
0
                debug_assert!(_was_removed);
1241
0
                return user_data;
1242
            }
1243
            (
1244
                (
1245
                    _,
1246
                    _,
1247
                    RequestDetail::RuntimeCallMerkleProof { .. }
1248
                    | RequestDetail::WarpSyncRequest { .. }
1249
                    | RequestDetail::BlockBodyDownload { .. },
1250
                ),
1251
                _,
1252
0
            ) => panic!(),
1253
        };
1254
1255
0
        self.runtime_download = RuntimeDownload::NotVerified {
1256
0
            downloaded_source: Some(source_id),
1257
0
            hint_doesnt_match,
1258
0
            trie_proof: merkle_proof,
1259
0
        };
1260
0
1261
0
        let _was_removed = self.in_progress_requests_by_source.remove(&(source_id, id));
1262
0
        debug_assert!(_was_removed);
1263
1264
0
        user_data
1265
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE20storage_get_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20storage_get_responseCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE20storage_get_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20storage_get_responseCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20storage_get_responseCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE20storage_get_responseCsibGXYHQB8Ea_25json_rpc_general_requests
1266
1267
    /// Injects a response and removes the given request from the state machine. Returns
1268
    /// the user data that was associated to it.
1269
    ///
1270
    /// # Panic
1271
    ///
1272
    /// Panics if the [`RequestId`] is invalid.
1273
    /// Panics if the [`RequestId`] doesn't correspond to a runtime Merkle call proof request.
1274
    ///
1275
0
    pub fn runtime_call_merkle_proof_response(
1276
0
        &mut self,
1277
0
        request_id: RequestId,
1278
0
        response: Vec<u8>,
1279
0
    ) -> TRq {
1280
0
        let (source_id, user_data, RequestDetail::RuntimeCallMerkleProof { .. }) =
1281
0
            self.in_progress_requests.remove(request_id.0)
1282
        else {
1283
            // Wrong request type.
1284
0
            panic!()
1285
        };
1286
1287
0
        for call in self.runtime_calls.values_mut() {
1288
0
            if matches!(call, CallProof::Downloading(rq_id) if *rq_id == request_id) {
1289
0
                *call = CallProof::Downloaded {
1290
0
                    downloaded_source: Some(source_id),
1291
0
                    proof: response,
1292
0
                };
1293
0
                break;
1294
0
            }
1295
        }
1296
1297
0
        let _was_removed = self
1298
0
            .in_progress_requests_by_source
1299
0
            .remove(&(source_id, request_id));
1300
0
        debug_assert!(_was_removed);
1301
1302
0
        user_data
1303
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE34runtime_call_merkle_proof_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE34runtime_call_merkle_proof_responseCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE34runtime_call_merkle_proof_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE34runtime_call_merkle_proof_responseCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE34runtime_call_merkle_proof_responseCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE34runtime_call_merkle_proof_responseCsibGXYHQB8Ea_25json_rpc_general_requests
1304
1305
    /// Injects a response and removes the given request from the state machine. Returns
1306
    /// the user data that was associated to it.
1307
    ///
1308
    /// If the header of the last fragment of the response is decodable, this function updates
1309
    /// the finalized block of the source.
1310
    ///
1311
    /// # Panic
1312
    ///
1313
    /// Panics if the [`RequestId`] is invalid.
1314
    /// Panics if the [`RequestId`] doesn't correspond to a warp sync request.
1315
    ///
1316
    // TODO: more zero cost API w.r.t. the fragments
1317
0
    pub fn warp_sync_request_response(
1318
0
        &mut self,
1319
0
        request_id: RequestId,
1320
0
        fragments: Vec<WarpSyncFragment>,
1321
0
        final_set_of_fragments: bool,
1322
0
    ) -> TRq {
1323
0
        let (rq_source_id, user_data) = match self.in_progress_requests.remove(request_id.0) {
1324
0
            (rq_source_id, user_data, RequestDetail::WarpSyncRequest { .. }) => {
1325
0
                (rq_source_id, user_data)
1326
            }
1327
0
            (_, _, _) => panic!(),
1328
        };
1329
1330
0
        debug_assert!(self.sources.contains(rq_source_id.0));
1331
1332
        // Since we send requests only to sources with an appropriate finalized block, we make
1333
        // sure that the finalized block of the source that sent the response matches the
1334
        // fragments that it sent.
1335
        // If we didn't do that, it would be possible for example to warp sync to block 200 while
1336
        // believing that the source is only at block 199, and thus the warp syncing would stall.
1337
0
        if let Some(last_header) = fragments
1338
0
            .last()
1339
0
            .and_then(|h| header::decode(&h.scale_encoded_header, self.block_number_bytes).ok())
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE26warp_sync_request_response0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE26warp_sync_request_response0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE26warp_sync_request_response0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE26warp_sync_request_response0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE26warp_sync_request_response0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE26warp_sync_request_response0CsibGXYHQB8Ea_25json_rpc_general_requests
1340
        {
1341
0
            let src_finalized_height = &mut self.sources[rq_source_id.0].finalized_block_height;
1342
1343
0
            let new_height = if final_set_of_fragments {
1344
                // If the source indicated that this is the last fragment, then we know that
1345
                // it's also equal to their finalized block.
1346
0
                last_header.number
1347
            } else {
1348
                // If this is not the last fragment, we know that the finalized block of the
1349
                // source is *at least* the one provided.
1350
                // TODO: could maybe do + gap or something?
1351
0
                cmp::max(*src_finalized_height, last_header.number.saturating_add(1))
1352
            };
1353
1354
0
            if *src_finalized_height != new_height {
1355
0
                let _was_in = self
1356
0
                    .sources_by_finalized_height
1357
0
                    .remove(&(*src_finalized_height, rq_source_id));
1358
0
                debug_assert!(_was_in);
1359
1360
0
                *src_finalized_height = new_height;
1361
0
1362
0
                let _inserted = self
1363
0
                    .sources_by_finalized_height
1364
0
                    .insert((*src_finalized_height, rq_source_id));
1365
0
                debug_assert!(_inserted);
1366
0
            }
1367
0
        }
1368
1369
0
        if self.warp_sync_fragments_download == Some(request_id) {
1370
0
            self.warp_sync_fragments_download = None;
1371
0
1372
0
            self.verify_queue.push_back(PendingVerify {
1373
0
                final_set_of_fragments,
1374
0
                downloaded_source: Some(rq_source_id),
1375
0
                fragments,
1376
0
                next_fragment_to_verify_index: 0,
1377
0
            });
1378
0
        }
1379
1380
0
        let _was_removed = self
1381
0
            .in_progress_requests_by_source
1382
0
            .remove(&(rq_source_id, request_id));
1383
0
        debug_assert!(_was_removed);
1384
1385
0
        user_data
1386
0
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE26warp_sync_request_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE26warp_sync_request_responseCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE26warp_sync_request_responseB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE26warp_sync_request_responseCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE26warp_sync_request_responseCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE26warp_sync_request_responseCsibGXYHQB8Ea_25json_rpc_general_requests
1387
1388
    /// Start processing one CPU operation.
1389
    ///
1390
    /// This function takes ownership of `self` and yields it back after the operation is finished.
1391
    // TODO: take a `&mut self` instead of `self` ; requires many changes in all.rs
1392
21
    pub fn process_one(self) -> ProcessOne<TSrc, TRq> {
1393
        // If we've downloaded everything that was needed, switch to "build chain information"
1394
        // mode.
1395
21
        if matches!(self.runtime_download, RuntimeDownload::Verified { .. })
1396
0
            && matches!(
1397
0
                self.body_download,
1398
                BodyDownload::NotNeeded | BodyDownload::Downloaded { .. }
1399
            )
1400
0
            && self
1401
0
                .runtime_calls
1402
0
                .values()
1403
0
                .all(|c| matches!(c, CallProof::Downloaded { .. }))
Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11process_one0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11process_one0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncppE11process_one0Ba_
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11process_one0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11process_one0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB6_8WarpSyncNtNtB8_3all19WarpSyncSourceExtraNtB12_20WarpSyncRequestExtraE11process_one0CsibGXYHQB8Ea_25json_rpc_general_requests
1404
        {
1405
0
            return ProcessOne::BuildChainInformation(BuildChainInformation { inner: self });
1406
21
        }
1407
21
1408
21
        if let RuntimeDownload::NotVerified { .. } = &self.runtime_download {
1409
0
            return ProcessOne::BuildRuntime(BuildRuntime { inner: self });
1410
21
        }
1411
21
1412
21
        if !self.verify_queue.is_empty() {
1413
0
            return ProcessOne::VerifyWarpSyncFragment(VerifyWarpSyncFragment { inner: self });
1414
21
        }
1415
21
1416
21
        ProcessOne::Idle(self)
1417
21
    }
Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB4_8WarpSyncppE11process_oneB8_
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11process_oneCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncppE11process_oneB8_
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11process_oneCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
1392
2
    pub fn process_one(self) -> ProcessOne<TSrc, TRq> {
1393
        // If we've downloaded everything that was needed, switch to "build chain information"
1394
        // mode.
1395
2
        if matches!(self.runtime_download, RuntimeDownload::Verified { .. })
1396
0
            && matches!(
1397
0
                self.body_download,
1398
                BodyDownload::NotNeeded | BodyDownload::Downloaded { .. }
1399
            )
1400
0
            && self
1401
0
                .runtime_calls
1402
0
                .values()
1403
0
                .all(|c| matches!(c, CallProof::Downloaded { .. }))
1404
        {
1405
0
            return ProcessOne::BuildChainInformation(BuildChainInformation { inner: self });
1406
2
        }
1407
2
1408
2
        if let RuntimeDownload::NotVerified { .. } = &self.runtime_download {
1409
0
            return ProcessOne::BuildRuntime(BuildRuntime { inner: self });
1410
2
        }
1411
2
1412
2
        if !self.verify_queue.is_empty() {
1413
0
            return ProcessOne::VerifyWarpSyncFragment(VerifyWarpSyncFragment { inner: self });
1414
2
        }
1415
2
1416
2
        ProcessOne::Idle(self)
1417
2
    }
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11process_oneCscDgN54JpMGG_6author
_RNvMs_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB4_8WarpSyncNtNtB6_3all19WarpSyncSourceExtraNtB10_20WarpSyncRequestExtraE11process_oneCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
1392
19
    pub fn process_one(self) -> ProcessOne<TSrc, TRq> {
1393
        // If we've downloaded everything that was needed, switch to "build chain information"
1394
        // mode.
1395
19
        if matches!(self.runtime_download, RuntimeDownload::Verified { .. })
1396
0
            && matches!(
1397
0
                self.body_download,
1398
                BodyDownload::NotNeeded | BodyDownload::Downloaded { .. }
1399
            )
1400
0
            && self
1401
0
                .runtime_calls
1402
0
                .values()
1403
0
                .all(|c| matches!(c, CallProof::Downloaded { .. }))
1404
        {
1405
0
            return ProcessOne::BuildChainInformation(BuildChainInformation { inner: self });
1406
19
        }
1407
19
1408
19
        if let RuntimeDownload::NotVerified { .. } = &self.runtime_download {
1409
0
            return ProcessOne::BuildRuntime(BuildRuntime { inner: self });
1410
19
        }
1411
19
1412
19
        if !self.verify_queue.is_empty() {
1413
0
            return ProcessOne::VerifyWarpSyncFragment(VerifyWarpSyncFragment { inner: self });
1414
19
        }
1415
19
1416
19
        ProcessOne::Idle(self)
1417
19
    }
1418
}
1419
1420
impl<TSrc, TRq> ops::Index<SourceId> for WarpSync<TSrc, TRq> {
1421
    type Output = TSrc;
1422
1423
    #[track_caller]
1424
0
    fn index(&self, source_id: SourceId) -> &TSrc {
1425
0
        debug_assert!(self.sources.contains(source_id.0));
1426
0
        &self.sources[source_id.0].user_data
1427
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncs0_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexB9_
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_8WarpSyncNtNtB7_3all19WarpSyncSourceExtraNtB11_20WarpSyncRequestExtraEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot4sync9warp_syncs0_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexB9_
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_8WarpSyncNtNtB7_3all19WarpSyncSourceExtraNtB11_20WarpSyncRequestExtraEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_8WarpSyncNtNtB7_3all19WarpSyncSourceExtraNtB11_20WarpSyncRequestExtraEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_8WarpSyncNtNtB7_3all19WarpSyncSourceExtraNtB11_20WarpSyncRequestExtraEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexCsibGXYHQB8Ea_25json_rpc_general_requests
1428
}
1429
1430
impl<TSrc, TRq> ops::IndexMut<SourceId> for WarpSync<TSrc, TRq> {
1431
    #[track_caller]
1432
0
    fn index_mut(&mut self, source_id: SourceId) -> &mut TSrc {
1433
0
        debug_assert!(self.sources.contains(source_id.0));
1434
0
        &mut self.sources[source_id.0].user_data
1435
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncs1_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutB9_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot4sync9warp_syncs1_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutB9_
1436
}
1437
1438
impl<TSrc, TRq> ops::Index<RequestId> for WarpSync<TSrc, TRq> {
1439
    type Output = TRq;
1440
1441
    #[track_caller]
1442
0
    fn index(&self, request_id: RequestId) -> &TRq {
1443
0
        debug_assert!(self.in_progress_requests.contains(request_id.0));
1444
0
        &self.in_progress_requests[request_id.0].1
1445
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncs2_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_9RequestIdE5indexB9_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot4sync9warp_syncs2_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_9RequestIdE5indexB9_
1446
}
1447
1448
impl<TSrc, TRq> ops::IndexMut<RequestId> for WarpSync<TSrc, TRq> {
1449
    #[track_caller]
1450
0
    fn index_mut(&mut self, request_id: RequestId) -> &mut TRq {
1451
0
        debug_assert!(self.in_progress_requests.contains(request_id.0));
1452
0
        &mut self.in_progress_requests[request_id.0].1
1453
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncs3_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_9RequestIdE9index_mutB9_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot4sync9warp_syncs3_0ppEINtB5_8WarpSyncppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_9RequestIdE9index_mutB9_
1454
}
1455
1456
/// Information about a request that the warp sync state machine would like to start.
1457
///
1458
/// See [`WarpSync::desired_requests`].
1459
#[derive(Debug, Clone)]
1460
pub enum DesiredRequest {
1461
    /// A warp sync request should be started.
1462
    WarpSyncRequest {
1463
        /// Starting point of the warp syncing. The first fragment of the response should be the
1464
        /// of the epoch that the starting point is in.
1465
        block_hash: [u8; 32],
1466
    },
1467
    /// A block body download should be started.
1468
    BlockBodyDownload {
1469
        /// Hash of the block whose body to download.
1470
        block_hash: [u8; 32],
1471
        /// Height of the block whose body to download.
1472
        block_number: u64,
1473
        /// Extrinsics trie root hash found in the header of the block.
1474
        extrinsics_root: [u8; 32],
1475
    },
1476
    /// A storage request of the runtime code and heap pages should be started.
1477
    StorageGetMerkleProof {
1478
        /// Hash of the block to request the parameters against.
1479
        block_hash: [u8; 32],
1480
        /// State trie root hash found in the header of the block.
1481
        state_trie_root: [u8; 32],
1482
        /// Keys whose values are requested.
1483
        // TODO: consider Cow<'static, [u8]> instead
1484
        keys: Vec<Vec<u8>>,
1485
    },
1486
    /// A call proof should be started.
1487
    RuntimeCallMerkleProof {
1488
        /// Hash of the header of the block the call should be made against.
1489
        block_hash: [u8; 32],
1490
        /// Name of the function of the call proof.
1491
        function_name: Cow<'static, str>,
1492
        /// Parameters of the call.
1493
        parameter_vectored: Cow<'static, [u8]>,
1494
    },
1495
}
1496
1497
/// Information about a request to add to the state machine.
1498
///
1499
/// See [`WarpSync::add_request`].
1500
#[derive(Debug, Clone)]
1501
pub enum RequestDetail {
1502
    /// See [`DesiredRequest::WarpSyncRequest`].
1503
    WarpSyncRequest {
1504
        /// See [`DesiredRequest::WarpSyncRequest::block_hash`].
1505
        block_hash: [u8; 32],
1506
    },
1507
    /// See [`DesiredRequest::BlockBodyDownload`].
1508
    BlockBodyDownload {
1509
        /// See [`DesiredRequest::BlockBodyDownload::block_hash`].
1510
        block_hash: [u8; 32],
1511
        /// See [`DesiredRequest::BlockBodyDownload::block_number`].
1512
        // TODO: remove this field as it's inappropriate, but this causes issues in all.rs
1513
        block_number: u64,
1514
    },
1515
    /// See [`DesiredRequest::StorageGetMerkleProof`].
1516
    StorageGetMerkleProof {
1517
        /// See [`DesiredRequest::StorageGetMerkleProof::block_hash`].
1518
        block_hash: [u8; 32],
1519
        /// See [`DesiredRequest::StorageGetMerkleProof::keys`].
1520
        keys: Vec<Vec<u8>>,
1521
    },
1522
    /// See [`DesiredRequest::RuntimeCallMerkleProof`].
1523
    RuntimeCallMerkleProof {
1524
        /// See [`DesiredRequest::RuntimeCallMerkleProof::block_hash`].
1525
        block_hash: [u8; 32],
1526
        /// See [`DesiredRequest::RuntimeCallMerkleProof::function_name`].
1527
        function_name: Cow<'static, str>,
1528
        /// See [`DesiredRequest::RuntimeCallMerkleProof::parameter_vectored`].
1529
        parameter_vectored: Cow<'static, [u8]>,
1530
    },
1531
}
1532
1533
/// Identifier for a request in the warp sync state machine.
1534
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
1535
pub struct RequestId(usize);
1536
1537
/// Return value of [`WarpSync::process_one`].
1538
pub enum ProcessOne<TSrc, TRq> {
1539
    /// Nothing to verify at the moment. The state machine is yielded back.
1540
    Idle(WarpSync<TSrc, TRq>),
1541
    /// Ready to verify a warp sync fragment.
1542
    ///
1543
    /// > **Note**: In case where a source has sent an empty list of fragment, which is invalid,
1544
    /// >           this variant will "verify" the list and produce an error.
1545
    VerifyWarpSyncFragment(VerifyWarpSyncFragment<TSrc, TRq>),
1546
    /// Ready to build the runtime of the chain..
1547
    BuildRuntime(BuildRuntime<TSrc, TRq>),
1548
    /// Ready to verify the parameters of the chain against the finalized block.
1549
    BuildChainInformation(BuildChainInformation<TSrc, TRq>),
1550
}
1551
1552
/// Ready to verify a warp sync fragment.
1553
///
1554
/// > **Note**: In case where a source has sent an empty list of fragment, which is invalid,
1555
/// >           this variant will "verify" the list and produce an error.
1556
pub struct VerifyWarpSyncFragment<TSrc, TRq> {
1557
    inner: WarpSync<TSrc, TRq>,
1558
}
1559
1560
impl<TSrc, TRq> VerifyWarpSyncFragment<TSrc, TRq> {
1561
    /// Returns the source that has sent the fragments that we are about to verify, and its user
1562
    /// data.
1563
    ///
1564
    /// Returns `None` if the source has been removed since the fragments have been downloaded.
1565
0
    pub fn proof_sender(&self) -> Option<(SourceId, &TSrc)> {
1566
0
        let entry_to_verify = self.inner.verify_queue.front().unwrap();
1567
0
        let source_id = entry_to_verify.downloaded_source?;
1568
0
        Some((source_id, &self.inner.sources[source_id.0].user_data))
1569
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentppE12proof_senderB9_
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE12proof_senderCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentppE12proof_senderB9_
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE12proof_senderCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE12proof_senderCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE12proof_senderCsibGXYHQB8Ea_25json_rpc_general_requests
1570
1571
    /// Verify one warp sync fragment.
1572
    ///
1573
    /// Must be passed a randomly-generated value that is used by the verification process. Note
1574
    /// that the verification is still deterministic.
1575
    ///
1576
    /// On success, returns the block hash and height that have been verified as being part of
1577
    /// the chain.
1578
    /// On error, returns why the verification has failed. The warp syncing process still
1579
    /// continues.
1580
0
    pub fn verify(
1581
0
        mut self,
1582
0
        randomness_seed: [u8; 32],
1583
0
    ) -> (
1584
0
        WarpSync<TSrc, TRq>,
1585
0
        Result<([u8; 32], u64), VerifyFragmentError>,
1586
0
    ) {
1587
0
        // A `VerifyWarpSyncFragment` is only ever created if `verify_queue` is non-empty.
1588
0
        debug_assert!(!self.inner.verify_queue.is_empty());
1589
0
        let fragments_to_verify = self
1590
0
            .inner
1591
0
            .verify_queue
1592
0
            .front_mut()
1593
0
            .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verify0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verify0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verify0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verify0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verify0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verify0CsibGXYHQB8Ea_25json_rpc_general_requests
1594
0
1595
0
        // The source has sent an empty list of fragments. This is invalid.
1596
0
        if fragments_to_verify.fragments.is_empty() {
1597
0
            self.inner.verify_queue.pop_front().unwrap();
1598
0
            return (self.inner, Err(VerifyFragmentError::EmptyProof));
1599
0
        }
1600
0
1601
0
        // Given that the list of fragments is non-empty, we are assuming that there are still
1602
0
        // fragments to verify, otherwise this entry should have been removed in a previous
1603
0
        // iteration.
1604
0
        let fragment_to_verify = fragments_to_verify
1605
0
            .fragments
1606
0
            .get(fragments_to_verify.next_fragment_to_verify_index)
1607
0
            .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys_0CsibGXYHQB8Ea_25json_rpc_general_requests
1608
1609
        // It has been checked at the warp sync initialization that the finality algorithm is
1610
        // indeed Grandpa.
1611
        let chain_information::ChainInformationFinality::Grandpa {
1612
0
            after_finalized_block_authorities_set_id,
1613
0
            finalized_triggered_authorities,
1614
            .. // TODO: support finalized_scheduled_change? difficult to implement
1615
0
        } = &mut self.inner.warped_finality
1616
        else {
1617
0
            unreachable!()
1618
        };
1619
1620
        // Decode the header and justification of the fragment.
1621
0
        let fragment_header_hash =
1622
0
            header::hash_from_scale_encoded_header(&fragment_to_verify.scale_encoded_header);
1623
0
        let fragment_decoded_header = match header::decode(
1624
0
            &fragment_to_verify.scale_encoded_header,
1625
0
            self.inner.block_number_bytes,
1626
0
        ) {
1627
0
            Ok(j) => j,
1628
0
            Err(err) => {
1629
0
                self.inner.verify_queue.clear();
1630
0
                self.inner.warp_sync_fragments_download = None;
1631
0
                return (self.inner, Err(VerifyFragmentError::InvalidHeader(err)));
1632
            }
1633
        };
1634
0
        let fragment_decoded_justification = match decode::decode_grandpa_justification(
1635
0
            &fragment_to_verify.scale_encoded_justification,
1636
0
            self.inner.block_number_bytes,
1637
0
        ) {
1638
0
            Ok(j) => j,
1639
0
            Err(err) => {
1640
0
                self.inner.verify_queue.clear();
1641
0
                self.inner.warp_sync_fragments_download = None;
1642
0
                return (
1643
0
                    self.inner,
1644
0
                    Err(VerifyFragmentError::InvalidJustification(err)),
1645
0
                );
1646
            }
1647
        };
1648
1649
        // Make sure that the header would actually advance the warp sync process forward.
1650
0
        if fragment_decoded_header.number <= self.inner.warped_header_number {
1651
0
            self.inner.verify_queue.clear();
1652
0
            self.inner.warp_sync_fragments_download = None;
1653
0
            return (
1654
0
                self.inner,
1655
0
                Err(VerifyFragmentError::BlockNumberNotIncrementing),
1656
0
            );
1657
0
        }
1658
0
1659
0
        // Make sure that the justification indeed corresponds to the header.
1660
0
        if *fragment_decoded_justification.target_hash != fragment_header_hash
1661
0
            || fragment_decoded_justification.target_number != fragment_decoded_header.number
1662
        {
1663
0
            let error = VerifyFragmentError::TargetHashMismatch {
1664
0
                justification_target_hash: *fragment_decoded_justification.target_hash,
1665
0
                justification_target_height: fragment_decoded_justification.target_number,
1666
0
                header_hash: fragment_header_hash,
1667
0
                header_height: fragment_decoded_header.number,
1668
0
            };
1669
0
            self.inner.verify_queue.clear();
1670
0
            self.inner.warp_sync_fragments_download = None;
1671
0
            return (self.inner, Err(error));
1672
0
        }
1673
1674
        // Check whether the justification is valid.
1675
0
        if let Err(err) = verify::verify_justification(verify::JustificationVerifyConfig {
1676
0
            justification: &fragment_to_verify.scale_encoded_justification,
1677
0
            block_number_bytes: self.inner.block_number_bytes,
1678
0
            authorities_list: finalized_triggered_authorities
1679
0
                .iter()
1680
0
                .map(|a| &a.public_key[..]),
Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys0_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys0_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys0_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys0_0CsibGXYHQB8Ea_25json_rpc_general_requests
1681
0
            authorities_set_id: *after_finalized_block_authorities_set_id,
1682
0
            randomness_seed,
1683
0
        }) {
1684
0
            self.inner.verify_queue.clear();
1685
0
            self.inner.warp_sync_fragments_download = None;
1686
0
            return (
1687
0
                self.inner,
1688
0
                Err(VerifyFragmentError::JustificationVerify(err)),
1689
0
            );
1690
0
        }
1691
0
1692
0
        // Try to grab the new list of authorities from the header.
1693
0
        let new_authorities_list = fragment_decoded_header
1694
0
            .digest
1695
0
            .logs()
1696
0
            .find_map(|log_item| match log_item {
1697
0
                header::DigestItemRef::GrandpaConsensus(grandpa_log_item) => match grandpa_log_item
1698
                {
1699
0
                    header::GrandpaConsensusLogRef::ScheduledChange(change)
1700
0
                    | header::GrandpaConsensusLogRef::ForcedChange { change, .. } => {
1701
0
                        Some(change.next_authorities)
1702
                    }
1703
0
                    _ => None,
1704
                },
1705
0
                _ => None,
1706
0
            })
Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys1_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys1_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys1_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys1_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys1_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys1_0CsibGXYHQB8Ea_25json_rpc_general_requests
1707
0
            .map(|next_authorities| {
1708
0
                next_authorities
1709
0
                    .map(header::GrandpaAuthority::from)
1710
0
                    .collect()
1711
0
            });
Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys2_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys2_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentppE6verifys2_0Bb_
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys2_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys2_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_22VerifyWarpSyncFragmentNtNtB9_3all19WarpSyncSourceExtraNtB1i_20WarpSyncRequestExtraE6verifys2_0CsibGXYHQB8Ea_25json_rpc_general_requests
1712
0
1713
0
        // Fragments must only include headers containing an update to the list of authorities,
1714
0
        // unless it's the very head of the chain.
1715
0
        if new_authorities_list.is_none()
1716
0
            && (!fragments_to_verify.final_set_of_fragments
1717
0
                || fragments_to_verify.next_fragment_to_verify_index
1718
0
                    != fragments_to_verify.fragments.len() - 1)
1719
        {
1720
0
            self.inner.verify_queue.clear();
1721
0
            self.inner.warp_sync_fragments_download = None;
1722
0
            return (self.inner, Err(VerifyFragmentError::NonMinimalProof));
1723
0
        }
1724
0
1725
0
        // Verification of the fragment has succeeded 🎉. We can now update `self`.
1726
0
        fragments_to_verify.next_fragment_to_verify_index += 1;
1727
0
        self.inner.warped_header_number = fragment_decoded_header.number;
1728
0
        self.inner.warped_header_state_root = *fragment_decoded_header.state_root;
1729
0
        self.inner.warped_header_extrinsics_root = *fragment_decoded_header.extrinsics_root;
1730
0
        self.inner.warped_header_hash = fragment_header_hash;
1731
0
        self.inner.warped_header = fragment_to_verify.scale_encoded_header.clone(); // TODO: figure out how to remove this clone()
1732
0
        self.inner.warped_block_ty = WarpedBlockTy::Normal;
1733
0
        self.inner.runtime_download = RuntimeDownload::NotStarted {
1734
0
            hint_doesnt_match: false,
1735
0
        };
1736
0
        if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
1737
0
            self.inner.body_download = BodyDownload::NotStarted;
1738
0
        }
1739
0
        self.inner.runtime_calls =
1740
0
            runtime_calls_default_value(self.inner.verified_chain_information.as_ref().consensus);
1741
0
        if let Some(new_authorities_list) = new_authorities_list {
1742
0
            *finalized_triggered_authorities = new_authorities_list;
1743
0
            *after_finalized_block_authorities_set_id += 1;
1744
0
        }
1745
0
        if fragments_to_verify.next_fragment_to_verify_index == fragments_to_verify.fragments.len()
1746
0
        {
1747
0
            self.inner.verify_queue.pop_front().unwrap();
1748
0
        }
1749
1750
        // Returning.
1751
0
        let result = Ok((
1752
0
            self.inner.warped_header_hash,
1753
0
            self.inner.warped_header_number,
1754
0
        ));
1755
0
        (self.inner, result)
1756
0
    }
Unexecuted instantiation: _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentppE6verifyB9_
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE6verifyCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentppE6verifyB9_
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE6verifyCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE6verifyCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs4_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_22VerifyWarpSyncFragmentNtNtB7_3all19WarpSyncSourceExtraNtB1g_20WarpSyncRequestExtraE6verifyCsibGXYHQB8Ea_25json_rpc_general_requests
1757
}
1758
1759
/// Error potentially returned by [`VerifyWarpSyncFragment::verify`].
1760
#[derive(Debug)]
1761
pub enum VerifyFragmentError {
1762
    /// Justification found within the fragment is invalid.
1763
    JustificationVerify(verify::JustificationVerifyError),
1764
    /// Mismatch between the block targeted by the justification and the header.
1765
    TargetHashMismatch {
1766
        /// Hash of the block the justification targets.
1767
        justification_target_hash: [u8; 32],
1768
        /// Height of the block the justification targets.
1769
        justification_target_height: u64,
1770
        /// Hash of the header.
1771
        header_hash: [u8; 32],
1772
        /// Height of the header.
1773
        header_height: u64,
1774
    },
1775
    /// Warp sync fragment doesn't contain an authorities list change when it should.
1776
    NonMinimalProof,
1777
    /// Header does not actually advance the warp syncing process. This means that a source has
1778
    /// sent a header below the requested hash.
1779
    BlockNumberNotIncrementing,
1780
    /// Warp sync proof is empty.
1781
    EmptyProof,
1782
    /// Failed to decode header.
1783
    InvalidHeader(header::Error),
1784
    /// Failed to decode justification.
1785
    InvalidJustification(decode::JustificationDecodeError),
1786
}
1787
1788
impl fmt::Display for VerifyFragmentError {
1789
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1790
0
        match self {
1791
0
            VerifyFragmentError::JustificationVerify(err) => fmt::Display::fmt(err, f),
1792
            VerifyFragmentError::TargetHashMismatch {
1793
0
                justification_target_hash,
1794
0
                justification_target_height,
1795
0
                header_hash,
1796
0
                header_height,
1797
0
            } => {
1798
0
                write!(
1799
0
                    f,
1800
0
                    "Justification target (hash: {}, height: {}) doesn't match the associated header (hash: {}, height: {})",
1801
0
                    HashDisplay(justification_target_hash),
1802
0
                    justification_target_height,
1803
0
                    HashDisplay(header_hash),
1804
0
                    header_height,
1805
0
                )
1806
            }
1807
0
            VerifyFragmentError::NonMinimalProof => write!(
1808
0
                f,
1809
0
                "Warp sync proof fragment doesn't contain an authorities list change"
1810
0
            ),
1811
0
            VerifyFragmentError::BlockNumberNotIncrementing => write!(
1812
0
                f,
1813
0
                "Warp sync proof header doesn't advance the warp syncing process"
1814
0
            ),
1815
0
            VerifyFragmentError::EmptyProof => write!(f, "Warp sync proof is empty"),
1816
0
            VerifyFragmentError::InvalidHeader(err) => write!(f, "Failed to decode header: {err}"),
1817
0
            VerifyFragmentError::InvalidJustification(err) => {
1818
0
                write!(f, "Failed to decode justification: {err}")
1819
            }
1820
        }
1821
0
    }
Unexecuted instantiation: _RNvXs5_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_19VerifyFragmentErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs5_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_19VerifyFragmentErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1822
}
1823
1824
/// Problem encountered during a call to [`BuildRuntime::build`] or
1825
/// [`BuildChainInformation::build`] that can be attributed to the source sending invalid data.
1826
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsG_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_17SourceMisbehaviorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsG_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_17SourceMisbehaviorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1827
#[display(fmt = "{error}")]
1828
pub struct SourceMisbehavior {
1829
    /// Source that committed the felony. `None` if the source has been removed between the moment
1830
    /// when the request has succeeded and when it has been verified.
1831
    pub source_id: Option<SourceId>,
1832
    /// Error that the source made.
1833
    pub error: SourceMisbehaviorTy,
1834
}
1835
1836
/// See [`SourceMisbehavior::error`].
1837
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsI_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_19SourceMisbehaviorTyNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsI_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_19SourceMisbehaviorTyNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1838
pub enum SourceMisbehaviorTy {
1839
    /// Failed to verify Merkle proof.
1840
    InvalidMerkleProof(proof_decode::Error),
1841
    /// Merkle proof is missing the necessary entries.
1842
    MerkleProofEntriesMissing,
1843
    /// Downloaded block body doesn't match the expected extrinsics root.
1844
    BlockBodyExtrinsicsRootMismatch,
1845
}
1846
1847
/// Problem encountered during a call to [`BuildRuntime::build`].
1848
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsK_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_17BuildRuntimeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsK_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_17BuildRuntimeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
1849
pub enum BuildRuntimeError {
1850
    /// The chain doesn't include any storage item at `:code`.
1851
    #[display(fmt = "The chain doesn't include any storage item at `:code`")]
1852
    MissingCode,
1853
    /// The storage item at `:heappages` is in an incorrect format.
1854
    #[display(fmt = "Invalid heap pages value: {_0}")]
1855
    InvalidHeapPages(executor::InvalidHeapPagesError),
1856
    /// Error building the runtime of the chain.
1857
    #[display(fmt = "Error building the runtime: {_0}")]
1858
    RuntimeBuild(executor::host::NewErr),
1859
    /// Source that has sent a proof didn't behave properly.
1860
    SourceMisbehavior(SourceMisbehavior),
1861
}
1862
1863
/// Ready to build the runtime of the finalized chain.
1864
pub struct BuildRuntime<TSrc, TRq> {
1865
    inner: WarpSync<TSrc, TRq>,
1866
}
1867
1868
impl<TSrc, TRq> BuildRuntime<TSrc, TRq> {
1869
    /// Build the runtime of the chain.
1870
    ///
1871
    /// Must be passed parameters used for the construction of the runtime: a hint as to whether
1872
    /// the runtime is trusted and/or will be executed again, and whether unresolved function
1873
    /// imports are allowed.
1874
0
    pub fn build(
1875
0
        mut self,
1876
0
        exec_hint: ExecHint,
1877
0
        allow_unresolved_imports: bool,
1878
0
    ) -> (WarpSync<TSrc, TRq>, Result<(), BuildRuntimeError>) {
1879
        let RuntimeDownload::NotVerified {
1880
0
            downloaded_source,
1881
0
            hint_doesnt_match,
1882
0
            trie_proof,
1883
0
        } = &mut self.inner.runtime_download
1884
        else {
1885
0
            unreachable!()
1886
        };
1887
1888
0
        let downloaded_runtime = mem::take(trie_proof);
1889
0
        let decoded_downloaded_runtime =
1890
0
            match proof_decode::decode_and_verify_proof(proof_decode::Config {
1891
0
                proof: &downloaded_runtime[..],
1892
0
            }) {
1893
0
                Ok(p) => p,
1894
0
                Err(err) => {
1895
0
                    let downloaded_source = *downloaded_source;
1896
0
                    self.inner.runtime_download = RuntimeDownload::NotStarted {
1897
0
                        hint_doesnt_match: *hint_doesnt_match,
1898
0
                    };
1899
0
                    return (
1900
0
                        self.inner,
1901
0
                        Err(BuildRuntimeError::SourceMisbehavior(SourceMisbehavior {
1902
0
                            source_id: downloaded_source,
1903
0
                            error: SourceMisbehaviorTy::InvalidMerkleProof(err),
1904
0
                        })),
1905
0
                    );
1906
                }
1907
            };
1908
1909
        let (
1910
0
            finalized_storage_code_merkle_value,
1911
0
            finalized_storage_code_closest_ancestor_excluding,
1912
        ) = {
1913
0
            let code_nibbles = trie::bytes_to_nibbles(b":code".iter().copied()).collect::<Vec<_>>();
1914
0
            match decoded_downloaded_runtime.closest_ancestor_in_proof(
1915
0
                &self.inner.warped_header_state_root,
1916
0
                code_nibbles.iter().take(code_nibbles.len() - 1).copied(),
1917
0
            ) {
1918
0
                Ok(Some(closest_ancestor_key)) => {
1919
0
                    let closest_ancestor_key = closest_ancestor_key.collect::<Vec<_>>();
1920
0
                    let next_nibble = code_nibbles[closest_ancestor_key.len()];
1921
0
                    let merkle_value = decoded_downloaded_runtime
1922
0
                        .trie_node_info(
1923
0
                            &self.inner.warped_header_state_root,
1924
0
                            closest_ancestor_key.iter().copied(),
1925
0
                        )
1926
0
                        .unwrap()
1927
0
                        .children
1928
0
                        .child(next_nibble)
1929
0
                        .merkle_value();
1930
0
1931
0
                    match merkle_value {
1932
0
                        Some(mv) => (mv.to_owned(), closest_ancestor_key),
1933
                        None => {
1934
0
                            self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
1935
0
                            self.inner.runtime_download = RuntimeDownload::NotStarted {
1936
0
                                hint_doesnt_match: *hint_doesnt_match,
1937
0
                            };
1938
0
                            if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
1939
0
                                self.inner.body_download = BodyDownload::NotStarted;
1940
0
                            }
1941
0
                            return (self.inner, Err(BuildRuntimeError::MissingCode));
1942
                        }
1943
                    }
1944
                }
1945
                Ok(None) => {
1946
0
                    self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
1947
0
                    self.inner.runtime_download = RuntimeDownload::NotStarted {
1948
0
                        hint_doesnt_match: *hint_doesnt_match,
1949
0
                    };
1950
0
                    if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
1951
0
                        self.inner.body_download = BodyDownload::NotStarted;
1952
0
                    }
1953
0
                    return (self.inner, Err(BuildRuntimeError::MissingCode));
1954
                }
1955
                Err(proof_decode::IncompleteProofError { .. }) => {
1956
0
                    let downloaded_source = *downloaded_source;
1957
0
                    self.inner.runtime_download = RuntimeDownload::NotStarted {
1958
0
                        hint_doesnt_match: *hint_doesnt_match,
1959
0
                    };
1960
0
                    if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
1961
0
                        self.inner.body_download = BodyDownload::NotStarted;
1962
0
                    }
1963
0
                    return (
1964
0
                        self.inner,
1965
0
                        Err(BuildRuntimeError::SourceMisbehavior(SourceMisbehavior {
1966
0
                            source_id: downloaded_source,
1967
0
                            error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
1968
0
                        })),
1969
0
                    );
1970
                }
1971
            }
1972
        };
1973
1974
0
        let finalized_storage_code = if let (false, Some(hint)) =
1975
0
            (*hint_doesnt_match, self.inner.code_trie_node_hint.as_ref())
1976
        {
1977
0
            if hint.merkle_value == finalized_storage_code_merkle_value {
1978
0
                &hint.storage_value
1979
            } else {
1980
0
                self.inner.runtime_download = RuntimeDownload::NotStarted {
1981
0
                    hint_doesnt_match: true,
1982
0
                };
1983
0
                return (self.inner, Ok(()));
1984
            }
1985
        } else {
1986
0
            match decoded_downloaded_runtime
1987
0
                .storage_value(&self.inner.warped_header_state_root, b":code")
1988
            {
1989
0
                Ok(Some((code, _))) => code,
1990
                Ok(None) => {
1991
0
                    self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
1992
0
                    self.inner.runtime_download = RuntimeDownload::NotStarted {
1993
0
                        hint_doesnt_match: *hint_doesnt_match,
1994
0
                    };
1995
0
                    if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
1996
0
                        self.inner.body_download = BodyDownload::NotStarted;
1997
0
                    }
1998
0
                    return (self.inner, Err(BuildRuntimeError::MissingCode));
1999
                }
2000
                Err(proof_decode::IncompleteProofError { .. }) => {
2001
0
                    let downloaded_source = *downloaded_source;
2002
0
                    return (
2003
0
                        self.inner,
2004
0
                        Err(BuildRuntimeError::SourceMisbehavior(SourceMisbehavior {
2005
0
                            source_id: downloaded_source,
2006
0
                            error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
2007
0
                        })),
2008
0
                    );
2009
                }
2010
            }
2011
        };
2012
2013
0
        let finalized_storage_heappages = match decoded_downloaded_runtime
2014
0
            .storage_value(&self.inner.warped_header_state_root, b":heappages")
2015
        {
2016
0
            Ok(val) => val.map(|(v, _)| v),
Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_12BuildRuntimeppE5build0Bb_
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5build0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeppE5build0Bb_
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5build0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5build0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5build0CsibGXYHQB8Ea_25json_rpc_general_requests
2017
            Err(proof_decode::IncompleteProofError { .. }) => {
2018
0
                let downloaded_source = *downloaded_source;
2019
0
                return (
2020
0
                    self.inner,
2021
0
                    Err(BuildRuntimeError::SourceMisbehavior(SourceMisbehavior {
2022
0
                        source_id: downloaded_source,
2023
0
                        error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
2024
0
                    })),
2025
0
                );
2026
            }
2027
        };
2028
2029
0
        let decoded_heap_pages =
2030
0
            match executor::storage_heap_pages_to_value(finalized_storage_heappages) {
2031
0
                Ok(hp) => hp,
2032
0
                Err(err) => {
2033
0
                    self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
2034
0
                    self.inner.runtime_download = RuntimeDownload::NotStarted {
2035
0
                        hint_doesnt_match: *hint_doesnt_match,
2036
0
                    };
2037
0
                    if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
2038
0
                        self.inner.body_download = BodyDownload::NotStarted;
2039
0
                    }
2040
0
                    return (self.inner, Err(BuildRuntimeError::InvalidHeapPages(err)));
2041
                }
2042
            };
2043
2044
0
        let runtime = match HostVmPrototype::new(host::Config {
2045
0
            module: &finalized_storage_code,
2046
0
            heap_pages: decoded_heap_pages,
2047
0
            exec_hint,
2048
0
            allow_unresolved_imports,
2049
0
        }) {
2050
0
            Ok(runtime) => runtime,
2051
0
            Err(err) => {
2052
0
                self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
2053
0
                self.inner.runtime_download = RuntimeDownload::NotStarted {
2054
0
                    hint_doesnt_match: *hint_doesnt_match,
2055
0
                };
2056
0
                if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
2057
0
                    self.inner.body_download = BodyDownload::NotStarted;
2058
0
                }
2059
0
                return (self.inner, Err(BuildRuntimeError::RuntimeBuild(err)));
2060
            }
2061
        };
2062
2063
0
        let chain_info_builder = chain_information::build::ChainInformationBuild::new(
2064
            chain_information::build::Config {
2065
                finalized_block_header: chain_information::build::ConfigFinalizedBlockHeader::Any {
2066
0
                    scale_encoded_header: self.inner.warped_header.clone(),
2067
0
                    known_finality: if self.inner.download_all_chain_information_storage_proofs {
2068
0
                        None
2069
                    } else {
2070
0
                        Some(self.inner.warped_finality.clone())
2071
                    },
2072
                },
2073
0
                block_number_bytes: self.inner.block_number_bytes,
2074
0
                runtime,
2075
            },
2076
        );
2077
2078
0
        if let chain_information::build::ChainInformationBuild::InProgress(in_progress) =
2079
0
            &chain_info_builder
2080
        {
2081
0
            for call in in_progress.remaining_calls() {
2082
0
                if let hashbrown::hash_map::Entry::Vacant(entry) =
2083
0
                    self.inner.runtime_calls.entry(call)
2084
0
                {
2085
0
                    entry.insert(CallProof::NotStarted);
2086
0
                }
2087
            }
2088
0
        }
2089
2090
0
        self.inner.runtime_download = RuntimeDownload::Verified {
2091
0
            downloaded_runtime: DownloadedRuntime {
2092
0
                storage_code: Some(finalized_storage_code.to_vec()),
2093
0
                storage_heap_pages: finalized_storage_heappages.map(|v| v.to_vec()),
Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_12BuildRuntimeppE5builds_0Bb_
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5builds_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeppE5builds_0Bb_
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5builds_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5builds_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_12BuildRuntimeNtNtB9_3all19WarpSyncSourceExtraNtB18_20WarpSyncRequestExtraE5builds_0CsibGXYHQB8Ea_25json_rpc_general_requests
2094
0
                code_merkle_value: Some(finalized_storage_code_merkle_value),
2095
0
                closest_ancestor_excluding: Some(finalized_storage_code_closest_ancestor_excluding),
2096
0
            },
2097
0
            chain_info_builder,
2098
0
        };
2099
0
2100
0
        (self.inner, Ok(()))
2101
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB5_12BuildRuntimeppE5buildB9_
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_12BuildRuntimeNtNtB7_3all19WarpSyncSourceExtraNtB16_20WarpSyncRequestExtraE5buildCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_12BuildRuntimeppE5buildB9_
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_12BuildRuntimeNtNtB7_3all19WarpSyncSourceExtraNtB16_20WarpSyncRequestExtraE5buildCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_12BuildRuntimeNtNtB7_3all19WarpSyncSourceExtraNtB16_20WarpSyncRequestExtraE5buildCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_12BuildRuntimeNtNtB7_3all19WarpSyncSourceExtraNtB16_20WarpSyncRequestExtraE5buildCsibGXYHQB8Ea_25json_rpc_general_requests
2102
}
2103
2104
/// Problem encountered during a call to [`BuildChainInformation::build`].
2105
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXsM_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncNtB5_26BuildChainInformationErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsM_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncNtB5_26BuildChainInformationErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
2106
pub enum BuildChainInformationError {
2107
    /// Error building the chain information.
2108
    #[display(fmt = "Error building the chain information: {_0}")]
2109
    ChainInformationBuild(chain_information::build::Error),
2110
    /// Source that has sent a proof didn't behave properly.
2111
    SourceMisbehavior(SourceMisbehavior),
2112
}
2113
2114
/// Ready to verify the parameters of the chain against the finalized block.
2115
pub struct BuildChainInformation<TSrc, TRq> {
2116
    inner: WarpSync<TSrc, TRq>,
2117
}
2118
2119
impl<TSrc, TRq> BuildChainInformation<TSrc, TRq> {
2120
    /// Build the information about the chain.
2121
0
    pub fn build(
2122
0
        mut self,
2123
0
    ) -> (
2124
0
        WarpSync<TSrc, TRq>,
2125
0
        Result<RuntimeInformation, BuildChainInformationError>,
2126
0
    ) {
2127
0
        let downloaded_body = match &mut self.inner.body_download {
2128
0
            BodyDownload::NotNeeded => None,
2129
            BodyDownload::Downloaded {
2130
0
                downloaded_source,
2131
0
                body,
2132
0
            } => {
2133
0
                if header::extrinsics_root(body) != self.inner.warped_header_extrinsics_root {
2134
0
                    let source_id = *downloaded_source;
2135
0
                    self.inner.body_download = BodyDownload::NotStarted;
2136
0
                    return (
2137
0
                        self.inner,
2138
0
                        Err(BuildChainInformationError::SourceMisbehavior(
2139
0
                            SourceMisbehavior {
2140
0
                                source_id,
2141
0
                                error: SourceMisbehaviorTy::BlockBodyExtrinsicsRootMismatch,
2142
0
                            },
2143
0
                        )),
2144
0
                    );
2145
0
                }
2146
0
2147
0
                Some(body)
2148
            }
2149
0
            _ => unreachable!(),
2150
        };
2151
2152
        let RuntimeDownload::Verified {
2153
0
            mut chain_info_builder,
2154
0
            downloaded_runtime,
2155
            ..
2156
0
        } = mem::replace(
2157
0
            &mut self.inner.runtime_download,
2158
0
            RuntimeDownload::NotStarted {
2159
0
                hint_doesnt_match: false,
2160
0
            },
2161
0
        )
2162
        else {
2163
0
            unreachable!()
2164
        };
2165
2166
0
        let runtime_calls = mem::take(&mut self.inner.runtime_calls);
2167
0
2168
0
        debug_assert!(runtime_calls
2169
0
            .values()
2170
0
            .all(|c| matches!(c, CallProof::Downloaded { .. })));
Unexecuted instantiation: _RNCNvMs7_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_21BuildChainInformationppE5builds_0Bb_
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5builds_0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationppE5builds_0Bb_
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5builds_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5builds_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5builds_0CsibGXYHQB8Ea_25json_rpc_general_requests
2171
2172
        // Decode all the Merkle proofs that have been received.
2173
0
        let calls = {
2174
0
            let mut decoded_proofs = hashbrown::HashMap::with_capacity_and_hasher(
2175
0
                runtime_calls.len(),
2176
0
                fnv::FnvBuildHasher::default(),
2177
0
            );
2178
2179
0
            for (call, proof) in runtime_calls {
2180
                let CallProof::Downloaded {
2181
0
                    proof,
2182
0
                    downloaded_source,
2183
0
                } = proof
2184
                else {
2185
0
                    unreachable!()
2186
                };
2187
2188
0
                let decoded_proof =
2189
0
                    match proof_decode::decode_and_verify_proof(proof_decode::Config {
2190
0
                        proof: proof.into_iter(),
2191
0
                    }) {
2192
0
                        Ok(d) => d,
2193
0
                        Err(err) => {
2194
0
                            return (
2195
0
                                self.inner,
2196
0
                                Err(BuildChainInformationError::SourceMisbehavior(
2197
0
                                    SourceMisbehavior {
2198
0
                                        source_id: downloaded_source,
2199
0
                                        error: SourceMisbehaviorTy::InvalidMerkleProof(err),
2200
0
                                    },
2201
0
                                )),
2202
0
                            );
2203
                        }
2204
                    };
2205
2206
0
                decoded_proofs.insert(call, (decoded_proof, downloaded_source));
2207
            }
2208
2209
0
            decoded_proofs
2210
        };
2211
2212
        loop {
2213
0
            let in_progress = match chain_info_builder {
2214
                chain_information::build::ChainInformationBuild::Finished {
2215
0
                    result: Ok(chain_information),
2216
0
                    virtual_machine,
2217
0
                } => {
2218
0
                    // This `if` is necessary as in principle we might have continued warp syncing
2219
0
                    // after downloading everything needed but before building the chain
2220
0
                    // information.
2221
0
                    if self.inner.warped_header_number
2222
0
                        == chain_information.as_ref().finalized_block_header.number
2223
0
                    {
2224
0
                        self.inner.warped_block_ty = WarpedBlockTy::AlreadyVerified;
2225
0
                    }
2226
2227
0
                    let finalized_body = downloaded_body.map(mem::take);
2228
0
                    if !matches!(self.inner.body_download, BodyDownload::NotNeeded) {
2229
0
                        self.inner.body_download = BodyDownload::NotStarted;
2230
0
                    }
2231
2232
0
                    self.inner.verified_chain_information = chain_information;
2233
0
                    self.inner.runtime_calls = runtime_calls_default_value(
2234
0
                        self.inner.verified_chain_information.as_ref().consensus,
2235
0
                    );
2236
0
                    return (
2237
0
                        self.inner,
2238
0
                        Ok(RuntimeInformation {
2239
0
                            finalized_runtime: virtual_machine,
2240
0
                            finalized_body,
2241
0
                            finalized_storage_code: downloaded_runtime.storage_code,
2242
0
                            finalized_storage_heap_pages: downloaded_runtime.storage_heap_pages,
2243
0
                            finalized_storage_code_merkle_value: downloaded_runtime
2244
0
                                .code_merkle_value,
2245
0
                            finalized_storage_code_closest_ancestor_excluding: downloaded_runtime
2246
0
                                .closest_ancestor_excluding,
2247
0
                        }),
2248
0
                    );
2249
                }
2250
                chain_information::build::ChainInformationBuild::Finished {
2251
0
                    result: Err(err),
2252
0
                    ..
2253
0
                } => {
2254
0
                    self.inner.warped_block_ty = WarpedBlockTy::KnownBad;
2255
0
                    return (
2256
0
                        self.inner,
2257
0
                        Err(BuildChainInformationError::ChainInformationBuild(err)),
2258
0
                    );
2259
                }
2260
0
                chain_information::build::ChainInformationBuild::InProgress(in_progress) => {
2261
0
                    in_progress
2262
                }
2263
            };
2264
2265
0
            chain_info_builder = match in_progress {
2266
0
                chain_information::build::InProgress::StorageGet(get) => {
2267
0
                    // TODO: child tries not supported
2268
0
                    let (proof, downloaded_source) = calls.get(&get.call_in_progress()).unwrap();
2269
0
                    let value = match proof
2270
0
                        .storage_value(&self.inner.warped_header_state_root, get.key().as_ref())
2271
                    {
2272
0
                        Ok(v) => v,
2273
                        Err(proof_decode::IncompleteProofError { .. }) => {
2274
0
                            return (
2275
0
                                self.inner,
2276
0
                                Err(BuildChainInformationError::SourceMisbehavior(
2277
0
                                    SourceMisbehavior {
2278
0
                                        source_id: *downloaded_source,
2279
0
                                        error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
2280
0
                                    },
2281
0
                                )),
2282
0
                            );
2283
                        }
2284
                    };
2285
2286
0
                    get.inject_value(value.map(|(val, ver)| (iter::once(val), ver)))
Unexecuted instantiation: _RNCNvMs7_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB7_21BuildChainInformationppE5build0Bb_
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5build0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationppE5build0Bb_
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5build0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5build0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB7_21BuildChainInformationNtNtB9_3all19WarpSyncSourceExtraNtB1h_20WarpSyncRequestExtraE5build0CsibGXYHQB8Ea_25json_rpc_general_requests
2287
                }
2288
0
                chain_information::build::InProgress::NextKey(nk) => {
2289
0
                    // TODO: child tries not supported
2290
0
                    let (proof, downloaded_source) = calls.get(&nk.call_in_progress()).unwrap();
2291
0
                    let value = match proof.next_key(
2292
0
                        &self.inner.warped_header_state_root,
2293
0
                        nk.key(),
2294
0
                        nk.or_equal(),
2295
0
                        nk.prefix(),
2296
0
                        nk.branch_nodes(),
2297
0
                    ) {
2298
0
                        Ok(v) => v,
2299
                        Err(proof_decode::IncompleteProofError { .. }) => {
2300
0
                            return (
2301
0
                                self.inner,
2302
0
                                Err(BuildChainInformationError::SourceMisbehavior(
2303
0
                                    SourceMisbehavior {
2304
0
                                        source_id: *downloaded_source,
2305
0
                                        error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
2306
0
                                    },
2307
0
                                )),
2308
0
                            );
2309
                        }
2310
                    };
2311
0
                    nk.inject_key(value)
2312
                }
2313
0
                chain_information::build::InProgress::ClosestDescendantMerkleValue(mv) => {
2314
0
                    // TODO: child tries not supported
2315
0
                    let (proof, downloaded_source) = calls.get(&mv.call_in_progress()).unwrap();
2316
0
                    let value = match proof.closest_descendant_merkle_value(
2317
0
                        &self.inner.warped_header_state_root,
2318
0
                        mv.key(),
2319
0
                    ) {
2320
0
                        Ok(v) => v,
2321
                        Err(proof_decode::IncompleteProofError { .. }) => {
2322
0
                            return (
2323
0
                                self.inner,
2324
0
                                Err(BuildChainInformationError::SourceMisbehavior(
2325
0
                                    SourceMisbehavior {
2326
0
                                        source_id: *downloaded_source,
2327
0
                                        error: SourceMisbehaviorTy::MerkleProofEntriesMissing,
2328
0
                                    },
2329
0
                                )),
2330
0
                            );
2331
                        }
2332
                    };
2333
0
                    mv.inject_merkle_value(value)
2334
                }
2335
            };
2336
        }
2337
0
    }
Unexecuted instantiation: _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot4sync9warp_syncINtB5_21BuildChainInformationppE5buildB9_
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_21BuildChainInformationNtNtB7_3all19WarpSyncSourceExtraNtB1f_20WarpSyncRequestExtraE5buildCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_21BuildChainInformationppE5buildB9_
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_21BuildChainInformationNtNtB7_3all19WarpSyncSourceExtraNtB1f_20WarpSyncRequestExtraE5buildCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_21BuildChainInformationNtNtB7_3all19WarpSyncSourceExtraNtB1f_20WarpSyncRequestExtraE5buildCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot4sync9warp_syncINtB5_21BuildChainInformationNtNtB7_3all19WarpSyncSourceExtraNtB1f_20WarpSyncRequestExtraE5buildCsibGXYHQB8Ea_25json_rpc_general_requests
2338
}
2339
2340
/// Returns `true` if `a` and `b` are equal.
2341
0
fn parameters_equal(mut a: &[u8], b: impl Iterator<Item = impl AsRef<[u8]>>) -> bool {
2342
0
    for slice in b {
2343
0
        let slice = slice.as_ref();
2344
0
2345
0
        if a.len() < slice.len() {
2346
0
            return false;
2347
0
        }
2348
0
2349
0
        if &a[..slice.len()] != slice {
2350
0
            return false;
2351
0
        }
2352
0
2353
0
        a = &a[slice.len()..];
2354
    }
2355
2356
0
    true
2357
0
}
Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot4sync9warp_sync16parameters_equalppEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync16parameters_equalINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBZ_EECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync16parameters_equalppEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync16parameters_equalINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBZ_EECsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync16parameters_equalINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBZ_EECscDgN54JpMGG_6author
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot4sync9warp_sync16parameters_equalINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyBZ_EECsibGXYHQB8Ea_25json_rpc_general_requests