Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/light-base/src/sync_service/standalone.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
use super::{
19
    BlockNotification, ConfigRelayChainRuntimeCodeHint, FinalizedBlockRuntime, Notification,
20
    SubscribeAll, ToBackground,
21
};
22
use crate::{log, network_service, platform::PlatformRef, util};
23
24
use alloc::{
25
    borrow::{Cow, ToOwned as _},
26
    boxed::Box,
27
    format,
28
    string::String,
29
    sync::Arc,
30
    vec::Vec,
31
};
32
use core::{
33
    cmp, iter,
34
    num::{NonZeroU32, NonZeroU64},
35
    pin::Pin,
36
    time::Duration,
37
};
38
use futures_lite::FutureExt as _;
39
use futures_util::{future, stream, FutureExt as _, StreamExt as _};
40
use hashbrown::HashMap;
41
use smoldot::{
42
    chain, header,
43
    informant::HashDisplay,
44
    libp2p,
45
    network::{self, codec},
46
    sync::all,
47
};
48
49
/// Starts a sync service background task to synchronize a standalone chain (relay chain or not).
50
0
pub(super) async fn start_standalone_chain<TPlat: PlatformRef>(
51
0
    log_target: String,
52
0
    platform: TPlat,
53
0
    chain_information: chain::chain_information::ValidChainInformation,
54
0
    block_number_bytes: usize,
55
0
    runtime_code_hint: Option<ConfigRelayChainRuntimeCodeHint>,
56
0
    mut from_foreground: Pin<Box<async_channel::Receiver<ToBackground>>>,
57
0
    network_service: Arc<network_service::NetworkServiceChain<TPlat>>,
58
0
) {
Unexecuted instantiation: _RINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpEB6_
Unexecuted instantiation: _RINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEB1r_
Unexecuted instantiation: _RINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpEB6_
59
0
    let mut task = Task {
60
0
        sync: Some(all::AllSync::new(all::Config {
61
0
            chain_information,
62
0
            block_number_bytes,
63
0
            // Since this module doesn't verify block bodies, any block (even invalid) is accepted
64
0
            // as long as it comes from a legitimate validator. Consequently, validators could
65
0
            // perform attacks by sending completely invalid blocks. Passing `false` to this
66
0
            // option would tighten the definition of what a "legitimate" validator is, and thus
67
0
            // reduce the feasibility of attacks, but not in a significant way. Passing `true`,
68
0
            // on the other hand, allows supporting chains that use custom consensus engines,
69
0
            // which is considered worth the trade-off.
70
0
            allow_unknown_consensus_engines: true,
71
0
            sources_capacity: 32,
72
0
            blocks_capacity: {
73
0
                // This is the maximum number of blocks between two consecutive justifications.
74
0
                1024
75
0
            },
76
0
            max_disjoint_headers: 1024,
77
0
            max_requests_per_block: NonZeroU32::new(3).unwrap(),
78
0
            download_ahead_blocks: {
79
0
                // Verifying a block mostly consists in:
80
0
                //
81
0
                // - Verifying a sr25519 signature for each block, plus a VRF output when the
82
0
                // block is claiming a primary BABE slot.
83
0
                // - Verifying one ed25519 signature per authority for every justification.
84
0
                //
85
0
                // At the time of writing, the speed of these operations hasn't been benchmarked.
86
0
                // It is likely that it varies quite a bit between the various environments (the
87
0
                // different browser engines, and NodeJS).
88
0
                //
89
0
                // Assuming a maximum verification speed of 5k blocks/sec and a 95% latency of one
90
0
                // second, the number of blocks to download ahead of time in order to not block
91
0
                // is 5k.
92
0
                NonZeroU32::new(5000).unwrap()
93
0
            },
94
0
            download_bodies: false,
95
0
            download_all_chain_information_storage_proofs: false,
96
0
            code_trie_node_hint: runtime_code_hint.map(|hint| all::ConfigCodeTrieNodeHint {
97
0
                merkle_value: hint.merkle_value,
98
0
                storage_value: hint.storage_value,
99
0
                closest_ancestor_excluding: hint.closest_ancestor_excluding,
100
0
            }),
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE00Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE00B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE00Ba_
101
0
        })),
102
0
        network_up_to_date_best: true,
103
0
        network_up_to_date_finalized: true,
104
0
        known_finalized_runtime: None,
105
0
        pending_requests: stream::FuturesUnordered::new(),
106
0
        warp_sync_taking_long_time_warning: future::Either::Left(Box::pin(
107
0
            platform.sleep(Duration::from_secs(10)),
108
0
        ))
109
0
        .fuse(),
110
0
        all_notifications: Vec::<async_channel::Sender<Notification>>::new(),
111
0
        log_target,
112
0
        from_network_service: None,
113
0
        network_service,
114
0
        peers_source_id_map: HashMap::with_capacity_and_hasher(
115
0
            0,
116
0
            util::SipHasherBuild::new({
117
0
                let mut seed = [0; 16];
118
0
                platform.fill_random_bytes(&mut seed);
119
0
                seed
120
0
            }),
121
0
        ),
122
0
        platform,
123
0
    };
124
125
    // Main loop of the syncing logic.
126
    //
127
    // This loop contains some CPU-heavy operations (e.g. verifying finality proofs and warp sync
128
    // proofs) but also responding to messages sent by the foreground sync service. In order to
129
    // avoid long delays in responding to foreground messages, the CPU-heavy operations are split
130
    // into small chunks, and each iteration of the loop processes at most one of these chunks and
131
    // processes one foreground message.
132
    loop {
133
        // Yield at every loop in order to provide better tasks granularity.
134
0
        futures_lite::future::yield_now().await;
135
136
        // Now waiting for some event to happen: a network event, a request from the frontend
137
        // of the sync service, or a request being finished.
138
        enum WakeUpReason {
139
            SyncProcess(all::ProcessOne<future::AbortHandle, (libp2p::PeerId, codec::Role), ()>),
140
            MustUpdateNetworkWithBestBlock,
141
            MustUpdateNetworkWithFinalizedBlock,
142
            MustSubscribeNetworkEvents,
143
            NetworkEvent(network_service::Event),
144
            ForegroundMessage(ToBackground),
145
            ForegroundClosed,
146
            StartRequest(all::SourceId, all::DesiredRequest),
147
            ObsoleteRequest(all::RequestId),
148
            RequestFinished(all::RequestId, Result<RequestOutcome, future::Aborted>),
149
            WarpSyncTakingLongTimeWarning,
150
        }
151
152
0
        let wake_up_reason = {
153
0
            async {
154
0
                if let Some(from_network_service) = task.from_network_service.as_mut() {
155
0
                    match from_network_service.next().await {
156
0
                        Some(ev) => WakeUpReason::NetworkEvent(ev),
157
                        None => {
158
0
                            task.from_network_service = None;
159
0
                            WakeUpReason::MustSubscribeNetworkEvents
160
                        }
161
                    }
162
                } else {
163
0
                    WakeUpReason::MustSubscribeNetworkEvents
164
                }
165
0
            }
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s_0Ba_
166
0
            .or(async {
167
0
                from_foreground.next().await.map_or(
168
0
                    WakeUpReason::ForegroundClosed,
169
0
                    WakeUpReason::ForegroundMessage,
170
0
                )
171
0
            })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s0_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s0_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s0_0Ba_
172
0
            .or(async {
173
0
                if task.pending_requests.is_empty() {
174
0
                    future::pending::<()>().await
175
0
                }
176
0
                let (request_id, result) = task.pending_requests.select_next_some().await;
177
0
                WakeUpReason::RequestFinished(request_id, result)
178
0
            })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s1_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s1_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s1_0Ba_
179
0
            .or(async {
180
0
                if !task.network_up_to_date_finalized {
181
0
                    WakeUpReason::MustUpdateNetworkWithFinalizedBlock
182
                } else {
183
0
                    future::pending().await
184
                }
185
0
            })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s2_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s2_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s2_0Ba_
186
0
            .or(async {
187
0
                if !task.network_up_to_date_best {
188
0
                    WakeUpReason::MustUpdateNetworkWithBestBlock
189
                } else {
190
0
                    future::pending().await
191
                }
192
0
            })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s3_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s3_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s3_0Ba_
193
0
            .or(async {
194
0
                (&mut task.warp_sync_taking_long_time_warning).await;
195
0
                task.warp_sync_taking_long_time_warning =
196
0
                    future::Either::Left(Box::pin(task.platform.sleep(Duration::from_secs(10))))
197
0
                        .fuse();
198
0
                WakeUpReason::WarpSyncTakingLongTimeWarning
199
0
            })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s4_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s4_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s4_0Ba_
200
0
            .or({
201
0
                let sync = &mut task.sync;
202
0
                async move {
203
                    // `desired_requests()` returns, in decreasing order of priority, the requests
204
                    // that should be started in order for the syncing to proceed. The fact that
205
                    // multiple requests are returned could be used to filter out undesired one. We
206
                    // use this filtering to enforce a maximum of one ongoing request per source.
207
0
                    let Some(s) = &sync else { unreachable!() };
208
0
                    if let Some((source_id, _, request_detail)) = s
209
0
                        .desired_requests()
210
0
                        .find(|(source_id, _, _)| s.source_num_ongoing_requests(*source_id) == 0)
Unexecuted instantiation: _RNCNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_00Bc_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s5_00B1x_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_00Bc_
211
                    {
212
0
                        return WakeUpReason::StartRequest(source_id, request_detail);
213
0
                    }
214
215
                    // There might be requests that are no longer necessary for a reason or
216
                    // another.
217
0
                    if let Some(request_id) = s.obsolete_requests().next() {
218
0
                        return WakeUpReason::ObsoleteRequest(request_id);
219
0
                    }
220
0
221
0
                    // TODO: eventually, process_one() shouldn't take ownership of the AllForks
222
0
                    match sync.take().unwrap_or_else(|| unreachable!()).process_one() {
Unexecuted instantiation: _RNCNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_0s_0Bc_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s5_0s_0B1x_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_0s_0Bc_
223
0
                        all::ProcessOne::AllSync(idle) => {
224
0
                            *sync = Some(idle);
225
0
                            future::pending().await
226
                        }
227
0
                        other => WakeUpReason::SyncProcess(other),
228
                    }
229
0
                }
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s5_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s5_0Ba_
230
0
            })
231
0
            .await
232
        };
233
234
0
        match wake_up_reason {
235
            WakeUpReason::SyncProcess(all::ProcessOne::AllSync(_)) => {
236
                // Shouldn't be reachable.
237
0
                unreachable!()
238
            }
239
240
0
            WakeUpReason::SyncProcess(all::ProcessOne::WarpSyncBuildRuntime(req)) => {
241
0
                // Warp syncing compiles the runtime. The compiled runtime will later be yielded
242
0
                // in the `WarpSyncFinished` variant, which is then provided as an event.
243
0
                let before_instant = task.platform.now();
244
0
                // Because the runtime being compiled has been validated by 2/3rds of the
245
0
                // validators of the chain, we can assume that it is valid. Doing so significantly
246
0
                // increases the compilation speed.
247
0
                let (new_sync, error) =
248
0
                    req.build(all::ExecHint::CompileWithNonDeterministicValidation, true);
249
0
                let elapsed = task.platform.now() - before_instant;
250
0
                match error {
251
0
                    Ok(()) => {
252
0
                        log!(
253
0
                            &task.platform,
254
0
                            Debug,
255
0
                            &task.log_target,
256
0
                            "warp-sync-runtime-build-success",
257
0
                            success = ?true,
258
0
                            duration = ?elapsed
259
0
                        );
260
0
                    }
261
0
                    Err(error) => {
262
0
                        log!(
263
0
                            &task.platform,
264
0
                            Debug,
265
0
                            &task.log_target,
266
0
                            "warp-sync-runtime-build-error",
267
0
                            ?error
268
0
                        );
269
0
                        if !matches!(error, all::WarpSyncBuildRuntimeError::SourceMisbehavior(_)) {
270
0
                            log!(
271
0
                                &task.platform,
272
0
                                Debug,
273
0
                                &task.log_target,
274
0
                                format!(
275
0
                                    "Failed to compile runtime during warp syncing process: {}",
276
0
                                    error
277
0
                                )
278
0
                            );
279
0
                        }
280
                    }
281
                };
282
0
                task.sync = Some(new_sync);
283
            }
284
285
0
            WakeUpReason::SyncProcess(all::ProcessOne::WarpSyncBuildChainInformation(req)) => {
286
0
                let (new_sync, error) = req.build();
287
0
                match error {
288
0
                    Ok(()) => {
289
0
                        log!(
290
0
                            &task.platform,
291
0
                            Debug,
292
0
                            &task.log_target,
293
0
                            "warp-sync-chain-information-build-success"
294
0
                        );
295
0
                    }
296
0
                    Err(error) => {
297
0
                        log!(
298
0
                            &task.platform,
299
0
                            Debug,
300
0
                            &task.log_target,
301
0
                            "warp-sync-chain-information-build-error",
302
0
                            ?error
303
0
                        );
304
0
                        if !matches!(
305
0
                            error,
306
                            all::WarpSyncBuildChainInformationError::SourceMisbehavior(_)
307
0
                        ) {
308
0
                            log!(
309
0
                                &task.platform,
310
0
                                Warn,
311
0
                                &task.log_target,
312
0
                                format!("Failed to build the chain information during warp syncing process: {}", error)
313
0
                            );
314
0
                        }
315
                    }
316
                };
317
0
                task.sync = Some(new_sync);
318
            }
319
320
            WakeUpReason::SyncProcess(all::ProcessOne::WarpSyncFinished {
321
0
                sync,
322
0
                finalized_block_runtime,
323
0
                finalized_storage_code,
324
0
                finalized_storage_code_closest_ancestor_excluding,
325
0
                finalized_storage_heap_pages,
326
0
                finalized_storage_code_merkle_value,
327
0
                finalized_body: _,
328
0
            }) => {
329
0
                log!(
330
0
                    &task.platform,
331
0
                    Debug,
332
0
                    &task.log_target,
333
0
                    format!(
334
0
                        "GrandPa warp sync finished to #{} ({})",
335
0
                        sync.finalized_block_number(),
336
0
                        HashDisplay(sync.finalized_block_hash())
337
0
                    )
338
0
                );
339
0
340
0
                task.sync = Some(sync);
341
0
342
0
                task.warp_sync_taking_long_time_warning =
343
0
                    future::Either::Right(future::pending()).fuse();
344
0
345
0
                task.known_finalized_runtime = Some(FinalizedBlockRuntime {
346
0
                    virtual_machine: finalized_block_runtime,
347
0
                    storage_code: finalized_storage_code,
348
0
                    storage_heap_pages: finalized_storage_heap_pages,
349
0
                    code_merkle_value: finalized_storage_code_merkle_value,
350
0
                    closest_ancestor_excluding: finalized_storage_code_closest_ancestor_excluding,
351
0
                });
352
0
353
0
                task.network_up_to_date_finalized = false;
354
0
                task.network_up_to_date_best = false;
355
0
                // Since there is a gap in the blocks, all active notifications to all blocks
356
0
                // must be cleared.
357
0
                task.all_notifications.clear();
358
0
            }
359
360
0
            WakeUpReason::SyncProcess(all::ProcessOne::VerifyWarpSyncFragment(verify)) => {
361
0
                // Grandpa warp sync fragment to verify.
362
0
                let sender_if_still_connected = verify
363
0
                    .proof_sender()
364
0
                    .map(|(_, (peer_id, _))| peer_id.clone());
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s6_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s6_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s6_0Ba_
365
0
366
0
                let (sync, result) = verify.perform({
367
0
                    let mut seed = [0; 32];
368
0
                    task.platform.fill_random_bytes(&mut seed);
369
0
                    seed
370
0
                });
371
0
                task.sync = Some(sync);
372
0
373
0
                match result {
374
0
                    Ok((fragment_hash, fragment_number)) => {
375
0
                        // TODO: must call `set_local_grandpa_state` and `set_local_best_block` so that other peers notify us of neighbor packets
376
0
                        log!(
377
0
                            &task.platform,
378
0
                            Debug,
379
0
                            &task.log_target,
380
0
                            "warp-sync-fragment-verify-success",
381
0
                            sender = sender_if_still_connected
382
0
                                .as_ref()
383
0
                                .map(|p| Cow::Owned(p.to_base58()))
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sy_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sy_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sy_0Ba_
384
0
                                .unwrap_or(Cow::Borrowed("<disconnected>")),
385
0
                            verified_hash = HashDisplay(&fragment_hash),
386
0
                            verified_height = fragment_number
387
0
                        );
388
0
                    }
389
0
                    Err(err) => {
390
0
                        log!(
391
0
                            &task.platform,
392
0
                            Debug,
393
0
                            &task.log_target,
394
0
                            format!(
395
0
                                "Failed to verify warp sync fragment from {}: {}{}",
396
0
                                sender_if_still_connected
397
0
                                    .as_ref()
398
0
                                    .map(|p| Cow::Owned(p.to_base58()))
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sz_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sz_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sz_0Ba_
399
0
                                    .unwrap_or(Cow::Borrowed("<disconnected>")),
400
                                err,
401
0
                                if matches!(err, all::VerifyFragmentError::JustificationVerify(_)) {
402
0
                                    ". This might be caused by a forced GrandPa authorities change having \
403
0
                                been enacted on the chain. If this is the case, please update the \
404
0
                                chain specification with a checkpoint past this forced change."
405
                                } else {
406
0
                                    ""
407
                                }
408
                            )
409
                        );
410
0
                        if let Some(sender_if_still_connected) = sender_if_still_connected {
411
0
                            task.network_service
412
0
                                .ban_and_disconnect(
413
0
                                    sender_if_still_connected,
414
0
                                    network_service::BanSeverity::High,
415
0
                                    "bad-warp-sync-fragment",
416
0
                                )
417
0
                                .await;
418
0
                        }
419
                    }
420
                }
421
            }
422
423
0
            WakeUpReason::SyncProcess(all::ProcessOne::VerifyBlock(verify)) => {
424
0
                // Header to verify.
425
0
                let verified_hash = verify.hash();
426
0
                match verify.verify_header(task.platform.now_from_unix_epoch()) {
427
                    all::HeaderVerifyOutcome::Success {
428
0
                        success,
429
0
                        is_new_best,
430
0
                        ..
431
0
                    } => {
432
0
                        let sync = task.sync.insert(success.finish(()));
433
0
434
0
                        log!(
435
0
                            &task.platform,
436
0
                            Debug,
437
0
                            &task.log_target,
438
0
                            "header-verify-success",
439
0
                            hash = HashDisplay(&verified_hash),
440
0
                            is_new_best = if is_new_best { "yes" } else { "no" }
441
                        );
442
443
0
                        if is_new_best {
444
0
                            task.network_up_to_date_best = false;
445
0
                        }
446
447
0
                        let (parent_hash, scale_encoded_header) = {
448
0
                            // TODO: the code below is `O(n)` complexity
449
0
                            let header = sync
450
0
                                .non_finalized_blocks_unordered()
451
0
                                .find(|h| h.hash(sync.block_number_bytes()) == verified_hash)
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s7_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s7_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s7_0Ba_
452
0
                                .unwrap();
453
0
                            (
454
0
                                *header.parent_hash,
455
0
                                header.scale_encoding_vec(sync.block_number_bytes()),
456
0
                            )
457
0
                        };
458
0
459
0
                        // Notify of the new block.
460
0
                        task.dispatch_all_subscribers({
461
0
                            Notification::Block(BlockNotification {
462
0
                                is_new_best,
463
0
                                scale_encoded_header,
464
0
                                parent_hash,
465
0
                            })
466
0
                        });
467
                    }
468
469
0
                    all::HeaderVerifyOutcome::Error { sync, error, .. } => {
470
0
                        task.sync = Some(sync);
471
0
472
0
                        // TODO: print which peer sent the header
473
0
                        log!(
474
0
                            &task.platform,
475
0
                            Debug,
476
0
                            &task.log_target,
477
0
                            "header-verify-error",
478
0
                            hash = HashDisplay(&verified_hash),
479
0
                            ?error
480
0
                        );
481
0
482
0
                        log!(
483
0
                            &task.platform,
484
0
                            Warn,
485
0
                            &task.log_target,
486
0
                            format!(
487
0
                                "Error while verifying header {}: {}",
488
0
                                HashDisplay(&verified_hash),
489
0
                                error
490
0
                            )
491
0
                        );
492
0
493
0
                        // TODO: ban peers that have announced the block
494
0
                        /*for peer_id in task.sync.knows_non_finalized_block(height, hash) {
495
0
                            task.network_service
496
0
                                .ban_and_disconnect(
497
0
                                    peer_id,
498
0
                                    network_service::BanSeverity::High,
499
0
                                    "bad-block",
500
0
                                )
501
0
                                .await;
502
0
                        }*/
503
0
                    }
504
                }
505
            }
506
507
0
            WakeUpReason::SyncProcess(all::ProcessOne::VerifyFinalityProof(verify)) => {
508
0
                // Finality proof to verify.
509
0
                let sender = verify.sender().1 .0.clone();
510
0
                match verify.perform({
511
0
                    let mut seed = [0; 32];
512
0
                    task.platform.fill_random_bytes(&mut seed);
513
0
                    seed
514
0
                }) {
515
                    (
516
0
                        sync,
517
0
                        all::FinalityProofVerifyOutcome::NewFinalized {
518
0
                            updates_best_block,
519
0
                            finalized_blocks_newest_to_oldest,
520
0
                            pruned_blocks,
521
0
                        },
522
0
                    ) => {
523
0
                        log!(
524
0
                            &task.platform,
525
0
                            Debug,
526
0
                            &task.log_target,
527
0
                            "finality-proof-verify-success",
528
0
                            finalized_blocks = finalized_blocks_newest_to_oldest.len(),
529
0
                            sender
530
0
                        );
531
0
532
0
                        if updates_best_block {
533
0
                            task.network_up_to_date_best = false;
534
0
                        }
535
0
                        task.network_up_to_date_finalized = false;
536
0
                        // Invalidate the cache of the runtime of the finalized blocks if any
537
0
                        // of the finalized blocks indicates that a runtime update happened.
538
0
                        if finalized_blocks_newest_to_oldest.iter().any(|b| {
539
0
                            header::decode(&b.header, sync.block_number_bytes())
540
0
                                .unwrap()
541
0
                                .digest
542
0
                                .has_runtime_environment_updated()
543
0
                        }) {
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s8_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s8_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s8_0Ba_
544
0
                            task.known_finalized_runtime = None;
545
0
                        }
546
0
                        task.dispatch_all_subscribers(Notification::Finalized {
547
0
                            hash: *sync.finalized_block_hash(),
548
0
                            best_block_hash_if_changed: if updates_best_block {
549
0
                                Some(*sync.best_block_hash())
550
                            } else {
551
0
                                None
552
                            },
553
0
                            pruned_blocks,
554
0
                        });
555
0
556
0
                        task.sync = Some(sync);
557
                    }
558
559
                    (
560
0
                        sync,
561
                        all::FinalityProofVerifyOutcome::AlreadyFinalized
562
                        | all::FinalityProofVerifyOutcome::GrandpaCommitPending,
563
0
                    ) => {
564
0
                        task.sync = Some(sync);
565
0
                    }
566
567
0
                    (sync, all::FinalityProofVerifyOutcome::JustificationError(error)) => {
568
0
                        task.sync = Some(sync);
569
0
570
0
                        log!(
571
0
                            &task.platform,
572
0
                            Debug,
573
0
                            &task.log_target,
574
0
                            "finality-proof-verify-error",
575
0
                            ?error,
576
0
                            sender,
577
0
                        );
578
579
                        // Errors of type `JustificationEngineMismatch` indicate that the chain
580
                        // uses a finality engine that smoldot doesn't recognize. This is a benign
581
                        // error that shouldn't lead to a ban.
582
0
                        if !matches!(
583
0
                            error,
584
                            all::JustificationVerifyError::JustificationEngineMismatch
585
                        ) {
586
0
                            log!(
587
0
                                &task.platform,
588
0
                                Warn,
589
0
                                &task.log_target,
590
0
                                format!("Error while verifying justification: {error}")
591
0
                            );
592
0
593
0
                            task.network_service
594
0
                                .ban_and_disconnect(
595
0
                                    sender,
596
0
                                    network_service::BanSeverity::High,
597
0
                                    "bad-justification",
598
0
                                )
599
0
                                .await;
600
0
                        }
601
                    }
602
603
0
                    (sync, all::FinalityProofVerifyOutcome::GrandpaCommitError(error)) => {
604
0
                        task.sync = Some(sync);
605
0
606
0
                        log!(
607
0
                            &task.platform,
608
0
                            Debug,
609
0
                            &task.log_target,
610
0
                            "finality-proof-verify-error",
611
0
                            ?error,
612
0
                            sender,
613
0
                        );
614
0
615
0
                        log!(
616
0
                            &task.platform,
617
0
                            Warn,
618
0
                            &task.log_target,
619
0
                            format!("Error while verifying GrandPa commit: {}", error)
620
0
                        );
621
0
622
0
                        task.network_service
623
0
                            .ban_and_disconnect(
624
0
                                sender,
625
0
                                network_service::BanSeverity::High,
626
0
                                "bad-grandpa-commit",
627
0
                            )
628
0
                            .await;
629
                    }
630
                }
631
            }
632
633
            WakeUpReason::NetworkEvent(network_service::Event::Connected {
634
0
                peer_id,
635
0
                role,
636
0
                best_block_number,
637
0
                best_block_hash,
638
0
            }) => {
639
0
                task.peers_source_id_map.insert(
640
0
                    peer_id.clone(),
641
0
                    task.sync
642
0
                        .as_mut()
643
0
                        .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s9_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0s9_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0s9_0Ba_
644
0
                        .prepare_add_source(best_block_number, best_block_hash)
645
0
                        .add_source((peer_id, role), ()),
646
0
                );
647
0
            }
648
649
0
            WakeUpReason::NetworkEvent(network_service::Event::Disconnected { peer_id }) => {
650
0
                let sync_source_id = task.peers_source_id_map.remove(&peer_id).unwrap();
651
0
                let (_, requests) = task
652
0
                    .sync
653
0
                    .as_mut()
654
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sa_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sa_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sa_0Ba_
655
0
                    .remove_source(sync_source_id);
656
657
                // The `Disconnect` network event indicates that the main notifications substream
658
                // with that peer has been closed, not necessarily that the connection as a whole
659
                // has been closed. As such, the in-progress network requests might continue if
660
                // we don't abort them.
661
0
                for (_, abort) in requests {
662
0
                    abort.abort();
663
0
                }
664
            }
665
666
            WakeUpReason::NetworkEvent(network_service::Event::BlockAnnounce {
667
0
                peer_id,
668
0
                announce,
669
0
            }) => {
670
0
                let sync_source_id = *task.peers_source_id_map.get(&peer_id).unwrap();
671
0
                let decoded = announce.decode();
672
0
673
0
                match task
674
0
                    .sync
675
0
                    .as_mut()
676
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sb_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sb_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sb_0Ba_
677
0
                    .block_announce(
678
0
                        sync_source_id,
679
0
                        decoded.scale_encoded_header.to_owned(),
680
0
                        decoded.is_best,
681
0
                    ) {
682
                    all::BlockAnnounceOutcome::TooOld {
683
0
                        announce_block_height,
684
0
                        ..
685
0
                    } => {
686
0
                        log!(
687
0
                            &task.platform,
688
0
                            Debug,
689
0
                            &task.log_target,
690
0
                            "block-announce",
691
0
                            sender = peer_id,
692
0
                            hash = HashDisplay(&header::hash_from_scale_encoded_header(
693
0
                                decoded.scale_encoded_header
694
0
                            )),
695
0
                            height = announce_block_height,
696
0
                            is_best = decoded.is_best,
697
0
                            outcome = "older-than-finalized-block",
698
0
                        );
699
0
                    }
700
0
                    all::BlockAnnounceOutcome::AlreadyVerified(known) => {
701
0
                        log!(
702
0
                            &task.platform,
703
0
                            Debug,
704
0
                            &task.log_target,
705
0
                            "block-announce",
706
0
                            sender = peer_id,
707
0
                            hash = HashDisplay(known.hash()),
708
0
                            height = known.height(),
709
0
                            parent_hash = HashDisplay(known.parent_hash()),
710
0
                            is_best = decoded.is_best,
711
0
                            outcome = "already-verified",
712
0
                        );
713
0
                        known.update_source_and_block();
714
0
                    }
715
0
                    all::BlockAnnounceOutcome::AlreadyPending(known) => {
716
0
                        log!(
717
0
                            &task.platform,
718
0
                            Debug,
719
0
                            &task.log_target,
720
0
                            "block-announce",
721
0
                            sender = peer_id,
722
0
                            hash = HashDisplay(known.hash()),
723
0
                            height = known.height(),
724
0
                            parent_hash = HashDisplay(known.parent_hash()),
725
0
                            is_best = decoded.is_best,
726
0
                            outcome = "already-pending",
727
0
                        );
728
0
                        known.update_source_and_block();
729
0
                    }
730
0
                    all::BlockAnnounceOutcome::Unknown(unknown) => {
731
0
                        log!(
732
0
                            &task.platform,
733
0
                            Debug,
734
0
                            &task.log_target,
735
0
                            "block-announce",
736
0
                            sender = peer_id,
737
0
                            hash = HashDisplay(unknown.hash()),
738
0
                            height = unknown.height(),
739
0
                            parent_hash = HashDisplay(unknown.parent_hash()),
740
0
                            is_best = decoded.is_best,
741
0
                            outcome = "previously-unknown",
742
0
                        );
743
0
                        unknown.insert_and_update_source(());
744
0
                    }
745
0
                    all::BlockAnnounceOutcome::InvalidHeader(error) => {
746
0
                        log!(
747
0
                            &task.platform,
748
0
                            Debug,
749
0
                            &task.log_target,
750
0
                            "block-announce",
751
0
                            sender = peer_id,
752
0
                            hash = HashDisplay(&header::hash_from_scale_encoded_header(
753
0
                                decoded.scale_encoded_header
754
0
                            )),
755
0
                            is_best = decoded.is_best,
756
0
                            outcome = "invalid-header",
757
0
                            ?error,
758
0
                        );
759
0
                        task.network_service
760
0
                            .ban_and_disconnect(
761
0
                                peer_id,
762
0
                                network_service::BanSeverity::High,
763
0
                                "bad-block-announce",
764
0
                            )
765
0
                            .await;
766
                    }
767
                }
768
            }
769
770
            WakeUpReason::NetworkEvent(network_service::Event::GrandpaNeighborPacket {
771
0
                peer_id,
772
0
                finalized_block_height,
773
0
            }) => {
774
0
                let sync_source_id = *task.peers_source_id_map.get(&peer_id).unwrap();
775
0
                task.sync
776
0
                    .as_mut()
777
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sc_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sc_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sc_0Ba_
778
0
                    .update_source_finality_state(sync_source_id, finalized_block_height);
779
0
            }
780
781
            WakeUpReason::NetworkEvent(network_service::Event::GrandpaCommitMessage {
782
0
                peer_id,
783
0
                message,
784
0
            }) => {
785
0
                let sync_source_id = *task.peers_source_id_map.get(&peer_id).unwrap();
786
0
                match task
787
0
                    .sync
788
0
                    .as_mut()
789
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sd_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sd_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sd_0Ba_
790
0
                    .grandpa_commit_message(sync_source_id, message.into_encoded())
791
                {
792
0
                    all::GrandpaCommitMessageOutcome::Queued => {
793
0
                        // TODO: print more details?
794
0
                        log!(
795
0
                            &task.platform,
796
0
                            Debug,
797
0
                            &task.log_target,
798
0
                            "grandpa-commit-message-queued",
799
0
                            sender = peer_id
800
0
                        );
801
0
                    }
802
0
                    all::GrandpaCommitMessageOutcome::Discarded => {
803
0
                        log!(
804
0
                            &task.platform,
805
0
                            Debug,
806
0
                            &task.log_target,
807
0
                            "grandpa-commit-message-ignored",
808
0
                            sender = peer_id
809
0
                        );
810
0
                    }
811
                }
812
            }
813
814
            WakeUpReason::MustSubscribeNetworkEvents => {
815
0
                debug_assert!(task.from_network_service.is_none());
816
0
                for (_, sync_source_id) in task.peers_source_id_map.drain() {
817
0
                    let (_, requests) = task
818
0
                        .sync
819
0
                        .as_mut()
820
0
                        .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0se_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0se_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0se_0Ba_
821
0
                        .remove_source(sync_source_id);
822
0
                    for (_, abort) in requests {
823
0
                        abort.abort();
824
0
                    }
825
                }
826
0
                task.from_network_service = Some(Box::pin(
827
                    // As documented, `subscribe().await` is expected to return quickly.
828
0
                    task.network_service.subscribe().await,
829
                ));
830
            }
831
832
            WakeUpReason::MustUpdateNetworkWithBestBlock => {
833
                // The networking service needs to be kept up to date with what the local node
834
                // considers as the best block.
835
                // For some reason, first building the future then executing it solves a borrow
836
                // checker error.
837
0
                let Some(sync) = &task.sync else {
838
0
                    unreachable!()
839
                };
840
841
0
                let fut = task
842
0
                    .network_service
843
0
                    .set_local_best_block(*sync.best_block_hash(), sync.best_block_number());
844
0
                fut.await;
845
846
0
                task.network_up_to_date_best = true;
847
            }
848
849
            WakeUpReason::MustUpdateNetworkWithFinalizedBlock => {
850
                // If the chain uses GrandPa, the networking has to be kept up-to-date with the
851
                // state of finalization for other peers to send back relevant gossip messages.
852
                // (code style) `grandpa_set_id` is extracted first in order to avoid borrowing
853
                // checker issues.
854
0
                let Some(sync) = &mut task.sync else {
855
0
                    unreachable!()
856
                };
857
858
0
                let grandpa_set_id =
859
                    if let chain::chain_information::ChainInformationFinalityRef::Grandpa {
860
0
                        after_finalized_block_authorities_set_id,
861
                        ..
862
0
                    } = sync.as_chain_information().as_ref().finality
863
                    {
864
0
                        Some(after_finalized_block_authorities_set_id)
865
                    } else {
866
0
                        None
867
                    };
868
869
0
                if let Some(set_id) = grandpa_set_id {
870
0
                    task.network_service
871
0
                        .set_local_grandpa_state(network::service::GrandpaState {
872
0
                            set_id,
873
0
                            round_number: 1, // TODO:
874
0
                            commit_finalized_height: sync.finalized_block_number(),
875
0
                        })
876
0
                        .await;
877
0
                }
878
879
0
                task.network_up_to_date_finalized = true;
880
            }
881
882
            WakeUpReason::ForegroundMessage(ToBackground::IsNearHeadOfChainHeuristic {
883
0
                send_back,
884
0
            }) => {
885
0
                // Frontend is querying something.
886
0
                let _ = send_back.send(
887
0
                    task.sync
888
0
                        .as_ref()
889
0
                        .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sf_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sf_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sf_0Ba_
890
0
                        .is_near_head_of_chain_heuristic(),
891
0
                );
892
0
            }
893
894
            WakeUpReason::ForegroundMessage(ToBackground::SubscribeAll {
895
0
                send_back,
896
0
                buffer_size,
897
0
                runtime_interest,
898
            }) => {
899
                // Frontend would like to subscribe to events.
900
901
0
                let Some(sync) = &task.sync else {
902
0
                    unreachable!()
903
                };
904
905
0
                let (tx, new_blocks) = async_channel::bounded(buffer_size.saturating_sub(1));
906
0
                task.all_notifications.push(tx);
907
0
908
0
                let non_finalized_blocks_ancestry_order = {
909
0
                    sync.non_finalized_blocks_ancestry_order()
910
0
                        .map(|h| {
911
0
                            let scale_encoding = h.scale_encoding_vec(sync.block_number_bytes());
912
0
                            BlockNotification {
913
0
                                is_new_best: header::hash_from_scale_encoded_header(
914
0
                                    &scale_encoding,
915
0
                                ) == *sync.best_block_hash(),
916
0
                                scale_encoded_header: scale_encoding,
917
0
                                parent_hash: *h.parent_hash,
918
0
                            }
919
0
                        })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sg_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sg_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sg_0Ba_
920
0
                        .collect()
921
0
                };
922
0
923
0
                let _ = send_back.send(SubscribeAll {
924
0
                    finalized_block_scale_encoded_header: sync.finalized_block_header().to_owned(),
925
0
                    finalized_block_runtime: if runtime_interest {
926
0
                        task.known_finalized_runtime.take()
927
                    } else {
928
0
                        None
929
                    },
930
0
                    non_finalized_blocks_ancestry_order,
931
0
                    new_blocks,
932
                });
933
            }
934
935
            WakeUpReason::ForegroundMessage(ToBackground::PeersAssumedKnowBlock {
936
0
                send_back,
937
0
                block_number,
938
0
                block_hash,
939
            }) => {
940
                // Frontend queries the list of peers which are expected to know about a certain
941
                // block.
942
0
                let Some(sync) = &task.sync else {
943
0
                    unreachable!()
944
                };
945
946
0
                let outcome = if block_number <= sync.finalized_block_number() {
947
0
                    sync.sources()
948
0
                        .filter(|source_id| {
949
0
                            let source_best = sync.source_best_block(*source_id);
950
0
                            source_best.0 > block_number
951
0
                                || (source_best.0 == block_number && *source_best.1 == block_hash)
952
0
                        })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sh_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sh_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sh_0Ba_
953
0
                        .map(|id| sync[id].0.clone())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0si_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0si_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0si_0Ba_
954
0
                        .collect()
955
                } else {
956
                    // As documented, `knows_non_finalized_block` would panic if the
957
                    // block height was below the one of the known finalized block.
958
0
                    sync.knows_non_finalized_block(block_number, &block_hash)
959
0
                        .map(|id| sync[id].0.clone())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sj_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sj_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sj_0Ba_
960
0
                        .collect()
961
                };
962
963
0
                let _ = send_back.send(outcome);
964
            }
965
966
0
            WakeUpReason::ForegroundMessage(ToBackground::SyncingPeers { send_back }) => {
967
0
                // Frontend is querying the list of peers.
968
0
                let Some(sync) = &task.sync else {
969
0
                    unreachable!()
970
                };
971
972
0
                let out = sync
973
0
                    .sources()
974
0
                    .map(|src| {
975
0
                        let (peer_id, role) = sync[src].clone();
976
0
                        let (height, hash) = sync.source_best_block(src);
977
0
                        (peer_id, role, height, *hash)
978
0
                    })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sk_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sk_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sk_0Ba_
979
0
                    .collect::<Vec<_>>();
980
0
981
0
                let _ = send_back.send(out);
982
            }
983
984
            WakeUpReason::ForegroundMessage(ToBackground::SerializeChainInformation {
985
0
                send_back,
986
0
            }) => {
987
0
                // Frontend is querying the chain information.
988
0
                let _ = send_back.send(Some(
989
0
                    task.sync
990
0
                        .as_ref()
991
0
                        .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sl_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sl_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sl_0Ba_
992
0
                        .as_chain_information()
993
0
                        .into(),
994
0
                ));
995
0
            }
996
997
            WakeUpReason::ForegroundClosed => {
998
                // The channel with the frontend sync service has been closed.
999
                // Closing the sync background task as a result.
1000
0
                return;
1001
            }
1002
1003
0
            WakeUpReason::RequestFinished(_, Err(_)) => {
1004
0
                // A request has been cancelled by the sync state machine. Nothing to do.
1005
0
            }
1006
1007
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::Block(Ok(v)))) => {
1008
0
                // Successful block request.
1009
0
                task.sync
1010
0
                    .as_mut()
1011
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sm_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sm_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sm_0Ba_
1012
0
                    .blocks_request_response(
1013
0
                        request_id,
1014
0
                        v.into_iter().filter_map(|block| {
1015
0
                            Some(all::BlockRequestSuccessBlock {
1016
0
                                scale_encoded_header: block.header?,
1017
0
                                scale_encoded_justifications: block
1018
0
                                    .justifications
1019
0
                                    .unwrap_or(Vec::new())
1020
0
                                    .into_iter()
1021
0
                                    .map(|j| all::Justification {
1022
0
                                        engine_id: j.engine_id,
1023
0
                                        justification: j.justification,
1024
0
                                    })
Unexecuted instantiation: _RNCNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sn_00Bc_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sn_00B1x_
Unexecuted instantiation: _RNCNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sn_00Bc_
1025
0
                                    .collect(),
1026
0
                                scale_encoded_extrinsics: Vec::new(),
1027
0
                                user_data: (),
1028
                            })
1029
0
                        }),
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sn_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sn_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sn_0Ba_
1030
0
                    );
1031
0
            }
1032
1033
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::Block(Err(_)))) => {
1034
                // Failed block request.
1035
0
                let Some(sync) = &mut task.sync else {
1036
0
                    unreachable!()
1037
                };
1038
1039
0
                let source_peer_id = sync[sync.request_source_id(request_id)].0.clone();
1040
0
1041
0
                task.network_service
1042
0
                    .ban_and_disconnect(
1043
0
                        source_peer_id,
1044
0
                        network_service::BanSeverity::Low,
1045
0
                        "failed-blocks-request",
1046
0
                    )
1047
0
                    .await;
1048
1049
0
                sync.remove_request(request_id);
1050
            }
1051
1052
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::WarpSync(Ok(result)))) => {
1053
0
                // Successful warp sync request.
1054
0
                let decoded = result.decode();
1055
0
                let fragments = decoded
1056
0
                    .fragments
1057
0
                    .into_iter()
1058
0
                    .map(|f| all::WarpSyncFragment {
1059
0
                        scale_encoded_header: f.scale_encoded_header.to_vec(),
1060
0
                        scale_encoded_justification: f.scale_encoded_justification.to_vec(),
1061
0
                    })
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0so_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0so_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0so_0Ba_
1062
0
                    .collect();
1063
0
                task.sync
1064
0
                    .as_mut()
1065
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sp_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sp_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sp_0Ba_
1066
0
                    .grandpa_warp_sync_response(request_id, fragments, decoded.is_finished);
1067
0
            }
1068
1069
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::WarpSync(Err(_)))) => {
1070
                // Failed warp sync request.
1071
0
                let Some(sync) = &mut task.sync else {
1072
0
                    unreachable!()
1073
                };
1074
1075
0
                task.network_service
1076
0
                    .ban_and_disconnect(
1077
0
                        sync[sync.request_source_id(request_id)].0.clone(),
1078
0
                        network_service::BanSeverity::Low,
1079
0
                        "failed-warp-sync-request",
1080
0
                    )
1081
0
                    .await;
1082
1083
0
                sync.remove_request(request_id);
1084
            }
1085
1086
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::Storage(Ok(r)))) => {
1087
0
                // Storage proof request.
1088
0
                let Some(sync) = &mut task.sync else {
1089
0
                    unreachable!()
1090
                };
1091
1092
0
                sync.storage_get_response(request_id, r);
1093
            }
1094
1095
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::Storage(Err(_)))) => {
1096
                // Storage proof request.
1097
0
                let Some(sync) = &mut task.sync else {
1098
0
                    unreachable!()
1099
                };
1100
1101
0
                task.network_service
1102
0
                    .ban_and_disconnect(
1103
0
                        sync[sync.request_source_id(request_id)].0.clone(),
1104
0
                        network_service::BanSeverity::Low,
1105
0
                        "failed-storage-request",
1106
0
                    )
1107
0
                    .await;
1108
1109
0
                sync.remove_request(request_id);
1110
            }
1111
1112
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::CallProof(Ok(r)))) => {
1113
0
                // Successful call proof request.
1114
0
                task.sync
1115
0
                    .as_mut()
1116
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sq_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sq_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sq_0Ba_
1117
0
                    .call_proof_response(request_id, r.decode().to_owned());
1118
0
                // TODO: need help from networking service to avoid this to_owned
1119
0
            }
1120
1121
0
            WakeUpReason::RequestFinished(request_id, Ok(RequestOutcome::CallProof(Err(_)))) => {
1122
                // Failed call proof request.
1123
0
                let Some(sync) = &mut task.sync else {
1124
0
                    unreachable!()
1125
                };
1126
1127
0
                task.network_service
1128
0
                    .ban_and_disconnect(
1129
0
                        sync[sync.request_source_id(request_id)].0.clone(),
1130
0
                        network_service::BanSeverity::Low,
1131
0
                        "failed-call-proof-request",
1132
0
                    )
1133
0
                    .await;
1134
1135
0
                sync.remove_request(request_id);
1136
            }
1137
1138
0
            WakeUpReason::ObsoleteRequest(request_id) => {
1139
0
                // We are no longer interested in the answer to that request.
1140
0
                let Some(sync) = &mut task.sync else {
1141
0
                    unreachable!()
1142
                };
1143
1144
0
                let abort_handle = sync.remove_request(request_id);
1145
0
                abort_handle.abort();
1146
            }
1147
1148
            WakeUpReason::StartRequest(
1149
0
                source_id,
1150
0
                all::DesiredRequest::BlocksRequest {
1151
0
                    first_block_hash,
1152
0
                    first_block_height,
1153
0
                    num_blocks,
1154
0
                    request_headers,
1155
0
                    request_bodies,
1156
0
                    request_justification,
1157
                },
1158
0
            ) => {
1159
0
                let Some(sync) = &mut task.sync else {
1160
0
                    unreachable!()
1161
                };
1162
1163
                // Before inserting the request back to the syncing state machine, clamp the number
1164
                // of blocks to the number of blocks we expect to receive.
1165
                // This constant corresponds to the maximum number of blocks that nodes will answer
1166
                // in one request. If this constant happens to be inaccurate, everything will still
1167
                // work but less efficiently.
1168
0
                let num_blocks = NonZeroU64::new(cmp::min(64, num_blocks.get())).unwrap();
1169
0
1170
0
                let peer_id = sync[source_id].0.clone(); // TODO: why does this require cloning? weird borrow chk issue
1171
0
1172
0
                let block_request = task.network_service.clone().blocks_request(
1173
0
                    peer_id,
1174
0
                    network::codec::BlocksRequestConfig {
1175
0
                        start: network::codec::BlocksRequestConfigStart::Hash(first_block_hash),
1176
0
                        desired_count: NonZeroU32::new(
1177
0
                            u32::try_from(num_blocks.get()).unwrap_or(u32::MAX),
1178
0
                        )
1179
0
                        .unwrap(),
1180
0
                        // The direction is hardcoded based on the documentation of the syncing
1181
0
                        // state machine.
1182
0
                        direction: network::codec::BlocksRequestDirection::Descending,
1183
0
                        fields: network::codec::BlocksRequestFields {
1184
0
                            header: request_headers,
1185
0
                            body: request_bodies,
1186
0
                            justifications: request_justification,
1187
0
                        },
1188
0
                    },
1189
0
                    Duration::from_secs(10),
1190
0
                );
1191
0
1192
0
                let (block_request, abort) = future::abortable(block_request);
1193
0
                let request_id = sync.add_request(
1194
0
                    source_id,
1195
0
                    all::RequestDetail::BlocksRequest {
1196
0
                        first_block_hash,
1197
0
                        first_block_height,
1198
0
                        num_blocks,
1199
0
                        request_headers,
1200
0
                        request_bodies,
1201
0
                        request_justification,
1202
0
                    },
1203
0
                    abort,
1204
0
                );
1205
0
1206
0
                task.pending_requests.push(Box::pin(async move {
1207
0
                    (request_id, block_request.await.map(RequestOutcome::Block))
1208
0
                }));
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sr_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sr_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sr_0Ba_
1209
            }
1210
1211
            WakeUpReason::StartRequest(
1212
0
                source_id,
1213
0
                all::DesiredRequest::WarpSync {
1214
0
                    sync_start_block_hash,
1215
                },
1216
0
            ) => {
1217
0
                let Some(sync) = &mut task.sync else {
1218
0
                    unreachable!()
1219
                };
1220
1221
0
                let peer_id = sync[source_id].0.clone(); // TODO: why does this require cloning? weird borrow chk issue
1222
0
1223
0
                let grandpa_request = task.network_service.clone().grandpa_warp_sync_request(
1224
0
                    peer_id,
1225
0
                    sync_start_block_hash,
1226
0
                    // The timeout needs to be long enough to potentially download the maximum
1227
0
                    // response size of 16 MiB. Assuming a 128 kiB/sec connection, that's
1228
0
                    // 128 seconds. Unfortunately, 128 seconds is way too large, and for
1229
0
                    // pragmatic reasons we use a lower value.
1230
0
                    Duration::from_secs(24),
1231
0
                );
1232
0
1233
0
                let (grandpa_request, abort) = future::abortable(grandpa_request);
1234
0
                let request_id = sync.add_request(
1235
0
                    source_id,
1236
0
                    all::RequestDetail::WarpSync {
1237
0
                        sync_start_block_hash,
1238
0
                    },
1239
0
                    abort,
1240
0
                );
1241
0
1242
0
                task.pending_requests.push(Box::pin(async move {
1243
0
                    (
1244
0
                        request_id,
1245
0
                        grandpa_request.await.map(RequestOutcome::WarpSync),
1246
0
                    )
1247
0
                }));
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0ss_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0ss_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0ss_0Ba_
1248
            }
1249
1250
            WakeUpReason::StartRequest(
1251
0
                source_id,
1252
0
                all::DesiredRequest::StorageGetMerkleProof {
1253
0
                    block_hash, keys, ..
1254
                },
1255
0
            ) => {
1256
0
                let Some(sync) = &mut task.sync else {
1257
0
                    unreachable!()
1258
                };
1259
1260
0
                let peer_id = sync[source_id].0.clone(); // TODO: why does this require cloning? weird borrow chk issue
1261
0
1262
0
                let storage_request = task.network_service.clone().storage_proof_request(
1263
0
                    peer_id,
1264
0
                    network::codec::StorageProofRequestConfig {
1265
0
                        block_hash,
1266
0
                        keys: keys.clone().into_iter(),
1267
0
                    },
1268
0
                    Duration::from_secs(16),
1269
0
                );
1270
0
1271
0
                let storage_request = async move {
1272
0
                    if let Ok(outcome) = storage_request.await {
1273
                        // TODO: log what happens
1274
0
                        Ok(outcome.decode().to_vec()) // TODO: no to_vec() here, needs some API change on the networking
1275
                    } else {
1276
0
                        Err(())
1277
                    }
1278
0
                };
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0st_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0st_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0st_0Ba_
1279
1280
0
                let (storage_request, abort) = future::abortable(storage_request);
1281
0
                let request_id = sync.add_request(
1282
0
                    source_id,
1283
0
                    all::RequestDetail::StorageGet { block_hash, keys },
1284
0
                    abort,
1285
0
                );
1286
0
1287
0
                task.pending_requests.push(Box::pin(async move {
1288
0
                    (
1289
0
                        request_id,
1290
0
                        storage_request.await.map(RequestOutcome::Storage),
1291
0
                    )
1292
0
                }));
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0su_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0su_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0su_0Ba_
1293
            }
1294
1295
            WakeUpReason::StartRequest(
1296
0
                source_id,
1297
0
                all::DesiredRequest::RuntimeCallMerkleProof {
1298
0
                    block_hash,
1299
0
                    function_name,
1300
0
                    parameter_vectored,
1301
                },
1302
0
            ) => {
1303
0
                let Some(sync) = &mut task.sync else {
1304
0
                    unreachable!()
1305
                };
1306
1307
0
                let peer_id = sync[source_id].0.clone(); // TODO: why does this require cloning? weird borrow chk issue
1308
0
1309
0
                let call_proof_request = {
1310
0
                    // TODO: all this copying is done because of lifetime requirements in NetworkService::call_proof_request; maybe check if it can be avoided
1311
0
                    let network_service = task.network_service.clone();
1312
0
                    let parameter_vectored = parameter_vectored.clone();
1313
0
                    let function_name = function_name.clone();
1314
0
                    async move {
1315
0
                        let rq = network_service.call_proof_request(
1316
0
                            peer_id,
1317
0
                            network::codec::CallProofRequestConfig {
1318
0
                                block_hash,
1319
0
                                method: Cow::Borrowed(&*function_name),
1320
0
                                parameter_vectored: iter::once(&parameter_vectored),
1321
0
                            },
1322
0
                            Duration::from_secs(16),
1323
0
                        );
1324
0
1325
0
                        match rq.await {
1326
0
                            Ok(p) => Ok(p),
1327
0
                            Err(_) => Err(()),
1328
                        }
1329
0
                    }
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sv_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sv_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sv_0Ba_
1330
                };
1331
1332
0
                let (call_proof_request, abort) = future::abortable(call_proof_request);
1333
0
                let request_id = sync.add_request(
1334
0
                    source_id,
1335
0
                    all::RequestDetail::RuntimeCallMerkleProof {
1336
0
                        block_hash,
1337
0
                        function_name,
1338
0
                        parameter_vectored,
1339
0
                    },
1340
0
                    abort,
1341
0
                );
1342
0
1343
0
                task.pending_requests.push(Box::pin(async move {
1344
0
                    (
1345
0
                        request_id,
1346
0
                        call_proof_request.await.map(RequestOutcome::CallProof),
1347
0
                    )
1348
0
                }));
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sw_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sw_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sw_0Ba_
1349
            }
1350
1351
            WakeUpReason::WarpSyncTakingLongTimeWarning => {
1352
0
                match task
1353
0
                    .sync
1354
0
                    .as_mut()
1355
0
                    .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sx_0Ba_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0sx_0B1v_
Unexecuted instantiation: _RNCNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0sx_0Ba_
1356
0
                    .status()
1357
                {
1358
0
                    all::Status::Sync => {}
1359
                    all::Status::WarpSyncFragments {
1360
                        source: None,
1361
0
                        finalized_block_hash,
1362
0
                        finalized_block_number,
1363
0
                    } => {
1364
0
                        log!(
1365
0
                            &task.platform,
1366
0
                            Warn,
1367
0
                            &task.log_target,
1368
0
                            format!(
1369
0
                                "GrandPa warp sync idle at block #{} (0x{})",
1370
0
                                finalized_block_number,
1371
0
                                HashDisplay(&finalized_block_hash)
1372
0
                            ),
1373
0
                        );
1374
0
                    }
1375
                    all::Status::WarpSyncFragments {
1376
0
                        finalized_block_hash,
1377
0
                        finalized_block_number,
1378
                        ..
1379
                    }
1380
                    | all::Status::WarpSyncChainInformation {
1381
0
                        finalized_block_hash,
1382
0
                        finalized_block_number,
1383
0
                    } => {
1384
0
                        log!(
1385
0
                            &task.platform,
1386
0
                            Warn,
1387
0
                            &task.log_target,
1388
0
                            format!(
1389
0
                                "GrandPa warp sync in progress. Block: #{} (0x{}).",
1390
0
                                finalized_block_number,
1391
0
                                HashDisplay(&finalized_block_hash)
1392
0
                            )
1393
0
                        );
1394
0
                    }
1395
                };
1396
            }
1397
        }
1398
    }
1399
0
}
Unexecuted instantiation: _RNCINvNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standalone22start_standalone_chainpE0B8_
Unexecuted instantiation: _RNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE0B1t_
Unexecuted instantiation: _RNCINvNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standalone22start_standalone_chainpE0B8_
1400
1401
struct Task<TPlat: PlatformRef> {
1402
    /// Log target to use for all logs that are emitted.
1403
    log_target: String,
1404
1405
    /// Access to the platform's capabilities.
1406
    platform: TPlat,
1407
1408
    /// Main syncing state machine. Contains a list of peers, requests, and blocks, and manages
1409
    /// everything about the non-finalized chain.
1410
    ///
1411
    /// For each request, we store a [`future::AbortHandle`] that can be used to abort the
1412
    /// request if desired.
1413
    ///
1414
    /// Always `Some`, except for temporary extraction.
1415
    sync: Option<all::AllSync<future::AbortHandle, (libp2p::PeerId, codec::Role), ()>>,
1416
1417
    /// If `Some`, contains the runtime of the current finalized block.
1418
    known_finalized_runtime: Option<FinalizedBlockRuntime>,
1419
1420
    /// For each networking peer, the index of the corresponding peer within the [`Task::sync`].
1421
    peers_source_id_map: HashMap<libp2p::PeerId, all::SourceId, util::SipHasherBuild>,
1422
1423
    /// `false` after the best block in the [`Task::sync`] has changed. Set back to `true`
1424
    /// after the networking has been notified of this change.
1425
    network_up_to_date_best: bool,
1426
    /// `false` after the finalized block in the [`Task::sync`] has changed. Set back to `true`
1427
    /// after the networking has been notified of this change.
1428
    network_up_to_date_finalized: bool,
1429
1430
    /// All event subscribers that are interested in events about the chain.
1431
    all_notifications: Vec<async_channel::Sender<Notification>>,
1432
1433
    /// Contains a `Delay` after which we print a warning about GrandPa warp sync taking a long
1434
    /// time. Set to `Pending` after the warp sync has finished, so that future remains pending
1435
    /// forever.
1436
    warp_sync_taking_long_time_warning:
1437
        future::Fuse<future::Either<Pin<Box<TPlat::Delay>>, future::Pending<()>>>,
1438
1439
    /// Chain of the network service. Used to send out requests to peers.
1440
    network_service: Arc<network_service::NetworkServiceChain<TPlat>>,
1441
    /// Events coming from the networking service. `None` if not subscribed yet.
1442
    from_network_service: Option<Pin<Box<async_channel::Receiver<network_service::Event>>>>,
1443
1444
    /// List of requests currently in progress.
1445
    pending_requests: stream::FuturesUnordered<
1446
        future::BoxFuture<'static, (all::RequestId, Result<RequestOutcome, future::Aborted>)>,
1447
    >,
1448
}
1449
1450
enum RequestOutcome {
1451
    Block(Result<Vec<codec::BlockData>, network_service::BlocksRequestError>),
1452
    WarpSync(
1453
        Result<
1454
            network::service::EncodedGrandpaWarpSyncResponse,
1455
            network_service::WarpSyncRequestError,
1456
        >,
1457
    ),
1458
    Storage(Result<Vec<u8>, ()>),
1459
    CallProof(Result<network::service::EncodedMerkleProof, ()>),
1460
}
1461
1462
impl<TPlat: PlatformRef> Task<TPlat> {
1463
    /// Sends a notification to all the notification receivers.
1464
0
    fn dispatch_all_subscribers(&mut self, notification: Notification) {
1465
        // Elements in `all_notifications` are removed one by one and inserted back if the
1466
        // channel is still open.
1467
0
        for index in (0..self.all_notifications.len()).rev() {
1468
0
            let subscription = self.all_notifications.swap_remove(index);
1469
0
            if subscription.try_send(notification.clone()).is_err() {
1470
0
                continue;
1471
0
            }
1472
0
1473
0
            self.all_notifications.push(subscription);
1474
        }
1475
0
    }
Unexecuted instantiation: _RNvMNtNtCsiGub1lfKphe_13smoldot_light12sync_service10standaloneINtB2_4TaskpE24dispatch_all_subscribersB6_
Unexecuted instantiation: _RNvMNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standaloneINtB2_4TaskNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefE24dispatch_all_subscribersB1e_
Unexecuted instantiation: _RNvMNtNtCsih6EgvAwZF2_13smoldot_light12sync_service10standaloneINtB2_4TaskpE24dispatch_all_subscribersB6_
1476
}