Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/sync/all_forks/sources.rs
Line
Count
Source (jump to first uncovered line)
1
// Substrate-lite
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
//! Collection of sources used for the `all_forks` syncing.
19
//!
20
//! Each source stored in the [`AllForksSources`] is associated to:
21
//!
22
//! - A [`SourceId`].
23
//! - A best block.
24
//! - A list of non-finalized blocks known by this source.
25
//! - An opaque user data, of type `TSrc`.
26
//!
27
28
use alloc::{collections::BTreeSet, vec::Vec};
29
use core::{fmt, ops};
30
31
/// Identifier for a source in the [`AllForksSources`].
32
//
33
// Implementation note: the `u64` values are never re-used, making it possible to avoid clearing
34
// obsolete SourceIds in the `AllForksSources` state machine.
35
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
36
pub struct SourceId(u64);
37
38
/// Collection of sources and which blocks they know about.
39
pub struct AllForksSources<TSrc> {
40
    /// Actual list of sources.
41
    sources: hashbrown::HashMap<SourceId, Source<TSrc>, fnv::FnvBuildHasher>,
42
43
    /// Identifier to allocate to the next source. Identifiers are never reused, which allows
44
    /// keeping obsolete identifiers in the internal state.
45
    next_source_id: SourceId,
46
47
    /// Stores `(source, block hash)` tuples. Each tuple is an information about the fact that
48
    /// this source knows about the given block. Only contains blocks whose height is strictly
49
    /// superior to [`AllForksSources::finalized_block_height`].
50
    known_blocks1: BTreeSet<(SourceId, u64, [u8; 32])>,
51
52
    /// Contains the same entries as [`AllForksSources::known_blocks1`], but in reverse.
53
    known_blocks2: BTreeSet<(u64, [u8; 32], SourceId)>,
54
55
    /// Height of the finalized block. All sources whose best block number is superior to this
56
    /// value is expected to know the entire finalized chain.
57
    finalized_block_height: u64,
58
}
59
60
/// Extra fields specific to each blocks source.
61
///
62
/// `best_block_number`/`best_block_hash` must be present in the known blocks.
63
#[derive(Debug)]
64
struct Source<TSrc> {
65
    best_block_number: u64,
66
    best_block_hash: [u8; 32],
67
    user_data: TSrc,
68
}
69
70
impl<TSrc> AllForksSources<TSrc> {
71
    /// Creates a new container. Must be passed the height of the known finalized block.
72
22
    pub fn new(sources_capacity: usize, finalized_block_height: u64) -> Self {
73
22
        AllForksSources {
74
22
            sources: hashbrown::HashMap::with_capacity_and_hasher(
75
22
                sources_capacity,
76
22
                Default::default(),
77
22
            ),
78
22
            next_source_id: SourceId(0),
79
22
            known_blocks1: Default::default(),
80
22
            known_blocks2: Default::default(),
81
22
            finalized_block_height,
82
22
        }
83
22
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE3newB8_
Line
Count
Source
72
1
    pub fn new(sources_capacity: usize, finalized_block_height: u64) -> Self {
73
1
        AllForksSources {
74
1
            sources: hashbrown::HashMap::with_capacity_and_hasher(
75
1
                sources_capacity,
76
1
                Default::default(),
77
1
            ),
78
1
            next_source_id: SourceId(0),
79
1
            known_blocks1: Default::default(),
80
1
            known_blocks2: Default::default(),
81
1
            finalized_block_height,
82
1
        }
83
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE3newCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE3newCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE3newB8_
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE3newCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
72
2
    pub fn new(sources_capacity: usize, finalized_block_height: u64) -> Self {
73
2
        AllForksSources {
74
2
            sources: hashbrown::HashMap::with_capacity_and_hasher(
75
2
                sources_capacity,
76
2
                Default::default(),
77
2
            ),
78
2
            next_source_id: SourceId(0),
79
2
            known_blocks1: Default::default(),
80
2
            known_blocks2: Default::default(),
81
2
            finalized_block_height,
82
2
        }
83
2
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE3newCscDgN54JpMGG_6author
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE3newCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
72
19
    pub fn new(sources_capacity: usize, finalized_block_height: u64) -> Self {
73
19
        AllForksSources {
74
19
            sources: hashbrown::HashMap::with_capacity_and_hasher(
75
19
                sources_capacity,
76
19
                Default::default(),
77
19
            ),
78
19
            next_source_id: SourceId(0),
79
19
            known_blocks1: Default::default(),
80
19
            known_blocks2: Default::default(),
81
19
            finalized_block_height,
82
19
        }
83
19
    }
84
85
    /// Returns the list of all [`SourceId`]s.
86
21
    pub fn keys(&'_ self) -> impl ExactSizeIterator<Item = SourceId> + '_ {
87
21
        self.sources.keys().copied()
88
21
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE4keysB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE4keysCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE4keysCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE4keysB8_
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE4keysCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
86
2
    pub fn keys(&'_ self) -> impl ExactSizeIterator<Item = SourceId> + '_ {
87
2
        self.sources.keys().copied()
88
2
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE4keysCscDgN54JpMGG_6author
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE4keysCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
86
19
    pub fn keys(&'_ self) -> impl ExactSizeIterator<Item = SourceId> + '_ {
87
19
        self.sources.keys().copied()
88
19
    }
89
90
    /// Returns true if the data structure is empty.
91
3
    pub fn is_empty(&self) -> bool {
92
3
        self.sources.is_empty()
93
3
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE8is_emptyB8_
Line
Count
Source
91
3
    pub fn is_empty(&self) -> bool {
92
3
        self.sources.is_empty()
93
3
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE8is_emptyB8_
94
95
    /// Returns the number of sources in the data structure.
96
2
    pub fn len(&self) -> usize {
97
2
        self.sources.len()
98
2
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE3lenB8_
Line
Count
Source
96
2
    pub fn len(&self) -> usize {
97
2
        self.sources.len()
98
2
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE3lenB8_
99
100
    /// Remove all the sources.
101
0
    pub fn clear(&mut self) {
102
0
        self.sources.clear();
103
0
        self.known_blocks1.clear();
104
0
        self.known_blocks2.clear();
105
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE5clearB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE5clearCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE5clearB8_
106
107
    /// Returns the list of all user datas of all sources.
108
0
    pub fn user_data_iter_mut(&'_ mut self) -> impl ExactSizeIterator<Item = &'_ mut TSrc> + '_ {
109
0
        self.sources.values_mut().map(|s| &mut s.user_data)
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE18user_data_iter_mut0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE18user_data_iter_mut0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE18user_data_iter_mut0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE18user_data_iter_mut0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE18user_data_iter_mut0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE18user_data_iter_mut0CsibGXYHQB8Ea_25json_rpc_general_requests
110
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE18user_data_iter_mutB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE18user_data_iter_mutCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE18user_data_iter_mutB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE18user_data_iter_mutCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE18user_data_iter_mutCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE18user_data_iter_mutCsibGXYHQB8Ea_25json_rpc_general_requests
111
112
    /// Returns the number of unique blocks in the data structure.
113
    // TODO: is this method needed at all?
114
5
    pub fn num_blocks(&self) -> usize {
115
5
        // TODO: optimize; shouldn't be O(n)
116
5
        self.known_blocks2
117
5
            .iter()
118
5
            .fold((0, None), |(uniques, prev), next| 
match (prev, next4
) {
119
1
                (Some((
pn, ph0
)), (nn, nh, _)) if pn == *nn &&
ph0
== *nh => {
120
0
                    (uniques, Some((pn, ph)))
121
                }
122
4
                (_, (nn, nh, _)) => (uniques + 1, Some((*nn, *nh))),
123
5
            
}4
)
_RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesuE10num_blocks0Ba_
Line
Count
Source
118
4
            .fold((0, None), |(uniques, prev), next| match (prev, next) {
119
1
                (Some((
pn, ph0
)), (nn, nh, _)) if pn == *nn &&
ph0
== *nh => {
120
0
                    (uniques, Some((pn, ph)))
121
                }
122
4
                (_, (nn, nh, _)) => (uniques + 1, Some((*nn, *nh))),
123
4
            })
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE10num_blocks0Ba_
124
5
            .0
125
5
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE10num_blocksB8_
Line
Count
Source
114
5
    pub fn num_blocks(&self) -> usize {
115
5
        // TODO: optimize; shouldn't be O(n)
116
5
        self.known_blocks2
117
5
            .iter()
118
5
            .fold((0, None), |(uniques, prev), next| match (prev, next) {
119
                (Some((pn, ph)), (nn, nh, _)) if pn == *nn && ph == *nh => {
120
                    (uniques, Some((pn, ph)))
121
                }
122
                (_, (nn, nh, _)) => (uniques + 1, Some((*nn, *nh))),
123
5
            })
124
5
            .0
125
5
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE10num_blocksB8_
126
127
    /// Returns the finalized block height this state machine knows about.
128
0
    pub fn finalized_block_height(&self) -> u64 {
129
0
        self.finalized_block_height
130
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE22finalized_block_heightB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE22finalized_block_heightCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE22finalized_block_heightCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE22finalized_block_heightB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE22finalized_block_heightCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE22finalized_block_heightCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE22finalized_block_heightCsibGXYHQB8Ea_25json_rpc_general_requests
131
132
    /// Add a new source to the container.
133
    ///
134
    /// The `user_data` parameter is opaque and decided entirely by the user. It can later be
135
    /// retrieved using the `Index` trait implementation of this container.
136
    ///
137
    /// Returns the newly-created source entry.
138
22
    pub fn add_source(
139
22
        &mut self,
140
22
        best_block_number: u64,
141
22
        best_block_hash: [u8; 32],
142
22
        user_data: TSrc,
143
22
    ) -> SourceId {
144
22
        let new_id = {
145
22
            let id = self.next_source_id;
146
22
            self.next_source_id.0 += 1;
147
22
            id
148
22
        };
149
22
150
22
        self.sources.insert(
151
22
            new_id,
152
22
            Source {
153
22
                best_block_number,
154
22
                best_block_hash,
155
22
                user_data,
156
22
            },
157
22
        );
158
22
159
22
        if best_block_number > self.finalized_block_height {
160
1
            self.known_blocks1
161
1
                .insert((new_id, best_block_number, best_block_hash));
162
1
            self.known_blocks2
163
1
                .insert((best_block_number, best_block_hash, new_id));
164
21
        }
165
166
22
        new_id
167
22
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE10add_sourceB8_
Line
Count
Source
138
1
    pub fn add_source(
139
1
        &mut self,
140
1
        best_block_number: u64,
141
1
        best_block_hash: [u8; 32],
142
1
        user_data: TSrc,
143
1
    ) -> SourceId {
144
1
        let new_id = {
145
1
            let id = self.next_source_id;
146
1
            self.next_source_id.0 += 1;
147
1
            id
148
1
        };
149
1
150
1
        self.sources.insert(
151
1
            new_id,
152
1
            Source {
153
1
                best_block_number,
154
1
                best_block_hash,
155
1
                user_data,
156
1
            },
157
1
        );
158
1
159
1
        if best_block_number > self.finalized_block_height {
160
1
            self.known_blocks1
161
1
                .insert((new_id, best_block_number, best_block_hash));
162
1
            self.known_blocks2
163
1
                .insert((best_block_number, best_block_hash, new_id));
164
1
        }
0
165
166
1
        new_id
167
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10add_sourceCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE10add_sourceCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE10add_sourceB8_
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10add_sourceCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
138
2
    pub fn add_source(
139
2
        &mut self,
140
2
        best_block_number: u64,
141
2
        best_block_hash: [u8; 32],
142
2
        user_data: TSrc,
143
2
    ) -> SourceId {
144
2
        let new_id = {
145
2
            let id = self.next_source_id;
146
2
            self.next_source_id.0 += 1;
147
2
            id
148
2
        };
149
2
150
2
        self.sources.insert(
151
2
            new_id,
152
2
            Source {
153
2
                best_block_number,
154
2
                best_block_hash,
155
2
                user_data,
156
2
            },
157
2
        );
158
2
159
2
        if best_block_number > self.finalized_block_height {
160
0
            self.known_blocks1
161
0
                .insert((new_id, best_block_number, best_block_hash));
162
0
            self.known_blocks2
163
0
                .insert((best_block_number, best_block_hash, new_id));
164
2
        }
165
166
2
        new_id
167
2
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10add_sourceCscDgN54JpMGG_6author
_RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10add_sourceCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
138
19
    pub fn add_source(
139
19
        &mut self,
140
19
        best_block_number: u64,
141
19
        best_block_hash: [u8; 32],
142
19
        user_data: TSrc,
143
19
    ) -> SourceId {
144
19
        let new_id = {
145
19
            let id = self.next_source_id;
146
19
            self.next_source_id.0 += 1;
147
19
            id
148
19
        };
149
19
150
19
        self.sources.insert(
151
19
            new_id,
152
19
            Source {
153
19
                best_block_number,
154
19
                best_block_hash,
155
19
                user_data,
156
19
            },
157
19
        );
158
19
159
19
        if best_block_number > self.finalized_block_height {
160
0
            self.known_blocks1
161
0
                .insert((new_id, best_block_number, best_block_hash));
162
0
            self.known_blocks2
163
0
                .insert((best_block_number, best_block_hash, new_id));
164
19
        }
165
166
19
        new_id
167
19
    }
168
169
    /// Removes the source from the [`AllForksSources`].
170
    ///
171
    /// Returns the user data that was originally passed to [`AllForksSources::add_source`].
172
    ///
173
    /// # Panic
174
    ///
175
    /// Panics if the [`SourceId`] is out of range.
176
    ///
177
    #[track_caller]
178
1
    pub fn remove(&mut self, source_id: SourceId) -> TSrc {
179
1
        let source = self.sources.remove(&source_id).unwrap();
180
1
181
1
        // Purge `known_blocks1` and `known_blocks2`.
182
1
        let known_blocks = self
183
1
            .known_blocks1
184
1
            .range((source_id, 0, [0; 32])..=(source_id, u64::MAX, [0xff; 32]))
185
1
            .map(|(_, n, h)| 
(*n, *h)0
)
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesuE6remove0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE6remove0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesTNtNtNtBa_6libp2p7peer_id6PeerIdNtNtNtNtBa_7network5codec15block_announces4RoleEE6remove0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE6remove0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE6remove0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE6remove0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE6remove0CsibGXYHQB8Ea_25json_rpc_general_requests
186
1
            .collect::<Vec<_>>();
187
1
        for (
height, hash0
) in known_blocks {
188
0
            let _was_in1 = self.known_blocks1.remove(&(source_id, height, hash));
189
0
            let _was_in2 = self.known_blocks2.remove(&(height, hash, source_id));
190
0
            debug_assert!(_was_in1);
191
0
            debug_assert!(_was_in2);
192
        }
193
194
1
        source.user_data
195
1
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE6removeB8_
Line
Count
Source
178
1
    pub fn remove(&mut self, source_id: SourceId) -> TSrc {
179
1
        let source = self.sources.remove(&source_id).unwrap();
180
1
181
1
        // Purge `known_blocks1` and `known_blocks2`.
182
1
        let known_blocks = self
183
1
            .known_blocks1
184
1
            .range((source_id, 0, [0; 32])..=(source_id, u64::MAX, [0xff; 32]))
185
1
            .map(|(_, n, h)| (*n, *h))
186
1
            .collect::<Vec<_>>();
187
1
        for (
height, hash0
) in known_blocks {
188
0
            let _was_in1 = self.known_blocks1.remove(&(source_id, height, hash));
189
0
            let _was_in2 = self.known_blocks2.remove(&(height, hash, source_id));
190
0
            debug_assert!(_was_in1);
191
0
            debug_assert!(_was_in2);
192
        }
193
194
1
        source.user_data
195
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE6removeCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE6removeCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE6removeB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE6removeCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE6removeCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE6removeCsibGXYHQB8Ea_25json_rpc_general_requests
196
197
    /// Updates the height of the finalized block.
198
    ///
199
    /// This removes from the collection, and will ignore in the future, all blocks whose height
200
    /// is inferior or equal to this value.
201
    ///
202
    /// # Panic
203
    ///
204
    /// Panics if the new height is inferior to the previous value.
205
    ///
206
1
    pub fn set_finalized_block_height(&mut self, height: u64) {
207
1
        assert!(height >= self.finalized_block_height);
208
209
1
        debug_assert_eq!(
210
1
            self.known_blocks2
211
1
                .range(
212
1
                    (0, [0; 32], SourceId(u64::MIN))
213
1
                        ..=(self.finalized_block_height, [0xff; 32], SourceId(u64::MAX)),
214
1
                )
215
1
                .count(),
216
            0
217
        );
218
219
1
        let entries = self
220
1
            .known_blocks2
221
1
            .range((0, [0; 32], SourceId(u64::MIN))..=(height, [0xff; 32], SourceId(u64::MAX)))
222
1
            .cloned()
223
1
            .collect::<Vec<_>>();
224
225
2
        for (
height, hash, source_id1
) in entries {
226
1
            self.known_blocks2.remove(&(height, hash, source_id));
227
1
            let _was_in = self.known_blocks1.remove(&(source_id, height, hash));
228
1
            debug_assert!(_was_in);
229
        }
230
231
1
        self.finalized_block_height = height;
232
1
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE26set_finalized_block_heightB8_
Line
Count
Source
206
1
    pub fn set_finalized_block_height(&mut self, height: u64) {
207
1
        assert!(height >= self.finalized_block_height);
208
209
1
        debug_assert_eq!(
210
1
            self.known_blocks2
211
1
                .range(
212
1
                    (0, [0; 32], SourceId(u64::MIN))
213
1
                        ..=(self.finalized_block_height, [0xff; 32], SourceId(u64::MAX)),
214
1
                )
215
1
                .count(),
216
            0
217
        );
218
219
1
        let entries = self
220
1
            .known_blocks2
221
1
            .range((0, [0; 32], SourceId(u64::MIN))..=(height, [0xff; 32], SourceId(u64::MAX)))
222
1
            .cloned()
223
1
            .collect::<Vec<_>>();
224
225
2
        for (
height, hash, source_id1
) in entries {
226
1
            self.known_blocks2.remove(&(height, hash, source_id));
227
1
            let _was_in = self.known_blocks1.remove(&(source_id, height, hash));
228
1
            debug_assert!(_was_in);
229
        }
230
231
1
        self.finalized_block_height = height;
232
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE26set_finalized_block_heightCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE26set_finalized_block_heightCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE26set_finalized_block_heightB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE26set_finalized_block_heightCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE26set_finalized_block_heightCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE26set_finalized_block_heightCsibGXYHQB8Ea_25json_rpc_general_requests
233
234
    /// Registers a new block that the source is aware of.
235
    ///
236
    /// Has no effect if `height` is inferior or equal to the finalized block height.
237
    ///
238
    /// # Panic
239
    ///
240
    /// Panics if the [`SourceId`] is out of range.
241
    ///
242
1
    pub fn add_known_block(&mut self, source_id: SourceId, height: u64, hash: [u8; 32]) {
243
1
        if height > self.finalized_block_height {
244
1
            self.known_blocks1.insert((source_id, height, hash));
245
1
            self.known_blocks2.insert((height, hash, source_id));
246
1
        }
0
247
1
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE15add_known_blockB8_
Line
Count
Source
242
1
    pub fn add_known_block(&mut self, source_id: SourceId, height: u64, hash: [u8; 32]) {
243
1
        if height > self.finalized_block_height {
244
1
            self.known_blocks1.insert((source_id, height, hash));
245
1
            self.known_blocks2.insert((height, hash, source_id));
246
1
        }
0
247
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE15add_known_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE15add_known_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE15add_known_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE15add_known_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE15add_known_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE15add_known_blockCsibGXYHQB8Ea_25json_rpc_general_requests
248
249
    /// Removes a block from the list of blocks the sources are aware of.
250
    ///
251
    /// > **Note**: Alongside with [`AllForksSources::set_finalized_block_height`], this method
252
    /// >           can be used to prevent the data structure from growing indefinitely.
253
1
    pub fn remove_known_block(&mut self, height: u64, hash: &[u8; 32]) {
254
1
        let sources = self
255
1
            .known_blocks2
256
1
            .range((height, *hash, SourceId(u64::MIN))..=(height, *hash, SourceId(u64::MAX)))
257
1
            .map(|(_, _, source)| *source)
_RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesuE18remove_known_block0Ba_
Line
Count
Source
257
1
            .map(|(_, _, source)| *source)
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE18remove_known_block0Ba_
258
1
            .collect::<Vec<_>>();
259
260
2
        for 
source_id1
in sources {
261
1
            self.known_blocks2.remove(&(height, *hash, source_id));
262
1
            let _was_in = self.known_blocks1.remove(&(source_id, height, *hash));
263
1
            debug_assert!(_was_in);
264
        }
265
1
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE18remove_known_blockB8_
Line
Count
Source
253
1
    pub fn remove_known_block(&mut self, height: u64, hash: &[u8; 32]) {
254
1
        let sources = self
255
1
            .known_blocks2
256
1
            .range((height, *hash, SourceId(u64::MIN))..=(height, *hash, SourceId(u64::MAX)))
257
1
            .map(|(_, _, source)| *source)
258
1
            .collect::<Vec<_>>();
259
260
2
        for 
source_id1
in sources {
261
1
            self.known_blocks2.remove(&(height, *hash, source_id));
262
1
            let _was_in = self.known_blocks1.remove(&(source_id, height, *hash));
263
1
            debug_assert!(_was_in);
264
        }
265
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE18remove_known_blockB8_
266
267
    /// Removes a block from the list of blocks the source is aware of.
268
    ///
269
    /// Has no effect if the source didn't know this block.
270
    ///
271
    /// > **Note**: Can be used when a request is sent to a node, and the node answers that it
272
    /// >           doesn't know about the requested block contrary to previously believed.
273
    ///
274
    /// # Panic
275
    ///
276
    /// Panics if the [`SourceId`] is out of range.
277
    ///
278
0
    pub fn source_remove_known_block(&mut self, source_id: SourceId, height: u64, hash: &[u8; 32]) {
279
0
        let _was_in1 = self.known_blocks1.remove(&(source_id, height, *hash));
280
0
        let _was_in2 = self.known_blocks2.remove(&(height, *hash, source_id));
281
0
        debug_assert_eq!(_was_in1, _was_in2);
282
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE25source_remove_known_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25source_remove_known_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE25source_remove_known_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25source_remove_known_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25source_remove_known_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25source_remove_known_blockCsibGXYHQB8Ea_25json_rpc_general_requests
283
284
    /// Registers a new block that the source is aware of and sets it as its best block.
285
    ///
286
    /// If the block height is inferior or equal to the finalized block height, the block itself
287
    /// isn't kept in memory but is still set as the source's best block.
288
    ///
289
    /// # Panic
290
    ///
291
    /// Panics if the [`SourceId`] is out of range.
292
    ///
293
    #[track_caller]
294
1
    pub fn add_known_block_and_set_best(
295
1
        &mut self,
296
1
        source_id: SourceId,
297
1
        height: u64,
298
1
        hash: [u8; 32],
299
1
    ) {
300
1
        self.add_known_block(source_id, height, hash);
301
1
302
1
        let source = self.sources.get_mut(&source_id).unwrap();
303
1
        source.best_block_number = height;
304
1
        source.best_block_hash = hash;
305
1
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE28add_known_block_and_set_bestB8_
Line
Count
Source
294
1
    pub fn add_known_block_and_set_best(
295
1
        &mut self,
296
1
        source_id: SourceId,
297
1
        height: u64,
298
1
        hash: [u8; 32],
299
1
    ) {
300
1
        self.add_known_block(source_id, height, hash);
301
1
302
1
        let source = self.sources.get_mut(&source_id).unwrap();
303
1
        source.best_block_number = height;
304
1
        source.best_block_hash = hash;
305
1
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE28add_known_block_and_set_bestCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE28add_known_block_and_set_bestCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE28add_known_block_and_set_bestB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE28add_known_block_and_set_bestCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE28add_known_block_and_set_bestCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE28add_known_block_and_set_bestCsibGXYHQB8Ea_25json_rpc_general_requests
306
307
    /// Returns the current best block of the given source.
308
    ///
309
    /// This corresponds either to the latest call to
310
    /// [`AllForksSources::add_known_block_and_set_best`], or to the parameter passed to
311
    /// [`AllForksSources::add_source`].
312
    ///
313
    /// # Panic
314
    ///
315
    /// Panics if the [`SourceId`] is invalid.
316
    ///
317
0
    pub fn best_block(&self, source_id: SourceId) -> (u64, &[u8; 32]) {
318
0
        let source = self.sources.get(&source_id).unwrap();
319
0
        (source.best_block_number, &source.best_block_hash)
320
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE10best_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10best_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE10best_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE10best_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10best_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10best_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE10best_blockCsibGXYHQB8Ea_25json_rpc_general_requests
321
322
    /// Returns the list of sources for which [`AllForksSources::knows_non_finalized_block`]
323
    /// would return `true`.
324
    ///
325
    /// # Panic
326
    ///
327
    /// Panics if `height` is inferior or equal to the finalized block height. Finalized blocks
328
    /// are intentionally not tracked by this data structure, and panicking when asking for a
329
    /// potentially-finalized block prevents potentially confusing or erroneous situations.
330
    ///
331
0
    pub fn knows_non_finalized_block<'a>(
332
0
        &'a self,
333
0
        height: u64,
334
0
        hash: &[u8; 32],
335
0
    ) -> impl Iterator<Item = SourceId> + 'a {
336
0
        assert!(height > self.finalized_block_height);
337
0
        self.known_blocks2
338
0
            .range((height, *hash, SourceId(u64::MIN))..=(height, *hash, SourceId(u64::MAX)))
339
0
            .map(|(_, _, id)| *id)
Unexecuted instantiation: _RNCNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE25knows_non_finalized_block0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE25knows_non_finalized_block0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesTNtNtNtBa_6libp2p7peer_id6PeerIdNtNtNtNtBa_7network5codec15block_announces4RoleEE25knows_non_finalized_block0CsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcespE25knows_non_finalized_block0Ba_
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE25knows_non_finalized_block0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE25knows_non_finalized_block0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEE25knows_non_finalized_block0CsibGXYHQB8Ea_25json_rpc_general_requests
340
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE25knows_non_finalized_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25knows_non_finalized_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesTNtNtNtB8_6libp2p7peer_id6PeerIdNtNtNtNtB8_7network5codec15block_announces4RoleEE25knows_non_finalized_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE25knows_non_finalized_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25knows_non_finalized_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25knows_non_finalized_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE25knows_non_finalized_blockCsibGXYHQB8Ea_25json_rpc_general_requests
341
342
    /// Returns true if [`AllForksSources::add_known_block`] or
343
    /// [`AllForksSources::add_known_block_and_set_best`] has earlier been called on this source
344
    /// with this height and hash, or if the source was originally created (using
345
    /// [`AllForksSources::add_source`]) with this height and hash.
346
    ///
347
    /// # Panic
348
    ///
349
    /// Panics if the [`SourceId`] is out of range.
350
    ///
351
    /// Panics if `height` is inferior or equal to the finalized block height. Finalized blocks
352
    /// are intentionally not tracked by this data structure, and panicking when asking for a
353
    /// potentially-finalized block prevents potentially confusing or erroneous situations.
354
    ///
355
5
    pub fn source_knows_non_finalized_block(
356
5
        &self,
357
5
        source_id: SourceId,
358
5
        height: u64,
359
5
        hash: &[u8; 32],
360
5
    ) -> bool {
361
5
        assert!(height > self.finalized_block_height);
362
5
        self.known_blocks1.contains(&(source_id, height, *hash))
363
5
    }
_RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesuE32source_knows_non_finalized_blockB8_
Line
Count
Source
355
5
    pub fn source_knows_non_finalized_block(
356
5
        &self,
357
5
        source_id: SourceId,
358
5
        height: u64,
359
5
        hash: &[u8; 32],
360
5
    ) -> bool {
361
5
        assert!(height > self.finalized_block_height);
362
5
        self.known_blocks1.contains(&(source_id, height, *hash))
363
5
    }
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE32source_knows_non_finalized_blockCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE32source_knows_non_finalized_blockB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE32source_knows_non_finalized_blockCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE32source_knows_non_finalized_blockCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE32source_knows_non_finalized_blockCsibGXYHQB8Ea_25json_rpc_general_requests
364
365
    /// Returns `true` if the [`SourceId`] is present in the collection.
366
0
    pub fn contains(&self, source_id: SourceId) -> bool {
367
0
        self.sources.contains_key(&source_id)
368
0
    }
Unexecuted instantiation: _RNvMNtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE8containsB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE8containsCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcespE8containsB8_
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE8containsCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE8containsCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvMNtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB2_15AllForksSourcesINtNtB4_14pending_blocks6SourceINtB4_6SourceNtNtB6_3all19AllForksSourceExtraEEE8containsCsibGXYHQB8Ea_25json_rpc_general_requests
369
}
370
371
impl<TSrc> ops::Index<SourceId> for AllForksSources<TSrc> {
372
    type Output = TSrc;
373
374
    #[track_caller]
375
21
    fn index(&self, id: SourceId) -> &TSrc {
376
21
        let source = self.sources.get(&id).unwrap();
377
21
        &source.user_data
378
21
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcess_0pEINtB5_15AllForksSourcespEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexBb_
Unexecuted instantiation: _RNvXs_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB4_8SourceIdE5indexCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXs_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesTNtNtNtBa_6libp2p7peer_id6PeerIdNtNtNtNtBa_7network5codec15block_announces4RoleEEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB4_8SourceIdE5indexCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcess_0pEINtB5_15AllForksSourcespEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_8SourceIdE5indexBb_
_RNvXs_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB4_8SourceIdE5indexCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
375
2
    fn index(&self, id: SourceId) -> &TSrc {
376
2
        let source = self.sources.get(&id).unwrap();
377
2
        &source.user_data
378
2
    }
Unexecuted instantiation: _RNvXs_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB4_8SourceIdE5indexCscDgN54JpMGG_6author
_RNvXs_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB4_15AllForksSourcesINtNtB6_14pending_blocks6SourceINtB6_6SourceNtNtB8_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB4_8SourceIdE5indexCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
375
19
    fn index(&self, id: SourceId) -> &TSrc {
376
19
        let source = self.sources.get(&id).unwrap();
377
19
        &source.user_data
378
19
    }
379
}
380
381
impl<TSrc> ops::IndexMut<SourceId> for AllForksSources<TSrc> {
382
    #[track_caller]
383
0
    fn index_mut(&mut self, id: SourceId) -> &mut TSrc {
384
0
        let source = self.sources.get_mut(&id).unwrap();
385
0
        &mut source.user_data
386
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcess0_0pEINtB5_15AllForksSourcespEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutBb_
Unexecuted instantiation: _RNvXs0_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB5_15AllForksSourcesINtNtB7_14pending_blocks6SourceINtB7_6SourceNtNtB9_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutCsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcess0_0pEINtB5_15AllForksSourcespEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutBb_
Unexecuted instantiation: _RNvXs0_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB5_15AllForksSourcesINtNtB7_14pending_blocks6SourceINtB7_6SourceNtNtB9_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutCsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNvXs0_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB5_15AllForksSourcesINtNtB7_14pending_blocks6SourceINtB7_6SourceNtNtB9_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutCscDgN54JpMGG_6author
Unexecuted instantiation: _RNvXs0_NtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcesINtB5_15AllForksSourcesINtNtB7_14pending_blocks6SourceINtB7_6SourceNtNtB9_3all19AllForksSourceExtraEEEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_8SourceIdE9index_mutCsibGXYHQB8Ea_25json_rpc_general_requests
387
}
388
389
impl<TSrc: fmt::Debug> fmt::Debug for AllForksSources<TSrc> {
390
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391
0
        f.debug_struct("AllForksSources")
392
0
            .field("sources", &self.sources)
393
0
            .field("finalized_block_height", &self.finalized_block_height)
394
0
            .finish()
395
0
    }
Unexecuted instantiation: _RNvXININtNtNtCsN16ciHI6Qf_7smoldot4sync9all_forks7sourcess1_0pEINtB5_15AllForksSourcespENtNtCsaYZPK01V26L_4core3fmt5Debug3fmtBb_
Unexecuted instantiation: _RNvXININtNtNtCseuYC0Zibziv_7smoldot4sync9all_forks7sourcess1_0pEINtB5_15AllForksSourcespENtNtCsaYZPK01V26L_4core3fmt5Debug3fmtBb_
396
}
397
398
#[cfg(test)]
399
mod tests {
400
    #[test]
401
1
    fn basic_works() {
402
1
        let mut sources = super::AllForksSources::new(256, 10);
403
1
        assert!(sources.is_empty());
404
1
        assert_eq!(sources.num_blocks(), 0);
405
406
1
        let source1 = sources.add_source(12, [1; 32], ());
407
1
        assert!(!sources.is_empty());
408
1
        assert_eq!(sources.len(), 1);
409
1
        assert_eq!(sources.num_blocks(), 1);
410
1
        assert!(sources.source_knows_non_finalized_block(source1, 12, &[1; 32]));
411
412
1
        sources.add_known_block_and_set_best(source1, 13, [2; 32]);
413
1
        assert_eq!(sources.num_blocks(), 2);
414
1
        assert!(sources.source_knows_non_finalized_block(source1, 12, &[1; 32]));
415
1
        assert!(sources.source_knows_non_finalized_block(source1, 13, &[2; 32]));
416
417
1
        sources.remove_known_block(13, &[2; 32]);
418
1
        assert_eq!(sources.num_blocks(), 1);
419
1
        assert!(sources.source_knows_non_finalized_block(source1, 12, &[1; 32]));
420
1
        assert!(!sources.source_knows_non_finalized_block(source1, 13, &[2; 32]));
421
422
1
        sources.set_finalized_block_height(12);
423
1
        assert_eq!(sources.num_blocks(), 0);
424
425
1
        sources.remove(source1);
426
1
        assert!(sources.is_empty());
427
1
        assert_eq!(sources.len(), 0);
428
1
    }
429
}