Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/network/service.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2023  Pierre Krieger
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
//! State machine of all networking connections.
19
//!
20
//! The [`ChainNetwork`] struct is a state machine containing multiple collections that are
21
//! controlled by the API user:
22
//!
23
//! - A list of networking connections, identified by a [`ConnectionId`]. Each connection is
24
//! either in the handshake phase, healthy, or shutting down. Each connection in the handshake
25
//! phase has an optional expected [`PeerId`] representing the identity of the node that is
26
//! expected to be reached once the handshake is finished. Each connection that is healthy or
27
//! shutting down has an (actual) [`PeerId`] associated to it.
28
//! - A list of chains, identified by a [`ChainId`].
29
//! - A set of "desired" `(ChainId, PeerId, GossipKind)` tuples representing, for each chain, the
30
//! identities of the nodes that the API user wants to establish a gossip link with.
31
//!
32
//! In addition to this, the [`ChainNetwork`] also exposes:
33
//!
34
//! - A set of `(ChainId, PeerId, GossipKind)` tuples representing the gossip links that have been
35
//! established.
36
//! - A list of outgoing requests, identified by a [`SubstreamId`], that have been sent to a peer
37
//! and that are awaiting a response.
38
//! - A list of ingoing requests, identified by a [`SubstreamId`], that have been received from a
39
//! peer and that must be answered by the API user.
40
//! - A list of outgoing gossip link connection attempts, identified by a [`SubstreamId`], that
41
//! must be answered by the peer.
42
//! - A set of `(ChainId, PeerId, GossipKind)` tuples representing the peers that would like to
43
//! establish a gossip link with the local node, and that are awaiting a response by the API user.
44
//!
45
//! # Usage
46
//!
47
//! At initialization, create a new [`ChainNetwork`] with [`ChainNetwork::new`], and add chains
48
//! using [`ChainNetwork::add_chain`].
49
//!
50
//! The [`ChainNetwork`] doesn't automatically open connections to peers. This must be done
51
//! manually using [`ChainNetwork::add_single_stream_connection`] or
52
//! [`ChainNetwork::add_multi_stream_connection`]. Choosing which peer to connect to and through
53
//! which address is outside of the scope of this module.
54
//!
55
//! Adding a connection using [`ChainNetwork::add_single_stream_connection`] or
56
//! [`ChainNetwork::add_multi_stream_connection`] returns a "connection task". This connection task
57
//! must be processed. TODO: expand explanation here
58
//!
59
//! After a message has been injected using [`ChainNetwork::inject_connection_message`], repeatedly
60
//! [`ChainNetwork::next_event`] until it returns `None` in order to determine what has happened.
61
//!
62
//! Once a connection has been established (which is indicated by a [`Event::HandshakeFinished`]
63
//! event), one can open a gossip link to this peer using [`ChainNetwork::gossip_open`].
64
//!
65
//! In order to faciliate this process, the [`ChainNetwork`] provides a "desired gossip links"
66
//! system. Use [`ChainNetwork::gossip_insert_desired`] and [`ChainNetwork::gossip_remove_desired`]
67
//! to insert or remove `(ChainId, PeerId, GossipKind)` tuples into the state machine. You can
68
//! then use [`ChainNetwork::unconnected_desired`] to obtain a list of [`PeerId`]s that are marked
69
//! as desired and for which a connection should be opened, and
70
//! [`ChainNetwork::connected_unopened_gossip_desired`] to obtain a list of [`PeerId`]s that are
71
//! marked as desired and that have a healthy connection and for which a gossip link should be
72
//! opened. Marking peers as desired only influences the return values of
73
//! [`ChainNetwork::unconnected_desired`] and [`ChainNetwork::connected_unopened_gossip_desired`]
74
//! and has no other effect.
75
//!
76
77
// TODO: expand explanations once the API is finalized
78
79
use crate::libp2p::collection;
80
use crate::network::codec;
81
use crate::util::{self, SipHasherBuild};
82
83
use alloc::{borrow::ToOwned as _, collections::BTreeSet, string::String, vec::Vec};
84
use core::{
85
    fmt,
86
    hash::Hash,
87
    iter,
88
    ops::{self, Add, Sub},
89
    time::Duration,
90
};
91
use rand_chacha::rand_core::{RngCore as _, SeedableRng as _};
92
93
pub use crate::libp2p::{
94
    collection::{
95
        ConnectionId, ConnectionToCoordinator, CoordinatorToConnection, InboundError,
96
        MultiStreamConnectionTask, MultiStreamHandshakeKind, NotificationsOutErr, ReadWrite,
97
        RequestError, SingleStreamConnectionTask, SingleStreamHandshakeKind, SubstreamId,
98
    },
99
    connection::noise::{self, NoiseKey},
100
    multiaddr::{self, Multiaddr},
101
    peer_id::{self, PeerId},
102
};
103
104
pub use crate::network::codec::{BlockAnnouncesHandshakeDecodeError, Role};
105
106
/// Configuration for a [`ChainNetwork`].
107
pub struct Config {
108
    /// Capacity to initially reserve to the list of connections.
109
    pub connections_capacity: usize,
110
111
    /// Capacity to reserve for the list of chains.
112
    pub chains_capacity: usize,
113
114
    /// Seed for the randomness within the networking state machine.
115
    ///
116
    /// While this seed influences the general behavior of the networking state machine, it
117
    /// notably isn't used when generating the ephemeral key used for the Diffie-Hellman
118
    /// handshake.
119
    /// This is a defensive measure against users passing a dummy seed instead of actual entropy.
120
    pub randomness_seed: [u8; 32],
121
122
    /// Amount of time after which a connection hathat ndshake is considered to have taken too long
123
    /// and must be aborted.
124
    pub handshake_timeout: Duration,
125
}
126
127
/// Configuration for a specific overlay network.
128
///
129
/// See [`ChainNetwork::add_chain`].
130
pub struct ChainConfig<TChain> {
131
    /// Opaque data chosen by the API user. Can later be accessed using the `Index`/`IndexMut`
132
    /// trait implementation of the [`ChainNetwork`].
133
    pub user_data: TChain,
134
135
    /// Hash of the genesis block (i.e. block number 0) according to the local node.
136
    pub genesis_hash: [u8; 32],
137
138
    /// Optional identifier to insert into the networking protocol names. Used to differentiate
139
    /// between chains with the same genesis hash.
140
    ///
141
    /// > **Note**: This value is typically found in the specification of the chain (the
142
    /// >           "chain spec").
143
    pub fork_id: Option<String>,
144
145
    /// Number of bytes of the block number in the networking protocol.
146
    pub block_number_bytes: usize,
147
148
    /// If `Some`, the chain uses the GrandPa networking protocol.
149
    pub grandpa_protocol_config: Option<GrandpaState>,
150
151
    /// `true` if incoming block requests are allowed.
152
    pub allow_inbound_block_requests: bool,
153
154
    /// Hash of the best block according to the local node.
155
    pub best_hash: [u8; 32],
156
    /// Height of the best block according to the local node.
157
    pub best_number: u64,
158
159
    /// Role of the local node. Sent to the remote nodes and used as a hint. Has no incidence
160
    /// on the behavior of any function.
161
    pub role: Role,
162
}
163
164
/// Identifier of a chain added through [`ChainNetwork::add_chain`].
165
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
166
pub struct ChainId(usize);
167
168
/// Data structure containing the list of all connections and their latest known state. See also
169
/// [the module-level documentation](..).
170
pub struct ChainNetwork<TChain, TConn, TNow> {
171
    /// Underlying data structure.
172
    inner: collection::Network<ConnectionInfo<TConn>, TNow>,
173
174
    /// List of all chains that have been added.
175
    // TODO: shrink to fit from time to time
176
    chains: slab::Slab<Chain<TChain>>,
177
178
    /// Chains indexed by genesis hash and fork ID.
179
    ///
180
    /// Contains the same number of entries as [`ChainNetwork::chains`]. The values are `usize`s
181
    /// that are indices into [`ChainNetwork::chains`].
182
    // TODO: shrink to fit from time to time
183
    chains_by_protocol_info:
184
        hashbrown::HashMap<([u8; 32], Option<String>), usize, fnv::FnvBuildHasher>,
185
186
    /// List of all known network identities. The `usize` in [`PeerIndex`] refers to an index
187
    /// within this list.
188
    // TODO: shrink to fit from time to time
189
    peers: slab::Slab<PeerId>,
190
191
    /// Same entries as [`ChainNetwork::peers`], by indexed differently.
192
    // TODO: shrink to fit from time to time
193
    peers_by_peer_id: hashbrown::HashMap<PeerId, PeerIndex, SipHasherBuild>,
194
195
    /// Connections indexed by the value in [`ConnectionInfo::peer_index`].
196
    connections_by_peer_id: BTreeSet<(PeerIndex, collection::ConnectionId)>,
197
198
    /// List of peers that have been marked as desired. Can include peers not connected to the
199
    /// local node yet.
200
    gossip_desired_peers_by_chain: BTreeSet<(usize, GossipKind, PeerIndex)>,
201
202
    /// Same entries as [`ChainNetwork::gossip_desired_peers_by_chain`] but indexed differently.
203
    gossip_desired_peers: BTreeSet<(PeerIndex, GossipKind, usize)>,
204
205
    /// Subset of peers in [`ChainNetwork::gossip_desired_peers`] for which no healthy
206
    /// connection exists.
207
    // TODO: shrink to fit from time to time
208
    unconnected_desired: hashbrown::HashSet<PeerIndex, fnv::FnvBuildHasher>,
209
210
    /// List of [`PeerId`]s that are marked as desired, and for which a healthy connection exists,
211
    /// but for which no substream connection (attempt or established) exists.
212
    // TODO: shrink to fit from time to time
213
    connected_unopened_gossip_desired:
214
        hashbrown::HashSet<(PeerIndex, ChainId, GossipKind), fnv::FnvBuildHasher>,
215
216
    /// List of [`PeerId`]s for which a substream connection (attempt or established) exists, but
217
    /// that are not marked as desired.
218
    // TODO: shrink to fit from time to time
219
    opened_gossip_undesired:
220
        hashbrown::HashSet<(ChainId, PeerIndex, GossipKind), fnv::FnvBuildHasher>,
221
222
    /// All the substreams of [`ChainNetwork::inner`], with info attached to them.
223
    // TODO: add a substream user data to `collection::Network` instead
224
    // TODO: shrink to fit from time to time
225
    substreams: hashbrown::HashMap<SubstreamId, SubstreamInfo, fnv::FnvBuildHasher>,
226
227
    /// All the outbound notification substreams, indexed by protocol, `PeerId`, and state.
228
    // TODO: unclear whether PeerId should come before or after the state, same for direction/state
229
    notification_substreams_by_peer_id: BTreeSet<(
230
        NotificationsProtocol,
231
        PeerIndex,
232
        SubstreamDirection,
233
        NotificationsSubstreamState,
234
        collection::SubstreamId,
235
    )>,
236
}
237
238
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
239
struct PeerIndex(usize);
240
241
struct Chain<TChain> {
242
    /// See [`ChainConfig::block_number_bytes`].
243
    block_number_bytes: usize,
244
245
    /// See [`ChainConfig::genesis_hash`].
246
    genesis_hash: [u8; 32],
247
    /// See [`ChainConfig::fork_id`].
248
    fork_id: Option<String>,
249
250
    /// See [`ChainConfig::role`].
251
    role: Role,
252
253
    /// See [`ChainConfig::best_hash`].
254
    best_hash: [u8; 32],
255
    /// See [`ChainConfig::best_number`].
256
    best_number: u64,
257
258
    /// See [`ChainConfig::grandpa_protocol_config`].
259
    grandpa_protocol_config: Option<GrandpaState>,
260
261
    /// See [`ChainConfig::allow_inbound_block_requests`].
262
    allow_inbound_block_requests: bool,
263
264
    /// See [`ChainConfig::user_data`].
265
    user_data: TChain,
266
}
267
268
/// See [`ChainNetwork::inner`].
269
struct ConnectionInfo<TConn> {
270
    address: Vec<u8>,
271
272
    /// Public key of the local node used for this connection.
273
    /// This information can be requested by the remote.
274
    ed25519_public_key: [u8; 32],
275
276
    /// Identity of the remote. Can be either the expected or the actual identity.
277
    ///
278
    /// `None` if unknown, which can only be the case if the connection is still in its handshake
279
    /// phase.
280
    peer_index: Option<PeerIndex>,
281
282
    /// User data decided by the API user.
283
    user_data: TConn,
284
}
285
286
/// See [`ChainNetwork::substreams`].
287
#[derive(Debug, Clone)]
288
struct SubstreamInfo {
289
    // TODO: substream <-> connection mapping should be provided by collection.rs instead
290
    connection_id: collection::ConnectionId,
291
    /// `None` if the substream concerns a chain that has been removed.
292
    protocol: Option<Protocol>,
293
}
294
295
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
296
enum Protocol {
297
    Identify,
298
    Ping,
299
    Notifications(NotificationsProtocol),
300
    Sync { chain_index: usize },
301
    LightUnknown { chain_index: usize },
302
    LightStorage { chain_index: usize },
303
    LightCall { chain_index: usize },
304
    Kad { chain_index: usize },
305
    SyncWarp { chain_index: usize },
306
    State { chain_index: usize },
307
}
308
309
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
310
enum NotificationsProtocol {
311
    BlockAnnounces { chain_index: usize },
312
    Transactions { chain_index: usize },
313
    Grandpa { chain_index: usize },
314
}
315
316
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
317
enum SubstreamDirection {
318
    In,
319
    Out,
320
}
321
322
impl SubstreamDirection {
323
    const MIN: Self = SubstreamDirection::In;
324
    const MAX: Self = SubstreamDirection::Out;
325
}
326
327
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
328
enum NotificationsSubstreamState {
329
    Pending,
330
    Open { asked_to_leave: bool },
331
}
332
333
impl NotificationsSubstreamState {
334
    const MIN: Self = NotificationsSubstreamState::Pending;
335
    const MAX: Self = NotificationsSubstreamState::Open {
336
        asked_to_leave: true,
337
    };
338
    const OPEN_MIN_VALUE: Self = NotificationsSubstreamState::Open {
339
        asked_to_leave: false,
340
    };
341
    const OPEN_MAX_VALUE: Self = NotificationsSubstreamState::Open {
342
        asked_to_leave: true,
343
    };
344
}
345
346
impl<TChain, TConn, TNow> ChainNetwork<TChain, TConn, TNow>
347
where
348
    TNow: Clone + Add<Duration, Output = TNow> + Sub<TNow, Output = Duration> + Ord,
349
{
350
    /// Initializes a new [`ChainNetwork`].
351
21
    pub fn new(config: Config) -> Self {
352
21
        let mut randomness = rand_chacha::ChaCha20Rng::from_seed(config.randomness_seed);
353
21
354
21
        ChainNetwork {
355
21
            inner: collection::Network::new(collection::Config {
356
21
                capacity: config.connections_capacity,
357
21
                max_inbound_substreams: 128, // TODO: arbitrary value ; this value should be dynamically adjusted based on the number of chains that have been added
358
21
                max_protocol_name_len: 64,
359
21
                randomness_seed: {
360
21
                    let mut seed = [0; 32];
361
21
                    randomness.fill_bytes(&mut seed);
362
21
                    seed
363
21
                },
364
21
                ping_protocol: "/ipfs/ping/1.0.0".into(),
365
21
                handshake_timeout: config.handshake_timeout,
366
21
            }),
367
21
            peers: slab::Slab::with_capacity(config.connections_capacity),
368
21
            peers_by_peer_id: hashbrown::HashMap::with_capacity_and_hasher(
369
21
                config.connections_capacity,
370
21
                SipHasherBuild::new({
371
21
                    let mut seed = [0; 16];
372
21
                    randomness.fill_bytes(&mut seed);
373
21
                    seed
374
21
                }),
375
21
            ),
376
21
            substreams: hashbrown::HashMap::with_capacity_and_hasher(
377
21
                config.connections_capacity * 20, // TODO: capacity?
378
21
                fnv::FnvBuildHasher::default(),
379
21
            ),
380
21
            connections_by_peer_id: BTreeSet::new(),
381
21
            notification_substreams_by_peer_id: BTreeSet::new(),
382
21
            gossip_desired_peers_by_chain: BTreeSet::new(),
383
21
            gossip_desired_peers: BTreeSet::new(),
384
21
            unconnected_desired: hashbrown::HashSet::with_capacity_and_hasher(
385
21
                config.connections_capacity,
386
21
                Default::default(),
387
21
            ),
388
21
            connected_unopened_gossip_desired: hashbrown::HashSet::with_capacity_and_hasher(
389
21
                config.connections_capacity,
390
21
                Default::default(),
391
21
            ),
392
21
            opened_gossip_undesired: hashbrown::HashSet::with_capacity_and_hasher(
393
21
                config.connections_capacity,
394
21
                Default::default(),
395
21
            ),
396
21
            chains: slab::Slab::with_capacity(config.chains_capacity),
397
21
            chains_by_protocol_info: hashbrown::HashMap::with_capacity_and_hasher(
398
21
                config.chains_capacity,
399
21
                Default::default(),
400
21
            ),
401
21
        }
402
21
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE3newB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE3newB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE3newB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE3newCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
351
2
    pub fn new(config: Config) -> Self {
352
2
        let mut randomness = rand_chacha::ChaCha20Rng::from_seed(config.randomness_seed);
353
2
354
2
        ChainNetwork {
355
2
            inner: collection::Network::new(collection::Config {
356
2
                capacity: config.connections_capacity,
357
2
                max_inbound_substreams: 128, // TODO: arbitrary value ; this value should be dynamically adjusted based on the number of chains that have been added
358
2
                max_protocol_name_len: 64,
359
2
                randomness_seed: {
360
2
                    let mut seed = [0; 32];
361
2
                    randomness.fill_bytes(&mut seed);
362
2
                    seed
363
2
                },
364
2
                ping_protocol: "/ipfs/ping/1.0.0".into(),
365
2
                handshake_timeout: config.handshake_timeout,
366
2
            }),
367
2
            peers: slab::Slab::with_capacity(config.connections_capacity),
368
2
            peers_by_peer_id: hashbrown::HashMap::with_capacity_and_hasher(
369
2
                config.connections_capacity,
370
2
                SipHasherBuild::new({
371
2
                    let mut seed = [0; 16];
372
2
                    randomness.fill_bytes(&mut seed);
373
2
                    seed
374
2
                }),
375
2
            ),
376
2
            substreams: hashbrown::HashMap::with_capacity_and_hasher(
377
2
                config.connections_capacity * 20, // TODO: capacity?
378
2
                fnv::FnvBuildHasher::default(),
379
2
            ),
380
2
            connections_by_peer_id: BTreeSet::new(),
381
2
            notification_substreams_by_peer_id: BTreeSet::new(),
382
2
            gossip_desired_peers_by_chain: BTreeSet::new(),
383
2
            gossip_desired_peers: BTreeSet::new(),
384
2
            unconnected_desired: hashbrown::HashSet::with_capacity_and_hasher(
385
2
                config.connections_capacity,
386
2
                Default::default(),
387
2
            ),
388
2
            connected_unopened_gossip_desired: hashbrown::HashSet::with_capacity_and_hasher(
389
2
                config.connections_capacity,
390
2
                Default::default(),
391
2
            ),
392
2
            opened_gossip_undesired: hashbrown::HashSet::with_capacity_and_hasher(
393
2
                config.connections_capacity,
394
2
                Default::default(),
395
2
            ),
396
2
            chains: slab::Slab::with_capacity(config.chains_capacity),
397
2
            chains_by_protocol_info: hashbrown::HashMap::with_capacity_and_hasher(
398
2
                config.chains_capacity,
399
2
                Default::default(),
400
2
            ),
401
2
        }
402
2
    }
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE3newCscDgN54JpMGG_6author
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE3newCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
351
19
    pub fn new(config: Config) -> Self {
352
19
        let mut randomness = rand_chacha::ChaCha20Rng::from_seed(config.randomness_seed);
353
19
354
19
        ChainNetwork {
355
19
            inner: collection::Network::new(collection::Config {
356
19
                capacity: config.connections_capacity,
357
19
                max_inbound_substreams: 128, // TODO: arbitrary value ; this value should be dynamically adjusted based on the number of chains that have been added
358
19
                max_protocol_name_len: 64,
359
19
                randomness_seed: {
360
19
                    let mut seed = [0; 32];
361
19
                    randomness.fill_bytes(&mut seed);
362
19
                    seed
363
19
                },
364
19
                ping_protocol: "/ipfs/ping/1.0.0".into(),
365
19
                handshake_timeout: config.handshake_timeout,
366
19
            }),
367
19
            peers: slab::Slab::with_capacity(config.connections_capacity),
368
19
            peers_by_peer_id: hashbrown::HashMap::with_capacity_and_hasher(
369
19
                config.connections_capacity,
370
19
                SipHasherBuild::new({
371
19
                    let mut seed = [0; 16];
372
19
                    randomness.fill_bytes(&mut seed);
373
19
                    seed
374
19
                }),
375
19
            ),
376
19
            substreams: hashbrown::HashMap::with_capacity_and_hasher(
377
19
                config.connections_capacity * 20, // TODO: capacity?
378
19
                fnv::FnvBuildHasher::default(),
379
19
            ),
380
19
            connections_by_peer_id: BTreeSet::new(),
381
19
            notification_substreams_by_peer_id: BTreeSet::new(),
382
19
            gossip_desired_peers_by_chain: BTreeSet::new(),
383
19
            gossip_desired_peers: BTreeSet::new(),
384
19
            unconnected_desired: hashbrown::HashSet::with_capacity_and_hasher(
385
19
                config.connections_capacity,
386
19
                Default::default(),
387
19
            ),
388
19
            connected_unopened_gossip_desired: hashbrown::HashSet::with_capacity_and_hasher(
389
19
                config.connections_capacity,
390
19
                Default::default(),
391
19
            ),
392
19
            opened_gossip_undesired: hashbrown::HashSet::with_capacity_and_hasher(
393
19
                config.connections_capacity,
394
19
                Default::default(),
395
19
            ),
396
19
            chains: slab::Slab::with_capacity(config.chains_capacity),
397
19
            chains_by_protocol_info: hashbrown::HashMap::with_capacity_and_hasher(
398
19
                config.chains_capacity,
399
19
                Default::default(),
400
19
            ),
401
19
        }
402
19
    }
403
404
    /// Adds a chain to the list of chains that is handled by the [`ChainNetwork`].
405
    ///
406
    /// It is not possible to add a chain if its protocol names would conflict with an existing
407
    /// chain.
408
21
    pub fn add_chain(&mut self, config: ChainConfig<TChain>) -> Result<ChainId, AddChainError> {
409
21
        let chain_entry = self.chains.vacant_entry();
410
21
        let chain_id = chain_entry.key();
411
21
412
21
        match self
413
21
            .chains_by_protocol_info
414
21
            .entry((config.genesis_hash, config.fork_id.clone()))
415
        {
416
21
            hashbrown::hash_map::Entry::Vacant(entry) => {
417
21
                entry.insert(chain_id);
418
21
            }
419
0
            hashbrown::hash_map::Entry::Occupied(entry) => {
420
0
                return Err(AddChainError::Duplicate {
421
0
                    existing_identical: ChainId(*entry.get()),
422
0
                })
423
            }
424
        }
425
426
21
        chain_entry.insert(Chain {
427
21
            block_number_bytes: config.block_number_bytes,
428
21
            genesis_hash: config.genesis_hash,
429
21
            fork_id: config.fork_id,
430
21
            role: config.role,
431
21
            best_hash: config.best_hash,
432
21
            best_number: config.best_number,
433
21
            allow_inbound_block_requests: config.allow_inbound_block_requests,
434
21
            grandpa_protocol_config: config.grandpa_protocol_config,
435
21
            user_data: config.user_data,
436
21
        });
437
21
438
21
        // TODO: consider optimizing this, as it's O(n) over the number of chains currently
439
21
        self.inner.set_max_protocol_name_len(
440
21
            self.chains
441
21
                .iter()
442
21
                .map(|chain| chain.1.fork_id.as_ref().map_or(0, |s| 
s.len() + 10
))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE9add_chain0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE9add_chain0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE9add_chain0Bb_
_RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
442
2
                .map(|chain| chain.1.fork_id.as_ref().map_or(0, |s| s.len() + 1))
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain0CscDgN54JpMGG_6author
_RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
442
19
                .map(|chain| chain.1.fork_id.as_ref().map_or(0, |s| s.len() + 1))
Unexecuted instantiation: _RNCNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB9_12ChainNetworkpppE9add_chain00Bd_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE9add_chain00B28_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkpppE9add_chain00Bd_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain00CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain00CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chain00CsibGXYHQB8Ea_25json_rpc_general_requests
443
21
                .max()
444
21
                .unwrap_or(0)
445
21
                + 64,
446
21
        );
447
21
448
21
        Ok(ChainId(chain_id))
449
21
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE9add_chainB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE9add_chainB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE9add_chainB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chainCsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
408
2
    pub fn add_chain(&mut self, config: ChainConfig<TChain>) -> Result<ChainId, AddChainError> {
409
2
        let chain_entry = self.chains.vacant_entry();
410
2
        let chain_id = chain_entry.key();
411
2
412
2
        match self
413
2
            .chains_by_protocol_info
414
2
            .entry((config.genesis_hash, config.fork_id.clone()))
415
        {
416
2
            hashbrown::hash_map::Entry::Vacant(entry) => {
417
2
                entry.insert(chain_id);
418
2
            }
419
0
            hashbrown::hash_map::Entry::Occupied(entry) => {
420
0
                return Err(AddChainError::Duplicate {
421
0
                    existing_identical: ChainId(*entry.get()),
422
0
                })
423
            }
424
        }
425
426
2
        chain_entry.insert(Chain {
427
2
            block_number_bytes: config.block_number_bytes,
428
2
            genesis_hash: config.genesis_hash,
429
2
            fork_id: config.fork_id,
430
2
            role: config.role,
431
2
            best_hash: config.best_hash,
432
2
            best_number: config.best_number,
433
2
            allow_inbound_block_requests: config.allow_inbound_block_requests,
434
2
            grandpa_protocol_config: config.grandpa_protocol_config,
435
2
            user_data: config.user_data,
436
2
        });
437
2
438
2
        // TODO: consider optimizing this, as it's O(n) over the number of chains currently
439
2
        self.inner.set_max_protocol_name_len(
440
2
            self.chains
441
2
                .iter()
442
2
                .map(|chain| chain.1.fork_id.as_ref().map_or(0, |s| s.len() + 1))
443
2
                .max()
444
2
                .unwrap_or(0)
445
2
                + 64,
446
2
        );
447
2
448
2
        Ok(ChainId(chain_id))
449
2
    }
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chainCscDgN54JpMGG_6author
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE9add_chainCsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
408
19
    pub fn add_chain(&mut self, config: ChainConfig<TChain>) -> Result<ChainId, AddChainError> {
409
19
        let chain_entry = self.chains.vacant_entry();
410
19
        let chain_id = chain_entry.key();
411
19
412
19
        match self
413
19
            .chains_by_protocol_info
414
19
            .entry((config.genesis_hash, config.fork_id.clone()))
415
        {
416
19
            hashbrown::hash_map::Entry::Vacant(entry) => {
417
19
                entry.insert(chain_id);
418
19
            }
419
0
            hashbrown::hash_map::Entry::Occupied(entry) => {
420
0
                return Err(AddChainError::Duplicate {
421
0
                    existing_identical: ChainId(*entry.get()),
422
0
                })
423
            }
424
        }
425
426
19
        chain_entry.insert(Chain {
427
19
            block_number_bytes: config.block_number_bytes,
428
19
            genesis_hash: config.genesis_hash,
429
19
            fork_id: config.fork_id,
430
19
            role: config.role,
431
19
            best_hash: config.best_hash,
432
19
            best_number: config.best_number,
433
19
            allow_inbound_block_requests: config.allow_inbound_block_requests,
434
19
            grandpa_protocol_config: config.grandpa_protocol_config,
435
19
            user_data: config.user_data,
436
19
        });
437
19
438
19
        // TODO: consider optimizing this, as it's O(n) over the number of chains currently
439
19
        self.inner.set_max_protocol_name_len(
440
19
            self.chains
441
19
                .iter()
442
19
                .map(|chain| chain.1.fork_id.as_ref().map_or(0, |s| s.len() + 1))
443
19
                .max()
444
19
                .unwrap_or(0)
445
19
                + 64,
446
19
        );
447
19
448
19
        Ok(ChainId(chain_id))
449
19
    }
450
451
    /// Removes a chain previously added with [`ChainNetwork::add_chain`].
452
    ///
453
    /// This function will return an error if any gossip link is currently open through the
454
    /// given chain. Gossip links should be closed prior to calling this function.
455
    ///
456
    /// Any request using the given chain will continue as normal.
457
    ///
458
    /// # Panic
459
    ///
460
    /// Panics if the [`ChainId`] is out of range.
461
    ///
462
0
    pub fn remove_chain(&mut self, chain_id: ChainId) -> Result<TChain, RemoveChainError> {
463
        // Check whether the chain is still in use.
464
0
        for protocol in [NotificationsProtocol::BlockAnnounces {
465
0
            chain_index: chain_id.0,
466
0
        }] {
467
0
            if self
468
0
                .notification_substreams_by_peer_id
469
0
                .range(
470
0
                    (
471
0
                        protocol,
472
0
                        PeerIndex(usize::MIN),
473
0
                        SubstreamDirection::Out,
474
0
                        NotificationsSubstreamState::OPEN_MIN_VALUE,
475
0
                        SubstreamId::MIN,
476
0
                    )
477
0
                        ..=(
478
0
                            protocol,
479
0
                            PeerIndex(usize::MAX),
480
0
                            SubstreamDirection::Out,
481
0
                            NotificationsSubstreamState::OPEN_MAX_VALUE,
482
0
                            SubstreamId::MAX,
483
0
                        ),
484
0
                )
485
0
                .find(|(_, _, direction, state, _)| {
486
0
                    matches!(*direction, SubstreamDirection::Out)
487
0
                        && matches!(*state, NotificationsSubstreamState::Open { .. })
488
0
                })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE12remove_chain0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE12remove_chain0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE12remove_chain0Bb_
489
0
                .is_some()
490
            {
491
0
                return Err(RemoveChainError::InUse);
492
0
            }
493
        }
494
495
        // Clean up desired peers.
496
0
        let desired = self
497
0
            .gossip_desired_peers_by_chain
498
0
            .range(
499
0
                (
500
0
                    chain_id.0,
501
0
                    GossipKind::ConsensusTransactions,
502
0
                    PeerIndex(usize::MIN),
503
0
                )
504
0
                    ..=(
505
0
                        chain_id.0,
506
0
                        GossipKind::ConsensusTransactions,
507
0
                        PeerIndex(usize::MAX),
508
0
                    ),
509
0
            )
510
0
            .map(|(_, _, peer_index)| *peer_index)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE12remove_chains_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE12remove_chains_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE12remove_chains_0Bb_
511
0
            .collect::<Vec<_>>();
512
0
        for desired in desired {
513
0
            self.gossip_remove_desired_inner(chain_id, desired, GossipKind::ConsensusTransactions);
514
0
        }
515
516
        // Close any notifications substream of the chain.
517
0
        for protocol in [
518
0
            NotificationsProtocol::BlockAnnounces {
519
0
                chain_index: chain_id.0,
520
0
            },
521
0
            NotificationsProtocol::Transactions {
522
0
                chain_index: chain_id.0,
523
0
            },
524
0
            NotificationsProtocol::Grandpa {
525
0
                chain_index: chain_id.0,
526
0
            },
527
        ] {
528
0
            for (protocol, peer_index, direction, state, substream_id) in self
529
0
                .notification_substreams_by_peer_id
530
0
                .range(
531
0
                    (
532
0
                        protocol,
533
0
                        PeerIndex(usize::MIN),
534
0
                        SubstreamDirection::MIN,
535
0
                        NotificationsSubstreamState::MIN,
536
0
                        SubstreamId::MIN,
537
0
                    )
538
0
                        ..=(
539
0
                            protocol,
540
0
                            PeerIndex(usize::MAX),
541
0
                            SubstreamDirection::MAX,
542
0
                            NotificationsSubstreamState::MAX,
543
0
                            SubstreamId::MAX,
544
0
                        ),
545
0
                )
546
0
                .cloned()
547
0
                .collect::<Vec<_>>()
548
            {
549
0
                self.notification_substreams_by_peer_id.remove(&(
550
0
                    protocol,
551
0
                    peer_index,
552
0
                    direction,
553
0
                    state,
554
0
                    substream_id,
555
0
                ));
556
0
557
0
                match (direction, state) {
558
                    (SubstreamDirection::In, NotificationsSubstreamState::Pending) => {
559
0
                        self.inner.reject_in_notifications(substream_id);
560
0
                        let _was_in = self.substreams.remove(&substream_id);
561
0
                        debug_assert!(_was_in.is_some());
562
                    }
563
                    (
564
                        SubstreamDirection::In,
565
                        NotificationsSubstreamState::Open {
566
                            asked_to_leave: true,
567
                        },
568
0
                    ) => {
569
0
                        self.substreams.get_mut(&substream_id).unwrap().protocol = None;
570
0
                    }
571
                    (
572
                        SubstreamDirection::In,
573
                        NotificationsSubstreamState::Open {
574
                            asked_to_leave: false,
575
                        },
576
0
                    ) => {
577
0
                        self.inner
578
0
                            .start_close_in_notifications(substream_id, Duration::from_secs(5));
579
0
                        // TODO: arbitrary timeout ^
580
0
                        self.substreams.get_mut(&substream_id).unwrap().protocol = None;
581
0
                    }
582
                    (SubstreamDirection::Out, _) => {
583
0
                        self.inner.close_out_notifications(substream_id);
584
0
                        let _was_in = self.substreams.remove(&substream_id);
585
0
                        debug_assert!(_was_in.is_some());
586
                    }
587
                }
588
            }
589
        }
590
591
        // Process request-response protocols.
592
        // TODO: how to do request-responses in non-O(n) time?
593
0
        for (_, substream) in &mut self.substreams {
594
0
            match substream.protocol {
595
                Some(Protocol::Notifications(NotificationsProtocol::BlockAnnounces {
596
0
                    chain_index,
597
                }))
598
                | Some(Protocol::Notifications(NotificationsProtocol::Transactions {
599
0
                    chain_index,
600
                }))
601
0
                | Some(Protocol::Notifications(NotificationsProtocol::Grandpa { chain_index }))
602
0
                | Some(Protocol::Sync { chain_index })
603
0
                | Some(Protocol::LightUnknown { chain_index })
604
0
                | Some(Protocol::LightStorage { chain_index })
605
0
                | Some(Protocol::LightCall { chain_index })
606
0
                | Some(Protocol::Kad { chain_index })
607
0
                | Some(Protocol::SyncWarp { chain_index })
608
0
                | Some(Protocol::State { chain_index }) => {
609
0
                    if chain_index != chain_id.0 {
610
0
                        continue;
611
0
                    }
612
                }
613
0
                Some(Protocol::Identify) | Some(Protocol::Ping) | None => continue,
614
            }
615
616
0
            substream.protocol = None;
617
618
            // TODO: cancel outgoing requests instead of just ignoring their response
619
            // TODO: must send back an error to the ingoing requests; this is not a huge deal because requests will time out on the remote's side, but it's very stupid nonetheless
620
        }
621
622
        // Actually remove the chain. This will panic if the `ChainId` is invalid.
623
0
        let chain = self.chains.remove(chain_id.0);
624
0
        let _was_in = self
625
0
            .chains_by_protocol_info
626
0
            .remove(&(chain.genesis_hash, chain.fork_id));
627
0
        debug_assert_eq!(_was_in, Some(chain_id.0));
628
629
0
        Ok(chain.user_data)
630
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE12remove_chainB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE12remove_chainB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE12remove_chainB9_
631
632
    /// Modifies the best block of the local node for the given chain. See
633
    /// [`ChainConfig::best_hash`] and [`ChainConfig::best_number`].
634
    ///
635
    /// This information is sent to remotes whenever a block announces substream is opened.
636
    ///
637
    /// # Panic
638
    ///
639
    /// Panics if the [`ChainId`] is out of range.
640
    ///
641
21
    pub fn set_chain_local_best_block(
642
21
        &mut self,
643
21
        chain_id: ChainId,
644
21
        best_hash: [u8; 32],
645
21
        best_number: u64,
646
21
    ) {
647
21
        let chain = &mut self.chains[chain_id.0];
648
21
        chain.best_hash = best_hash;
649
21
        chain.best_number = best_number;
650
21
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE26set_chain_local_best_blockB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE26set_chain_local_best_blockB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE26set_chain_local_best_blockB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE26set_chain_local_best_blockB19_
Line
Count
Source
641
21
    pub fn set_chain_local_best_block(
642
21
        &mut self,
643
21
        chain_id: ChainId,
644
21
        best_hash: [u8; 32],
645
21
        best_number: u64,
646
21
    ) {
647
21
        let chain = &mut self.chains[chain_id.0];
648
21
        chain.best_hash = best_hash;
649
21
        chain.best_number = best_number;
650
21
    }
651
652
    /// Returns the list of all the chains that have been added.
653
251
    pub fn chains(&'_ self) -> impl ExactSizeIterator<Item = ChainId> + '_ {
654
251
        self.chains.iter().map(|(idx, _)| ChainId(idx))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE6chains0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE6chains0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE6chains0Bb_
_RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE6chains0B1b_
Line
Count
Source
654
251
        self.chains.iter().map(|(idx, _)| ChainId(idx))
655
251
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE6chainsB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE6chainsB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE6chainsB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE6chainsB19_
Line
Count
Source
653
251
    pub fn chains(&'_ self) -> impl ExactSizeIterator<Item = ChainId> + '_ {
654
251
        self.chains.iter().map(|(idx, _)| ChainId(idx))
655
251
    }
656
657
    /// Returns the value passed as [`ChainConfig::block_number_bytes`] for the given chain.
658
    ///
659
    /// # Panic
660
    ///
661
    /// Panics if the given [`ChainId`] is invalid.
662
    ///
663
0
    pub fn block_number_bytes(&self, chain_id: ChainId) -> usize {
664
0
        self.chains[chain_id.0].block_number_bytes
665
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE18block_number_bytesB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE18block_number_bytesB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18block_number_bytesB19_
666
667
    /// Marks the given chain-peer combination as "desired".
668
    ///
669
    /// Has no effect if it was already marked as desired.
670
    ///
671
    /// Returns `true` if the peer has been marked as desired, and `false` if it was already
672
    /// marked as desired.
673
    ///
674
    /// # Panic
675
    ///
676
    /// Panics if the given [`ChainId`] is invalid.
677
    ///
678
0
    pub fn gossip_insert_desired(
679
0
        &mut self,
680
0
        chain_id: ChainId,
681
0
        peer_id: PeerId,
682
0
        kind: GossipKind,
683
0
    ) -> bool {
684
0
        assert!(self.chains.contains(chain_id.0));
685
686
0
        let peer_index = self.peer_index_or_insert(peer_id);
687
0
688
0
        if !self
689
0
            .gossip_desired_peers_by_chain
690
0
            .insert((chain_id.0, kind, peer_index))
691
        {
692
            // Return if already marked as desired, as there's nothing more to update.
693
            // Note that this doesn't cover the possibility where the peer was desired with
694
            // another chain.
695
0
            return false;
696
0
        }
697
0
698
0
        let _was_inserted = self
699
0
            .gossip_desired_peers
700
0
            .insert((peer_index, kind, chain_id.0));
701
0
        debug_assert!(_was_inserted);
702
703
0
        self.opened_gossip_undesired
704
0
            .remove(&(chain_id, peer_index, kind));
705
0
706
0
        //  Add either to `unconnected_desired` or to `connected_unopened_gossip_desired`,
707
0
        // depending on the situation.
708
0
        if self
709
0
            .connections_by_peer_id
710
0
            .range((peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX))
711
0
            .any(|(_, connection_id)| {
712
0
                let state = self.inner.connection_state(*connection_id);
713
0
                state.established && !state.shutting_down
714
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE21gossip_insert_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE21gossip_insert_desired0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE21gossip_insert_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE21gossip_insert_desired0B1b_
715
        {
716
0
            if self
717
0
                .notification_substreams_by_peer_id
718
0
                .range(
719
0
                    (
720
0
                        NotificationsProtocol::BlockAnnounces {
721
0
                            chain_index: chain_id.0,
722
0
                        },
723
0
                        peer_index,
724
0
                        SubstreamDirection::Out,
725
0
                        NotificationsSubstreamState::MIN,
726
0
                        SubstreamId::MIN,
727
0
                    )
728
0
                        ..=(
729
0
                            NotificationsProtocol::BlockAnnounces {
730
0
                                chain_index: chain_id.0,
731
0
                            },
732
0
                            peer_index,
733
0
                            SubstreamDirection::Out,
734
0
                            NotificationsSubstreamState::MAX,
735
0
                            SubstreamId::MAX,
736
0
                        ),
737
0
                )
738
0
                .next()
739
0
                .is_none()
740
            {
741
0
                let _was_inserted = self
742
0
                    .connected_unopened_gossip_desired
743
0
                    .insert((peer_index, chain_id, kind));
744
0
                debug_assert!(_was_inserted);
745
0
            }
746
0
        }
747
748
0
        if !self
749
0
            .connections_by_peer_id
750
0
            .range((peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX))
751
0
            .any(|(_, connection_id)| {
752
0
                let state = self.inner.connection_state(*connection_id);
753
0
                !state.shutting_down
754
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE21gossip_insert_desireds_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE21gossip_insert_desireds_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE21gossip_insert_desireds_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE21gossip_insert_desireds_0B1b_
755
0
        {
756
0
            // Note that that `PeerId` might already be desired towards a different chain, in
757
0
            // which case it is already present in `unconnected_desired`.
758
0
            self.unconnected_desired.insert(peer_index);
759
0
        }
760
761
0
        true
762
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE21gossip_insert_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE21gossip_insert_desiredB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE21gossip_insert_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE21gossip_insert_desiredB19_
763
764
    /// Removes the given chain-peer combination from the list of desired chain-peers.
765
    ///
766
    /// Has no effect if it was not marked as desired.
767
    ///
768
    /// Returns `true` if the peer was desired on this chain.
769
    ///
770
    /// # Panic
771
    ///
772
    /// Panics if the given [`ChainId`] is invalid.
773
    ///
774
0
    pub fn gossip_remove_desired(
775
0
        &mut self,
776
0
        chain_id: ChainId,
777
0
        peer_id: &PeerId,
778
0
        kind: GossipKind,
779
0
    ) -> bool {
780
0
        assert!(self.chains.contains(chain_id.0));
781
782
0
        let Some(&peer_index) = self.peers_by_peer_id.get(peer_id) else {
783
            // If the `PeerId` is unknown, then it wasn't marked as desired.
784
0
            return false;
785
        };
786
787
0
        self.gossip_remove_desired_inner(chain_id, peer_index, kind)
788
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE21gossip_remove_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE21gossip_remove_desiredB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE21gossip_remove_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE21gossip_remove_desiredB19_
789
790
0
    fn gossip_remove_desired_inner(
791
0
        &mut self,
792
0
        chain_id: ChainId,
793
0
        peer_index: PeerIndex,
794
0
        kind: GossipKind,
795
0
    ) -> bool {
796
0
        if !self
797
0
            .gossip_desired_peers_by_chain
798
0
            .remove(&(chain_id.0, kind, peer_index))
799
        {
800
            // Return if wasn't marked as desired, as there's nothing more to update.
801
0
            return false;
802
0
        }
803
0
804
0
        self.gossip_desired_peers
805
0
            .remove(&(peer_index, kind, chain_id.0));
806
0
807
0
        self.connected_unopened_gossip_desired
808
0
            .remove(&(peer_index, chain_id, kind));
809
0
810
0
        if self
811
0
            .gossip_desired_peers
812
0
            .range((peer_index, kind, usize::MIN)..=(peer_index, kind, usize::MAX))
813
0
            .next()
814
0
            .is_none()
815
0
        {
816
0
            self.unconnected_desired.remove(&peer_index);
817
0
        }
818
819
0
        if self
820
0
            .notification_substreams_by_peer_id
821
0
            .range(
822
0
                (
823
0
                    NotificationsProtocol::BlockAnnounces {
824
0
                        chain_index: chain_id.0,
825
0
                    },
826
0
                    peer_index,
827
0
                    SubstreamDirection::Out,
828
0
                    NotificationsSubstreamState::MIN,
829
0
                    SubstreamId::MIN,
830
0
                )
831
0
                    ..=(
832
0
                        NotificationsProtocol::BlockAnnounces {
833
0
                            chain_index: chain_id.0,
834
0
                        },
835
0
                        peer_index,
836
0
                        SubstreamDirection::Out,
837
0
                        NotificationsSubstreamState::MAX,
838
0
                        SubstreamId::MAX,
839
0
                    ),
840
0
            )
841
0
            .next()
842
0
            .is_some()
843
        {
844
0
            let _was_inserted = self
845
0
                .opened_gossip_undesired
846
0
                .insert((chain_id, peer_index, kind));
847
0
            debug_assert!(_was_inserted);
848
0
        }
849
850
0
        self.try_clean_up_peer(peer_index);
851
0
852
0
        true
853
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE27gossip_remove_desired_innerB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE27gossip_remove_desired_innerB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE27gossip_remove_desired_innerB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE27gossip_remove_desired_innerB19_
854
855
    /// Removes the given peer from the list of desired chain-peers of all the chains that exist.
856
    ///
857
    /// Has no effect if it was not marked as desired.
858
0
    pub fn gossip_remove_desired_all(&mut self, peer_id: &PeerId, kind: GossipKind) {
859
0
        let Some(&peer_index) = self.peers_by_peer_id.get(peer_id) else {
860
            // If the `PeerId` is unknown, then it wasn't marked as desired.
861
0
            return;
862
        };
863
864
0
        let chains = {
865
0
            // TODO: this works only because there's only one GossipKind
866
0
            let mut chains_and_after =
867
0
                self.gossip_desired_peers
868
0
                    .split_off(&(peer_index, kind, usize::MIN));
869
0
            let mut chains_after =
870
0
                chains_and_after.split_off(&(PeerIndex(peer_index.0 + 1), kind, usize::MIN));
871
0
            self.gossip_desired_peers.append(&mut chains_after);
872
0
            chains_and_after
873
        };
874
875
0
        for (_removed_peer_index, _, chain_index) in chains {
876
0
            debug_assert_eq!(_removed_peer_index, peer_index);
877
0
            let _was_in =
878
0
                self.gossip_desired_peers_by_chain
879
0
                    .remove(&(chain_index, kind, peer_index));
880
0
            debug_assert!(_was_in);
881
0
            self.connected_unopened_gossip_desired.remove(&(
882
0
                peer_index,
883
0
                ChainId(chain_index),
884
0
                kind,
885
0
            ));
886
        }
887
888
0
        self.unconnected_desired.remove(&peer_index);
889
0
        self.try_clean_up_peer(peer_index);
890
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE25gossip_remove_desired_allB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE25gossip_remove_desired_allB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE25gossip_remove_desired_allB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE25gossip_remove_desired_allB19_
891
892
    /// Returns the list of gossip-desired peers for the given chain, in no specific order.
893
    ///
894
    /// # Panic
895
    ///
896
    /// Panics if the given [`ChainId`] is invalid.
897
    ///
898
147
    pub fn gossip_desired_iter(
899
147
        &self,
900
147
        chain_id: ChainId,
901
147
        kind: GossipKind,
902
147
    ) -> impl Iterator<Item = &'_ PeerId> + '_ {
903
147
        self.gossip_desired_peers_by_chain
904
147
            .range(
905
147
                (chain_id.0, kind, PeerIndex(usize::MIN))
906
147
                    ..=(chain_id.0, kind, PeerIndex(usize::MAX)),
907
147
            )
908
147
            .map(|(_, _, peer_index)| 
&self.peers[peer_index.0]0
)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE19gossip_desired_iter0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE19gossip_desired_iter0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE19gossip_desired_iter0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE19gossip_desired_iter0B1b_
909
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE19gossip_desired_iterB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE19gossip_desired_iterB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE19gossip_desired_iterB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE19gossip_desired_iterB19_
Line
Count
Source
898
147
    pub fn gossip_desired_iter(
899
147
        &self,
900
147
        chain_id: ChainId,
901
147
        kind: GossipKind,
902
147
    ) -> impl Iterator<Item = &'_ PeerId> + '_ {
903
147
        self.gossip_desired_peers_by_chain
904
147
            .range(
905
147
                (chain_id.0, kind, PeerIndex(usize::MIN))
906
147
                    ..=(chain_id.0, kind, PeerIndex(usize::MAX)),
907
147
            )
908
147
            .map(|(_, _, peer_index)| &self.peers[peer_index.0])
909
147
    }
910
911
    /// Returns the number of gossip-desired peers for the given chain.
912
    ///
913
    /// # Panic
914
    ///
915
    /// Panics if the given [`ChainId`] is invalid.
916
    ///
917
147
    pub fn gossip_desired_num(&self, chain_id: ChainId, kind: GossipKind) -> usize {
918
147
        self.gossip_desired_iter(chain_id, kind).count()
919
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE18gossip_desired_numB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18gossip_desired_numB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE18gossip_desired_numB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18gossip_desired_numB19_
Line
Count
Source
917
147
    pub fn gossip_desired_num(&self, chain_id: ChainId, kind: GossipKind) -> usize {
918
147
        self.gossip_desired_iter(chain_id, kind).count()
919
147
    }
920
921
    /// Returns the list of [`PeerId`]s that are desired (for any chain) but for which no
922
    /// connection exists.
923
    ///
924
    /// > **Note**: Connections that are currently in the process of shutting down are also
925
    /// >           ignored for the purpose of this function.
926
147
    pub fn unconnected_desired(&'_ self) -> impl ExactSizeIterator<Item = &'_ PeerId> + Clone + '_ {
927
147
        self.unconnected_desired
928
147
            .iter()
929
147
            .map(|peer_index| 
&self.peers[peer_index.0]0
)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE19unconnected_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE19unconnected_desired0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE19unconnected_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE19unconnected_desired0B1b_
930
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE19unconnected_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE19unconnected_desiredB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE19unconnected_desiredB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE19unconnected_desiredB19_
Line
Count
Source
926
147
    pub fn unconnected_desired(&'_ self) -> impl ExactSizeIterator<Item = &'_ PeerId> + Clone + '_ {
927
147
        self.unconnected_desired
928
147
            .iter()
929
147
            .map(|peer_index| &self.peers[peer_index.0])
930
147
    }
931
932
    /// Returns the list of [`PeerId`]s that are marked as desired, and for which a healthy
933
    /// connection exists, but for which no substream connection attempt exists.
934
147
    pub fn connected_unopened_gossip_desired(
935
147
        &'_ self,
936
147
    ) -> impl ExactSizeIterator<Item = (&'_ PeerId, ChainId, GossipKind)> + Clone + '_ {
937
147
        self.connected_unopened_gossip_desired.iter().map(
938
147
            move |(peer_index, chain_id, gossip_kind)| {
939
0
                (&self.peers[peer_index.0], *chain_id, *gossip_kind)
940
147
            },
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE33connected_unopened_gossip_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE33connected_unopened_gossip_desired0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE33connected_unopened_gossip_desired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE33connected_unopened_gossip_desired0B1b_
941
147
        )
942
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE33connected_unopened_gossip_desiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE33connected_unopened_gossip_desiredB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE33connected_unopened_gossip_desiredB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE33connected_unopened_gossip_desiredB19_
Line
Count
Source
934
147
    pub fn connected_unopened_gossip_desired(
935
147
        &'_ self,
936
147
    ) -> impl ExactSizeIterator<Item = (&'_ PeerId, ChainId, GossipKind)> + Clone + '_ {
937
147
        self.connected_unopened_gossip_desired.iter().map(
938
147
            move |(peer_index, chain_id, gossip_kind)| {
939
                (&self.peers[peer_index.0], *chain_id, *gossip_kind)
940
147
            },
941
147
        )
942
147
    }
943
944
    /// Returns the list of [`PeerId`]s for which a substream connection or connection attempt
945
    /// exists but that are not marked as desired.
946
0
    pub fn opened_gossip_undesired(
947
0
        &'_ self,
948
0
    ) -> impl ExactSizeIterator<Item = (&'_ PeerId, ChainId, GossipKind)> + Clone + '_ {
949
0
        self.opened_gossip_undesired
950
0
            .iter()
951
0
            .map(move |(chain_id, peer_index, gossip_kind)| {
952
0
                (&self.peers[peer_index.0], *chain_id, *gossip_kind)
953
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE23opened_gossip_undesired0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE23opened_gossip_undesired0Bb_
954
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE23opened_gossip_undesiredB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE23opened_gossip_undesiredB9_
955
956
    /// Returns the list of [`PeerId`]s for which a substream connection or connection attempt
957
    /// exists against the given chain but that are not marked as desired.
958
    ///
959
    /// # Panic
960
    ///
961
    /// Panics if the [`ChainId`] is invalid.
962
    ///
963
0
    pub fn opened_gossip_undesired_by_chain(
964
0
        &'_ self,
965
0
        chain_id: ChainId,
966
0
    ) -> impl Iterator<Item = (&'_ PeerId, GossipKind)> + Clone + '_ {
967
0
        // TODO: optimize and add an ExactSizeIterator bound to the return value, and update the users to use len() instead of count()
968
0
        self.opened_gossip_undesired
969
0
            .iter()
970
0
            .filter(move |(c, _, _)| *c == chain_id)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE32opened_gossip_undesired_by_chain0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32opened_gossip_undesired_by_chain0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE32opened_gossip_undesired_by_chain0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32opened_gossip_undesired_by_chain0B1b_
971
0
            .map(move |(_, peer_index, gossip_kind)| (&self.peers[peer_index.0], *gossip_kind))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE32opened_gossip_undesired_by_chains_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32opened_gossip_undesired_by_chains_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE32opened_gossip_undesired_by_chains_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32opened_gossip_undesired_by_chains_0B1b_
972
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE32opened_gossip_undesired_by_chainB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32opened_gossip_undesired_by_chainB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE32opened_gossip_undesired_by_chainB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32opened_gossip_undesired_by_chainB19_
973
974
    /// Adds a single-stream connection to the state machine.
975
    ///
976
    /// This connection hasn't finished handshaking and the [`PeerId`] of the remote isn't known
977
    /// yet.
978
    ///
979
    /// If `expected_peer_id` is `Some`, this connection is expected to reach the given [`PeerId`].
980
    /// The `expected_peer_id` is only used to influence the result of
981
    /// [`ChainNetwork::unconnected_desired`].
982
    ///
983
    /// Must be passed the moment (as a `TNow`) when the connection has first been opened, in
984
    /// order to determine when the handshake timeout expires.
985
    ///
986
    /// The `remote_addr` is the multiaddress used to reach back the remote. In the case of TCP, it
987
    /// contains the TCP dialing port of the remote. The remote can ask, through the `identify`
988
    /// libp2p protocol, its own address, in which case we send it. Because the multiaddress
989
    /// specification is flexible, this module doesn't attempt to parse the address.
990
0
    pub fn add_single_stream_connection(
991
0
        &mut self,
992
0
        when_connection_start: TNow,
993
0
        handshake_kind: SingleStreamHandshakeKind,
994
0
        remote_addr: Vec<u8>,
995
0
        expected_peer_id: Option<PeerId>,
996
0
        user_data: TConn,
997
0
    ) -> (ConnectionId, SingleStreamConnectionTask<TNow>) {
998
0
        let substreams_capacity = 16; // TODO: ?
999
0
        let ed25519_public_key = match handshake_kind {
1000
0
            SingleStreamHandshakeKind::MultistreamSelectNoiseYamux { noise_key, .. } => {
1001
0
                *noise_key.libp2p_public_ed25519_key()
1002
0
            }
1003
0
        };
1004
0
        let expected_peer_index =
1005
0
            expected_peer_id.map(|peer_id| self.peer_index_or_insert(peer_id));
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE28add_single_stream_connection0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE28add_single_stream_connection0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE28add_single_stream_connection0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE28add_single_stream_connection0B1b_
1006
0
        let (id, task) = self.inner.insert_single_stream(
1007
0
            when_connection_start,
1008
0
            handshake_kind,
1009
0
            substreams_capacity,
1010
0
            ConnectionInfo {
1011
0
                address: remote_addr,
1012
0
                ed25519_public_key,
1013
0
                peer_index: expected_peer_index,
1014
0
                user_data,
1015
0
            },
1016
0
        );
1017
0
        if let Some(expected_peer_index) = expected_peer_index {
1018
0
            self.unconnected_desired.remove(&expected_peer_index);
1019
0
            self.connections_by_peer_id
1020
0
                .insert((expected_peer_index, id));
1021
0
        }
1022
0
        (id, task)
1023
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE28add_single_stream_connectionB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE28add_single_stream_connectionB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE28add_single_stream_connectionB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE28add_single_stream_connectionB19_
1024
1025
    /// Adds a multi-stream connection to the state machine.
1026
    ///
1027
    /// This connection hasn't finished handshaking and the [`PeerId`] of the remote isn't known
1028
    /// yet.
1029
    ///
1030
    /// If `expected_peer_id` is `Some`, this connection is expected to reach the given [`PeerId`].
1031
    /// The `expected_peer_id` is only used to influence the result of
1032
    /// [`ChainNetwork::unconnected_desired`].
1033
    ///
1034
    /// Must be passed the moment (as a `TNow`) when the connection has first been opened, in
1035
    /// order to determine when the handshake timeout expires.
1036
    ///
1037
    /// The `remote_addr` is the multiaddress used to reach back the remote. In the case of TCP, it
1038
    /// contains the TCP dialing port of the remote. The remote can ask, through the `identify`
1039
    /// libp2p protocol, its own address, in which case we send it. Because the multiaddress
1040
    /// specification is flexible, this module doesn't attempt to parse the address.
1041
0
    pub fn add_multi_stream_connection<TSubId>(
1042
0
        &mut self,
1043
0
        when_connection_start: TNow,
1044
0
        handshake_kind: MultiStreamHandshakeKind,
1045
0
        remote_addr: Vec<u8>,
1046
0
        expected_peer_id: Option<PeerId>,
1047
0
        user_data: TConn,
1048
0
    ) -> (ConnectionId, MultiStreamConnectionTask<TNow, TSubId>)
1049
0
    where
1050
0
        TSubId: Clone + PartialEq + Eq + Hash,
1051
0
    {
1052
0
        let substreams_capacity = 16; // TODO: ?
1053
0
        let ed25519_public_key = match handshake_kind {
1054
0
            MultiStreamHandshakeKind::WebRtc { noise_key, .. } => {
1055
0
                *noise_key.libp2p_public_ed25519_key()
1056
0
            }
1057
0
        };
1058
0
        let expected_peer_index =
1059
0
            expected_peer_id.map(|peer_id| self.peer_index_or_insert(peer_id));
Unexecuted instantiation: _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB8_12ChainNetworkpppE27add_multi_stream_connectionpE0Bc_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBc_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE27add_multi_stream_connectionjE0B27_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkpppE27add_multi_stream_connectionpE0Bc_
1060
0
        let (id, task) = self.inner.insert_multi_stream(
1061
0
            when_connection_start,
1062
0
            handshake_kind,
1063
0
            substreams_capacity,
1064
0
            ConnectionInfo {
1065
0
                address: remote_addr,
1066
0
                peer_index: expected_peer_index,
1067
0
                ed25519_public_key,
1068
0
                user_data,
1069
0
            },
1070
0
        );
1071
0
        if let Some(expected_peer_index) = expected_peer_index {
1072
0
            self.unconnected_desired.remove(&expected_peer_index);
1073
0
            self.connections_by_peer_id
1074
0
                .insert((expected_peer_index, id));
1075
0
        }
1076
0
        (id, task)
1077
0
    }
Unexecuted instantiation: _RINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB6_12ChainNetworkpppE27add_multi_stream_connectionpEBa_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBa_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE27add_multi_stream_connectionjEB25_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkpppE27add_multi_stream_connectionpEBa_
1078
1079
    /// Returns the number of connections, both handshaking or established.
1080
0
    pub fn num_connections(&self) -> usize {
1081
0
        self.inner.len()
1082
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE15num_connectionsB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE15num_connectionsB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE15num_connectionsB19_
1083
1084
    /// Returns the remote address that was passed to [`ChainNetwork::add_single_stream_connection`]
1085
    /// or [`ChainNetwork::add_multi_stream_connection`] for the given connection.
1086
    ///
1087
    /// > **Note**: This module does in no way attempt to parse the address. This function simply
1088
    /// >           returns the value that was provided by the API user, whatever it is.
1089
    ///
1090
    /// # Panic
1091
    ///
1092
    /// Panics if the [`ConnectionId`] is invalid.
1093
    ///
1094
0
    pub fn connection_remote_addr(&self, id: ConnectionId) -> &[u8] {
1095
0
        &self.inner[id].address
1096
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE22connection_remote_addrB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE22connection_remote_addrB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE22connection_remote_addrB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE22connection_remote_addrB19_
1097
1098
    /// Returns the number of connections with the given peer.
1099
    ///
1100
    /// Both connections that have and have not finished their handshaking phase are considered.
1101
0
    pub fn num_potential_and_established_connections(&self, peer_id: &PeerId) -> usize {
1102
0
        let Some(&peer_index) = self.peers_by_peer_id.get(peer_id) else {
1103
0
            return 0;
1104
        };
1105
1106
0
        self.connections_by_peer_id
1107
0
            .range((peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX))
1108
0
            .count()
1109
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE41num_potential_and_established_connectionsB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE41num_potential_and_established_connectionsB9_
1110
1111
    /// Pulls a message that must be sent to a connection.
1112
    ///
1113
    /// The message must be passed to [`SingleStreamConnectionTask::inject_coordinator_message`]
1114
    /// or [`MultiStreamConnectionTask::inject_coordinator_message`] in the appropriate connection.
1115
    ///
1116
    /// This function guarantees that the [`ConnectionId`] always refers to a connection that
1117
    /// is still alive, in the sense that [`SingleStreamConnectionTask::inject_coordinator_message`]
1118
    /// or [`MultiStreamConnectionTask::inject_coordinator_message`] has never returned `None`
1119
    /// and that no [`Event::Disconnected`] or [`Event::PreHandshakeDisconnected`] has been
1120
    /// generated for this connection.
1121
147
    pub fn pull_message_to_connection(
1122
147
        &mut self,
1123
147
    ) -> Option<(ConnectionId, CoordinatorToConnection)> {
1124
147
        self.inner.pull_message_to_connection()
1125
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE26pull_message_to_connectionB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE26pull_message_to_connectionB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE26pull_message_to_connectionB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE26pull_message_to_connectionB19_
Line
Count
Source
1121
147
    pub fn pull_message_to_connection(
1122
147
        &mut self,
1123
147
    ) -> Option<(ConnectionId, CoordinatorToConnection)> {
1124
147
        self.inner.pull_message_to_connection()
1125
147
    }
1126
1127
    /// Injects into the state machine a message generated by
1128
    /// [`SingleStreamConnectionTask::pull_message_to_coordinator`] or
1129
    /// [`MultiStreamConnectionTask::pull_message_to_coordinator`].
1130
0
    pub fn inject_connection_message(
1131
0
        &mut self,
1132
0
        connection_id: ConnectionId,
1133
0
        message: ConnectionToCoordinator,
1134
0
    ) {
1135
0
        self.inner.inject_connection_message(connection_id, message)
1136
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE25inject_connection_messageB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE25inject_connection_messageB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE25inject_connection_messageB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE25inject_connection_messageB19_
1137
1138
    /// Returns the next event produced by the service.
1139
147
    pub fn next_event(&mut self) -> Option<Event<TConn>> {
1140
        loop {
1141
147
            let 
inner_event0
= self.inner.next_event()?;
1142
0
            match inner_event {
1143
                collection::Event::HandshakeFinished {
1144
0
                    id,
1145
0
                    peer_id: actual_peer_id,
1146
0
                } => {
1147
0
                    // A handshaking connection has finished its handshake. We must update `self`
1148
0
                    // and return an event.
1149
0
                    // What makes this a bit complicated is the possibility that the actual PeerId
1150
0
                    // might not be the same as the one that was expected.
1151
0
1152
0
                    let actual_peer_index = self.peer_index_or_insert(actual_peer_id);
1153
0
                    let expected_peer_index = self.inner[id].peer_index;
1154
1155
0
                    match expected_peer_index {
1156
0
                        None => {
1157
0
                            // The connection didn't have any expected PeerId.
1158
0
                            self.inner[id].peer_index = Some(actual_peer_index);
1159
0
                            self.unconnected_desired.remove(&actual_peer_index);
1160
0
                        }
1161
0
                        Some(expected_peer_index) if expected_peer_index != actual_peer_index => {
1162
0
                            // The actual PeerId doesn't match the expected PeerId.
1163
0
1164
0
                            // Update the connection owner.
1165
0
                            self.inner[id].peer_index = Some(actual_peer_index);
1166
0
                            let _was_removed = self
1167
0
                                .connections_by_peer_id
1168
0
                                .remove(&(expected_peer_index, id));
1169
0
                            debug_assert!(_was_removed);
1170
0
                            let _was_inserted =
1171
0
                                self.connections_by_peer_id.insert((actual_peer_index, id));
1172
0
                            debug_assert!(_was_inserted);
1173
1174
                            // Update `unconnected_desired`.
1175
0
                            self.unconnected_desired.remove(&actual_peer_index);
1176
0
                            if self
1177
0
                                .gossip_desired_peers
1178
0
                                .range(
1179
0
                                    (
1180
0
                                        expected_peer_index,
1181
0
                                        GossipKind::ConsensusTransactions,
1182
0
                                        usize::MIN,
1183
0
                                    )
1184
0
                                        ..=(
1185
0
                                            expected_peer_index,
1186
0
                                            GossipKind::ConsensusTransactions,
1187
0
                                            usize::MAX,
1188
0
                                        ),
1189
0
                                )
1190
0
                                .next()
1191
0
                                .is_some()
1192
0
                                && !self
1193
0
                                    .connections_by_peer_id
1194
0
                                    .range(
1195
0
                                        (expected_peer_index, ConnectionId::MIN)
1196
0
                                            ..=(expected_peer_index, ConnectionId::MAX),
1197
0
                                    )
1198
0
                                    .any(|(_, connection_id)| {
1199
0
                                        let state = self.inner.connection_state(*connection_id);
1200
0
                                        !state.shutting_down
1201
0
                                    })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_event0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_event0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_event0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_event0B1b_
1202
                            {
1203
0
                                let _was_inserted =
1204
0
                                    self.unconnected_desired.insert(expected_peer_index);
1205
0
                                debug_assert!(_was_inserted);
1206
0
                            }
1207
                        }
1208
                        _ => {
1209
                            // Expected matches actual.
1210
0
                            debug_assert_eq!(expected_peer_index, Some(actual_peer_index));
1211
                        }
1212
                    }
1213
1214
                    // TODO: limit the number of connections per peer?
1215
1216
                    // Insert the new connection in `self.connected_unopened_gossip_desired`
1217
                    // if relevant.
1218
0
                    for (_, _, chain_id) in self.gossip_desired_peers.range(
1219
0
                        (
1220
0
                            actual_peer_index,
1221
0
                            GossipKind::ConsensusTransactions,
1222
0
                            usize::MIN,
1223
0
                        )
1224
0
                            ..=(
1225
0
                                actual_peer_index,
1226
0
                                GossipKind::ConsensusTransactions,
1227
0
                                usize::MAX,
1228
0
                            ),
1229
0
                    ) {
1230
0
                        if self
1231
0
                            .notification_substreams_by_peer_id
1232
0
                            .range(
1233
0
                                (
1234
0
                                    NotificationsProtocol::BlockAnnounces {
1235
0
                                        chain_index: *chain_id,
1236
0
                                    },
1237
0
                                    actual_peer_index,
1238
0
                                    SubstreamDirection::Out,
1239
0
                                    NotificationsSubstreamState::MIN,
1240
0
                                    SubstreamId::MIN,
1241
0
                                )
1242
0
                                    ..=(
1243
0
                                        NotificationsProtocol::BlockAnnounces {
1244
0
                                            chain_index: *chain_id,
1245
0
                                        },
1246
0
                                        actual_peer_index,
1247
0
                                        SubstreamDirection::Out,
1248
0
                                        NotificationsSubstreamState::MAX,
1249
0
                                        SubstreamId::MAX,
1250
0
                                    ),
1251
0
                            )
1252
0
                            .next()
1253
0
                            .is_none()
1254
0
                        {
1255
0
                            self.connected_unopened_gossip_desired.insert((
1256
0
                                actual_peer_index,
1257
0
                                ChainId(*chain_id),
1258
0
                                GossipKind::ConsensusTransactions,
1259
0
                            ));
1260
0
                        }
1261
                    }
1262
1263
                    // Try to clean up the expected peer index.
1264
                    // This is done at the very end so that `self` is in a coherent state.
1265
0
                    let expected_peer_id = expected_peer_index.map(|idx| self.peers[idx.0].clone());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events_0B1b_
1266
0
                    if let Some(expected_peer_index) = expected_peer_index {
1267
0
                        if expected_peer_index != actual_peer_index {
1268
0
                            self.try_clean_up_peer(expected_peer_index);
1269
0
                        }
1270
0
                    }
1271
1272
                    // Small sanity check.
1273
0
                    debug_assert!(!self.unconnected_desired.contains(&actual_peer_index));
1274
1275
0
                    return Some(Event::HandshakeFinished {
1276
0
                        id,
1277
0
                        expected_peer_id,
1278
0
                        peer_id: self.peers[actual_peer_index.0].clone(),
1279
0
                    });
1280
                }
1281
1282
0
                collection::Event::PingOutFailed { id }
1283
0
                | collection::Event::StartShutdown { id, .. } => {
1284
                    // A connection has started its shutdown, or must start its shutdown.
1285
1286
                    // We handle a ping failure the same way as a shutdown start, as we react to
1287
                    // a ping failure by starting the shutdown of the connection. Thus, the clean
1288
                    // up phase is the same in both cases.
1289
0
                    if let collection::Event::PingOutFailed { .. } = inner_event {
1290
0
                        self.inner.start_shutdown(id);
1291
0
                    }
1292
1293
                    // TODO: IMPORTANT this event should be turned into `NewOutboundSubstreamsForbidden` and the `reason` removed; see <https://github.com/smol-dot/smoldot/pull/391>
1294
1295
                    // Nothing more to do if the connection is inbound and handshaking.
1296
0
                    let Some(peer_index) = self.inner[id].peer_index else {
1297
0
                        debug_assert!(!self.inner.connection_state(id).established);
1298
0
                        continue;
1299
                    };
1300
1301
                    // If peer is desired, and we have no connection or only shutting down
1302
                    // connections, add peer to `unconnected_desired` and remove it from
1303
                    // `connected_unopened_gossip_desired`.
1304
0
                    if self
1305
0
                        .gossip_desired_peers
1306
0
                        .range(
1307
0
                            (peer_index, GossipKind::ConsensusTransactions, usize::MIN)
1308
0
                                ..=(peer_index, GossipKind::ConsensusTransactions, usize::MAX),
1309
0
                        )
1310
0
                        .count()
1311
0
                        != 0
1312
                    {
1313
0
                        if !self
1314
0
                            .connections_by_peer_id
1315
0
                            .range(
1316
0
                                (peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX),
1317
0
                            )
1318
0
                            .any(|(_, connection_id)| {
1319
0
                                let state = self.inner.connection_state(*connection_id);
1320
0
                                !state.shutting_down
1321
0
                            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events0_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events0_0B1b_
1322
0
                        {
1323
0
                            self.unconnected_desired.insert(peer_index);
1324
0
                        }
1325
0
                        if !self
1326
0
                            .connections_by_peer_id
1327
0
                            .range(
1328
0
                                (peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX),
1329
0
                            )
1330
0
                            .any(|(_, connection_id)| {
1331
0
                                let state = self.inner.connection_state(*connection_id);
1332
0
                                state.established && !state.shutting_down
1333
0
                            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events1_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events1_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events1_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events1_0B1b_
1334
                        {
1335
0
                            for (_, _, chain_index) in self.gossip_desired_peers.range(
1336
0
                                (peer_index, GossipKind::ConsensusTransactions, usize::MIN)
1337
0
                                    ..=(peer_index, GossipKind::ConsensusTransactions, usize::MAX),
1338
0
                            ) {
1339
0
                                self.connected_unopened_gossip_desired.remove(&(
1340
0
                                    peer_index,
1341
0
                                    ChainId(*chain_index),
1342
0
                                    GossipKind::ConsensusTransactions,
1343
0
                                ));
1344
0
                            }
1345
0
                        }
1346
0
                    }
1347
                }
1348
1349
                collection::Event::Shutdown {
1350
0
                    id,
1351
0
                    was_established,
1352
0
                    user_data: connection_info,
1353
0
                } => {
1354
0
                    // A connection has been completely closed.
1355
0
                    // The underlying state machine guarantees that all the substreams have been
1356
0
                    // closed beforehand through other events.
1357
0
1358
0
                    debug_assert!(connection_info.peer_index.is_some() || !was_established);
1359
1360
0
                    let peer_id = connection_info
1361
0
                        .peer_index
1362
0
                        .map(|peer_index| self.peers[peer_index.0].clone());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events2_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events2_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events2_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events2_0B1b_
1363
1364
0
                    if let Some(peer_index) = connection_info.peer_index {
1365
0
                        let _was_removed = self.connections_by_peer_id.remove(&(peer_index, id));
1366
0
                        debug_assert!(_was_removed);
1367
0
                        self.try_clean_up_peer(peer_index);
1368
0
                    }
1369
1370
                    // TODO: IMPORTANT this event should indicate a clean shutdown, a pre-handshake interruption, a protocol error, a reset, etc. and should get a `reason`; see <https://github.com/smol-dot/smoldot/pull/391>
1371
1372
0
                    if was_established {
1373
0
                        return Some(Event::Disconnected {
1374
0
                            id,
1375
0
                            address: connection_info.address,
1376
0
                            peer_id: peer_id.unwrap(),
1377
0
                            user_data: connection_info.user_data,
1378
0
                        });
1379
                    } else {
1380
0
                        return Some(Event::PreHandshakeDisconnected {
1381
0
                            id,
1382
0
                            address: connection_info.address,
1383
0
                            expected_peer_id: peer_id,
1384
0
                            user_data: connection_info.user_data,
1385
0
                        });
1386
                    }
1387
                }
1388
1389
0
                collection::Event::InboundError { .. } => {
1390
0
                    // TODO: report the error for diagnostic purposes, but revisit the concept of "InboundError"
1391
0
                }
1392
1393
                collection::Event::InboundNegotiated {
1394
0
                    id,
1395
0
                    substream_id,
1396
0
                    protocol_name,
1397
                } => {
1398
                    // An inbound substream opened by the remote would like to negotiate the given
1399
                    // protocol. We must decide whether to accept this protocol or instead reject
1400
                    // the substream.
1401
                    // If accepted, we must also save the protocol somewhere in `self` in order to
1402
                    // load it later once things happen on this substream.
1403
0
                    let Ok(protocol) = self.recognize_protocol(&protocol_name) else {
1404
0
                        self.inner.reject_inbound(substream_id);
1405
0
                        continue;
1406
                    };
1407
1408
0
                    let inbound_type = match protocol {
1409
0
                        Protocol::Identify => collection::InboundTy::Request {
1410
0
                            request_max_size: None,
1411
0
                        },
1412
0
                        Protocol::Ping => collection::InboundTy::Ping,
1413
0
                        Protocol::Notifications(NotificationsProtocol::Grandpa { chain_index })
1414
0
                            if self.chains[chain_index].grandpa_protocol_config.is_none() =>
1415
0
                        {
1416
0
                            self.inner.reject_inbound(substream_id);
1417
0
                            continue;
1418
                        }
1419
0
                        Protocol::Notifications(p) => collection::InboundTy::Notifications {
1420
0
                            max_handshake_size: self.notifications_protocol_max_handshake_size(p),
1421
0
                        },
1422
0
                        Protocol::Sync { chain_index }
1423
0
                            if self.chains[chain_index].allow_inbound_block_requests =>
1424
0
                        {
1425
0
                            collection::InboundTy::Request {
1426
0
                                request_max_size: Some(1024),
1427
0
                            }
1428
                        }
1429
                        Protocol::Sync { .. } => {
1430
0
                            self.inner.reject_inbound(substream_id);
1431
0
                            continue;
1432
                        }
1433
1434
                        // TODO: the protocols below are not supported yet
1435
                        Protocol::LightUnknown { .. }
1436
                        | Protocol::Kad { .. }
1437
                        | Protocol::SyncWarp { .. }
1438
                        | Protocol::State { .. } => {
1439
0
                            self.inner.reject_inbound(substream_id);
1440
0
                            continue;
1441
                        }
1442
1443
                        Protocol::LightStorage { .. } | Protocol::LightCall { .. } => {
1444
0
                            unreachable!()
1445
                        }
1446
                    };
1447
1448
0
                    self.inner.accept_inbound(substream_id, inbound_type);
1449
0
1450
0
                    let _prev_value = self.substreams.insert(
1451
0
                        substream_id,
1452
0
                        SubstreamInfo {
1453
0
                            connection_id: id,
1454
0
                            protocol: Some(protocol),
1455
0
                        },
1456
0
                    );
1457
0
                    debug_assert!(_prev_value.is_none());
1458
                }
1459
1460
                collection::Event::InboundNegotiatedCancel { .. } => {
1461
                    // Because we immediately accept or reject substreams, this event can never
1462
                    // happen.
1463
0
                    unreachable!()
1464
                }
1465
1466
0
                collection::Event::InboundAcceptedCancel { substream_id } => {
1467
0
                    // An inbound substream has been aborted after having been accepted.
1468
0
                    // Since we don't report any event to the API user when a substream is
1469
0
                    // accepted, we have nothing to do but clean up our local state.
1470
0
                    let _was_in = self.substreams.remove(&substream_id);
1471
0
                    debug_assert!(_was_in.is_some());
1472
                }
1473
1474
                collection::Event::Response {
1475
0
                    substream_id,
1476
0
                    response,
1477
0
                } => {
1478
0
                    // Received a response to a request in a request-response protocol.
1479
0
                    let substream_info = self
1480
0
                        .substreams
1481
0
                        .remove(&substream_id)
1482
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events3_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events3_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events3_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events3_0B1b_
1483
0
                    let peer_index = *self.inner[substream_info.connection_id]
1484
0
                        .peer_index
1485
0
                        .as_ref()
1486
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events4_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events4_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events4_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events4_0B1b_
1487
1488
                    // Decode/verify the response.
1489
0
                    let (response, chain_index) = match substream_info.protocol {
1490
0
                        None => continue,
1491
0
                        Some(Protocol::Identify) => todo!(), // TODO: we don't send identify requests yet, so it's fine to leave this unimplemented
1492
0
                        Some(Protocol::Sync { chain_index, .. }) => (
1493
0
                            RequestResult::Blocks(
1494
0
                                response.map_err(BlocksRequestError::Request).and_then(
1495
0
                                    |response| {
1496
0
                                        codec::decode_block_response(&response)
1497
0
                                            .map_err(BlocksRequestError::Decode)
1498
0
                                    },
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events5_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events5_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events5_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events5_0B1b_
1499
0
                                ),
1500
0
                            ),
1501
0
                            chain_index,
1502
0
                        ),
1503
0
                        Some(Protocol::LightUnknown { .. }) => unreachable!(),
1504
0
                        Some(Protocol::LightStorage { chain_index, .. }) => (
1505
0
                            RequestResult::StorageProof(
1506
0
                                response
1507
0
                                    .map_err(StorageProofRequestError::Request)
1508
0
                                    .and_then(|payload| {
1509
0
                                        match codec::decode_storage_or_call_proof_response(
1510
0
                                            codec::StorageOrCallProof::StorageProof,
1511
0
                                            &payload,
1512
                                        ) {
1513
0
                                            Err(err) => Err(StorageProofRequestError::Decode(err)),
1514
                                            Ok(None) => {
1515
0
                                                Err(StorageProofRequestError::RemoteCouldntAnswer)
1516
                                            }
1517
0
                                            Ok(Some(_)) => Ok(EncodedMerkleProof(
1518
0
                                                payload,
1519
0
                                                codec::StorageOrCallProof::StorageProof,
1520
0
                                            )),
1521
                                        }
1522
0
                                    }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events6_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events6_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events6_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events6_0B1b_
1523
0
                            ),
1524
0
                            chain_index,
1525
0
                        ),
1526
0
                        Some(Protocol::LightCall { chain_index, .. }) => (
1527
0
                            RequestResult::CallProof(
1528
0
                                response.map_err(CallProofRequestError::Request).and_then(
1529
0
                                    |payload| match codec::decode_storage_or_call_proof_response(
1530
0
                                        codec::StorageOrCallProof::CallProof,
1531
0
                                        &payload,
1532
                                    ) {
1533
0
                                        Err(err) => Err(CallProofRequestError::Decode(err)),
1534
0
                                        Ok(None) => Err(CallProofRequestError::RemoteCouldntAnswer),
1535
0
                                        Ok(Some(_)) => Ok(EncodedMerkleProof(
1536
0
                                            payload,
1537
0
                                            codec::StorageOrCallProof::CallProof,
1538
0
                                        )),
1539
0
                                    },
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events7_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events7_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events7_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events7_0B1b_
1540
0
                                ),
1541
0
                            ),
1542
0
                            chain_index,
1543
0
                        ),
1544
0
                        Some(Protocol::Kad { chain_index, .. }) => (
1545
0
                            RequestResult::KademliaFindNode(
1546
0
                                response
1547
0
                                    .map_err(KademliaFindNodeError::RequestFailed)
1548
0
                                    .and_then(|payload| {
1549
0
                                        match codec::decode_find_node_response(&payload) {
1550
0
                                            Err(err) => {
1551
0
                                                Err(KademliaFindNodeError::DecodeError(err))
1552
                                            }
1553
0
                                            Ok(nodes) => Ok(nodes),
1554
                                        }
1555
0
                                    }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events8_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events8_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events8_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events8_0B1b_
1556
0
                            ),
1557
0
                            chain_index,
1558
0
                        ),
1559
0
                        Some(Protocol::SyncWarp { chain_index }) => (
1560
0
                            RequestResult::GrandpaWarpSync(
1561
0
                                response
1562
0
                                    .map_err(GrandpaWarpSyncRequestError::Request)
1563
0
                                    .and_then(|message| {
1564
0
                                        if let Err(err) = codec::decode_grandpa_warp_sync_response(
1565
0
                                            &message,
1566
0
                                            self.chains[chain_index].block_number_bytes,
1567
0
                                        ) {
1568
0
                                            Err(GrandpaWarpSyncRequestError::Decode(err))
1569
                                        } else {
1570
0
                                            Ok(EncodedGrandpaWarpSyncResponse {
1571
0
                                                message,
1572
0
                                                block_number_bytes: self.chains[chain_index]
1573
0
                                                    .block_number_bytes,
1574
0
                                            })
1575
                                        }
1576
0
                                    }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events9_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_events9_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_events9_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_events9_0B1b_
1577
0
                            ),
1578
0
                            chain_index,
1579
0
                        ),
1580
0
                        Some(Protocol::State { chain_index, .. }) => (
1581
0
                            RequestResult::State(
1582
0
                                response
1583
0
                                    .map_err(StateRequestError::Request)
1584
0
                                    .and_then(|payload| {
1585
0
                                        if let Err(err) = codec::decode_state_response(&payload) {
1586
0
                                            Err(StateRequestError::Decode(err))
1587
                                        } else {
1588
0
                                            Ok(EncodedStateResponse(payload))
1589
                                        }
1590
0
                                    }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsa_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsa_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsa_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsa_0B1b_
1591
0
                            ),
1592
0
                            chain_index,
1593
0
                        ),
1594
1595
                        // The protocols below aren't request-response protocols.
1596
0
                        Some(Protocol::Ping) | Some(Protocol::Notifications(_)) => unreachable!(),
1597
                    };
1598
1599
0
                    return Some(Event::RequestResult {
1600
0
                        peer_id: self.peers[peer_index.0].clone(),
1601
0
                        chain_id: ChainId(chain_index),
1602
0
                        substream_id,
1603
0
                        response,
1604
0
                    });
1605
                }
1606
1607
                collection::Event::RequestIn {
1608
0
                    substream_id,
1609
0
                    request_payload,
1610
0
                } => {
1611
0
                    // Received a request on a request-response protocol.
1612
0
                    let substream_info = self
1613
0
                        .substreams
1614
0
                        .get(&substream_id)
1615
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsb_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsb_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsb_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsb_0B1b_
1616
0
                    let peer_id = self.peers[self.inner[substream_info.connection_id]
1617
0
                        .peer_index
1618
0
                        .as_ref()
1619
0
                        .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsc_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsc_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsc_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsc_0B1b_
1620
0
                        .0]
1621
0
                        .clone();
1622
1623
0
                    match substream_info.protocol {
1624
0
                        None => {
1625
0
                            // Substream concerns a chain that has been removed.
1626
0
                            let _ = self.substreams.remove(&substream_id);
1627
0
                            self.inner.respond_in_request(substream_id, Err(()));
1628
0
                        }
1629
                        Some(Protocol::Identify) => {
1630
0
                            if request_payload.is_empty() {
1631
0
                                return Some(Event::IdentifyRequestIn {
1632
0
                                    peer_id,
1633
0
                                    substream_id,
1634
0
                                });
1635
                            } else {
1636
                                // TODO: can this actually be reached? isn't the inner code going to refuse a bad request anyway due to no length prefix?
1637
0
                                let _ = self.substreams.remove(&substream_id);
1638
0
                                self.inner.respond_in_request(substream_id, Err(()));
1639
0
                                return Some(Event::ProtocolError {
1640
0
                                    peer_id,
1641
0
                                    error: ProtocolError::BadIdentifyRequest,
1642
0
                                });
1643
                            }
1644
                        }
1645
0
                        Some(Protocol::Sync { chain_index }) => {
1646
0
                            match codec::decode_block_request(
1647
0
                                self.chains[chain_index].block_number_bytes,
1648
0
                                &request_payload,
1649
0
                            ) {
1650
0
                                Ok(config) => {
1651
0
                                    return Some(Event::BlocksRequestIn {
1652
0
                                        peer_id,
1653
0
                                        chain_id: ChainId(chain_index),
1654
0
                                        config,
1655
0
                                        substream_id,
1656
0
                                    })
1657
                                }
1658
0
                                Err(error) => {
1659
0
                                    let _ = self.substreams.remove(&substream_id);
1660
0
                                    self.inner.respond_in_request(substream_id, Err(()));
1661
0
                                    return Some(Event::ProtocolError {
1662
0
                                        peer_id,
1663
0
                                        error: ProtocolError::BadBlocksRequest(error),
1664
0
                                    });
1665
                                }
1666
                            }
1667
                        }
1668
                        // Any other protocol is declined when the protocol is negotiated.
1669
0
                        _ => unreachable!(),
1670
                    }
1671
                }
1672
1673
0
                collection::Event::RequestInCancel { substream_id } => {
1674
0
                    // The remote has cancelled a previously-emitted request. Propagate this event
1675
0
                    // to the API user.
1676
0
                    let _was_in = self.substreams.remove(&substream_id);
1677
0
                    debug_assert!(_was_in.is_some());
1678
0
                    return Some(Event::RequestInCancel { substream_id });
1679
                }
1680
1681
                // TODO: this whole block of code is too complex
1682
                collection::Event::NotificationsOutResult {
1683
0
                    substream_id,
1684
0
                    result,
1685
                } => {
1686
                    // Outgoing notifications substream has finished opening.
1687
                    // TODO: this if is pretty hacky
1688
0
                    let substream_info = if result.is_ok() {
1689
0
                        self.substreams
1690
0
                            .get(&substream_id)
1691
0
                            .unwrap_or_else(|| unreachable!())
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsd_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsd_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsd_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsd_0B1b_
1692
0
                            .clone()
1693
                    } else {
1694
0
                        self.substreams.remove(&substream_id).unwrap()
1695
                    };
1696
0
                    let connection_id = substream_info.connection_id;
1697
0
                    let peer_index = *self.inner[connection_id]
1698
0
                        .peer_index
1699
0
                        .as_ref()
1700
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventse_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventse_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventse_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventse_0B1b_
1701
0
                    let Some(Protocol::Notifications(substream_protocol)) = substream_info.protocol
1702
                    else {
1703
                        // All outgoing substream attempts are cancelled when a chain is removed,
1704
                        // as such `protocol` can't be `None`.
1705
0
                        unreachable!();
1706
                    };
1707
1708
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
1709
0
                        substream_protocol,
1710
0
                        peer_index,
1711
0
                        SubstreamDirection::Out,
1712
0
                        NotificationsSubstreamState::Pending,
1713
0
                        substream_id,
1714
0
                    ));
1715
0
                    debug_assert!(_was_in);
1716
1717
                    // The behaviour is very specific to the protocol.
1718
0
                    match substream_protocol {
1719
0
                        NotificationsProtocol::BlockAnnounces { chain_index } => {
1720
                            // Parse the handshake to check whether it's correct.
1721
0
                            let result = match &result {
1722
0
                                Ok(handshake) => {
1723
0
                                    match codec::decode_block_announces_handshake(
1724
0
                                        self.chains[chain_index].block_number_bytes,
1725
0
                                        handshake,
1726
                                    ) {
1727
0
                                        Ok(decoded_handshake)
1728
0
                                            if *decoded_handshake.genesis_hash
1729
0
                                                == self.chains[chain_index].genesis_hash =>
1730
0
                                        {
1731
0
                                            Ok(decoded_handshake)
1732
                                        }
1733
0
                                        Ok(decoded_handshake) => {
1734
0
                                            Err(GossipConnectError::GenesisMismatch {
1735
0
                                                local_genesis: self.chains[chain_index]
1736
0
                                                    .genesis_hash,
1737
0
                                                remote_genesis: *decoded_handshake.genesis_hash,
1738
0
                                            })
1739
                                        }
1740
0
                                        Err(err) => Err(GossipConnectError::HandshakeDecode(err)),
1741
                                    }
1742
                                }
1743
0
                                Err(err) => Err(GossipConnectError::Substream(err.clone())),
1744
                            };
1745
1746
0
                            match result {
1747
0
                                Ok(decoded_handshake) => {
1748
0
                                    let _was_inserted =
1749
0
                                        self.notification_substreams_by_peer_id.insert((
1750
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
1751
0
                                            peer_index,
1752
0
                                            SubstreamDirection::Out,
1753
0
                                            NotificationsSubstreamState::Open {
1754
0
                                                asked_to_leave: false,
1755
0
                                            },
1756
0
                                            substream_id,
1757
0
                                        ));
1758
0
                                    debug_assert!(_was_inserted);
1759
1760
0
                                    for other_protocol in
1761
0
                                        iter::once(NotificationsProtocol::Transactions {
1762
0
                                            chain_index,
1763
0
                                        })
1764
0
                                        .chain(
1765
0
                                            self.chains[chain_index]
1766
0
                                                .grandpa_protocol_config
1767
0
                                                .is_some()
1768
0
                                                .then(|| NotificationsProtocol::Grandpa {
1769
0
                                                    chain_index,
1770
0
                                                }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsf_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsf_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsf_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsf_0B1b_
1771
0
                                        )
1772
                                    {
1773
0
                                        if self
1774
0
                                            .notification_substreams_by_peer_id
1775
0
                                            .range(
1776
0
                                                (
1777
0
                                                    other_protocol,
1778
0
                                                    peer_index,
1779
0
                                                    SubstreamDirection::Out,
1780
0
                                                    NotificationsSubstreamState::MIN,
1781
0
                                                    SubstreamId::MIN,
1782
0
                                                )
1783
0
                                                    ..=(
1784
0
                                                        other_protocol,
1785
0
                                                        peer_index,
1786
0
                                                        SubstreamDirection::Out,
1787
0
                                                        NotificationsSubstreamState::MAX,
1788
0
                                                        SubstreamId::MAX,
1789
0
                                                    ),
1790
0
                                            )
1791
0
                                            .next()
1792
0
                                            .is_some()
1793
                                        {
1794
0
                                            continue;
1795
0
                                        }
1796
1797
0
                                        let new_substream_id = self.inner.open_out_notifications(
1798
0
                                            connection_id,
1799
0
                                            codec::encode_protocol_name_string(
1800
0
                                                match other_protocol {
1801
                                                    NotificationsProtocol::Transactions {
1802
0
                                                        chain_index,
1803
0
                                                    } => codec::ProtocolName::Transactions {
1804
0
                                                        genesis_hash: self.chains[chain_index]
1805
0
                                                            .genesis_hash,
1806
0
                                                        fork_id: self.chains[chain_index]
1807
0
                                                            .fork_id
1808
0
                                                            .as_deref(),
1809
0
                                                    },
1810
                                                    NotificationsProtocol::Grandpa {
1811
0
                                                        chain_index,
1812
0
                                                    } => codec::ProtocolName::Grandpa {
1813
0
                                                        genesis_hash: self.chains[chain_index]
1814
0
                                                            .genesis_hash,
1815
0
                                                        fork_id: self.chains[chain_index]
1816
0
                                                            .fork_id
1817
0
                                                            .as_deref(),
1818
0
                                                    },
1819
0
                                                    _ => unreachable!(),
1820
                                                },
1821
                                            ),
1822
0
                                            self.notifications_protocol_handshake_timeout(
1823
0
                                                other_protocol,
1824
0
                                            ),
1825
0
                                            self.notifications_protocol_handshake(other_protocol),
1826
0
                                            self.notifications_protocol_max_handshake_size(
1827
0
                                                other_protocol,
1828
0
                                            ),
1829
0
                                        );
1830
0
1831
0
                                        self.substreams.insert(
1832
0
                                            new_substream_id,
1833
0
                                            SubstreamInfo {
1834
0
                                                connection_id,
1835
0
                                                protocol: Some(Protocol::Notifications(
1836
0
                                                    other_protocol,
1837
0
                                                )),
1838
0
                                            },
1839
0
                                        );
1840
0
1841
0
                                        self.notification_substreams_by_peer_id.insert((
1842
0
                                            other_protocol,
1843
0
                                            peer_index,
1844
0
                                            SubstreamDirection::Out,
1845
0
                                            NotificationsSubstreamState::Pending,
1846
0
                                            new_substream_id,
1847
0
                                        ));
1848
                                    }
1849
1850
0
                                    return Some(Event::GossipConnected {
1851
0
                                        peer_id: self.peers[peer_index.0].clone(),
1852
0
                                        chain_id: ChainId(chain_index),
1853
0
                                        kind: GossipKind::ConsensusTransactions,
1854
0
                                        role: decoded_handshake.role,
1855
0
                                        best_number: decoded_handshake.best_number,
1856
0
                                        best_hash: *decoded_handshake.best_hash,
1857
0
                                    });
1858
                                }
1859
0
                                Err(error) => {
1860
0
                                    if self
1861
0
                                        .connections_by_peer_id
1862
0
                                        .range(
1863
0
                                            (peer_index, ConnectionId::MIN)
1864
0
                                                ..=(peer_index, ConnectionId::MIN),
1865
0
                                        )
1866
0
                                        .any(|(_, c)| {
1867
0
                                            let state = self.inner.connection_state(*c);
1868
0
                                            state.established && !state.shutting_down
1869
0
                                        })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsg_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsg_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsg_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsg_0B1b_
1870
0
                                        && self.gossip_desired_peers_by_chain.contains(&(
1871
0
                                            chain_index,
1872
0
                                            GossipKind::ConsensusTransactions,
1873
0
                                            peer_index,
1874
0
                                        ))
1875
                                    {
1876
0
                                        debug_assert!(self
1877
0
                                            .notification_substreams_by_peer_id
1878
0
                                            .range(
1879
0
                                                (
1880
0
                                                    NotificationsProtocol::BlockAnnounces {
1881
0
                                                        chain_index
1882
0
                                                    },
1883
0
                                                    peer_index,
1884
0
                                                    SubstreamDirection::Out,
1885
0
                                                    NotificationsSubstreamState::OPEN_MIN_VALUE,
1886
0
                                                    SubstreamId::MIN,
1887
0
                                                )
1888
0
                                                    ..=(
1889
0
                                                        NotificationsProtocol::BlockAnnounces {
1890
0
                                                            chain_index
1891
0
                                                        },
1892
0
                                                        peer_index,
1893
0
                                                        SubstreamDirection::Out,
1894
0
                                                        NotificationsSubstreamState::OPEN_MAX_VALUE,
1895
0
                                                        SubstreamId::MAX,
1896
0
                                                    ),
1897
0
                                            )
1898
0
                                            .next()
1899
0
                                            .is_none());
1900
1901
0
                                        self.connected_unopened_gossip_desired.insert((
1902
0
                                            peer_index,
1903
0
                                            ChainId(chain_index),
1904
0
                                            GossipKind::ConsensusTransactions,
1905
0
                                        ));
1906
0
                                    }
1907
1908
0
                                    self.opened_gossip_undesired.remove(&(
1909
0
                                        ChainId(chain_index),
1910
0
                                        peer_index,
1911
0
                                        GossipKind::ConsensusTransactions,
1912
0
                                    ));
1913
0
1914
0
                                    // TODO: pretty hacky
1915
0
                                    if let GossipConnectError::HandshakeDecode(_)
1916
0
                                    | GossipConnectError::GenesisMismatch { .. } = error
1917
0
                                    {
1918
0
                                        self.inner.close_out_notifications(substream_id);
1919
0
                                        self.substreams.remove(&substream_id).unwrap();
1920
0
                                    }
1921
1922
                                    // Close all the notification substreams of that chain.
1923
0
                                    for other_protocol in [
1924
0
                                        NotificationsProtocol::BlockAnnounces { chain_index },
1925
0
                                        NotificationsProtocol::Transactions { chain_index },
1926
0
                                        NotificationsProtocol::Grandpa { chain_index },
1927
                                    ] {
1928
0
                                        for (substream_id, direction, state) in self
1929
0
                                            .notification_substreams_by_peer_id
1930
0
                                            .range(
1931
0
                                                (
1932
0
                                                    other_protocol,
1933
0
                                                    peer_index,
1934
0
                                                    SubstreamDirection::MIN,
1935
0
                                                    NotificationsSubstreamState::MIN,
1936
0
                                                    SubstreamId::MIN,
1937
0
                                                )
1938
0
                                                    ..=(
1939
0
                                                        other_protocol,
1940
0
                                                        peer_index,
1941
0
                                                        SubstreamDirection::MAX,
1942
0
                                                        NotificationsSubstreamState::MAX,
1943
0
                                                        SubstreamId::MAX,
1944
0
                                                    ),
1945
0
                                            )
1946
0
                                            .map(|(_, _, dir, state, s)| (*s, *dir, *state))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsh_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsh_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsh_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsh_0B1b_
1947
0
                                            .collect::<Vec<_>>()
1948
                                        {
1949
0
                                            match (direction, state) {
1950
                                                (SubstreamDirection::Out, _) => {
1951
0
                                                    self.inner
1952
0
                                                        .close_out_notifications(substream_id);
1953
0
1954
0
                                                    let _was_in = self
1955
0
                                                        .notification_substreams_by_peer_id
1956
0
                                                        .remove(&(
1957
0
                                                            other_protocol,
1958
0
                                                            peer_index,
1959
0
                                                            direction,
1960
0
                                                            state,
1961
0
                                                            substream_id,
1962
0
                                                        ));
1963
0
                                                    debug_assert!(_was_in);
1964
0
                                                    let _was_in =
1965
0
                                                        self.substreams.remove(&substream_id);
1966
0
                                                    debug_assert!(_was_in.is_some());
1967
                                                }
1968
                                                (
1969
                                                    SubstreamDirection::In,
1970
                                                    NotificationsSubstreamState::Pending,
1971
                                                ) => {
1972
0
                                                    self.inner
1973
0
                                                        .reject_in_notifications(substream_id);
1974
0
1975
0
                                                    let _was_in = self
1976
0
                                                        .notification_substreams_by_peer_id
1977
0
                                                        .remove(&(
1978
0
                                                            other_protocol,
1979
0
                                                            peer_index,
1980
0
                                                            direction,
1981
0
                                                            state,
1982
0
                                                            substream_id,
1983
0
                                                        ));
1984
0
                                                    debug_assert!(_was_in);
1985
0
                                                    let _was_in =
1986
0
                                                        self.substreams.remove(&substream_id);
1987
0
                                                    debug_assert!(_was_in.is_some());
1988
                                                }
1989
                                                (
1990
                                                    SubstreamDirection::In,
1991
                                                    NotificationsSubstreamState::Open {
1992
                                                        asked_to_leave: false,
1993
                                                    },
1994
                                                ) => {
1995
0
                                                    self.inner.start_close_in_notifications(
1996
0
                                                        substream_id,
1997
0
                                                        Duration::from_secs(5),
1998
0
                                                    ); // TODO: arbitrary constant
1999
0
2000
0
                                                    let _was_removed = self
2001
0
                                                        .notification_substreams_by_peer_id
2002
0
                                                        .remove(&(
2003
0
                                                            other_protocol,
2004
0
                                                            peer_index,
2005
0
                                                            SubstreamDirection::In,
2006
0
                                                            NotificationsSubstreamState::Open {
2007
0
                                                                asked_to_leave: false,
2008
0
                                                            },
2009
0
                                                            substream_id,
2010
0
                                                        ));
2011
0
                                                    debug_assert!(_was_removed);
2012
0
                                                    let _was_inserted = self
2013
0
                                                        .notification_substreams_by_peer_id
2014
0
                                                        .insert((
2015
0
                                                            other_protocol,
2016
0
                                                            peer_index,
2017
0
                                                            SubstreamDirection::In,
2018
0
                                                            NotificationsSubstreamState::Open {
2019
0
                                                                asked_to_leave: true,
2020
0
                                                            },
2021
0
                                                            substream_id,
2022
0
                                                        ));
2023
0
                                                    debug_assert!(_was_inserted);
2024
                                                }
2025
                                                (
2026
                                                    SubstreamDirection::In,
2027
                                                    NotificationsSubstreamState::Open {
2028
                                                        asked_to_leave: true,
2029
                                                    },
2030
0
                                                ) => {
2031
0
                                                    // Nothing to do.
2032
0
                                                }
2033
                                            }
2034
                                        }
2035
                                    }
2036
2037
0
                                    return Some(Event::GossipOpenFailed {
2038
0
                                        peer_id: self.peers[peer_index.0].clone(),
2039
0
                                        chain_id: ChainId(chain_index),
2040
0
                                        kind: GossipKind::ConsensusTransactions,
2041
0
                                        error,
2042
0
                                    });
2043
                                }
2044
                            }
2045
                        }
2046
2047
0
                        NotificationsProtocol::Transactions { chain_index }
2048
0
                        | NotificationsProtocol::Grandpa { chain_index } => {
2049
                            // TODO: doesn't check the handshakes
2050
2051
                            // This can only happen if we have a block announces substream with
2052
                            // that peer, otherwise the substream opening attempt should have
2053
                            // been cancelled.
2054
0
                            debug_assert!(self
2055
0
                                .notification_substreams_by_peer_id
2056
0
                                .range(
2057
0
                                    (
2058
0
                                        NotificationsProtocol::BlockAnnounces { chain_index },
2059
0
                                        peer_index,
2060
0
                                        SubstreamDirection::Out,
2061
0
                                        NotificationsSubstreamState::OPEN_MIN_VALUE,
2062
0
                                        SubstreamId::MIN
2063
0
                                    )
2064
0
                                        ..=(
2065
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
2066
0
                                            peer_index,
2067
0
                                            SubstreamDirection::Out,
2068
0
                                            NotificationsSubstreamState::OPEN_MAX_VALUE,
2069
0
                                            SubstreamId::MAX
2070
0
                                        )
2071
0
                                )
2072
0
                                .next()
2073
0
                                .is_some());
2074
2075
                            // If the substream failed to open, we simply try again.
2076
                            // Trying again means that we might be hammering the remote with
2077
                            // substream requests, however as of the writing of this text this is
2078
                            // necessary in order to bypass an issue in Substrate.
2079
                            // Note that in the situation where the connection is shutting down,
2080
                            // we don't re-open the substream on a different connection, but
2081
                            // that's ok as the block announces substream should be closed soon.
2082
0
                            if result.is_err() {
2083
0
                                if self.inner.connection_state(connection_id).shutting_down {
2084
0
                                    continue;
2085
0
                                }
2086
2087
0
                                let new_substream_id = self.inner.open_out_notifications(
2088
0
                                    connection_id,
2089
0
                                    codec::encode_protocol_name_string(match substream_protocol {
2090
                                        NotificationsProtocol::Transactions { .. } => {
2091
0
                                            codec::ProtocolName::Transactions {
2092
0
                                                genesis_hash: self.chains[chain_index].genesis_hash,
2093
0
                                                fork_id: self.chains[chain_index]
2094
0
                                                    .fork_id
2095
0
                                                    .as_deref(),
2096
0
                                            }
2097
                                        }
2098
                                        NotificationsProtocol::Grandpa { .. } => {
2099
0
                                            codec::ProtocolName::Grandpa {
2100
0
                                                genesis_hash: self.chains[chain_index].genesis_hash,
2101
0
                                                fork_id: self.chains[chain_index]
2102
0
                                                    .fork_id
2103
0
                                                    .as_deref(),
2104
0
                                            }
2105
                                        }
2106
0
                                        _ => unreachable!(),
2107
                                    }),
2108
0
                                    self.notifications_protocol_handshake_timeout(
2109
0
                                        substream_protocol,
2110
0
                                    ),
2111
0
                                    self.notifications_protocol_handshake(substream_protocol),
2112
0
                                    self.notifications_protocol_max_handshake_size(
2113
0
                                        substream_protocol,
2114
0
                                    ),
2115
0
                                );
2116
0
                                let _was_inserted =
2117
0
                                    self.notification_substreams_by_peer_id.insert((
2118
0
                                        substream_protocol,
2119
0
                                        peer_index,
2120
0
                                        SubstreamDirection::Out,
2121
0
                                        NotificationsSubstreamState::Pending,
2122
0
                                        new_substream_id,
2123
0
                                    ));
2124
0
                                debug_assert!(_was_inserted);
2125
0
                                let _prev_value = self.substreams.insert(
2126
0
                                    new_substream_id,
2127
0
                                    SubstreamInfo {
2128
0
                                        connection_id,
2129
0
                                        protocol: substream_info.protocol,
2130
0
                                    },
2131
0
                                );
2132
0
                                debug_assert!(_prev_value.is_none());
2133
0
                                continue;
2134
0
                            }
2135
0
2136
0
                            let _was_inserted = self.notification_substreams_by_peer_id.insert((
2137
0
                                substream_protocol,
2138
0
                                peer_index,
2139
0
                                SubstreamDirection::Out,
2140
0
                                NotificationsSubstreamState::Open {
2141
0
                                    asked_to_leave: false,
2142
0
                                },
2143
0
                                substream_id,
2144
0
                            ));
2145
0
                            debug_assert!(_was_inserted);
2146
2147
                            // In case of Grandpa, we immediately send a neighbor packet with
2148
                            // the current local state.
2149
0
                            if matches!(substream_protocol, NotificationsProtocol::Grandpa { .. }) {
2150
0
                                let grandpa_state = &self.chains[chain_index]
2151
0
                                    .grandpa_protocol_config
2152
0
                                    .as_ref()
2153
0
                                    .unwrap();
2154
0
                                let packet = codec::GrandpaNotificationRef::Neighbor(
2155
0
                                    codec::NeighborPacket {
2156
0
                                        round_number: grandpa_state.round_number,
2157
0
                                        set_id: grandpa_state.set_id,
2158
0
                                        commit_finalized_height: grandpa_state
2159
0
                                            .commit_finalized_height,
2160
0
                                    },
2161
0
                                )
2162
0
                                .scale_encoding(self.chains[chain_index].block_number_bytes)
2163
0
                                .fold(Vec::new(), |mut a, b| {
2164
0
                                    a.extend_from_slice(b.as_ref());
2165
0
                                    a
2166
0
                                });
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsi_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsi_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsi_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsi_0B1b_
2167
0
                                match self.inner.queue_notification(substream_id, packet) {
2168
0
                                    Ok(()) => {}
2169
                                    Err(collection::QueueNotificationError::QueueFull) => {
2170
0
                                        unreachable!()
2171
                                    }
2172
                                }
2173
0
                            }
2174
                        }
2175
                    }
2176
                }
2177
2178
0
                collection::Event::NotificationsOutCloseDemanded { substream_id }
2179
0
                | collection::Event::NotificationsOutReset { substream_id } => {
2180
                    // Outgoing notifications substream has been closed or must be closed.
2181
                    // These two situations are handled together, as we immediately react to a
2182
                    // demanded closing by performing the closing. The rest of the code is thus
2183
                    // the same for both situations.
2184
2185
                    // If the request demands the closing, we immediately comply.
2186
0
                    if matches!(
2187
0
                        inner_event,
2188
                        collection::Event::NotificationsOutCloseDemanded { .. }
2189
0
                    ) {
2190
0
                        self.inner.close_out_notifications(substream_id);
2191
0
                    }
2192
2193
                    // Load various information about the substream and connection.
2194
0
                    let substream_info = self
2195
0
                        .substreams
2196
0
                        .remove(&substream_id)
2197
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsj_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsj_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsj_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsj_0B1b_
2198
0
                    let connection_id = substream_info.connection_id;
2199
0
                    let peer_index = *self.inner[connection_id]
2200
0
                        .peer_index
2201
0
                        .as_ref()
2202
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsk_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsk_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsk_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsk_0B1b_
2203
2204
                    // All outgoing substream attempts are cancelled when a chain is removed, as
2205
                    // such `protocol` can't be `None`.
2206
0
                    let Some(Protocol::Notifications(substream_protocol)) = substream_info.protocol
2207
                    else {
2208
0
                        unreachable!();
2209
                    };
2210
2211
                    // Clean up the local state.
2212
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
2213
0
                        substream_protocol,
2214
0
                        peer_index,
2215
0
                        SubstreamDirection::Out,
2216
0
                        NotificationsSubstreamState::Open {
2217
0
                            asked_to_leave: false,
2218
0
                        },
2219
0
                        substream_id,
2220
0
                    ));
2221
0
                    debug_assert!(_was_in);
2222
2223
                    // Rest of the code depends on the protocol.
2224
0
                    match substream_protocol {
2225
0
                        NotificationsProtocol::BlockAnnounces { chain_index } => {
2226
0
                            self.opened_gossip_undesired.remove(&(
2227
0
                                ChainId(chain_index),
2228
0
                                peer_index,
2229
0
                                GossipKind::ConsensusTransactions,
2230
0
                            ));
2231
0
2232
0
                            // Insert back in `connected_unopened_gossip_desired` if relevant.
2233
0
                            if self.gossip_desired_peers_by_chain.contains(&(
2234
0
                                chain_index,
2235
0
                                GossipKind::ConsensusTransactions,
2236
0
                                peer_index,
2237
0
                            )) && self
2238
0
                                .connections_by_peer_id
2239
0
                                .range(
2240
0
                                    (peer_index, ConnectionId::MIN)
2241
0
                                        ..=(peer_index, ConnectionId::MAX),
2242
0
                                )
2243
0
                                .any(|(_, connection_id)| {
2244
0
                                    let state = self.inner.connection_state(*connection_id);
2245
0
                                    state.established && !state.shutting_down
2246
0
                                })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsl_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsl_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsl_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsl_0B1b_
2247
                            {
2248
0
                                debug_assert!(self
2249
0
                                    .notification_substreams_by_peer_id
2250
0
                                    .range(
2251
0
                                        (
2252
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
2253
0
                                            peer_index,
2254
0
                                            SubstreamDirection::Out,
2255
0
                                            NotificationsSubstreamState::MIN,
2256
0
                                            SubstreamId::MIN,
2257
0
                                        )
2258
0
                                            ..=(
2259
0
                                                NotificationsProtocol::BlockAnnounces {
2260
0
                                                    chain_index
2261
0
                                                },
2262
0
                                                peer_index,
2263
0
                                                SubstreamDirection::Out,
2264
0
                                                NotificationsSubstreamState::MAX,
2265
0
                                                SubstreamId::MAX,
2266
0
                                            ),
2267
0
                                    )
2268
0
                                    .next()
2269
0
                                    .is_none());
2270
2271
0
                                let _was_inserted =
2272
0
                                    self.connected_unopened_gossip_desired.insert((
2273
0
                                        peer_index,
2274
0
                                        ChainId(chain_index),
2275
0
                                        GossipKind::ConsensusTransactions,
2276
0
                                    ));
2277
0
                                debug_assert!(_was_inserted);
2278
0
                            }
2279
2280
                            // The transactions and Grandpa protocols are tied to the block
2281
                            // announces substream. As such, we also close any transactions or
2282
                            // grandpa substream, either pending or fully opened.
2283
0
                            for proto in [
2284
0
                                NotificationsProtocol::Transactions { chain_index },
2285
0
                                NotificationsProtocol::Grandpa { chain_index },
2286
                            ] {
2287
0
                                for (substream_direction, substream_state, substream_id) in self
2288
0
                                    .notification_substreams_by_peer_id
2289
0
                                    .range(
2290
0
                                        (
2291
0
                                            proto,
2292
0
                                            peer_index,
2293
0
                                            SubstreamDirection::MIN,
2294
0
                                            NotificationsSubstreamState::MIN,
2295
0
                                            SubstreamId::MIN,
2296
0
                                        )
2297
0
                                            ..=(
2298
0
                                                proto,
2299
0
                                                peer_index,
2300
0
                                                SubstreamDirection::MAX,
2301
0
                                                NotificationsSubstreamState::MAX,
2302
0
                                                SubstreamId::MAX,
2303
0
                                            ),
2304
0
                                    )
2305
0
                                    .map(|(_, _, direction, state, substream_id)| {
2306
0
                                        (*direction, *state, *substream_id)
2307
0
                                    })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsm_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsm_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsm_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsm_0B1b_
2308
0
                                    .collect::<Vec<_>>()
2309
                                {
2310
0
                                    match (substream_direction, substream_state) {
2311
                                        (SubstreamDirection::Out, _) => {
2312
0
                                            self.inner.close_out_notifications(substream_id);
2313
0
                                            let _was_removed =
2314
0
                                                self.notification_substreams_by_peer_id.remove(&(
2315
0
                                                    proto,
2316
0
                                                    peer_index,
2317
0
                                                    SubstreamDirection::Out,
2318
0
                                                    substream_state,
2319
0
                                                    substream_id,
2320
0
                                                ));
2321
0
                                            debug_assert!(_was_removed);
2322
0
                                            self.substreams.remove(&substream_id);
2323
                                        }
2324
                                        (
2325
                                            SubstreamDirection::In,
2326
                                            NotificationsSubstreamState::Pending,
2327
                                        ) => {
2328
                                            // Inbound notification substreams are always accepted
2329
                                            // or rejected immediately when a gossip link is open.
2330
0
                                            unreachable!()
2331
                                        }
2332
                                        (
2333
                                            SubstreamDirection::In,
2334
                                            NotificationsSubstreamState::Open {
2335
                                                asked_to_leave: true,
2336
                                            },
2337
0
                                        ) => {
2338
0
                                            // Nothing to do.
2339
0
                                        }
2340
                                        (
2341
                                            SubstreamDirection::In,
2342
                                            NotificationsSubstreamState::Open {
2343
                                                asked_to_leave: false,
2344
                                            },
2345
                                        ) => {
2346
0
                                            self.inner.start_close_in_notifications(
2347
0
                                                substream_id,
2348
0
                                                Duration::from_secs(5), // TODO: arbitrary constant
2349
0
                                            );
2350
0
                                            let _was_removed =
2351
0
                                                self.notification_substreams_by_peer_id.remove(&(
2352
0
                                                    proto,
2353
0
                                                    peer_index,
2354
0
                                                    SubstreamDirection::In,
2355
0
                                                    NotificationsSubstreamState::Open {
2356
0
                                                        asked_to_leave: false,
2357
0
                                                    },
2358
0
                                                    substream_id,
2359
0
                                                ));
2360
0
                                            debug_assert!(_was_removed);
2361
0
                                            let _was_inserted =
2362
0
                                                self.notification_substreams_by_peer_id.insert((
2363
0
                                                    proto,
2364
0
                                                    peer_index,
2365
0
                                                    SubstreamDirection::In,
2366
0
                                                    NotificationsSubstreamState::Open {
2367
0
                                                        asked_to_leave: true,
2368
0
                                                    },
2369
0
                                                    substream_id,
2370
0
                                                ));
2371
0
                                            debug_assert!(_was_inserted);
2372
                                        }
2373
                                    }
2374
                                }
2375
                            }
2376
2377
0
                            return Some(Event::GossipDisconnected {
2378
0
                                peer_id: self.peers[peer_index.0].clone(),
2379
0
                                chain_id: ChainId(chain_index),
2380
0
                                kind: GossipKind::ConsensusTransactions,
2381
0
                            });
2382
                        }
2383
2384
                        // The transactions and grandpa protocols are tied to the block announces
2385
                        // substream. If there is a block announce substream with the peer, we try
2386
                        // to reopen these two substreams.
2387
                        NotificationsProtocol::Transactions { .. }
2388
                        | NotificationsProtocol::Grandpa { .. } => {
2389
                            // Don't actually try to reopen if the connection is shutting down.
2390
                            // Note that we don't try to reopen on a different connection, as the
2391
                            // block announces substream will very soon be closed too anyway.
2392
0
                            if self.inner.connection_state(connection_id).shutting_down {
2393
0
                                continue;
2394
0
                            }
2395
2396
0
                            let new_substream_id = self.inner.open_out_notifications(
2397
0
                                connection_id,
2398
0
                                codec::encode_protocol_name_string(match substream_protocol {
2399
0
                                    NotificationsProtocol::Transactions { chain_index } => {
2400
0
                                        codec::ProtocolName::Transactions {
2401
0
                                            genesis_hash: self.chains[chain_index].genesis_hash,
2402
0
                                            fork_id: self.chains[chain_index].fork_id.as_deref(),
2403
0
                                        }
2404
                                    }
2405
0
                                    NotificationsProtocol::Grandpa { chain_index } => {
2406
0
                                        codec::ProtocolName::Grandpa {
2407
0
                                            genesis_hash: self.chains[chain_index].genesis_hash,
2408
0
                                            fork_id: self.chains[chain_index].fork_id.as_deref(),
2409
0
                                        }
2410
                                    }
2411
0
                                    _ => unreachable!(),
2412
                                }),
2413
0
                                self.notifications_protocol_handshake_timeout(substream_protocol),
2414
0
                                self.notifications_protocol_handshake(substream_protocol),
2415
0
                                self.notifications_protocol_max_handshake_size(substream_protocol),
2416
0
                            );
2417
0
                            self.substreams.insert(
2418
0
                                new_substream_id,
2419
0
                                SubstreamInfo {
2420
0
                                    connection_id,
2421
0
                                    protocol: Some(Protocol::Notifications(substream_protocol)),
2422
0
                                },
2423
0
                            );
2424
0
                            self.notification_substreams_by_peer_id.insert((
2425
0
                                substream_protocol,
2426
0
                                peer_index,
2427
0
                                SubstreamDirection::Out,
2428
0
                                NotificationsSubstreamState::Pending,
2429
0
                                new_substream_id,
2430
0
                            ));
2431
                        }
2432
                    }
2433
                }
2434
2435
0
                collection::Event::NotificationsInOpen { substream_id, .. } => {
2436
0
                    // Remote would like to open a notifications substream with us.
2437
0
2438
0
                    // There exists three possible ways to handle this event:
2439
0
                    //
2440
0
                    // - Accept the demand immediately. This happens if the API user has opened
2441
0
                    //   a gossip substream in the past or is currently trying to open a gossip
2442
0
                    //   substream with this peer.
2443
0
                    // - Refuse the demand immediately. This happens if there already exists a
2444
0
                    //   pending inbound notifications substream. Opening multiple notification
2445
0
                    //   substreams of the same protocol is a protocol violation. This also happens
2446
0
                    //   for transactions and grandpa substreams if no block announce substream is
2447
0
                    //   open.
2448
0
                    // - Generate an event to ask the API user whether to accept the demand. This
2449
0
                    //   happens specifically for block announce substreams.
2450
0
2451
0
                    // Extract various bits of information about the substream.
2452
0
                    // Instantly reject the substream if it concerns a chain that has since then
2453
0
                    // been removed from `self`, which can happen if the protocol name was already
2454
0
                    // negotiated when the chain was removed.
2455
0
                    let substream_info = self
2456
0
                        .substreams
2457
0
                        .get(&substream_id)
2458
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsn_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsn_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsn_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsn_0B1b_
2459
0
                    let peer_index = *self.inner[substream_info.connection_id]
2460
0
                        .peer_index
2461
0
                        .as_ref()
2462
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventso_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventso_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventso_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventso_0B1b_
2463
0
                    let Some(substream_protocol) = substream_info.protocol else {
2464
0
                        self.inner.reject_in_notifications(substream_id);
2465
0
                        self.substreams.remove(&substream_id);
2466
0
                        continue;
2467
                    };
2468
0
                    let Protocol::Notifications(substream_protocol) = substream_protocol else {
2469
0
                        unreachable!()
2470
                    };
2471
0
                    let (NotificationsProtocol::BlockAnnounces { chain_index }
2472
0
                    | NotificationsProtocol::Transactions { chain_index }
2473
0
                    | NotificationsProtocol::Grandpa { chain_index }) = substream_protocol;
2474
2475
                    // Check whether a substream with the same protocol already exists with that
2476
                    // peer, and if so deny the request.
2477
                    // Note that substreams with `asked_to_leave` equal to `true` are ignored when
2478
                    // searching, as in this case it's not a protocol violation.
2479
0
                    if self
2480
0
                        .notification_substreams_by_peer_id
2481
0
                        .range(
2482
0
                            (
2483
0
                                substream_protocol,
2484
0
                                peer_index,
2485
0
                                SubstreamDirection::In,
2486
0
                                NotificationsSubstreamState::MIN,
2487
0
                                SubstreamId::MIN,
2488
0
                            )
2489
0
                                ..(
2490
0
                                    substream_protocol,
2491
0
                                    peer_index,
2492
0
                                    SubstreamDirection::In,
2493
0
                                    NotificationsSubstreamState::Open {
2494
0
                                        asked_to_leave: true,
2495
0
                                    },
2496
0
                                    SubstreamId::MIN,
2497
0
                                ),
2498
0
                        )
2499
0
                        .next()
2500
0
                        .is_some()
2501
                    {
2502
0
                        self.inner.reject_in_notifications(substream_id);
2503
0
                        let _was_removed = self.substreams.remove(&substream_id);
2504
0
                        debug_assert!(_was_removed.is_some());
2505
0
                        continue;
2506
0
                    }
2507
0
2508
0
                    // If an outgoing block announces notifications protocol (either pending or
2509
0
                    // fully open) exists, accept the substream immediately.
2510
0
                    if self
2511
0
                        .notification_substreams_by_peer_id
2512
0
                        .range(
2513
0
                            (
2514
0
                                NotificationsProtocol::BlockAnnounces { chain_index },
2515
0
                                peer_index,
2516
0
                                SubstreamDirection::Out,
2517
0
                                NotificationsSubstreamState::MIN,
2518
0
                                SubstreamId::MIN,
2519
0
                            )
2520
0
                                ..=(
2521
0
                                    NotificationsProtocol::BlockAnnounces { chain_index },
2522
0
                                    peer_index,
2523
0
                                    SubstreamDirection::Out,
2524
0
                                    NotificationsSubstreamState::MAX,
2525
0
                                    SubstreamId::MAX,
2526
0
                                ),
2527
0
                        )
2528
0
                        .next()
2529
0
                        .is_some()
2530
                    {
2531
0
                        let _was_inserted = self.notification_substreams_by_peer_id.insert((
2532
0
                            substream_protocol,
2533
0
                            peer_index,
2534
0
                            SubstreamDirection::In,
2535
0
                            NotificationsSubstreamState::Open {
2536
0
                                asked_to_leave: false,
2537
0
                            },
2538
0
                            substream_id,
2539
0
                        ));
2540
0
                        debug_assert!(_was_inserted);
2541
0
                        self.inner.accept_in_notifications(
2542
0
                            substream_id,
2543
0
                            self.notifications_protocol_handshake(substream_protocol),
2544
0
                            self.notifications_protocol_max_notification_size(substream_protocol),
2545
0
                        );
2546
0
                        continue;
2547
0
                    }
2548
2549
                    // It is forbidden to cold-open a substream other than the block announces
2550
                    // substream.
2551
0
                    if !matches!(
2552
0
                        substream_protocol,
2553
                        NotificationsProtocol::BlockAnnounces { .. }
2554
                    ) {
2555
0
                        self.inner.reject_in_notifications(substream_id);
2556
0
                        let _was_removed = self.substreams.remove(&substream_id);
2557
0
                        debug_assert!(_was_removed.is_some());
2558
0
                        continue;
2559
0
                    }
2560
0
2561
0
                    // Update the local state and return the event.
2562
0
                    debug_assert!(matches!(
2563
0
                        substream_protocol,
2564
                        NotificationsProtocol::BlockAnnounces { .. }
2565
                    ));
2566
0
                    self.notification_substreams_by_peer_id.insert((
2567
0
                        substream_protocol,
2568
0
                        peer_index,
2569
0
                        SubstreamDirection::In,
2570
0
                        NotificationsSubstreamState::Pending,
2571
0
                        substream_id,
2572
0
                    ));
2573
0
                    return Some(Event::GossipInDesired {
2574
0
                        peer_id: self.peers[peer_index.0].clone(),
2575
0
                        chain_id: ChainId(chain_index),
2576
0
                        kind: GossipKind::ConsensusTransactions,
2577
0
                    });
2578
                }
2579
2580
0
                collection::Event::NotificationsInOpenCancel { substream_id } => {
2581
0
                    // Remote has cancelled a pending `NotificationsInOpen`.
2582
0
2583
0
                    let substream_info = self
2584
0
                        .substreams
2585
0
                        .remove(&substream_id)
2586
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsp_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsp_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsp_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsp_0B1b_
2587
0
                    let peer_index = *self.inner[substream_info.connection_id]
2588
0
                        .peer_index
2589
0
                        .as_ref()
2590
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsq_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsq_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsq_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsq_0B1b_
2591
2592
                    // All incoming notification substreams are immediately accepted/rejected
2593
                    // except for block announce substreams. Additionally, when a chain is removed,
2594
                    // all its pending block announce substreams are rejected. Therefore, this
2595
                    // event can only happen for block announce substreams.
2596
                    let Some(Protocol::Notifications(NotificationsProtocol::BlockAnnounces {
2597
0
                        chain_index,
2598
0
                    })) = substream_info.protocol
2599
                    else {
2600
0
                        unreachable!()
2601
                    };
2602
2603
                    // Clean up the local state.
2604
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
2605
0
                        NotificationsProtocol::BlockAnnounces { chain_index },
2606
0
                        peer_index,
2607
0
                        SubstreamDirection::In,
2608
0
                        NotificationsSubstreamState::Pending,
2609
0
                        substream_id,
2610
0
                    ));
2611
0
                    debug_assert!(_was_in);
2612
2613
                    // Notify API user.
2614
0
                    return Some(Event::GossipInDesiredCancel {
2615
0
                        peer_id: self.peers[peer_index.0].clone(),
2616
0
                        chain_id: ChainId(chain_index),
2617
0
                        kind: GossipKind::ConsensusTransactions,
2618
0
                    });
2619
                }
2620
2621
                collection::Event::NotificationsIn {
2622
0
                    substream_id,
2623
0
                    notification,
2624
0
                } => {
2625
0
                    // Received a notification from a remote.
2626
0
                    let substream_info = self
2627
0
                        .substreams
2628
0
                        .get(&substream_id)
2629
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsr_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventsr_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventsr_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventsr_0B1b_
2630
0
                    let substream_protocol = match substream_info.protocol {
2631
                        None => {
2632
                            // Substream concerns a chain that has been removed.
2633
                            // Ignore the notification.
2634
0
                            continue;
2635
                        }
2636
0
                        Some(Protocol::Notifications(p)) => p,
2637
0
                        Some(_) => unreachable!(),
2638
                    };
2639
0
                    let (NotificationsProtocol::BlockAnnounces { chain_index }
2640
0
                    | NotificationsProtocol::Transactions { chain_index }
2641
0
                    | NotificationsProtocol::Grandpa { chain_index }) = substream_protocol;
2642
0
                    let peer_index = *self.inner[substream_info.connection_id]
2643
0
                        .peer_index
2644
0
                        .as_ref()
2645
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventss_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventss_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventss_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventss_0B1b_
2646
0
2647
0
                    // Check whether there is an open outgoing block announces substream, as this
2648
0
                    // means that we are "gossip-connected". If not, then the notification is
2649
0
                    // silently discarded.
2650
0
                    if self
2651
0
                        .notification_substreams_by_peer_id
2652
0
                        .range(
2653
0
                            (
2654
0
                                NotificationsProtocol::BlockAnnounces { chain_index },
2655
0
                                peer_index,
2656
0
                                SubstreamDirection::Out,
2657
0
                                NotificationsSubstreamState::OPEN_MIN_VALUE,
2658
0
                                collection::SubstreamId::MIN,
2659
0
                            )
2660
0
                                ..=(
2661
0
                                    NotificationsProtocol::BlockAnnounces { chain_index },
2662
0
                                    peer_index,
2663
0
                                    SubstreamDirection::Out,
2664
0
                                    NotificationsSubstreamState::OPEN_MAX_VALUE,
2665
0
                                    collection::SubstreamId::MAX,
2666
0
                                ),
2667
0
                        )
2668
0
                        .next()
2669
0
                        .is_none()
2670
                    {
2671
0
                        continue;
2672
0
                    }
2673
0
2674
0
                    // Decode the notification and return an event.
2675
0
                    match substream_protocol {
2676
                        NotificationsProtocol::BlockAnnounces { .. } => {
2677
0
                            if let Err(err) = codec::decode_block_announce(
2678
0
                                &notification,
2679
0
                                self.chains[chain_index].block_number_bytes,
2680
0
                            ) {
2681
0
                                return Some(Event::ProtocolError {
2682
0
                                    error: ProtocolError::BadBlockAnnounce(err),
2683
0
                                    peer_id: self.peers[peer_index.0].clone(),
2684
0
                                });
2685
0
                            }
2686
0
2687
0
                            return Some(Event::BlockAnnounce {
2688
0
                                chain_id: ChainId(chain_index),
2689
0
                                peer_id: self.peers[peer_index.0].clone(),
2690
0
                                announce: EncodedBlockAnnounce {
2691
0
                                    message: notification,
2692
0
                                    block_number_bytes: self.chains[chain_index].block_number_bytes,
2693
0
                                },
2694
0
                            });
2695
                        }
2696
0
                        NotificationsProtocol::Transactions { .. } => {
2697
0
                            // TODO: not implemented
2698
0
                        }
2699
                        NotificationsProtocol::Grandpa { .. } => {
2700
0
                            let decoded_notif = match codec::decode_grandpa_notification(
2701
0
                                &notification,
2702
0
                                self.chains[chain_index].block_number_bytes,
2703
0
                            ) {
2704
0
                                Ok(n) => n,
2705
0
                                Err(err) => {
2706
0
                                    return Some(Event::ProtocolError {
2707
0
                                        error: ProtocolError::BadGrandpaNotification(err),
2708
0
                                        peer_id: self.peers[peer_index.0].clone(),
2709
0
                                    })
2710
                                }
2711
                            };
2712
2713
0
                            match decoded_notif {
2714
                                codec::GrandpaNotificationRef::Commit(_) => {
2715
0
                                    return Some(Event::GrandpaCommitMessage {
2716
0
                                        chain_id: ChainId(chain_index),
2717
0
                                        peer_id: self.peers[peer_index.0].clone(),
2718
0
                                        message: EncodedGrandpaCommitMessage {
2719
0
                                            message: notification,
2720
0
                                            block_number_bytes: self.chains[chain_index]
2721
0
                                                .block_number_bytes,
2722
0
                                        },
2723
0
                                    })
2724
                                }
2725
0
                                codec::GrandpaNotificationRef::Neighbor(n) => {
2726
0
                                    return Some(Event::GrandpaNeighborPacket {
2727
0
                                        chain_id: ChainId(chain_index),
2728
0
                                        peer_id: self.peers[peer_index.0].clone(),
2729
0
                                        state: GrandpaState {
2730
0
                                            round_number: n.round_number,
2731
0
                                            set_id: n.set_id,
2732
0
                                            commit_finalized_height: n.commit_finalized_height,
2733
0
                                        },
2734
0
                                    })
2735
                                }
2736
0
                                _ => {
2737
0
                                    // Any other type of message is currently ignored. Support
2738
0
                                    // for them could be added in the future.
2739
0
                                }
2740
                            }
2741
                        }
2742
                    }
2743
                }
2744
2745
0
                collection::Event::NotificationsInClose { substream_id, .. } => {
2746
                    // An incoming notifications substream has been closed.
2747
                    // Nothing to do except clean up the local state.
2748
0
                    let Some(substream_info) = self.substreams.remove(&substream_id) else {
2749
0
                        unreachable!()
2750
                    };
2751
0
                    let peer_index = *self.inner[substream_info.connection_id]
2752
0
                        .peer_index
2753
0
                        .as_ref()
2754
0
                        .unwrap_or_else(|| unreachable!());
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventst_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventst_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE10next_eventst_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventst_0B1b_
2755
0
                    let Some(protocol) = substream_info.protocol else {
2756
                        // Substream concerns a chain that has since then been removed.
2757
0
                        continue;
2758
                    };
2759
0
                    let Protocol::Notifications(protocol) = protocol else {
2760
0
                        unreachable!()
2761
                    };
2762
2763
                    // Clean up with both `asked_to_leave` equal to `true` or `false`, as we don't
2764
                    // know in which of the two the substream is.
2765
0
                    let _was_in1 = self.notification_substreams_by_peer_id.remove(&(
2766
0
                        protocol,
2767
0
                        peer_index,
2768
0
                        SubstreamDirection::In,
2769
0
                        NotificationsSubstreamState::Open {
2770
0
                            asked_to_leave: false,
2771
0
                        },
2772
0
                        substream_id,
2773
0
                    ));
2774
0
                    let _was_in2 = self.notification_substreams_by_peer_id.remove(&(
2775
0
                        protocol,
2776
0
                        peer_index,
2777
0
                        SubstreamDirection::In,
2778
0
                        NotificationsSubstreamState::Open {
2779
0
                            asked_to_leave: true,
2780
0
                        },
2781
0
                        substream_id,
2782
0
                    ));
2783
0
                    debug_assert!(_was_in1 || _was_in2);
2784
                }
2785
2786
0
                collection::Event::PingOutSuccess { id, ping_time } => {
2787
                    // The connection is necessarily past its handshake phase, and thus
2788
                    // the `peer_index` is necessarily known and valid.
2789
0
                    let Some(peer_index) = self.inner[id].peer_index else {
2790
0
                        unreachable!()
2791
                    };
2792
0
                    return Some(Event::PingOutSuccess {
2793
0
                        id,
2794
0
                        peer_id: self.peers[peer_index.0].clone(),
2795
0
                        ping_time,
2796
0
                    });
2797
                }
2798
            }
2799
        }
2800
147
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE10next_eventB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE10next_eventB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE10next_eventB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE10next_eventB19_
Line
Count
Source
1139
147
    pub fn next_event(&mut self) -> Option<Event<TConn>> {
1140
        loop {
1141
147
            let 
inner_event0
= self.inner.next_event()?;
1142
0
            match inner_event {
1143
                collection::Event::HandshakeFinished {
1144
0
                    id,
1145
0
                    peer_id: actual_peer_id,
1146
0
                } => {
1147
0
                    // A handshaking connection has finished its handshake. We must update `self`
1148
0
                    // and return an event.
1149
0
                    // What makes this a bit complicated is the possibility that the actual PeerId
1150
0
                    // might not be the same as the one that was expected.
1151
0
1152
0
                    let actual_peer_index = self.peer_index_or_insert(actual_peer_id);
1153
0
                    let expected_peer_index = self.inner[id].peer_index;
1154
1155
0
                    match expected_peer_index {
1156
0
                        None => {
1157
0
                            // The connection didn't have any expected PeerId.
1158
0
                            self.inner[id].peer_index = Some(actual_peer_index);
1159
0
                            self.unconnected_desired.remove(&actual_peer_index);
1160
0
                        }
1161
0
                        Some(expected_peer_index) if expected_peer_index != actual_peer_index => {
1162
0
                            // The actual PeerId doesn't match the expected PeerId.
1163
0
1164
0
                            // Update the connection owner.
1165
0
                            self.inner[id].peer_index = Some(actual_peer_index);
1166
0
                            let _was_removed = self
1167
0
                                .connections_by_peer_id
1168
0
                                .remove(&(expected_peer_index, id));
1169
0
                            debug_assert!(_was_removed);
1170
0
                            let _was_inserted =
1171
0
                                self.connections_by_peer_id.insert((actual_peer_index, id));
1172
0
                            debug_assert!(_was_inserted);
1173
1174
                            // Update `unconnected_desired`.
1175
0
                            self.unconnected_desired.remove(&actual_peer_index);
1176
0
                            if self
1177
0
                                .gossip_desired_peers
1178
0
                                .range(
1179
0
                                    (
1180
0
                                        expected_peer_index,
1181
0
                                        GossipKind::ConsensusTransactions,
1182
0
                                        usize::MIN,
1183
0
                                    )
1184
0
                                        ..=(
1185
0
                                            expected_peer_index,
1186
0
                                            GossipKind::ConsensusTransactions,
1187
0
                                            usize::MAX,
1188
0
                                        ),
1189
0
                                )
1190
0
                                .next()
1191
0
                                .is_some()
1192
0
                                && !self
1193
0
                                    .connections_by_peer_id
1194
0
                                    .range(
1195
0
                                        (expected_peer_index, ConnectionId::MIN)
1196
0
                                            ..=(expected_peer_index, ConnectionId::MAX),
1197
0
                                    )
1198
0
                                    .any(|(_, connection_id)| {
1199
                                        let state = self.inner.connection_state(*connection_id);
1200
                                        !state.shutting_down
1201
0
                                    })
1202
                            {
1203
0
                                let _was_inserted =
1204
0
                                    self.unconnected_desired.insert(expected_peer_index);
1205
0
                                debug_assert!(_was_inserted);
1206
0
                            }
1207
                        }
1208
                        _ => {
1209
                            // Expected matches actual.
1210
0
                            debug_assert_eq!(expected_peer_index, Some(actual_peer_index));
1211
                        }
1212
                    }
1213
1214
                    // TODO: limit the number of connections per peer?
1215
1216
                    // Insert the new connection in `self.connected_unopened_gossip_desired`
1217
                    // if relevant.
1218
0
                    for (_, _, chain_id) in self.gossip_desired_peers.range(
1219
0
                        (
1220
0
                            actual_peer_index,
1221
0
                            GossipKind::ConsensusTransactions,
1222
0
                            usize::MIN,
1223
0
                        )
1224
0
                            ..=(
1225
0
                                actual_peer_index,
1226
0
                                GossipKind::ConsensusTransactions,
1227
0
                                usize::MAX,
1228
0
                            ),
1229
0
                    ) {
1230
0
                        if self
1231
0
                            .notification_substreams_by_peer_id
1232
0
                            .range(
1233
0
                                (
1234
0
                                    NotificationsProtocol::BlockAnnounces {
1235
0
                                        chain_index: *chain_id,
1236
0
                                    },
1237
0
                                    actual_peer_index,
1238
0
                                    SubstreamDirection::Out,
1239
0
                                    NotificationsSubstreamState::MIN,
1240
0
                                    SubstreamId::MIN,
1241
0
                                )
1242
0
                                    ..=(
1243
0
                                        NotificationsProtocol::BlockAnnounces {
1244
0
                                            chain_index: *chain_id,
1245
0
                                        },
1246
0
                                        actual_peer_index,
1247
0
                                        SubstreamDirection::Out,
1248
0
                                        NotificationsSubstreamState::MAX,
1249
0
                                        SubstreamId::MAX,
1250
0
                                    ),
1251
0
                            )
1252
0
                            .next()
1253
0
                            .is_none()
1254
0
                        {
1255
0
                            self.connected_unopened_gossip_desired.insert((
1256
0
                                actual_peer_index,
1257
0
                                ChainId(*chain_id),
1258
0
                                GossipKind::ConsensusTransactions,
1259
0
                            ));
1260
0
                        }
1261
                    }
1262
1263
                    // Try to clean up the expected peer index.
1264
                    // This is done at the very end so that `self` is in a coherent state.
1265
0
                    let expected_peer_id = expected_peer_index.map(|idx| self.peers[idx.0].clone());
1266
0
                    if let Some(expected_peer_index) = expected_peer_index {
1267
0
                        if expected_peer_index != actual_peer_index {
1268
0
                            self.try_clean_up_peer(expected_peer_index);
1269
0
                        }
1270
0
                    }
1271
1272
                    // Small sanity check.
1273
0
                    debug_assert!(!self.unconnected_desired.contains(&actual_peer_index));
1274
1275
0
                    return Some(Event::HandshakeFinished {
1276
0
                        id,
1277
0
                        expected_peer_id,
1278
0
                        peer_id: self.peers[actual_peer_index.0].clone(),
1279
0
                    });
1280
                }
1281
1282
0
                collection::Event::PingOutFailed { id }
1283
0
                | collection::Event::StartShutdown { id, .. } => {
1284
                    // A connection has started its shutdown, or must start its shutdown.
1285
1286
                    // We handle a ping failure the same way as a shutdown start, as we react to
1287
                    // a ping failure by starting the shutdown of the connection. Thus, the clean
1288
                    // up phase is the same in both cases.
1289
0
                    if let collection::Event::PingOutFailed { .. } = inner_event {
1290
0
                        self.inner.start_shutdown(id);
1291
0
                    }
1292
1293
                    // TODO: IMPORTANT this event should be turned into `NewOutboundSubstreamsForbidden` and the `reason` removed; see <https://github.com/smol-dot/smoldot/pull/391>
1294
1295
                    // Nothing more to do if the connection is inbound and handshaking.
1296
0
                    let Some(peer_index) = self.inner[id].peer_index else {
1297
0
                        debug_assert!(!self.inner.connection_state(id).established);
1298
0
                        continue;
1299
                    };
1300
1301
                    // If peer is desired, and we have no connection or only shutting down
1302
                    // connections, add peer to `unconnected_desired` and remove it from
1303
                    // `connected_unopened_gossip_desired`.
1304
0
                    if self
1305
0
                        .gossip_desired_peers
1306
0
                        .range(
1307
0
                            (peer_index, GossipKind::ConsensusTransactions, usize::MIN)
1308
0
                                ..=(peer_index, GossipKind::ConsensusTransactions, usize::MAX),
1309
0
                        )
1310
0
                        .count()
1311
0
                        != 0
1312
                    {
1313
0
                        if !self
1314
0
                            .connections_by_peer_id
1315
0
                            .range(
1316
0
                                (peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX),
1317
0
                            )
1318
0
                            .any(|(_, connection_id)| {
1319
                                let state = self.inner.connection_state(*connection_id);
1320
                                !state.shutting_down
1321
0
                            })
1322
0
                        {
1323
0
                            self.unconnected_desired.insert(peer_index);
1324
0
                        }
1325
0
                        if !self
1326
0
                            .connections_by_peer_id
1327
0
                            .range(
1328
0
                                (peer_index, ConnectionId::MIN)..=(peer_index, ConnectionId::MAX),
1329
0
                            )
1330
0
                            .any(|(_, connection_id)| {
1331
                                let state = self.inner.connection_state(*connection_id);
1332
                                state.established && !state.shutting_down
1333
0
                            })
1334
                        {
1335
0
                            for (_, _, chain_index) in self.gossip_desired_peers.range(
1336
0
                                (peer_index, GossipKind::ConsensusTransactions, usize::MIN)
1337
0
                                    ..=(peer_index, GossipKind::ConsensusTransactions, usize::MAX),
1338
0
                            ) {
1339
0
                                self.connected_unopened_gossip_desired.remove(&(
1340
0
                                    peer_index,
1341
0
                                    ChainId(*chain_index),
1342
0
                                    GossipKind::ConsensusTransactions,
1343
0
                                ));
1344
0
                            }
1345
0
                        }
1346
0
                    }
1347
                }
1348
1349
                collection::Event::Shutdown {
1350
0
                    id,
1351
0
                    was_established,
1352
0
                    user_data: connection_info,
1353
0
                } => {
1354
0
                    // A connection has been completely closed.
1355
0
                    // The underlying state machine guarantees that all the substreams have been
1356
0
                    // closed beforehand through other events.
1357
0
1358
0
                    debug_assert!(connection_info.peer_index.is_some() || !was_established);
1359
1360
0
                    let peer_id = connection_info
1361
0
                        .peer_index
1362
0
                        .map(|peer_index| self.peers[peer_index.0].clone());
1363
1364
0
                    if let Some(peer_index) = connection_info.peer_index {
1365
0
                        let _was_removed = self.connections_by_peer_id.remove(&(peer_index, id));
1366
0
                        debug_assert!(_was_removed);
1367
0
                        self.try_clean_up_peer(peer_index);
1368
0
                    }
1369
1370
                    // TODO: IMPORTANT this event should indicate a clean shutdown, a pre-handshake interruption, a protocol error, a reset, etc. and should get a `reason`; see <https://github.com/smol-dot/smoldot/pull/391>
1371
1372
0
                    if was_established {
1373
0
                        return Some(Event::Disconnected {
1374
0
                            id,
1375
0
                            address: connection_info.address,
1376
0
                            peer_id: peer_id.unwrap(),
1377
0
                            user_data: connection_info.user_data,
1378
0
                        });
1379
                    } else {
1380
0
                        return Some(Event::PreHandshakeDisconnected {
1381
0
                            id,
1382
0
                            address: connection_info.address,
1383
0
                            expected_peer_id: peer_id,
1384
0
                            user_data: connection_info.user_data,
1385
0
                        });
1386
                    }
1387
                }
1388
1389
0
                collection::Event::InboundError { .. } => {
1390
0
                    // TODO: report the error for diagnostic purposes, but revisit the concept of "InboundError"
1391
0
                }
1392
1393
                collection::Event::InboundNegotiated {
1394
0
                    id,
1395
0
                    substream_id,
1396
0
                    protocol_name,
1397
                } => {
1398
                    // An inbound substream opened by the remote would like to negotiate the given
1399
                    // protocol. We must decide whether to accept this protocol or instead reject
1400
                    // the substream.
1401
                    // If accepted, we must also save the protocol somewhere in `self` in order to
1402
                    // load it later once things happen on this substream.
1403
0
                    let Ok(protocol) = self.recognize_protocol(&protocol_name) else {
1404
0
                        self.inner.reject_inbound(substream_id);
1405
0
                        continue;
1406
                    };
1407
1408
0
                    let inbound_type = match protocol {
1409
0
                        Protocol::Identify => collection::InboundTy::Request {
1410
0
                            request_max_size: None,
1411
0
                        },
1412
0
                        Protocol::Ping => collection::InboundTy::Ping,
1413
0
                        Protocol::Notifications(NotificationsProtocol::Grandpa { chain_index })
1414
0
                            if self.chains[chain_index].grandpa_protocol_config.is_none() =>
1415
0
                        {
1416
0
                            self.inner.reject_inbound(substream_id);
1417
0
                            continue;
1418
                        }
1419
0
                        Protocol::Notifications(p) => collection::InboundTy::Notifications {
1420
0
                            max_handshake_size: self.notifications_protocol_max_handshake_size(p),
1421
0
                        },
1422
0
                        Protocol::Sync { chain_index }
1423
0
                            if self.chains[chain_index].allow_inbound_block_requests =>
1424
0
                        {
1425
0
                            collection::InboundTy::Request {
1426
0
                                request_max_size: Some(1024),
1427
0
                            }
1428
                        }
1429
                        Protocol::Sync { .. } => {
1430
0
                            self.inner.reject_inbound(substream_id);
1431
0
                            continue;
1432
                        }
1433
1434
                        // TODO: the protocols below are not supported yet
1435
                        Protocol::LightUnknown { .. }
1436
                        | Protocol::Kad { .. }
1437
                        | Protocol::SyncWarp { .. }
1438
                        | Protocol::State { .. } => {
1439
0
                            self.inner.reject_inbound(substream_id);
1440
0
                            continue;
1441
                        }
1442
1443
                        Protocol::LightStorage { .. } | Protocol::LightCall { .. } => {
1444
0
                            unreachable!()
1445
                        }
1446
                    };
1447
1448
0
                    self.inner.accept_inbound(substream_id, inbound_type);
1449
0
1450
0
                    let _prev_value = self.substreams.insert(
1451
0
                        substream_id,
1452
0
                        SubstreamInfo {
1453
0
                            connection_id: id,
1454
0
                            protocol: Some(protocol),
1455
0
                        },
1456
0
                    );
1457
0
                    debug_assert!(_prev_value.is_none());
1458
                }
1459
1460
                collection::Event::InboundNegotiatedCancel { .. } => {
1461
                    // Because we immediately accept or reject substreams, this event can never
1462
                    // happen.
1463
0
                    unreachable!()
1464
                }
1465
1466
0
                collection::Event::InboundAcceptedCancel { substream_id } => {
1467
0
                    // An inbound substream has been aborted after having been accepted.
1468
0
                    // Since we don't report any event to the API user when a substream is
1469
0
                    // accepted, we have nothing to do but clean up our local state.
1470
0
                    let _was_in = self.substreams.remove(&substream_id);
1471
0
                    debug_assert!(_was_in.is_some());
1472
                }
1473
1474
                collection::Event::Response {
1475
0
                    substream_id,
1476
0
                    response,
1477
0
                } => {
1478
0
                    // Received a response to a request in a request-response protocol.
1479
0
                    let substream_info = self
1480
0
                        .substreams
1481
0
                        .remove(&substream_id)
1482
0
                        .unwrap_or_else(|| unreachable!());
1483
0
                    let peer_index = *self.inner[substream_info.connection_id]
1484
0
                        .peer_index
1485
0
                        .as_ref()
1486
0
                        .unwrap_or_else(|| unreachable!());
1487
1488
                    // Decode/verify the response.
1489
0
                    let (response, chain_index) = match substream_info.protocol {
1490
0
                        None => continue,
1491
0
                        Some(Protocol::Identify) => todo!(), // TODO: we don't send identify requests yet, so it's fine to leave this unimplemented
1492
0
                        Some(Protocol::Sync { chain_index, .. }) => (
1493
0
                            RequestResult::Blocks(
1494
0
                                response.map_err(BlocksRequestError::Request).and_then(
1495
0
                                    |response| {
1496
                                        codec::decode_block_response(&response)
1497
                                            .map_err(BlocksRequestError::Decode)
1498
0
                                    },
1499
0
                                ),
1500
0
                            ),
1501
0
                            chain_index,
1502
0
                        ),
1503
0
                        Some(Protocol::LightUnknown { .. }) => unreachable!(),
1504
0
                        Some(Protocol::LightStorage { chain_index, .. }) => (
1505
0
                            RequestResult::StorageProof(
1506
0
                                response
1507
0
                                    .map_err(StorageProofRequestError::Request)
1508
0
                                    .and_then(|payload| {
1509
                                        match codec::decode_storage_or_call_proof_response(
1510
                                            codec::StorageOrCallProof::StorageProof,
1511
                                            &payload,
1512
                                        ) {
1513
                                            Err(err) => Err(StorageProofRequestError::Decode(err)),
1514
                                            Ok(None) => {
1515
                                                Err(StorageProofRequestError::RemoteCouldntAnswer)
1516
                                            }
1517
                                            Ok(Some(_)) => Ok(EncodedMerkleProof(
1518
                                                payload,
1519
                                                codec::StorageOrCallProof::StorageProof,
1520
                                            )),
1521
                                        }
1522
0
                                    }),
1523
0
                            ),
1524
0
                            chain_index,
1525
0
                        ),
1526
0
                        Some(Protocol::LightCall { chain_index, .. }) => (
1527
0
                            RequestResult::CallProof(
1528
0
                                response.map_err(CallProofRequestError::Request).and_then(
1529
0
                                    |payload| match codec::decode_storage_or_call_proof_response(
1530
                                        codec::StorageOrCallProof::CallProof,
1531
                                        &payload,
1532
                                    ) {
1533
                                        Err(err) => Err(CallProofRequestError::Decode(err)),
1534
                                        Ok(None) => Err(CallProofRequestError::RemoteCouldntAnswer),
1535
                                        Ok(Some(_)) => Ok(EncodedMerkleProof(
1536
                                            payload,
1537
                                            codec::StorageOrCallProof::CallProof,
1538
                                        )),
1539
0
                                    },
1540
0
                                ),
1541
0
                            ),
1542
0
                            chain_index,
1543
0
                        ),
1544
0
                        Some(Protocol::Kad { chain_index, .. }) => (
1545
0
                            RequestResult::KademliaFindNode(
1546
0
                                response
1547
0
                                    .map_err(KademliaFindNodeError::RequestFailed)
1548
0
                                    .and_then(|payload| {
1549
                                        match codec::decode_find_node_response(&payload) {
1550
                                            Err(err) => {
1551
                                                Err(KademliaFindNodeError::DecodeError(err))
1552
                                            }
1553
                                            Ok(nodes) => Ok(nodes),
1554
                                        }
1555
0
                                    }),
1556
0
                            ),
1557
0
                            chain_index,
1558
0
                        ),
1559
0
                        Some(Protocol::SyncWarp { chain_index }) => (
1560
0
                            RequestResult::GrandpaWarpSync(
1561
0
                                response
1562
0
                                    .map_err(GrandpaWarpSyncRequestError::Request)
1563
0
                                    .and_then(|message| {
1564
                                        if let Err(err) = codec::decode_grandpa_warp_sync_response(
1565
                                            &message,
1566
                                            self.chains[chain_index].block_number_bytes,
1567
                                        ) {
1568
                                            Err(GrandpaWarpSyncRequestError::Decode(err))
1569
                                        } else {
1570
                                            Ok(EncodedGrandpaWarpSyncResponse {
1571
                                                message,
1572
                                                block_number_bytes: self.chains[chain_index]
1573
                                                    .block_number_bytes,
1574
                                            })
1575
                                        }
1576
0
                                    }),
1577
0
                            ),
1578
0
                            chain_index,
1579
0
                        ),
1580
0
                        Some(Protocol::State { chain_index, .. }) => (
1581
0
                            RequestResult::State(
1582
0
                                response
1583
0
                                    .map_err(StateRequestError::Request)
1584
0
                                    .and_then(|payload| {
1585
                                        if let Err(err) = codec::decode_state_response(&payload) {
1586
                                            Err(StateRequestError::Decode(err))
1587
                                        } else {
1588
                                            Ok(EncodedStateResponse(payload))
1589
                                        }
1590
0
                                    }),
1591
0
                            ),
1592
0
                            chain_index,
1593
0
                        ),
1594
1595
                        // The protocols below aren't request-response protocols.
1596
0
                        Some(Protocol::Ping) | Some(Protocol::Notifications(_)) => unreachable!(),
1597
                    };
1598
1599
0
                    return Some(Event::RequestResult {
1600
0
                        peer_id: self.peers[peer_index.0].clone(),
1601
0
                        chain_id: ChainId(chain_index),
1602
0
                        substream_id,
1603
0
                        response,
1604
0
                    });
1605
                }
1606
1607
                collection::Event::RequestIn {
1608
0
                    substream_id,
1609
0
                    request_payload,
1610
0
                } => {
1611
0
                    // Received a request on a request-response protocol.
1612
0
                    let substream_info = self
1613
0
                        .substreams
1614
0
                        .get(&substream_id)
1615
0
                        .unwrap_or_else(|| unreachable!());
1616
0
                    let peer_id = self.peers[self.inner[substream_info.connection_id]
1617
0
                        .peer_index
1618
0
                        .as_ref()
1619
0
                        .unwrap_or_else(|| unreachable!())
1620
0
                        .0]
1621
0
                        .clone();
1622
1623
0
                    match substream_info.protocol {
1624
0
                        None => {
1625
0
                            // Substream concerns a chain that has been removed.
1626
0
                            let _ = self.substreams.remove(&substream_id);
1627
0
                            self.inner.respond_in_request(substream_id, Err(()));
1628
0
                        }
1629
                        Some(Protocol::Identify) => {
1630
0
                            if request_payload.is_empty() {
1631
0
                                return Some(Event::IdentifyRequestIn {
1632
0
                                    peer_id,
1633
0
                                    substream_id,
1634
0
                                });
1635
                            } else {
1636
                                // TODO: can this actually be reached? isn't the inner code going to refuse a bad request anyway due to no length prefix?
1637
0
                                let _ = self.substreams.remove(&substream_id);
1638
0
                                self.inner.respond_in_request(substream_id, Err(()));
1639
0
                                return Some(Event::ProtocolError {
1640
0
                                    peer_id,
1641
0
                                    error: ProtocolError::BadIdentifyRequest,
1642
0
                                });
1643
                            }
1644
                        }
1645
0
                        Some(Protocol::Sync { chain_index }) => {
1646
0
                            match codec::decode_block_request(
1647
0
                                self.chains[chain_index].block_number_bytes,
1648
0
                                &request_payload,
1649
0
                            ) {
1650
0
                                Ok(config) => {
1651
0
                                    return Some(Event::BlocksRequestIn {
1652
0
                                        peer_id,
1653
0
                                        chain_id: ChainId(chain_index),
1654
0
                                        config,
1655
0
                                        substream_id,
1656
0
                                    })
1657
                                }
1658
0
                                Err(error) => {
1659
0
                                    let _ = self.substreams.remove(&substream_id);
1660
0
                                    self.inner.respond_in_request(substream_id, Err(()));
1661
0
                                    return Some(Event::ProtocolError {
1662
0
                                        peer_id,
1663
0
                                        error: ProtocolError::BadBlocksRequest(error),
1664
0
                                    });
1665
                                }
1666
                            }
1667
                        }
1668
                        // Any other protocol is declined when the protocol is negotiated.
1669
0
                        _ => unreachable!(),
1670
                    }
1671
                }
1672
1673
0
                collection::Event::RequestInCancel { substream_id } => {
1674
0
                    // The remote has cancelled a previously-emitted request. Propagate this event
1675
0
                    // to the API user.
1676
0
                    let _was_in = self.substreams.remove(&substream_id);
1677
0
                    debug_assert!(_was_in.is_some());
1678
0
                    return Some(Event::RequestInCancel { substream_id });
1679
                }
1680
1681
                // TODO: this whole block of code is too complex
1682
                collection::Event::NotificationsOutResult {
1683
0
                    substream_id,
1684
0
                    result,
1685
                } => {
1686
                    // Outgoing notifications substream has finished opening.
1687
                    // TODO: this if is pretty hacky
1688
0
                    let substream_info = if result.is_ok() {
1689
0
                        self.substreams
1690
0
                            .get(&substream_id)
1691
0
                            .unwrap_or_else(|| unreachable!())
1692
0
                            .clone()
1693
                    } else {
1694
0
                        self.substreams.remove(&substream_id).unwrap()
1695
                    };
1696
0
                    let connection_id = substream_info.connection_id;
1697
0
                    let peer_index = *self.inner[connection_id]
1698
0
                        .peer_index
1699
0
                        .as_ref()
1700
0
                        .unwrap_or_else(|| unreachable!());
1701
0
                    let Some(Protocol::Notifications(substream_protocol)) = substream_info.protocol
1702
                    else {
1703
                        // All outgoing substream attempts are cancelled when a chain is removed,
1704
                        // as such `protocol` can't be `None`.
1705
0
                        unreachable!();
1706
                    };
1707
1708
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
1709
0
                        substream_protocol,
1710
0
                        peer_index,
1711
0
                        SubstreamDirection::Out,
1712
0
                        NotificationsSubstreamState::Pending,
1713
0
                        substream_id,
1714
0
                    ));
1715
0
                    debug_assert!(_was_in);
1716
1717
                    // The behaviour is very specific to the protocol.
1718
0
                    match substream_protocol {
1719
0
                        NotificationsProtocol::BlockAnnounces { chain_index } => {
1720
                            // Parse the handshake to check whether it's correct.
1721
0
                            let result = match &result {
1722
0
                                Ok(handshake) => {
1723
0
                                    match codec::decode_block_announces_handshake(
1724
0
                                        self.chains[chain_index].block_number_bytes,
1725
0
                                        handshake,
1726
                                    ) {
1727
0
                                        Ok(decoded_handshake)
1728
0
                                            if *decoded_handshake.genesis_hash
1729
0
                                                == self.chains[chain_index].genesis_hash =>
1730
0
                                        {
1731
0
                                            Ok(decoded_handshake)
1732
                                        }
1733
0
                                        Ok(decoded_handshake) => {
1734
0
                                            Err(GossipConnectError::GenesisMismatch {
1735
0
                                                local_genesis: self.chains[chain_index]
1736
0
                                                    .genesis_hash,
1737
0
                                                remote_genesis: *decoded_handshake.genesis_hash,
1738
0
                                            })
1739
                                        }
1740
0
                                        Err(err) => Err(GossipConnectError::HandshakeDecode(err)),
1741
                                    }
1742
                                }
1743
0
                                Err(err) => Err(GossipConnectError::Substream(err.clone())),
1744
                            };
1745
1746
0
                            match result {
1747
0
                                Ok(decoded_handshake) => {
1748
0
                                    let _was_inserted =
1749
0
                                        self.notification_substreams_by_peer_id.insert((
1750
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
1751
0
                                            peer_index,
1752
0
                                            SubstreamDirection::Out,
1753
0
                                            NotificationsSubstreamState::Open {
1754
0
                                                asked_to_leave: false,
1755
0
                                            },
1756
0
                                            substream_id,
1757
0
                                        ));
1758
0
                                    debug_assert!(_was_inserted);
1759
1760
0
                                    for other_protocol in
1761
0
                                        iter::once(NotificationsProtocol::Transactions {
1762
0
                                            chain_index,
1763
0
                                        })
1764
0
                                        .chain(
1765
0
                                            self.chains[chain_index]
1766
0
                                                .grandpa_protocol_config
1767
0
                                                .is_some()
1768
0
                                                .then(|| NotificationsProtocol::Grandpa {
1769
                                                    chain_index,
1770
0
                                                }),
1771
0
                                        )
1772
                                    {
1773
0
                                        if self
1774
0
                                            .notification_substreams_by_peer_id
1775
0
                                            .range(
1776
0
                                                (
1777
0
                                                    other_protocol,
1778
0
                                                    peer_index,
1779
0
                                                    SubstreamDirection::Out,
1780
0
                                                    NotificationsSubstreamState::MIN,
1781
0
                                                    SubstreamId::MIN,
1782
0
                                                )
1783
0
                                                    ..=(
1784
0
                                                        other_protocol,
1785
0
                                                        peer_index,
1786
0
                                                        SubstreamDirection::Out,
1787
0
                                                        NotificationsSubstreamState::MAX,
1788
0
                                                        SubstreamId::MAX,
1789
0
                                                    ),
1790
0
                                            )
1791
0
                                            .next()
1792
0
                                            .is_some()
1793
                                        {
1794
0
                                            continue;
1795
0
                                        }
1796
1797
0
                                        let new_substream_id = self.inner.open_out_notifications(
1798
0
                                            connection_id,
1799
0
                                            codec::encode_protocol_name_string(
1800
0
                                                match other_protocol {
1801
                                                    NotificationsProtocol::Transactions {
1802
0
                                                        chain_index,
1803
0
                                                    } => codec::ProtocolName::Transactions {
1804
0
                                                        genesis_hash: self.chains[chain_index]
1805
0
                                                            .genesis_hash,
1806
0
                                                        fork_id: self.chains[chain_index]
1807
0
                                                            .fork_id
1808
0
                                                            .as_deref(),
1809
0
                                                    },
1810
                                                    NotificationsProtocol::Grandpa {
1811
0
                                                        chain_index,
1812
0
                                                    } => codec::ProtocolName::Grandpa {
1813
0
                                                        genesis_hash: self.chains[chain_index]
1814
0
                                                            .genesis_hash,
1815
0
                                                        fork_id: self.chains[chain_index]
1816
0
                                                            .fork_id
1817
0
                                                            .as_deref(),
1818
0
                                                    },
1819
0
                                                    _ => unreachable!(),
1820
                                                },
1821
                                            ),
1822
0
                                            self.notifications_protocol_handshake_timeout(
1823
0
                                                other_protocol,
1824
0
                                            ),
1825
0
                                            self.notifications_protocol_handshake(other_protocol),
1826
0
                                            self.notifications_protocol_max_handshake_size(
1827
0
                                                other_protocol,
1828
0
                                            ),
1829
0
                                        );
1830
0
1831
0
                                        self.substreams.insert(
1832
0
                                            new_substream_id,
1833
0
                                            SubstreamInfo {
1834
0
                                                connection_id,
1835
0
                                                protocol: Some(Protocol::Notifications(
1836
0
                                                    other_protocol,
1837
0
                                                )),
1838
0
                                            },
1839
0
                                        );
1840
0
1841
0
                                        self.notification_substreams_by_peer_id.insert((
1842
0
                                            other_protocol,
1843
0
                                            peer_index,
1844
0
                                            SubstreamDirection::Out,
1845
0
                                            NotificationsSubstreamState::Pending,
1846
0
                                            new_substream_id,
1847
0
                                        ));
1848
                                    }
1849
1850
0
                                    return Some(Event::GossipConnected {
1851
0
                                        peer_id: self.peers[peer_index.0].clone(),
1852
0
                                        chain_id: ChainId(chain_index),
1853
0
                                        kind: GossipKind::ConsensusTransactions,
1854
0
                                        role: decoded_handshake.role,
1855
0
                                        best_number: decoded_handshake.best_number,
1856
0
                                        best_hash: *decoded_handshake.best_hash,
1857
0
                                    });
1858
                                }
1859
0
                                Err(error) => {
1860
0
                                    if self
1861
0
                                        .connections_by_peer_id
1862
0
                                        .range(
1863
0
                                            (peer_index, ConnectionId::MIN)
1864
0
                                                ..=(peer_index, ConnectionId::MIN),
1865
0
                                        )
1866
0
                                        .any(|(_, c)| {
1867
                                            let state = self.inner.connection_state(*c);
1868
                                            state.established && !state.shutting_down
1869
0
                                        })
1870
0
                                        && self.gossip_desired_peers_by_chain.contains(&(
1871
0
                                            chain_index,
1872
0
                                            GossipKind::ConsensusTransactions,
1873
0
                                            peer_index,
1874
0
                                        ))
1875
                                    {
1876
0
                                        debug_assert!(self
1877
0
                                            .notification_substreams_by_peer_id
1878
0
                                            .range(
1879
0
                                                (
1880
0
                                                    NotificationsProtocol::BlockAnnounces {
1881
0
                                                        chain_index
1882
0
                                                    },
1883
0
                                                    peer_index,
1884
0
                                                    SubstreamDirection::Out,
1885
0
                                                    NotificationsSubstreamState::OPEN_MIN_VALUE,
1886
0
                                                    SubstreamId::MIN,
1887
0
                                                )
1888
0
                                                    ..=(
1889
0
                                                        NotificationsProtocol::BlockAnnounces {
1890
0
                                                            chain_index
1891
0
                                                        },
1892
0
                                                        peer_index,
1893
0
                                                        SubstreamDirection::Out,
1894
0
                                                        NotificationsSubstreamState::OPEN_MAX_VALUE,
1895
0
                                                        SubstreamId::MAX,
1896
0
                                                    ),
1897
0
                                            )
1898
0
                                            .next()
1899
0
                                            .is_none());
1900
1901
0
                                        self.connected_unopened_gossip_desired.insert((
1902
0
                                            peer_index,
1903
0
                                            ChainId(chain_index),
1904
0
                                            GossipKind::ConsensusTransactions,
1905
0
                                        ));
1906
0
                                    }
1907
1908
0
                                    self.opened_gossip_undesired.remove(&(
1909
0
                                        ChainId(chain_index),
1910
0
                                        peer_index,
1911
0
                                        GossipKind::ConsensusTransactions,
1912
0
                                    ));
1913
0
1914
0
                                    // TODO: pretty hacky
1915
0
                                    if let GossipConnectError::HandshakeDecode(_)
1916
0
                                    | GossipConnectError::GenesisMismatch { .. } = error
1917
0
                                    {
1918
0
                                        self.inner.close_out_notifications(substream_id);
1919
0
                                        self.substreams.remove(&substream_id).unwrap();
1920
0
                                    }
1921
1922
                                    // Close all the notification substreams of that chain.
1923
0
                                    for other_protocol in [
1924
0
                                        NotificationsProtocol::BlockAnnounces { chain_index },
1925
0
                                        NotificationsProtocol::Transactions { chain_index },
1926
0
                                        NotificationsProtocol::Grandpa { chain_index },
1927
                                    ] {
1928
0
                                        for (substream_id, direction, state) in self
1929
0
                                            .notification_substreams_by_peer_id
1930
0
                                            .range(
1931
0
                                                (
1932
0
                                                    other_protocol,
1933
0
                                                    peer_index,
1934
0
                                                    SubstreamDirection::MIN,
1935
0
                                                    NotificationsSubstreamState::MIN,
1936
0
                                                    SubstreamId::MIN,
1937
0
                                                )
1938
0
                                                    ..=(
1939
0
                                                        other_protocol,
1940
0
                                                        peer_index,
1941
0
                                                        SubstreamDirection::MAX,
1942
0
                                                        NotificationsSubstreamState::MAX,
1943
0
                                                        SubstreamId::MAX,
1944
0
                                                    ),
1945
0
                                            )
1946
0
                                            .map(|(_, _, dir, state, s)| (*s, *dir, *state))
1947
0
                                            .collect::<Vec<_>>()
1948
                                        {
1949
0
                                            match (direction, state) {
1950
                                                (SubstreamDirection::Out, _) => {
1951
0
                                                    self.inner
1952
0
                                                        .close_out_notifications(substream_id);
1953
0
1954
0
                                                    let _was_in = self
1955
0
                                                        .notification_substreams_by_peer_id
1956
0
                                                        .remove(&(
1957
0
                                                            other_protocol,
1958
0
                                                            peer_index,
1959
0
                                                            direction,
1960
0
                                                            state,
1961
0
                                                            substream_id,
1962
0
                                                        ));
1963
0
                                                    debug_assert!(_was_in);
1964
0
                                                    let _was_in =
1965
0
                                                        self.substreams.remove(&substream_id);
1966
0
                                                    debug_assert!(_was_in.is_some());
1967
                                                }
1968
                                                (
1969
                                                    SubstreamDirection::In,
1970
                                                    NotificationsSubstreamState::Pending,
1971
                                                ) => {
1972
0
                                                    self.inner
1973
0
                                                        .reject_in_notifications(substream_id);
1974
0
1975
0
                                                    let _was_in = self
1976
0
                                                        .notification_substreams_by_peer_id
1977
0
                                                        .remove(&(
1978
0
                                                            other_protocol,
1979
0
                                                            peer_index,
1980
0
                                                            direction,
1981
0
                                                            state,
1982
0
                                                            substream_id,
1983
0
                                                        ));
1984
0
                                                    debug_assert!(_was_in);
1985
0
                                                    let _was_in =
1986
0
                                                        self.substreams.remove(&substream_id);
1987
0
                                                    debug_assert!(_was_in.is_some());
1988
                                                }
1989
                                                (
1990
                                                    SubstreamDirection::In,
1991
                                                    NotificationsSubstreamState::Open {
1992
                                                        asked_to_leave: false,
1993
                                                    },
1994
                                                ) => {
1995
0
                                                    self.inner.start_close_in_notifications(
1996
0
                                                        substream_id,
1997
0
                                                        Duration::from_secs(5),
1998
0
                                                    ); // TODO: arbitrary constant
1999
0
2000
0
                                                    let _was_removed = self
2001
0
                                                        .notification_substreams_by_peer_id
2002
0
                                                        .remove(&(
2003
0
                                                            other_protocol,
2004
0
                                                            peer_index,
2005
0
                                                            SubstreamDirection::In,
2006
0
                                                            NotificationsSubstreamState::Open {
2007
0
                                                                asked_to_leave: false,
2008
0
                                                            },
2009
0
                                                            substream_id,
2010
0
                                                        ));
2011
0
                                                    debug_assert!(_was_removed);
2012
0
                                                    let _was_inserted = self
2013
0
                                                        .notification_substreams_by_peer_id
2014
0
                                                        .insert((
2015
0
                                                            other_protocol,
2016
0
                                                            peer_index,
2017
0
                                                            SubstreamDirection::In,
2018
0
                                                            NotificationsSubstreamState::Open {
2019
0
                                                                asked_to_leave: true,
2020
0
                                                            },
2021
0
                                                            substream_id,
2022
0
                                                        ));
2023
0
                                                    debug_assert!(_was_inserted);
2024
                                                }
2025
                                                (
2026
                                                    SubstreamDirection::In,
2027
                                                    NotificationsSubstreamState::Open {
2028
                                                        asked_to_leave: true,
2029
                                                    },
2030
0
                                                ) => {
2031
0
                                                    // Nothing to do.
2032
0
                                                }
2033
                                            }
2034
                                        }
2035
                                    }
2036
2037
0
                                    return Some(Event::GossipOpenFailed {
2038
0
                                        peer_id: self.peers[peer_index.0].clone(),
2039
0
                                        chain_id: ChainId(chain_index),
2040
0
                                        kind: GossipKind::ConsensusTransactions,
2041
0
                                        error,
2042
0
                                    });
2043
                                }
2044
                            }
2045
                        }
2046
2047
0
                        NotificationsProtocol::Transactions { chain_index }
2048
0
                        | NotificationsProtocol::Grandpa { chain_index } => {
2049
                            // TODO: doesn't check the handshakes
2050
2051
                            // This can only happen if we have a block announces substream with
2052
                            // that peer, otherwise the substream opening attempt should have
2053
                            // been cancelled.
2054
0
                            debug_assert!(self
2055
0
                                .notification_substreams_by_peer_id
2056
0
                                .range(
2057
0
                                    (
2058
0
                                        NotificationsProtocol::BlockAnnounces { chain_index },
2059
0
                                        peer_index,
2060
0
                                        SubstreamDirection::Out,
2061
0
                                        NotificationsSubstreamState::OPEN_MIN_VALUE,
2062
0
                                        SubstreamId::MIN
2063
0
                                    )
2064
0
                                        ..=(
2065
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
2066
0
                                            peer_index,
2067
0
                                            SubstreamDirection::Out,
2068
0
                                            NotificationsSubstreamState::OPEN_MAX_VALUE,
2069
0
                                            SubstreamId::MAX
2070
0
                                        )
2071
0
                                )
2072
0
                                .next()
2073
0
                                .is_some());
2074
2075
                            // If the substream failed to open, we simply try again.
2076
                            // Trying again means that we might be hammering the remote with
2077
                            // substream requests, however as of the writing of this text this is
2078
                            // necessary in order to bypass an issue in Substrate.
2079
                            // Note that in the situation where the connection is shutting down,
2080
                            // we don't re-open the substream on a different connection, but
2081
                            // that's ok as the block announces substream should be closed soon.
2082
0
                            if result.is_err() {
2083
0
                                if self.inner.connection_state(connection_id).shutting_down {
2084
0
                                    continue;
2085
0
                                }
2086
2087
0
                                let new_substream_id = self.inner.open_out_notifications(
2088
0
                                    connection_id,
2089
0
                                    codec::encode_protocol_name_string(match substream_protocol {
2090
                                        NotificationsProtocol::Transactions { .. } => {
2091
0
                                            codec::ProtocolName::Transactions {
2092
0
                                                genesis_hash: self.chains[chain_index].genesis_hash,
2093
0
                                                fork_id: self.chains[chain_index]
2094
0
                                                    .fork_id
2095
0
                                                    .as_deref(),
2096
0
                                            }
2097
                                        }
2098
                                        NotificationsProtocol::Grandpa { .. } => {
2099
0
                                            codec::ProtocolName::Grandpa {
2100
0
                                                genesis_hash: self.chains[chain_index].genesis_hash,
2101
0
                                                fork_id: self.chains[chain_index]
2102
0
                                                    .fork_id
2103
0
                                                    .as_deref(),
2104
0
                                            }
2105
                                        }
2106
0
                                        _ => unreachable!(),
2107
                                    }),
2108
0
                                    self.notifications_protocol_handshake_timeout(
2109
0
                                        substream_protocol,
2110
0
                                    ),
2111
0
                                    self.notifications_protocol_handshake(substream_protocol),
2112
0
                                    self.notifications_protocol_max_handshake_size(
2113
0
                                        substream_protocol,
2114
0
                                    ),
2115
0
                                );
2116
0
                                let _was_inserted =
2117
0
                                    self.notification_substreams_by_peer_id.insert((
2118
0
                                        substream_protocol,
2119
0
                                        peer_index,
2120
0
                                        SubstreamDirection::Out,
2121
0
                                        NotificationsSubstreamState::Pending,
2122
0
                                        new_substream_id,
2123
0
                                    ));
2124
0
                                debug_assert!(_was_inserted);
2125
0
                                let _prev_value = self.substreams.insert(
2126
0
                                    new_substream_id,
2127
0
                                    SubstreamInfo {
2128
0
                                        connection_id,
2129
0
                                        protocol: substream_info.protocol,
2130
0
                                    },
2131
0
                                );
2132
0
                                debug_assert!(_prev_value.is_none());
2133
0
                                continue;
2134
0
                            }
2135
0
2136
0
                            let _was_inserted = self.notification_substreams_by_peer_id.insert((
2137
0
                                substream_protocol,
2138
0
                                peer_index,
2139
0
                                SubstreamDirection::Out,
2140
0
                                NotificationsSubstreamState::Open {
2141
0
                                    asked_to_leave: false,
2142
0
                                },
2143
0
                                substream_id,
2144
0
                            ));
2145
0
                            debug_assert!(_was_inserted);
2146
2147
                            // In case of Grandpa, we immediately send a neighbor packet with
2148
                            // the current local state.
2149
0
                            if matches!(substream_protocol, NotificationsProtocol::Grandpa { .. }) {
2150
0
                                let grandpa_state = &self.chains[chain_index]
2151
0
                                    .grandpa_protocol_config
2152
0
                                    .as_ref()
2153
0
                                    .unwrap();
2154
0
                                let packet = codec::GrandpaNotificationRef::Neighbor(
2155
0
                                    codec::NeighborPacket {
2156
0
                                        round_number: grandpa_state.round_number,
2157
0
                                        set_id: grandpa_state.set_id,
2158
0
                                        commit_finalized_height: grandpa_state
2159
0
                                            .commit_finalized_height,
2160
0
                                    },
2161
0
                                )
2162
0
                                .scale_encoding(self.chains[chain_index].block_number_bytes)
2163
0
                                .fold(Vec::new(), |mut a, b| {
2164
                                    a.extend_from_slice(b.as_ref());
2165
                                    a
2166
0
                                });
2167
0
                                match self.inner.queue_notification(substream_id, packet) {
2168
0
                                    Ok(()) => {}
2169
                                    Err(collection::QueueNotificationError::QueueFull) => {
2170
0
                                        unreachable!()
2171
                                    }
2172
                                }
2173
0
                            }
2174
                        }
2175
                    }
2176
                }
2177
2178
0
                collection::Event::NotificationsOutCloseDemanded { substream_id }
2179
0
                | collection::Event::NotificationsOutReset { substream_id } => {
2180
                    // Outgoing notifications substream has been closed or must be closed.
2181
                    // These two situations are handled together, as we immediately react to a
2182
                    // demanded closing by performing the closing. The rest of the code is thus
2183
                    // the same for both situations.
2184
2185
                    // If the request demands the closing, we immediately comply.
2186
0
                    if matches!(
2187
0
                        inner_event,
2188
                        collection::Event::NotificationsOutCloseDemanded { .. }
2189
0
                    ) {
2190
0
                        self.inner.close_out_notifications(substream_id);
2191
0
                    }
2192
2193
                    // Load various information about the substream and connection.
2194
0
                    let substream_info = self
2195
0
                        .substreams
2196
0
                        .remove(&substream_id)
2197
0
                        .unwrap_or_else(|| unreachable!());
2198
0
                    let connection_id = substream_info.connection_id;
2199
0
                    let peer_index = *self.inner[connection_id]
2200
0
                        .peer_index
2201
0
                        .as_ref()
2202
0
                        .unwrap_or_else(|| unreachable!());
2203
2204
                    // All outgoing substream attempts are cancelled when a chain is removed, as
2205
                    // such `protocol` can't be `None`.
2206
0
                    let Some(Protocol::Notifications(substream_protocol)) = substream_info.protocol
2207
                    else {
2208
0
                        unreachable!();
2209
                    };
2210
2211
                    // Clean up the local state.
2212
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
2213
0
                        substream_protocol,
2214
0
                        peer_index,
2215
0
                        SubstreamDirection::Out,
2216
0
                        NotificationsSubstreamState::Open {
2217
0
                            asked_to_leave: false,
2218
0
                        },
2219
0
                        substream_id,
2220
0
                    ));
2221
0
                    debug_assert!(_was_in);
2222
2223
                    // Rest of the code depends on the protocol.
2224
0
                    match substream_protocol {
2225
0
                        NotificationsProtocol::BlockAnnounces { chain_index } => {
2226
0
                            self.opened_gossip_undesired.remove(&(
2227
0
                                ChainId(chain_index),
2228
0
                                peer_index,
2229
0
                                GossipKind::ConsensusTransactions,
2230
0
                            ));
2231
0
2232
0
                            // Insert back in `connected_unopened_gossip_desired` if relevant.
2233
0
                            if self.gossip_desired_peers_by_chain.contains(&(
2234
0
                                chain_index,
2235
0
                                GossipKind::ConsensusTransactions,
2236
0
                                peer_index,
2237
0
                            )) && self
2238
0
                                .connections_by_peer_id
2239
0
                                .range(
2240
0
                                    (peer_index, ConnectionId::MIN)
2241
0
                                        ..=(peer_index, ConnectionId::MAX),
2242
0
                                )
2243
0
                                .any(|(_, connection_id)| {
2244
                                    let state = self.inner.connection_state(*connection_id);
2245
                                    state.established && !state.shutting_down
2246
0
                                })
2247
                            {
2248
0
                                debug_assert!(self
2249
0
                                    .notification_substreams_by_peer_id
2250
0
                                    .range(
2251
0
                                        (
2252
0
                                            NotificationsProtocol::BlockAnnounces { chain_index },
2253
0
                                            peer_index,
2254
0
                                            SubstreamDirection::Out,
2255
0
                                            NotificationsSubstreamState::MIN,
2256
0
                                            SubstreamId::MIN,
2257
0
                                        )
2258
0
                                            ..=(
2259
0
                                                NotificationsProtocol::BlockAnnounces {
2260
0
                                                    chain_index
2261
0
                                                },
2262
0
                                                peer_index,
2263
0
                                                SubstreamDirection::Out,
2264
0
                                                NotificationsSubstreamState::MAX,
2265
0
                                                SubstreamId::MAX,
2266
0
                                            ),
2267
0
                                    )
2268
0
                                    .next()
2269
0
                                    .is_none());
2270
2271
0
                                let _was_inserted =
2272
0
                                    self.connected_unopened_gossip_desired.insert((
2273
0
                                        peer_index,
2274
0
                                        ChainId(chain_index),
2275
0
                                        GossipKind::ConsensusTransactions,
2276
0
                                    ));
2277
0
                                debug_assert!(_was_inserted);
2278
0
                            }
2279
2280
                            // The transactions and Grandpa protocols are tied to the block
2281
                            // announces substream. As such, we also close any transactions or
2282
                            // grandpa substream, either pending or fully opened.
2283
0
                            for proto in [
2284
0
                                NotificationsProtocol::Transactions { chain_index },
2285
0
                                NotificationsProtocol::Grandpa { chain_index },
2286
                            ] {
2287
0
                                for (substream_direction, substream_state, substream_id) in self
2288
0
                                    .notification_substreams_by_peer_id
2289
0
                                    .range(
2290
0
                                        (
2291
0
                                            proto,
2292
0
                                            peer_index,
2293
0
                                            SubstreamDirection::MIN,
2294
0
                                            NotificationsSubstreamState::MIN,
2295
0
                                            SubstreamId::MIN,
2296
0
                                        )
2297
0
                                            ..=(
2298
0
                                                proto,
2299
0
                                                peer_index,
2300
0
                                                SubstreamDirection::MAX,
2301
0
                                                NotificationsSubstreamState::MAX,
2302
0
                                                SubstreamId::MAX,
2303
0
                                            ),
2304
0
                                    )
2305
0
                                    .map(|(_, _, direction, state, substream_id)| {
2306
                                        (*direction, *state, *substream_id)
2307
0
                                    })
2308
0
                                    .collect::<Vec<_>>()
2309
                                {
2310
0
                                    match (substream_direction, substream_state) {
2311
                                        (SubstreamDirection::Out, _) => {
2312
0
                                            self.inner.close_out_notifications(substream_id);
2313
0
                                            let _was_removed =
2314
0
                                                self.notification_substreams_by_peer_id.remove(&(
2315
0
                                                    proto,
2316
0
                                                    peer_index,
2317
0
                                                    SubstreamDirection::Out,
2318
0
                                                    substream_state,
2319
0
                                                    substream_id,
2320
0
                                                ));
2321
0
                                            debug_assert!(_was_removed);
2322
0
                                            self.substreams.remove(&substream_id);
2323
                                        }
2324
                                        (
2325
                                            SubstreamDirection::In,
2326
                                            NotificationsSubstreamState::Pending,
2327
                                        ) => {
2328
                                            // Inbound notification substreams are always accepted
2329
                                            // or rejected immediately when a gossip link is open.
2330
0
                                            unreachable!()
2331
                                        }
2332
                                        (
2333
                                            SubstreamDirection::In,
2334
                                            NotificationsSubstreamState::Open {
2335
                                                asked_to_leave: true,
2336
                                            },
2337
0
                                        ) => {
2338
0
                                            // Nothing to do.
2339
0
                                        }
2340
                                        (
2341
                                            SubstreamDirection::In,
2342
                                            NotificationsSubstreamState::Open {
2343
                                                asked_to_leave: false,
2344
                                            },
2345
                                        ) => {
2346
0
                                            self.inner.start_close_in_notifications(
2347
0
                                                substream_id,
2348
0
                                                Duration::from_secs(5), // TODO: arbitrary constant
2349
0
                                            );
2350
0
                                            let _was_removed =
2351
0
                                                self.notification_substreams_by_peer_id.remove(&(
2352
0
                                                    proto,
2353
0
                                                    peer_index,
2354
0
                                                    SubstreamDirection::In,
2355
0
                                                    NotificationsSubstreamState::Open {
2356
0
                                                        asked_to_leave: false,
2357
0
                                                    },
2358
0
                                                    substream_id,
2359
0
                                                ));
2360
0
                                            debug_assert!(_was_removed);
2361
0
                                            let _was_inserted =
2362
0
                                                self.notification_substreams_by_peer_id.insert((
2363
0
                                                    proto,
2364
0
                                                    peer_index,
2365
0
                                                    SubstreamDirection::In,
2366
0
                                                    NotificationsSubstreamState::Open {
2367
0
                                                        asked_to_leave: true,
2368
0
                                                    },
2369
0
                                                    substream_id,
2370
0
                                                ));
2371
0
                                            debug_assert!(_was_inserted);
2372
                                        }
2373
                                    }
2374
                                }
2375
                            }
2376
2377
0
                            return Some(Event::GossipDisconnected {
2378
0
                                peer_id: self.peers[peer_index.0].clone(),
2379
0
                                chain_id: ChainId(chain_index),
2380
0
                                kind: GossipKind::ConsensusTransactions,
2381
0
                            });
2382
                        }
2383
2384
                        // The transactions and grandpa protocols are tied to the block announces
2385
                        // substream. If there is a block announce substream with the peer, we try
2386
                        // to reopen these two substreams.
2387
                        NotificationsProtocol::Transactions { .. }
2388
                        | NotificationsProtocol::Grandpa { .. } => {
2389
                            // Don't actually try to reopen if the connection is shutting down.
2390
                            // Note that we don't try to reopen on a different connection, as the
2391
                            // block announces substream will very soon be closed too anyway.
2392
0
                            if self.inner.connection_state(connection_id).shutting_down {
2393
0
                                continue;
2394
0
                            }
2395
2396
0
                            let new_substream_id = self.inner.open_out_notifications(
2397
0
                                connection_id,
2398
0
                                codec::encode_protocol_name_string(match substream_protocol {
2399
0
                                    NotificationsProtocol::Transactions { chain_index } => {
2400
0
                                        codec::ProtocolName::Transactions {
2401
0
                                            genesis_hash: self.chains[chain_index].genesis_hash,
2402
0
                                            fork_id: self.chains[chain_index].fork_id.as_deref(),
2403
0
                                        }
2404
                                    }
2405
0
                                    NotificationsProtocol::Grandpa { chain_index } => {
2406
0
                                        codec::ProtocolName::Grandpa {
2407
0
                                            genesis_hash: self.chains[chain_index].genesis_hash,
2408
0
                                            fork_id: self.chains[chain_index].fork_id.as_deref(),
2409
0
                                        }
2410
                                    }
2411
0
                                    _ => unreachable!(),
2412
                                }),
2413
0
                                self.notifications_protocol_handshake_timeout(substream_protocol),
2414
0
                                self.notifications_protocol_handshake(substream_protocol),
2415
0
                                self.notifications_protocol_max_handshake_size(substream_protocol),
2416
0
                            );
2417
0
                            self.substreams.insert(
2418
0
                                new_substream_id,
2419
0
                                SubstreamInfo {
2420
0
                                    connection_id,
2421
0
                                    protocol: Some(Protocol::Notifications(substream_protocol)),
2422
0
                                },
2423
0
                            );
2424
0
                            self.notification_substreams_by_peer_id.insert((
2425
0
                                substream_protocol,
2426
0
                                peer_index,
2427
0
                                SubstreamDirection::Out,
2428
0
                                NotificationsSubstreamState::Pending,
2429
0
                                new_substream_id,
2430
0
                            ));
2431
                        }
2432
                    }
2433
                }
2434
2435
0
                collection::Event::NotificationsInOpen { substream_id, .. } => {
2436
0
                    // Remote would like to open a notifications substream with us.
2437
0
2438
0
                    // There exists three possible ways to handle this event:
2439
0
                    //
2440
0
                    // - Accept the demand immediately. This happens if the API user has opened
2441
0
                    //   a gossip substream in the past or is currently trying to open a gossip
2442
0
                    //   substream with this peer.
2443
0
                    // - Refuse the demand immediately. This happens if there already exists a
2444
0
                    //   pending inbound notifications substream. Opening multiple notification
2445
0
                    //   substreams of the same protocol is a protocol violation. This also happens
2446
0
                    //   for transactions and grandpa substreams if no block announce substream is
2447
0
                    //   open.
2448
0
                    // - Generate an event to ask the API user whether to accept the demand. This
2449
0
                    //   happens specifically for block announce substreams.
2450
0
2451
0
                    // Extract various bits of information about the substream.
2452
0
                    // Instantly reject the substream if it concerns a chain that has since then
2453
0
                    // been removed from `self`, which can happen if the protocol name was already
2454
0
                    // negotiated when the chain was removed.
2455
0
                    let substream_info = self
2456
0
                        .substreams
2457
0
                        .get(&substream_id)
2458
0
                        .unwrap_or_else(|| unreachable!());
2459
0
                    let peer_index = *self.inner[substream_info.connection_id]
2460
0
                        .peer_index
2461
0
                        .as_ref()
2462
0
                        .unwrap_or_else(|| unreachable!());
2463
0
                    let Some(substream_protocol) = substream_info.protocol else {
2464
0
                        self.inner.reject_in_notifications(substream_id);
2465
0
                        self.substreams.remove(&substream_id);
2466
0
                        continue;
2467
                    };
2468
0
                    let Protocol::Notifications(substream_protocol) = substream_protocol else {
2469
0
                        unreachable!()
2470
                    };
2471
0
                    let (NotificationsProtocol::BlockAnnounces { chain_index }
2472
0
                    | NotificationsProtocol::Transactions { chain_index }
2473
0
                    | NotificationsProtocol::Grandpa { chain_index }) = substream_protocol;
2474
2475
                    // Check whether a substream with the same protocol already exists with that
2476
                    // peer, and if so deny the request.
2477
                    // Note that substreams with `asked_to_leave` equal to `true` are ignored when
2478
                    // searching, as in this case it's not a protocol violation.
2479
0
                    if self
2480
0
                        .notification_substreams_by_peer_id
2481
0
                        .range(
2482
0
                            (
2483
0
                                substream_protocol,
2484
0
                                peer_index,
2485
0
                                SubstreamDirection::In,
2486
0
                                NotificationsSubstreamState::MIN,
2487
0
                                SubstreamId::MIN,
2488
0
                            )
2489
0
                                ..(
2490
0
                                    substream_protocol,
2491
0
                                    peer_index,
2492
0
                                    SubstreamDirection::In,
2493
0
                                    NotificationsSubstreamState::Open {
2494
0
                                        asked_to_leave: true,
2495
0
                                    },
2496
0
                                    SubstreamId::MIN,
2497
0
                                ),
2498
0
                        )
2499
0
                        .next()
2500
0
                        .is_some()
2501
                    {
2502
0
                        self.inner.reject_in_notifications(substream_id);
2503
0
                        let _was_removed = self.substreams.remove(&substream_id);
2504
0
                        debug_assert!(_was_removed.is_some());
2505
0
                        continue;
2506
0
                    }
2507
0
2508
0
                    // If an outgoing block announces notifications protocol (either pending or
2509
0
                    // fully open) exists, accept the substream immediately.
2510
0
                    if self
2511
0
                        .notification_substreams_by_peer_id
2512
0
                        .range(
2513
0
                            (
2514
0
                                NotificationsProtocol::BlockAnnounces { chain_index },
2515
0
                                peer_index,
2516
0
                                SubstreamDirection::Out,
2517
0
                                NotificationsSubstreamState::MIN,
2518
0
                                SubstreamId::MIN,
2519
0
                            )
2520
0
                                ..=(
2521
0
                                    NotificationsProtocol::BlockAnnounces { chain_index },
2522
0
                                    peer_index,
2523
0
                                    SubstreamDirection::Out,
2524
0
                                    NotificationsSubstreamState::MAX,
2525
0
                                    SubstreamId::MAX,
2526
0
                                ),
2527
0
                        )
2528
0
                        .next()
2529
0
                        .is_some()
2530
                    {
2531
0
                        let _was_inserted = self.notification_substreams_by_peer_id.insert((
2532
0
                            substream_protocol,
2533
0
                            peer_index,
2534
0
                            SubstreamDirection::In,
2535
0
                            NotificationsSubstreamState::Open {
2536
0
                                asked_to_leave: false,
2537
0
                            },
2538
0
                            substream_id,
2539
0
                        ));
2540
0
                        debug_assert!(_was_inserted);
2541
0
                        self.inner.accept_in_notifications(
2542
0
                            substream_id,
2543
0
                            self.notifications_protocol_handshake(substream_protocol),
2544
0
                            self.notifications_protocol_max_notification_size(substream_protocol),
2545
0
                        );
2546
0
                        continue;
2547
0
                    }
2548
2549
                    // It is forbidden to cold-open a substream other than the block announces
2550
                    // substream.
2551
0
                    if !matches!(
2552
0
                        substream_protocol,
2553
                        NotificationsProtocol::BlockAnnounces { .. }
2554
                    ) {
2555
0
                        self.inner.reject_in_notifications(substream_id);
2556
0
                        let _was_removed = self.substreams.remove(&substream_id);
2557
0
                        debug_assert!(_was_removed.is_some());
2558
0
                        continue;
2559
0
                    }
2560
0
2561
0
                    // Update the local state and return the event.
2562
0
                    debug_assert!(matches!(
2563
0
                        substream_protocol,
2564
                        NotificationsProtocol::BlockAnnounces { .. }
2565
                    ));
2566
0
                    self.notification_substreams_by_peer_id.insert((
2567
0
                        substream_protocol,
2568
0
                        peer_index,
2569
0
                        SubstreamDirection::In,
2570
0
                        NotificationsSubstreamState::Pending,
2571
0
                        substream_id,
2572
0
                    ));
2573
0
                    return Some(Event::GossipInDesired {
2574
0
                        peer_id: self.peers[peer_index.0].clone(),
2575
0
                        chain_id: ChainId(chain_index),
2576
0
                        kind: GossipKind::ConsensusTransactions,
2577
0
                    });
2578
                }
2579
2580
0
                collection::Event::NotificationsInOpenCancel { substream_id } => {
2581
0
                    // Remote has cancelled a pending `NotificationsInOpen`.
2582
0
2583
0
                    let substream_info = self
2584
0
                        .substreams
2585
0
                        .remove(&substream_id)
2586
0
                        .unwrap_or_else(|| unreachable!());
2587
0
                    let peer_index = *self.inner[substream_info.connection_id]
2588
0
                        .peer_index
2589
0
                        .as_ref()
2590
0
                        .unwrap_or_else(|| unreachable!());
2591
2592
                    // All incoming notification substreams are immediately accepted/rejected
2593
                    // except for block announce substreams. Additionally, when a chain is removed,
2594
                    // all its pending block announce substreams are rejected. Therefore, this
2595
                    // event can only happen for block announce substreams.
2596
                    let Some(Protocol::Notifications(NotificationsProtocol::BlockAnnounces {
2597
0
                        chain_index,
2598
0
                    })) = substream_info.protocol
2599
                    else {
2600
0
                        unreachable!()
2601
                    };
2602
2603
                    // Clean up the local state.
2604
0
                    let _was_in = self.notification_substreams_by_peer_id.remove(&(
2605
0
                        NotificationsProtocol::BlockAnnounces { chain_index },
2606
0
                        peer_index,
2607
0
                        SubstreamDirection::In,
2608
0
                        NotificationsSubstreamState::Pending,
2609
0
                        substream_id,
2610
0
                    ));
2611
0
                    debug_assert!(_was_in);
2612
2613
                    // Notify API user.
2614
0
                    return Some(Event::GossipInDesiredCancel {
2615
0
                        peer_id: self.peers[peer_index.0].clone(),
2616
0
                        chain_id: ChainId(chain_index),
2617
0
                        kind: GossipKind::ConsensusTransactions,
2618
0
                    });
2619
                }
2620
2621
                collection::Event::NotificationsIn {
2622
0
                    substream_id,
2623
0
                    notification,
2624
0
                } => {
2625
0
                    // Received a notification from a remote.
2626
0
                    let substream_info = self
2627
0
                        .substreams
2628
0
                        .get(&substream_id)
2629
0
                        .unwrap_or_else(|| unreachable!());
2630
0
                    let substream_protocol = match substream_info.protocol {
2631
                        None => {
2632
                            // Substream concerns a chain that has been removed.
2633
                            // Ignore the notification.
2634
0
                            continue;
2635
                        }
2636
0
                        Some(Protocol::Notifications(p)) => p,
2637
0
                        Some(_) => unreachable!(),
2638
                    };
2639
0
                    let (NotificationsProtocol::BlockAnnounces { chain_index }
2640
0
                    | NotificationsProtocol::Transactions { chain_index }
2641
0
                    | NotificationsProtocol::Grandpa { chain_index }) = substream_protocol;
2642
0
                    let peer_index = *self.inner[substream_info.connection_id]
2643
0
                        .peer_index
2644
0
                        .as_ref()
2645
0
                        .unwrap_or_else(|| unreachable!());
2646
0
2647
0
                    // Check whether there is an open outgoing block announces substream, as this
2648
0
                    // means that we are "gossip-connected". If not, then the notification is
2649
0
                    // silently discarded.
2650
0
                    if self
2651
0
                        .notification_substreams_by_peer_id
2652
0
                        .range(
2653
0
                            (
2654
0
                                NotificationsProtocol::BlockAnnounces { chain_index },
2655
0
                                peer_index,
2656
0
                                SubstreamDirection::Out,
2657
0
                                NotificationsSubstreamState::OPEN_MIN_VALUE,
2658
0
                                collection::SubstreamId::MIN,
2659
0
                            )
2660
0
                                ..=(
2661
0
                                    NotificationsProtocol::BlockAnnounces { chain_index },
2662
0
                                    peer_index,
2663
0
                                    SubstreamDirection::Out,
2664
0
                                    NotificationsSubstreamState::OPEN_MAX_VALUE,
2665
0
                                    collection::SubstreamId::MAX,
2666
0
                                ),
2667
0
                        )
2668
0
                        .next()
2669
0
                        .is_none()
2670
                    {
2671
0
                        continue;
2672
0
                    }
2673
0
2674
0
                    // Decode the notification and return an event.
2675
0
                    match substream_protocol {
2676
                        NotificationsProtocol::BlockAnnounces { .. } => {
2677
0
                            if let Err(err) = codec::decode_block_announce(
2678
0
                                &notification,
2679
0
                                self.chains[chain_index].block_number_bytes,
2680
0
                            ) {
2681
0
                                return Some(Event::ProtocolError {
2682
0
                                    error: ProtocolError::BadBlockAnnounce(err),
2683
0
                                    peer_id: self.peers[peer_index.0].clone(),
2684
0
                                });
2685
0
                            }
2686
0
2687
0
                            return Some(Event::BlockAnnounce {
2688
0
                                chain_id: ChainId(chain_index),
2689
0
                                peer_id: self.peers[peer_index.0].clone(),
2690
0
                                announce: EncodedBlockAnnounce {
2691
0
                                    message: notification,
2692
0
                                    block_number_bytes: self.chains[chain_index].block_number_bytes,
2693
0
                                },
2694
0
                            });
2695
                        }
2696
0
                        NotificationsProtocol::Transactions { .. } => {
2697
0
                            // TODO: not implemented
2698
0
                        }
2699
                        NotificationsProtocol::Grandpa { .. } => {
2700
0
                            let decoded_notif = match codec::decode_grandpa_notification(
2701
0
                                &notification,
2702
0
                                self.chains[chain_index].block_number_bytes,
2703
0
                            ) {
2704
0
                                Ok(n) => n,
2705
0
                                Err(err) => {
2706
0
                                    return Some(Event::ProtocolError {
2707
0
                                        error: ProtocolError::BadGrandpaNotification(err),
2708
0
                                        peer_id: self.peers[peer_index.0].clone(),
2709
0
                                    })
2710
                                }
2711
                            };
2712
2713
0
                            match decoded_notif {
2714
                                codec::GrandpaNotificationRef::Commit(_) => {
2715
0
                                    return Some(Event::GrandpaCommitMessage {
2716
0
                                        chain_id: ChainId(chain_index),
2717
0
                                        peer_id: self.peers[peer_index.0].clone(),
2718
0
                                        message: EncodedGrandpaCommitMessage {
2719
0
                                            message: notification,
2720
0
                                            block_number_bytes: self.chains[chain_index]
2721
0
                                                .block_number_bytes,
2722
0
                                        },
2723
0
                                    })
2724
                                }
2725
0
                                codec::GrandpaNotificationRef::Neighbor(n) => {
2726
0
                                    return Some(Event::GrandpaNeighborPacket {
2727
0
                                        chain_id: ChainId(chain_index),
2728
0
                                        peer_id: self.peers[peer_index.0].clone(),
2729
0
                                        state: GrandpaState {
2730
0
                                            round_number: n.round_number,
2731
0
                                            set_id: n.set_id,
2732
0
                                            commit_finalized_height: n.commit_finalized_height,
2733
0
                                        },
2734
0
                                    })
2735
                                }
2736
0
                                _ => {
2737
0
                                    // Any other type of message is currently ignored. Support
2738
0
                                    // for them could be added in the future.
2739
0
                                }
2740
                            }
2741
                        }
2742
                    }
2743
                }
2744
2745
0
                collection::Event::NotificationsInClose { substream_id, .. } => {
2746
                    // An incoming notifications substream has been closed.
2747
                    // Nothing to do except clean up the local state.
2748
0
                    let Some(substream_info) = self.substreams.remove(&substream_id) else {
2749
0
                        unreachable!()
2750
                    };
2751
0
                    let peer_index = *self.inner[substream_info.connection_id]
2752
0
                        .peer_index
2753
0
                        .as_ref()
2754
0
                        .unwrap_or_else(|| unreachable!());
2755
0
                    let Some(protocol) = substream_info.protocol else {
2756
                        // Substream concerns a chain that has since then been removed.
2757
0
                        continue;
2758
                    };
2759
0
                    let Protocol::Notifications(protocol) = protocol else {
2760
0
                        unreachable!()
2761
                    };
2762
2763
                    // Clean up with both `asked_to_leave` equal to `true` or `false`, as we don't
2764
                    // know in which of the two the substream is.
2765
0
                    let _was_in1 = self.notification_substreams_by_peer_id.remove(&(
2766
0
                        protocol,
2767
0
                        peer_index,
2768
0
                        SubstreamDirection::In,
2769
0
                        NotificationsSubstreamState::Open {
2770
0
                            asked_to_leave: false,
2771
0
                        },
2772
0
                        substream_id,
2773
0
                    ));
2774
0
                    let _was_in2 = self.notification_substreams_by_peer_id.remove(&(
2775
0
                        protocol,
2776
0
                        peer_index,
2777
0
                        SubstreamDirection::In,
2778
0
                        NotificationsSubstreamState::Open {
2779
0
                            asked_to_leave: true,
2780
0
                        },
2781
0
                        substream_id,
2782
0
                    ));
2783
0
                    debug_assert!(_was_in1 || _was_in2);
2784
                }
2785
2786
0
                collection::Event::PingOutSuccess { id, ping_time } => {
2787
                    // The connection is necessarily past its handshake phase, and thus
2788
                    // the `peer_index` is necessarily known and valid.
2789
0
                    let Some(peer_index) = self.inner[id].peer_index else {
2790
0
                        unreachable!()
2791
                    };
2792
0
                    return Some(Event::PingOutSuccess {
2793
0
                        id,
2794
0
                        peer_id: self.peers[peer_index.0].clone(),
2795
0
                        ping_time,
2796
0
                    });
2797
                }
2798
            }
2799
        }
2800
147
    }
2801
2802
    /// Sends a blocks request to the given peer.
2803
    ///
2804
    /// The code in this module does not verify the response in any way. The blocks might be
2805
    /// completely different from the ones requested, or might be missing some information. In
2806
    /// other words, the response is completely untrusted.
2807
    ///
2808
    /// This function might generate a message destined a connection. Use
2809
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
2810
    ///
2811
    /// # Panic
2812
    ///
2813
    /// Panics if the [`ChainId`] is invalid.
2814
    ///
2815
    // TODO: more docs
2816
0
    pub fn start_blocks_request(
2817
0
        &mut self,
2818
0
        target: &PeerId,
2819
0
        chain_id: ChainId,
2820
0
        config: codec::BlocksRequestConfig,
2821
0
        timeout: Duration,
2822
0
    ) -> Result<SubstreamId, StartRequestError> {
2823
0
        let request_data = codec::build_block_request(
2824
0
            self.chains[chain_id.0].block_number_bytes,
2825
0
            &config,
2826
0
        )
2827
0
        .fold(Vec::new(), |mut a, b| {
2828
0
            a.extend_from_slice(b.as_ref());
2829
0
            a
2830
0
        });
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE20start_blocks_request0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE20start_blocks_request0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE20start_blocks_request0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE20start_blocks_request0B1b_
2831
0
2832
0
        self.start_request(
2833
0
            target,
2834
0
            request_data,
2835
0
            Protocol::Sync {
2836
0
                chain_index: chain_id.0,
2837
0
            },
2838
0
            timeout,
2839
0
        )
2840
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE20start_blocks_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE20start_blocks_requestB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE20start_blocks_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE20start_blocks_requestB19_
2841
2842
    ///
2843
    /// # Panic
2844
    ///
2845
    /// Panics if the [`ChainId`] is invalid.
2846
    ///
2847
    // TODO: docs
2848
0
    pub fn start_grandpa_warp_sync_request(
2849
0
        &mut self,
2850
0
        target: &PeerId,
2851
0
        chain_id: ChainId,
2852
0
        begin_hash: [u8; 32],
2853
0
        timeout: Duration,
2854
0
    ) -> Result<SubstreamId, StartRequestError> {
2855
0
        let request_data = begin_hash.to_vec();
2856
0
2857
0
        self.start_request(
2858
0
            target,
2859
0
            request_data,
2860
0
            Protocol::SyncWarp {
2861
0
                chain_index: chain_id.0,
2862
0
            },
2863
0
            timeout,
2864
0
        )
2865
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE31start_grandpa_warp_sync_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE31start_grandpa_warp_sync_requestB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE31start_grandpa_warp_sync_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE31start_grandpa_warp_sync_requestB19_
2866
2867
    /// Sends a state request to a peer.
2868
    ///
2869
    /// A state request makes it possible to download the storage of the chain at a given block.
2870
    /// The response is not unverified by this function. In other words, the peer is free to send
2871
    /// back erroneous data. It is the responsibility of the API user to verify the storage by
2872
    /// calculating the state trie root hash and comparing it with the value stored in the
2873
    /// block's header.
2874
    ///
2875
    /// Because response have a size limit, it is unlikely that a single request will return the
2876
    /// entire storage of the chain at once. Instead, call this function multiple times, each call
2877
    /// passing a `start_key` that follows the last key of the previous response.
2878
    ///
2879
    /// This function might generate a message destined a connection. Use
2880
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
2881
    ///
2882
    /// # Panic
2883
    ///
2884
    /// Panics if the [`ChainId`] is invalid.
2885
    ///
2886
0
    pub fn start_state_request(
2887
0
        &mut self,
2888
0
        target: &PeerId,
2889
0
        chain_id: ChainId,
2890
0
        block_hash: &[u8; 32],
2891
0
        start_key: codec::StateRequestStart,
2892
0
        timeout: Duration,
2893
0
    ) -> Result<SubstreamId, StartRequestError> {
2894
0
        let request_data = codec::build_state_request(codec::StateRequest {
2895
0
            block_hash,
2896
0
            start_key,
2897
0
        })
2898
0
        .fold(Vec::new(), |mut a, b| {
2899
0
            a.extend_from_slice(b.as_ref());
2900
0
            a
2901
0
        });
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE19start_state_request0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE19start_state_request0Bb_
2902
0
2903
0
        self.start_request(
2904
0
            target,
2905
0
            request_data,
2906
0
            Protocol::State {
2907
0
                chain_index: chain_id.0,
2908
0
            },
2909
0
            timeout,
2910
0
        )
2911
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE19start_state_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE19start_state_requestB9_
2912
2913
    /// Sends a storage request to the given peer.
2914
    ///
2915
    /// This function might generate a message destined a connection. Use
2916
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
2917
    ///
2918
    /// # Panic
2919
    ///
2920
    /// Panics if the [`ChainId`] is invalid.
2921
    ///
2922
    // TODO: more docs
2923
0
    pub fn start_storage_proof_request(
2924
0
        &mut self,
2925
0
        target: &PeerId,
2926
0
        chain_id: ChainId,
2927
0
        config: codec::StorageProofRequestConfig<impl Iterator<Item = impl AsRef<[u8]> + Clone>>,
2928
0
        timeout: Duration,
2929
0
    ) -> Result<SubstreamId, StartRequestMaybeTooLargeError> {
2930
0
        let request_data =
2931
0
            codec::build_storage_proof_request(config).fold(Vec::new(), |mut a, b| {
2932
0
                a.extend_from_slice(b.as_ref());
2933
0
                a
2934
0
            });
Unexecuted instantiation: _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB8_12ChainNetworkpppE27start_storage_proof_requestppE0Bc_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBc_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE27start_storage_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB5E_9into_iter8IntoIterB5B_EE0B27_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkpppE27start_storage_proof_requestppE0Bc_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBc_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE27start_storage_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB4H_9into_iter8IntoIterB4E_EE0B1c_
2935
0
2936
0
        // The request data can possibly by higher than the protocol limit, especially due to the
2937
0
        // call data.
2938
0
        // TODO: check limit
2939
0
2940
0
        Ok(self.start_request(
2941
0
            target,
2942
0
            request_data,
2943
0
            Protocol::LightStorage {
2944
0
                chain_index: chain_id.0,
2945
0
            },
2946
0
            timeout,
2947
0
        )?)
2948
0
    }
Unexecuted instantiation: _RINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB6_12ChainNetworkpppE27start_storage_proof_requestppEBa_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBa_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE27start_storage_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB5C_9into_iter8IntoIterB5z_EEB25_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkpppE27start_storage_proof_requestppEBa_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBa_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE27start_storage_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB4F_9into_iter8IntoIterB4C_EEB1a_
2949
2950
    /// Sends a call proof request to the given peer.
2951
    ///
2952
    /// This request is similar to [`ChainNetwork::start_storage_proof_request`]. Instead of
2953
    /// requesting specific keys, we request the list of all the keys that are accessed for a
2954
    /// specific runtime call.
2955
    ///
2956
    /// There exists no guarantee that the proof is complete (i.e. that it contains all the
2957
    /// necessary entries), as it is impossible to know this from just the proof itself. As such,
2958
    /// this method is just an optimization. When performing the actual call, regular storage proof
2959
    /// requests should be performed if the key is not present in the call proof response.
2960
    ///
2961
    /// This function might generate a message destined a connection. Use
2962
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
2963
    ///
2964
    /// # Panic
2965
    ///
2966
    /// Panics if the [`ChainId`] is invalid.
2967
    ///
2968
0
    pub fn start_call_proof_request(
2969
0
        &mut self,
2970
0
        target: &PeerId,
2971
0
        chain_id: ChainId,
2972
0
        config: codec::CallProofRequestConfig<'_, impl Iterator<Item = impl AsRef<[u8]>>>,
2973
0
        timeout: Duration,
2974
0
    ) -> Result<SubstreamId, StartRequestMaybeTooLargeError> {
2975
0
        let request_data = codec::build_call_proof_request(config).fold(Vec::new(), |mut a, b| {
2976
0
            a.extend_from_slice(b.as_ref());
2977
0
            a
2978
0
        });
Unexecuted instantiation: _RNCINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB8_12ChainNetworkpppE24start_call_proof_requestppE0Bc_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBc_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE24start_call_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB5B_9into_iter8IntoIterB5y_EE0B27_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkpppE24start_call_proof_requestppE0Bc_
Unexecuted instantiation: _RNCINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB8_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBc_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE24start_call_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB4E_9into_iter8IntoIterB4B_EE0B1c_
2979
0
2980
0
        // The request data can possibly by higher than the protocol limit, especially due to the
2981
0
        // call data.
2982
0
        // TODO: check limit
2983
0
2984
0
        Ok(self.start_request(
2985
0
            target,
2986
0
            request_data,
2987
0
            Protocol::LightCall {
2988
0
                chain_index: chain_id.0,
2989
0
            },
2990
0
            timeout,
2991
0
        )?)
2992
0
    }
Unexecuted instantiation: _RINvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB6_12ChainNetworkpppE24start_call_proof_requestppEBa_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBa_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE24start_call_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB5z_9into_iter8IntoIterB5w_EEB25_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkpppE24start_call_proof_requestppEBa_
Unexecuted instantiation: _RINvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB6_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBa_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE24start_call_proof_requestINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtB4C_9into_iter8IntoIterB4z_EEB1a_
2993
2994
    /// Sends a Kademlia find node request to the given peer.
2995
    ///
2996
    /// This function might generate a message destined a connection. Use
2997
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
2998
    ///
2999
    /// # Panic
3000
    ///
3001
    /// Panics if the [`ChainId`] is invalid.
3002
    ///
3003
0
    pub fn start_kademlia_find_node_request(
3004
0
        &mut self,
3005
0
        target: &PeerId,
3006
0
        chain_id: ChainId,
3007
0
        peer_id_to_find: &PeerId,
3008
0
        timeout: Duration,
3009
0
    ) -> Result<SubstreamId, StartRequestError> {
3010
0
        let request_data = codec::build_find_node_request(peer_id_to_find.as_bytes());
3011
0
3012
0
        // The request data can possibly by higher than the protocol limit, especially due to the
3013
0
        // call data.
3014
0
        // TODO: check limit
3015
0
3016
0
        self.start_request(
3017
0
            target,
3018
0
            request_data,
3019
0
            Protocol::Kad {
3020
0
                chain_index: chain_id.0,
3021
0
            },
3022
0
            timeout,
3023
0
        )
3024
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE32start_kademlia_find_node_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32start_kademlia_find_node_requestB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE32start_kademlia_find_node_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32start_kademlia_find_node_requestB19_
3025
3026
    /// Underlying implementation of all the functions that start requests.
3027
0
    fn start_request(
3028
0
        &mut self,
3029
0
        target: &PeerId,
3030
0
        request_data: Vec<u8>,
3031
0
        protocol: Protocol,
3032
0
        timeout: Duration,
3033
0
    ) -> Result<SubstreamId, StartRequestError> {
3034
0
        let Some(&peer_index) = self.peers_by_peer_id.get(target) else {
3035
            // If the `PeerId` is unknown, then we also don't have any connection to it.
3036
0
            return Err(StartRequestError::NoConnection);
3037
        };
3038
3039
        // TODO: this is O(n) but is it really a problem? you're only supposed to have max 1 or 2 connections per PeerId
3040
0
        let connection_id = self
3041
0
            .connections_by_peer_id
3042
0
            .range(
3043
0
                (peer_index, collection::ConnectionId::MIN)
3044
0
                    ..=(peer_index, collection::ConnectionId::MAX),
3045
0
            )
3046
0
            .map(|(_, connection_id)| *connection_id)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE13start_request0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE13start_request0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE13start_request0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE13start_request0B1b_
3047
0
            .find(|connection_id| {
3048
0
                let state = self.inner.connection_state(*connection_id);
3049
0
                state.established && !state.shutting_down
3050
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE13start_requests_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE13start_requests_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE13start_requests_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE13start_requests_0B1b_
3051
0
            .ok_or(StartRequestError::NoConnection)?;
3052
3053
0
        let protocol_name = {
3054
0
            let protocol_name = match protocol {
3055
0
                Protocol::Identify => codec::ProtocolName::Identify,
3056
0
                Protocol::Ping => codec::ProtocolName::Ping,
3057
0
                Protocol::Notifications(NotificationsProtocol::BlockAnnounces { chain_index }) => {
3058
0
                    let chain_info = &self.chains[chain_index];
3059
0
                    codec::ProtocolName::BlockAnnounces {
3060
0
                        genesis_hash: chain_info.genesis_hash,
3061
0
                        fork_id: chain_info.fork_id.as_deref(),
3062
0
                    }
3063
                }
3064
0
                Protocol::Notifications(NotificationsProtocol::Transactions { chain_index }) => {
3065
0
                    let chain_info = &self.chains[chain_index];
3066
0
                    codec::ProtocolName::Transactions {
3067
0
                        genesis_hash: chain_info.genesis_hash,
3068
0
                        fork_id: chain_info.fork_id.as_deref(),
3069
0
                    }
3070
                }
3071
0
                Protocol::Notifications(NotificationsProtocol::Grandpa { chain_index }) => {
3072
0
                    let chain_info = &self.chains[chain_index];
3073
0
                    codec::ProtocolName::Grandpa {
3074
0
                        genesis_hash: chain_info.genesis_hash,
3075
0
                        fork_id: chain_info.fork_id.as_deref(),
3076
0
                    }
3077
                }
3078
0
                Protocol::Sync { chain_index } => {
3079
0
                    let chain_info = &self.chains[chain_index];
3080
0
                    codec::ProtocolName::Sync {
3081
0
                        genesis_hash: chain_info.genesis_hash,
3082
0
                        fork_id: chain_info.fork_id.as_deref(),
3083
0
                    }
3084
                }
3085
0
                Protocol::LightUnknown { chain_index } => {
3086
0
                    let chain_info = &self.chains[chain_index];
3087
0
                    codec::ProtocolName::Light {
3088
0
                        genesis_hash: chain_info.genesis_hash,
3089
0
                        fork_id: chain_info.fork_id.as_deref(),
3090
0
                    }
3091
                }
3092
0
                Protocol::LightStorage { chain_index } => {
3093
0
                    let chain_info = &self.chains[chain_index];
3094
0
                    codec::ProtocolName::Light {
3095
0
                        genesis_hash: chain_info.genesis_hash,
3096
0
                        fork_id: chain_info.fork_id.as_deref(),
3097
0
                    }
3098
                }
3099
0
                Protocol::LightCall { chain_index } => {
3100
0
                    let chain_info = &self.chains[chain_index];
3101
0
                    codec::ProtocolName::Light {
3102
0
                        genesis_hash: chain_info.genesis_hash,
3103
0
                        fork_id: chain_info.fork_id.as_deref(),
3104
0
                    }
3105
                }
3106
0
                Protocol::Kad { chain_index } => {
3107
0
                    let chain_info = &self.chains[chain_index];
3108
0
                    codec::ProtocolName::Kad {
3109
0
                        genesis_hash: chain_info.genesis_hash,
3110
0
                        fork_id: chain_info.fork_id.as_deref(),
3111
0
                    }
3112
                }
3113
0
                Protocol::SyncWarp { chain_index } => {
3114
0
                    let chain_info = &self.chains[chain_index];
3115
0
                    codec::ProtocolName::SyncWarp {
3116
0
                        genesis_hash: chain_info.genesis_hash,
3117
0
                        fork_id: chain_info.fork_id.as_deref(),
3118
0
                    }
3119
                }
3120
0
                Protocol::State { chain_index } => {
3121
0
                    let chain_info = &self.chains[chain_index];
3122
0
                    codec::ProtocolName::State {
3123
0
                        genesis_hash: chain_info.genesis_hash,
3124
0
                        fork_id: chain_info.fork_id.as_deref(),
3125
0
                    }
3126
                }
3127
            };
3128
3129
0
            codec::encode_protocol_name_string(protocol_name)
3130
0
        };
3131
0
3132
0
        let substream_id = self.inner.start_request(
3133
0
            connection_id,
3134
0
            protocol_name,
3135
0
            Some(request_data),
3136
0
            timeout,
3137
0
            16 * 1024 * 1024,
3138
0
        );
3139
0
3140
0
        let _prev_value = self.substreams.insert(
3141
0
            substream_id,
3142
0
            SubstreamInfo {
3143
0
                connection_id,
3144
0
                protocol: Some(protocol),
3145
0
            },
3146
0
        );
3147
0
        debug_assert!(_prev_value.is_none());
3148
3149
0
        Ok(substream_id)
3150
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE13start_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE13start_requestB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE13start_requestB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE13start_requestB19_
3151
3152
    /// Responds to an identify request. Call this function in response to
3153
    /// a [`Event::IdentifyRequestIn`].
3154
    ///
3155
    /// Only the `agent_version` needs to be specified. The other fields are automatically
3156
    /// filled by the [`ChainNetwork`].
3157
    ///
3158
    /// This function might generate a message destined a connection. Use
3159
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
3160
    ///
3161
    /// # Panic
3162
    ///
3163
    /// Panics if the [`SubstreamId`] is invalid or doesn't correspond to a blocks request or
3164
    /// if the request has been cancelled with a [`Event::RequestInCancel`].
3165
    ///
3166
0
    pub fn respond_identify(&mut self, substream_id: SubstreamId, agent_version: &str) {
3167
0
        let substream_info = self.substreams.remove(&substream_id).unwrap();
3168
0
        assert!(matches!(
3169
0
            substream_info.protocol,
3170
            Some(Protocol::Identify { .. })
3171
        ));
3172
3173
0
        let response = {
3174
0
            let observed_addr = &self.inner[substream_info.connection_id].address;
3175
0
            let ed25519_public_key = &self.inner[substream_info.connection_id].ed25519_public_key;
3176
0
3177
0
            let supported_protocols = [codec::ProtocolName::Ping, codec::ProtocolName::Identify]
3178
0
                .into_iter()
3179
0
                .chain(self.chains.iter().flat_map(|(_, chain)| {
3180
0
                    [
3181
0
                        codec::ProtocolName::BlockAnnounces {
3182
0
                            genesis_hash: chain.genesis_hash,
3183
0
                            fork_id: chain.fork_id.as_deref(),
3184
0
                        },
3185
0
                        codec::ProtocolName::Transactions {
3186
0
                            genesis_hash: chain.genesis_hash,
3187
0
                            fork_id: chain.fork_id.as_deref(),
3188
0
                        },
3189
0
                    ]
3190
0
                    .into_iter()
3191
0
                    .chain(
3192
0
                        chain
3193
0
                            .grandpa_protocol_config
3194
0
                            .is_some()
3195
0
                            .then_some(codec::ProtocolName::Grandpa {
3196
0
                                genesis_hash: chain.genesis_hash,
3197
0
                                fork_id: chain.fork_id.as_deref(),
3198
0
                            })
3199
0
                            .into_iter(),
3200
0
                    )
3201
0
                    .chain(
3202
0
                        chain
3203
0
                            .allow_inbound_block_requests
3204
0
                            .then_some(codec::ProtocolName::Sync {
3205
0
                                genesis_hash: chain.genesis_hash,
3206
0
                                fork_id: chain.fork_id.as_deref(),
3207
0
                            })
3208
0
                            .into_iter(),
3209
0
                    )
3210
0
                }));
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identify0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE16respond_identify0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identify0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE16respond_identify0B1b_
3211
0
3212
0
            let supported_protocols_names = supported_protocols
3213
0
                .map(codec::encode_protocol_name_string)
3214
0
                .collect::<Vec<_>>();
3215
0
3216
0
            codec::build_identify_response(codec::IdentifyResponse {
3217
0
                protocol_version: "/substrate/1.0", // TODO: same value as in Substrate, see also https://github.com/paritytech/substrate/issues/14331
3218
0
                agent_version,
3219
0
                ed25519_public_key: *ed25519_public_key,
3220
0
                listen_addrs: iter::empty(), // TODO:
3221
0
                observed_addr,
3222
0
                protocols: supported_protocols_names.iter().map(|p| &p[..]),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identifys_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE16respond_identifys_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identifys_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE16respond_identifys_0B1b_
3223
0
            })
3224
0
            .fold(Vec::new(), |mut a, b| {
3225
0
                a.extend_from_slice(b.as_ref());
3226
0
                a
3227
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identifys0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE16respond_identifys0_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE16respond_identifys0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE16respond_identifys0_0B1b_
3228
0
        };
3229
0
3230
0
        self.inner.respond_in_request(substream_id, Ok(response));
3231
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE16respond_identifyB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE16respond_identifyB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE16respond_identifyB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE16respond_identifyB19_
3232
3233
    /// Responds to a blocks request. Call this function in response to
3234
    /// a [`Event::BlocksRequestIn`].
3235
    ///
3236
    /// Pass `None` in order to deny the request. Do this if blocks aren't available locally.
3237
    ///
3238
    /// This function might generate a message destined a connection. Use
3239
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
3240
    ///
3241
    /// # Panic
3242
    ///
3243
    /// Panics if the [`SubstreamId`] is invalid or doesn't correspond to a blocks request or
3244
    /// if the request has been cancelled with a [`Event::RequestInCancel`].
3245
    ///
3246
    // TOOD: more zero-cost parameter
3247
0
    pub fn respond_blocks(
3248
0
        &mut self,
3249
0
        substream_id: SubstreamId,
3250
0
        response: Option<Vec<codec::BlockData>>,
3251
0
    ) {
3252
0
        let substream_info = self.substreams.remove(&substream_id).unwrap();
3253
0
        assert!(matches!(
3254
0
            substream_info.protocol,
3255
            Some(Protocol::Sync { .. })
3256
        ));
3257
3258
0
        let response = if let Some(response) = response {
3259
0
            Ok(
3260
0
                codec::build_block_response(response).fold(Vec::new(), |mut a, b| {
3261
0
                    a.extend_from_slice(b.as_ref());
3262
0
                    a
3263
0
                }),
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE14respond_blocks0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE14respond_blocks0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE14respond_blocks0B1b_
3264
0
            )
3265
        } else {
3266
0
            Err(())
3267
        };
3268
3269
0
        self.inner.respond_in_request(substream_id, response);
3270
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE14respond_blocksB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE14respond_blocksB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE14respond_blocksB19_
3271
3272
    /// Returns the list of all peers for a [`Event::GossipConnected`] event of the given kind has
3273
    /// been emitted.
3274
    /// It is possible to send gossip notifications to these peers.
3275
    ///
3276
    /// # Panic
3277
    ///
3278
    /// Panics if the [`ChainId`] is invalid.
3279
    ///
3280
105
    pub fn gossip_connected_peers(
3281
105
        &'_ self,
3282
105
        chain_id: ChainId,
3283
105
        kind: GossipKind,
3284
105
    ) -> impl Iterator<Item = &'_ PeerId> + '_ {
3285
105
        assert!(self.chains.contains(chain_id.0));
3286
105
        let GossipKind::ConsensusTransactions = kind;
3287
105
3288
105
        self.notification_substreams_by_peer_id
3289
105
            .range(
3290
105
                (
3291
105
                    NotificationsProtocol::BlockAnnounces {
3292
105
                        chain_index: chain_id.0,
3293
105
                    },
3294
105
                    PeerIndex(usize::MIN),
3295
105
                    SubstreamDirection::Out,
3296
105
                    NotificationsSubstreamState::MIN,
3297
105
                    SubstreamId::MIN,
3298
105
                )
3299
105
                    ..=(
3300
105
                        NotificationsProtocol::BlockAnnounces {
3301
105
                            chain_index: chain_id.0,
3302
105
                        },
3303
105
                        PeerIndex(usize::MAX),
3304
105
                        SubstreamDirection::Out,
3305
105
                        NotificationsSubstreamState::MAX,
3306
105
                        SubstreamId::MAX,
3307
105
                    ),
3308
105
            )
3309
105
            .filter(move |(_, _, d, s, _)| {
3310
0
                *d == SubstreamDirection::Out
3311
0
                    && matches!(*s, NotificationsSubstreamState::Open { .. })
3312
105
            
}0
)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE22gossip_connected_peers0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE22gossip_connected_peers0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE22gossip_connected_peers0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE22gossip_connected_peers0B1b_
3313
105
            .map(|(_, peer_index, _, _, _)| 
&self.peers[peer_index.0]0
)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE22gossip_connected_peerss_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE22gossip_connected_peerss_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE22gossip_connected_peerss_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE22gossip_connected_peerss_0B1b_
3314
105
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE22gossip_connected_peersB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE22gossip_connected_peersB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE22gossip_connected_peersB9_
_RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE22gossip_connected_peersB19_
Line
Count
Source
3280
105
    pub fn gossip_connected_peers(
3281
105
        &'_ self,
3282
105
        chain_id: ChainId,
3283
105
        kind: GossipKind,
3284
105
    ) -> impl Iterator<Item = &'_ PeerId> + '_ {
3285
105
        assert!(self.chains.contains(chain_id.0));
3286
105
        let GossipKind::ConsensusTransactions = kind;
3287
105
3288
105
        self.notification_substreams_by_peer_id
3289
105
            .range(
3290
105
                (
3291
105
                    NotificationsProtocol::BlockAnnounces {
3292
105
                        chain_index: chain_id.0,
3293
105
                    },
3294
105
                    PeerIndex(usize::MIN),
3295
105
                    SubstreamDirection::Out,
3296
105
                    NotificationsSubstreamState::MIN,
3297
105
                    SubstreamId::MIN,
3298
105
                )
3299
105
                    ..=(
3300
105
                        NotificationsProtocol::BlockAnnounces {
3301
105
                            chain_index: chain_id.0,
3302
105
                        },
3303
105
                        PeerIndex(usize::MAX),
3304
105
                        SubstreamDirection::Out,
3305
105
                        NotificationsSubstreamState::MAX,
3306
105
                        SubstreamId::MAX,
3307
105
                    ),
3308
105
            )
3309
105
            .filter(move |(_, _, d, s, _)| {
3310
                *d == SubstreamDirection::Out
3311
                    && matches!(*s, NotificationsSubstreamState::Open { .. })
3312
105
            })
3313
105
            .map(|(_, peer_index, _, _, _)| &self.peers[peer_index.0])
3314
105
    }
3315
3316
    /// Returns the list of all peers for a [`Event::GossipConnected`] event of the given kind has
3317
    /// been emitted.
3318
    /// It is possible to send gossip notifications to these peers.
3319
    ///
3320
    /// # Panic
3321
    ///
3322
    /// Panics if the [`ChainId`] is invalid.
3323
    ///
3324
0
    pub fn gossip_is_connected(
3325
0
        &'_ self,
3326
0
        chain_id: ChainId,
3327
0
        target: &PeerId,
3328
0
        kind: GossipKind,
3329
0
    ) -> bool {
3330
0
        assert!(self.chains.contains(chain_id.0));
3331
0
        let GossipKind::ConsensusTransactions = kind;
3332
3333
0
        let Some(&peer_index) = self.peers_by_peer_id.get(target) else {
3334
            // If the `PeerId` is unknown, then we also don't have any gossip link to it.
3335
0
            return false;
3336
        };
3337
3338
0
        self.notification_substreams_by_peer_id
3339
0
            .range(
3340
0
                (
3341
0
                    NotificationsProtocol::BlockAnnounces {
3342
0
                        chain_index: chain_id.0,
3343
0
                    },
3344
0
                    peer_index,
3345
0
                    SubstreamDirection::Out,
3346
0
                    NotificationsSubstreamState::OPEN_MIN_VALUE,
3347
0
                    SubstreamId::MIN,
3348
0
                )
3349
0
                    ..=(
3350
0
                        NotificationsProtocol::BlockAnnounces {
3351
0
                            chain_index: chain_id.0,
3352
0
                        },
3353
0
                        peer_index,
3354
0
                        SubstreamDirection::Out,
3355
0
                        NotificationsSubstreamState::OPEN_MAX_VALUE,
3356
0
                        SubstreamId::MAX,
3357
0
                    ),
3358
0
            )
3359
0
            .next()
3360
0
            .is_some()
3361
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE19gossip_is_connectedB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE19gossip_is_connectedB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE19gossip_is_connectedB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE19gossip_is_connectedB19_
3362
3363
    /// Open a gossiping substream with the given peer on the given chain.
3364
    ///
3365
    /// Either a [`Event::GossipConnected`] or [`Event::GossipOpenFailed`] is guaranteed to later
3366
    /// be generated, unless [`ChainNetwork::gossip_close`] is called in the meanwhile.
3367
    ///
3368
    /// # Panic
3369
    ///
3370
    /// Panics if the [`ChainId`] is invalid.
3371
    ///
3372
0
    pub fn gossip_open(
3373
0
        &mut self,
3374
0
        chain_id: ChainId,
3375
0
        target: &PeerId,
3376
0
        kind: GossipKind,
3377
0
    ) -> Result<(), OpenGossipError> {
3378
0
        let GossipKind::ConsensusTransactions = kind;
3379
3380
0
        let Some(&peer_index) = self.peers_by_peer_id.get(target) else {
3381
            // If the `PeerId` is unknown, then we also don't have any connection to it.
3382
0
            return Err(OpenGossipError::NoConnection);
3383
        };
3384
3385
0
        let chain_info = &self.chains[chain_id.0];
3386
0
3387
0
        // It is forbidden to open more than one gossip notifications substream with any given
3388
0
        // peer.
3389
0
        if self
3390
0
            .notification_substreams_by_peer_id
3391
0
            .range(
3392
0
                (
3393
0
                    NotificationsProtocol::BlockAnnounces {
3394
0
                        chain_index: chain_id.0,
3395
0
                    },
3396
0
                    peer_index,
3397
0
                    SubstreamDirection::Out,
3398
0
                    NotificationsSubstreamState::MIN,
3399
0
                    SubstreamId::MIN,
3400
0
                )
3401
0
                    ..=(
3402
0
                        NotificationsProtocol::BlockAnnounces {
3403
0
                            chain_index: chain_id.0,
3404
0
                        },
3405
0
                        peer_index,
3406
0
                        SubstreamDirection::Out,
3407
0
                        NotificationsSubstreamState::MAX,
3408
0
                        SubstreamId::MAX,
3409
0
                    ),
3410
0
            )
3411
0
            .next()
3412
0
            .is_some()
3413
        {
3414
0
            return Err(OpenGossipError::AlreadyOpened);
3415
0
        }
3416
3417
        // Choose the connection on which to open the substream.
3418
        // This is done ahead of time, as we don't want to do anything before potentially
3419
        // returning an error.
3420
        // TODO: this is O(n) but is it really a problem? you're only supposed to have max 1 or 2 connections per PeerId
3421
0
        let connection_id = self
3422
0
            .connections_by_peer_id
3423
0
            .range(
3424
0
                (peer_index, collection::ConnectionId::MIN)
3425
0
                    ..=(peer_index, collection::ConnectionId::MAX),
3426
0
            )
3427
0
            .map(|(_, connection_id)| *connection_id)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_open0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE11gossip_open0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_open0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE11gossip_open0B1b_
3428
0
            .find(|connection_id| {
3429
0
                let state = self.inner.connection_state(*connection_id);
3430
0
                state.established && !state.shutting_down
3431
0
            })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_opens_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE11gossip_opens_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_opens_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE11gossip_opens_0B1b_
3432
0
            .ok_or(OpenGossipError::NoConnection)?;
3433
3434
        // Accept inbound substreams.
3435
0
        for (protocol, in_substream_id) in [
3436
0
            NotificationsProtocol::BlockAnnounces {
3437
0
                chain_index: chain_id.0,
3438
0
            },
3439
0
            NotificationsProtocol::Transactions {
3440
0
                chain_index: chain_id.0,
3441
0
            },
3442
0
            NotificationsProtocol::Grandpa {
3443
0
                chain_index: chain_id.0,
3444
0
            },
3445
0
        ]
3446
0
        .into_iter()
3447
0
        .flat_map(|protocol| {
3448
0
            self.notification_substreams_by_peer_id
3449
0
                .range(
3450
0
                    (
3451
0
                        protocol,
3452
0
                        peer_index,
3453
0
                        SubstreamDirection::In,
3454
0
                        NotificationsSubstreamState::Pending,
3455
0
                        SubstreamId::MIN,
3456
0
                    )
3457
0
                        ..=(
3458
0
                            protocol,
3459
0
                            peer_index,
3460
0
                            SubstreamDirection::In,
3461
0
                            NotificationsSubstreamState::Pending,
3462
0
                            SubstreamId::MAX,
3463
0
                        ),
3464
0
                )
3465
0
                .map(move |&(_, _, _, _, substream_id)| (protocol, substream_id))
Unexecuted instantiation: _RNCNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB9_12ChainNetworkpppE11gossip_opens0_00Bd_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE11gossip_opens0_00B28_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkpppE11gossip_opens0_00Bd_
Unexecuted instantiation: _RNCNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB9_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBd_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE11gossip_opens0_00B1d_
3466
0
        })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_opens0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE11gossip_opens0_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE11gossip_opens0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE11gossip_opens0_0B1b_
3467
0
        .collect::<Vec<_>>()
3468
        {
3469
0
            let _was_removed = self.notification_substreams_by_peer_id.remove(&(
3470
0
                protocol,
3471
0
                peer_index,
3472
0
                SubstreamDirection::In,
3473
0
                NotificationsSubstreamState::Pending,
3474
0
                in_substream_id,
3475
0
            ));
3476
0
            debug_assert!(_was_removed);
3477
3478
0
            let _was_inserted = self.notification_substreams_by_peer_id.insert((
3479
0
                protocol,
3480
0
                peer_index,
3481
0
                SubstreamDirection::In,
3482
0
                NotificationsSubstreamState::Open {
3483
0
                    asked_to_leave: false,
3484
0
                },
3485
0
                in_substream_id,
3486
0
            ));
3487
0
            debug_assert!(_was_inserted);
3488
3489
0
            self.inner.accept_in_notifications(
3490
0
                in_substream_id,
3491
0
                self.notifications_protocol_handshake(protocol),
3492
0
                self.notifications_protocol_max_notification_size(protocol),
3493
0
            )
3494
        }
3495
3496
        // Open the block announces substream.
3497
0
        let substream_id = self.inner.open_out_notifications(
3498
0
            connection_id,
3499
0
            codec::encode_protocol_name_string(codec::ProtocolName::BlockAnnounces {
3500
0
                genesis_hash: chain_info.genesis_hash,
3501
0
                fork_id: chain_info.fork_id.as_deref(),
3502
0
            }),
3503
0
            self.notifications_protocol_handshake_timeout(NotificationsProtocol::BlockAnnounces {
3504
0
                chain_index: chain_id.0,
3505
0
            }),
3506
0
            self.notifications_protocol_handshake(NotificationsProtocol::BlockAnnounces {
3507
0
                chain_index: chain_id.0,
3508
0
            }),
3509
0
            self.notifications_protocol_max_handshake_size(NotificationsProtocol::BlockAnnounces {
3510
0
                chain_index: chain_id.0,
3511
0
            }),
3512
0
        );
3513
0
        let _prev_value = self.substreams.insert(
3514
0
            substream_id,
3515
0
            SubstreamInfo {
3516
0
                connection_id,
3517
0
                protocol: Some(Protocol::Notifications(
3518
0
                    NotificationsProtocol::BlockAnnounces {
3519
0
                        chain_index: chain_id.0,
3520
0
                    },
3521
0
                )),
3522
0
            },
3523
0
        );
3524
0
        debug_assert!(_prev_value.is_none());
3525
0
        let _was_inserted = self.notification_substreams_by_peer_id.insert((
3526
0
            NotificationsProtocol::BlockAnnounces {
3527
0
                chain_index: chain_id.0,
3528
0
            },
3529
0
            peer_index,
3530
0
            SubstreamDirection::Out,
3531
0
            NotificationsSubstreamState::Pending,
3532
0
            substream_id,
3533
0
        ));
3534
0
        debug_assert!(_was_inserted);
3535
3536
        // Update the desired peers tracking.
3537
0
        if !self
3538
0
            .gossip_desired_peers
3539
0
            .contains(&(peer_index, kind, chain_id.0))
3540
        {
3541
0
            let _was_inserted = self.opened_gossip_undesired.insert((
3542
0
                chain_id,
3543
0
                peer_index,
3544
0
                GossipKind::ConsensusTransactions,
3545
0
            ));
3546
0
            debug_assert!(_was_inserted);
3547
0
        }
3548
0
        self.connected_unopened_gossip_desired
3549
0
            .remove(&(peer_index, chain_id, kind));
3550
0
3551
0
        Ok(())
3552
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE11gossip_openB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE11gossip_openB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE11gossip_openB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE11gossip_openB19_
3553
3554
    /// Switches the gossip link to the given peer to the "closed" state.
3555
    ///
3556
    /// This can be used:
3557
    ///
3558
    /// - To close a opening in progress after having called [`ChainNetwork::gossip_open`], in
3559
    /// which case no [`Event::GossipConnected`] or [`Event::GossipOpenFailed`] is generated.
3560
    /// - To close a fully open gossip link. All the notifications that have been queued are still
3561
    /// delivered. No event is generated.
3562
    /// - To respond to a [`Event::GossipInDesired`] by rejecting the request.
3563
    ///
3564
    /// # Panic
3565
    ///
3566
    /// Panics if [`ChainId`] is invalid.
3567
    ///
3568
0
    pub fn gossip_close(
3569
0
        &mut self,
3570
0
        chain_id: ChainId,
3571
0
        peer_id: &PeerId,
3572
0
        kind: GossipKind,
3573
0
    ) -> Result<(), CloseGossipError> {
3574
0
        let GossipKind::ConsensusTransactions = kind;
3575
3576
0
        let Some(&peer_index) = self.peers_by_peer_id.get(peer_id) else {
3577
            // If the `PeerId` is unknown, then we also don't have any gossip link to it.
3578
0
            return Err(CloseGossipError::NotOpen);
3579
        };
3580
3581
        // An `assert!` is necessary because we don't actually access the chain information
3582
        // anywhere, but still want to panic if the chain is invalid.
3583
0
        assert!(self.chains.contains(chain_id.0));
3584
3585
        // Track whether this function closed anything in order to know whether to return an
3586
        // error at the end.
3587
0
        let mut has_closed_something = false;
3588
3589
        // Close all substreams, pending or open.
3590
0
        for protocol in [
3591
0
            NotificationsProtocol::BlockAnnounces {
3592
0
                chain_index: chain_id.0,
3593
0
            },
3594
0
            NotificationsProtocol::Transactions {
3595
0
                chain_index: chain_id.0,
3596
0
            },
3597
0
            NotificationsProtocol::Grandpa {
3598
0
                chain_index: chain_id.0,
3599
0
            },
3600
        ] {
3601
0
            for (substream_id, direction, state) in self
3602
0
                .notification_substreams_by_peer_id
3603
0
                .range(
3604
0
                    (
3605
0
                        protocol,
3606
0
                        peer_index,
3607
0
                        SubstreamDirection::In,
3608
0
                        NotificationsSubstreamState::MIN,
3609
0
                        SubstreamId::MIN,
3610
0
                    )
3611
0
                        ..=(
3612
0
                            protocol,
3613
0
                            peer_index,
3614
0
                            SubstreamDirection::Out,
3615
0
                            NotificationsSubstreamState::MAX,
3616
0
                            SubstreamId::MAX,
3617
0
                        ),
3618
0
                )
3619
0
                .map(|(_, _, dir, state, sub_id)| (*sub_id, *dir, *state))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE12gossip_close0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE12gossip_close0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE12gossip_close0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE12gossip_close0B1b_
3620
0
                .collect::<Vec<_>>()
3621
            {
3622
0
                has_closed_something = true;
3623
0
3624
0
                match (direction, state) {
3625
                    (SubstreamDirection::Out, _) => {
3626
0
                        self.inner.close_out_notifications(substream_id);
3627
0
3628
0
                        let _was_in = self.notification_substreams_by_peer_id.remove(&(
3629
0
                            protocol,
3630
0
                            peer_index,
3631
0
                            direction,
3632
0
                            state,
3633
0
                            substream_id,
3634
0
                        ));
3635
0
                        debug_assert!(_was_in);
3636
0
                        let _was_in = self.substreams.remove(&substream_id);
3637
0
                        debug_assert!(_was_in.is_some());
3638
                    }
3639
                    (SubstreamDirection::In, NotificationsSubstreamState::Pending) => {
3640
0
                        self.inner.reject_in_notifications(substream_id);
3641
0
3642
0
                        let _was_in = self.notification_substreams_by_peer_id.remove(&(
3643
0
                            protocol,
3644
0
                            peer_index,
3645
0
                            direction,
3646
0
                            state,
3647
0
                            substream_id,
3648
0
                        ));
3649
0
                        debug_assert!(_was_in);
3650
0
                        let _was_in = self.substreams.remove(&substream_id);
3651
0
                        debug_assert!(_was_in.is_some());
3652
                    }
3653
                    (
3654
                        SubstreamDirection::In,
3655
                        NotificationsSubstreamState::Open {
3656
                            asked_to_leave: false,
3657
                        },
3658
                    ) => {
3659
0
                        self.inner
3660
0
                            .start_close_in_notifications(substream_id, Duration::from_secs(5)); // TODO: arbitrary constant
3661
0
3662
0
                        let _was_removed = self.notification_substreams_by_peer_id.remove(&(
3663
0
                            protocol,
3664
0
                            peer_index,
3665
0
                            SubstreamDirection::In,
3666
0
                            NotificationsSubstreamState::Open {
3667
0
                                asked_to_leave: false,
3668
0
                            },
3669
0
                            substream_id,
3670
0
                        ));
3671
0
                        debug_assert!(_was_removed);
3672
0
                        let _was_inserted = self.notification_substreams_by_peer_id.insert((
3673
0
                            protocol,
3674
0
                            peer_index,
3675
0
                            SubstreamDirection::In,
3676
0
                            NotificationsSubstreamState::Open {
3677
0
                                asked_to_leave: true,
3678
0
                            },
3679
0
                            substream_id,
3680
0
                        ));
3681
0
                        debug_assert!(_was_inserted);
3682
                    }
3683
                    (
3684
                        SubstreamDirection::In,
3685
                        NotificationsSubstreamState::Open {
3686
                            asked_to_leave: true,
3687
                        },
3688
0
                    ) => {
3689
0
                        // Nothing to do.
3690
0
                    }
3691
                }
3692
            }
3693
        }
3694
3695
        // Desired peers tracking update.
3696
0
        self.opened_gossip_undesired.remove(&(
3697
0
            chain_id,
3698
0
            peer_index,
3699
0
            GossipKind::ConsensusTransactions,
3700
0
        ));
3701
0
3702
0
        if has_closed_something {
3703
0
            Ok(())
3704
        } else {
3705
0
            Err(CloseGossipError::NotOpen)
3706
        }
3707
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE12gossip_closeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE12gossip_closeB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE12gossip_closeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE12gossip_closeB19_
3708
3709
    /// Update the state of the local node with regards to GrandPa rounds.
3710
    ///
3711
    /// Calling this method does two things:
3712
    ///
3713
    /// - Send on all the active GrandPa substreams a "neighbor packet" indicating the state of
3714
    ///   the local node.
3715
    /// - Update the neighbor packet that is automatically sent to peers when a GrandPa substream
3716
    ///   gets opened.
3717
    ///
3718
    /// In other words, calling this function atomically informs all the present and future peers
3719
    /// of the state of the local node regarding the GrandPa protocol.
3720
    ///
3721
    /// > **Note**: The information passed as parameter isn't validated in any way by this method.
3722
    ///
3723
    /// This function might generate a message destined to connections. Use
3724
    /// [`ChainNetwork::pull_message_to_connection`] to process these messages after it has
3725
    /// returned.
3726
    ///
3727
    /// # Panic
3728
    ///
3729
    /// Panics if [`ChainId`] is invalid, or if the chain has GrandPa disabled.
3730
    ///
3731
0
    pub fn gossip_broadcast_grandpa_state_and_update(
3732
0
        &mut self,
3733
0
        chain_id: ChainId,
3734
0
        grandpa_state: GrandpaState,
3735
0
    ) {
3736
0
        // Bytes of the neighbor packet to send out.
3737
0
        let packet = codec::GrandpaNotificationRef::Neighbor(codec::NeighborPacket {
3738
0
            round_number: grandpa_state.round_number,
3739
0
            set_id: grandpa_state.set_id,
3740
0
            commit_finalized_height: grandpa_state.commit_finalized_height,
3741
0
        })
3742
0
        .scale_encoding(self.chains[chain_id.0].block_number_bytes)
3743
0
        .fold(Vec::new(), |mut a, b| {
3744
0
            a.extend_from_slice(b.as_ref());
3745
0
            a
3746
0
        });
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_update0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE41gossip_broadcast_grandpa_state_and_update0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_update0Bb_
3747
3748
        // Now sending out to all the grandpa substreams that exist.
3749
        // TODO: O(n)
3750
0
        for (_, _, _, _, substream_id) in
3751
0
            self.notification_substreams_by_peer_id
3752
0
                .iter()
3753
0
                .filter(|(p, _, d, s, _)| {
3754
0
                    *p == NotificationsProtocol::Grandpa {
3755
0
                        chain_index: chain_id.0,
3756
0
                    } && *d == SubstreamDirection::Out
3757
0
                        && matches!(*s, NotificationsSubstreamState::Open { .. })
3758
0
                })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_updates_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE41gossip_broadcast_grandpa_state_and_updates_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_updates_0Bb_
3759
        {
3760
0
            match self.inner.queue_notification(*substream_id, packet.clone()) {
3761
0
                Ok(()) => {}
3762
0
                Err(collection::QueueNotificationError::QueueFull) => {}
3763
            }
3764
        }
3765
3766
        // Update the locally-stored state.
3767
0
        *self.chains[chain_id.0]
3768
0
            .grandpa_protocol_config
3769
0
            .as_mut()
3770
0
            .unwrap() = grandpa_state;
3771
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_updateB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE41gossip_broadcast_grandpa_state_and_updateB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE41gossip_broadcast_grandpa_state_and_updateB9_
3772
3773
    /// Sends a block announce gossip message to the given peer.
3774
    ///
3775
    /// If no [`Event::GossipConnected`] event of kind [`GossipKind::ConsensusTransactions`] has
3776
    /// been emitted for the given peer, then a [`QueueNotificationError::NoConnection`] will be
3777
    /// returned.
3778
    ///
3779
    /// This function might generate a message destined a connection. Use
3780
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
3781
    ///
3782
    /// # Panic
3783
    ///
3784
    /// Panics if the [`ChainId`] is invalid.
3785
    ///
3786
    // TODO: there this extra parameter in block announces that is unused on many chains but not always
3787
0
    pub fn gossip_send_block_announce(
3788
0
        &mut self,
3789
0
        target: &PeerId,
3790
0
        chain_id: ChainId,
3791
0
        scale_encoded_header: &[u8],
3792
0
        is_best: bool,
3793
0
    ) -> Result<(), QueueNotificationError> {
3794
0
        let notification = codec::encode_block_announce(codec::BlockAnnounceRef {
3795
0
            scale_encoded_header,
3796
0
            is_best,
3797
0
        })
3798
0
        .fold(Vec::new(), |mut a, b| {
3799
0
            a.extend_from_slice(b.as_ref());
3800
0
            a
3801
0
        });
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE26gossip_send_block_announce0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE26gossip_send_block_announce0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE26gossip_send_block_announce0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE26gossip_send_block_announce0B1b_
3802
0
3803
0
        self.queue_notification(
3804
0
            target,
3805
0
            NotificationsProtocol::BlockAnnounces {
3806
0
                chain_index: chain_id.0,
3807
0
            },
3808
0
            notification,
3809
0
        )
3810
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE26gossip_send_block_announceB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE26gossip_send_block_announceB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE26gossip_send_block_announceB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE26gossip_send_block_announceB19_
3811
3812
    /// Sends a transaction gossip message to the given peer.
3813
    ///
3814
    /// Must be passed the SCALE-encoded transaction.
3815
    ///
3816
    /// If no [`Event::GossipConnected`] event of kind [`GossipKind::ConsensusTransactions`] has
3817
    /// been emitted for the given peer, then a [`QueueNotificationError::NoConnection`] will be
3818
    /// returned.
3819
    ///
3820
    /// This function might generate a message destined connections. Use
3821
    /// [`ChainNetwork::pull_message_to_connection`] to process messages after it has returned.
3822
    ///
3823
    /// # Panic
3824
    ///
3825
    /// Panics if the [`ChainId`] is invalid.
3826
    ///
3827
    // TODO: function is awkward due to tx substream not being necessarily always open
3828
0
    pub fn gossip_send_transaction(
3829
0
        &mut self,
3830
0
        target: &PeerId,
3831
0
        chain_id: ChainId,
3832
0
        extrinsic: &[u8],
3833
0
    ) -> Result<(), QueueNotificationError> {
3834
0
        let mut val = Vec::with_capacity(1 + extrinsic.len());
3835
0
        val.extend_from_slice(util::encode_scale_compact_usize(1).as_ref());
3836
0
        val.extend_from_slice(extrinsic);
3837
0
        self.queue_notification(
3838
0
            target,
3839
0
            NotificationsProtocol::Transactions {
3840
0
                chain_index: chain_id.0,
3841
0
            },
3842
0
            val,
3843
0
        )
3844
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE23gossip_send_transactionB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE23gossip_send_transactionB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE23gossip_send_transactionB9_
3845
3846
    /// Inner implementation for all the notifications sends.
3847
0
    fn queue_notification(
3848
0
        &mut self,
3849
0
        target: &PeerId,
3850
0
        protocol: NotificationsProtocol,
3851
0
        notification: Vec<u8>,
3852
0
    ) -> Result<(), QueueNotificationError> {
3853
0
        let Some(&peer_index) = self.peers_by_peer_id.get(target) else {
3854
            // If the `PeerId` is unknown, then we also don't have any gossip link to it.
3855
0
            return Err(QueueNotificationError::NoConnection);
3856
        };
3857
3858
0
        let chain_index = match protocol {
3859
0
            NotificationsProtocol::BlockAnnounces { chain_index } => chain_index,
3860
0
            NotificationsProtocol::Transactions { chain_index } => chain_index,
3861
0
            NotificationsProtocol::Grandpa { chain_index } => chain_index,
3862
        };
3863
3864
0
        assert!(self.chains.contains(chain_index));
3865
3866
        // We first find a block announces substream for that peer.
3867
        // TODO: only relevant for GossipKind::ConsensusTransactions
3868
        // If none is found, then we are not considered "gossip-connected", and return an error
3869
        // no matter what, even if a substream of the requested protocol exists.
3870
0
        let block_announces_substream = self
3871
0
            .notification_substreams_by_peer_id
3872
0
            .range(
3873
0
                (
3874
0
                    NotificationsProtocol::BlockAnnounces { chain_index },
3875
0
                    peer_index,
3876
0
                    SubstreamDirection::Out,
3877
0
                    NotificationsSubstreamState::OPEN_MIN_VALUE,
3878
0
                    SubstreamId::MIN,
3879
0
                )
3880
0
                    ..=(
3881
0
                        NotificationsProtocol::BlockAnnounces { chain_index },
3882
0
                        peer_index,
3883
0
                        SubstreamDirection::Out,
3884
0
                        NotificationsSubstreamState::OPEN_MAX_VALUE,
3885
0
                        SubstreamId::MAX,
3886
0
                    ),
3887
0
            )
3888
0
            .next()
3889
0
            .map(|(_, _, _, _, substream_id)| *substream_id)
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18queue_notification0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18queue_notification0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18queue_notification0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18queue_notification0B1b_
3890
0
            .ok_or(QueueNotificationError::NoConnection)?;
3891
3892
        // Now find a substream of the requested protocol.
3893
0
        let substream_id = if matches!(protocol, NotificationsProtocol::BlockAnnounces { .. }) {
3894
0
            block_announces_substream
3895
        } else {
3896
0
            let id = self
3897
0
                .notification_substreams_by_peer_id
3898
0
                .range(
3899
0
                    (
3900
0
                        protocol,
3901
0
                        peer_index,
3902
0
                        SubstreamDirection::Out,
3903
0
                        NotificationsSubstreamState::OPEN_MIN_VALUE,
3904
0
                        SubstreamId::MIN,
3905
0
                    )
3906
0
                        ..=(
3907
0
                            protocol,
3908
0
                            peer_index,
3909
0
                            SubstreamDirection::Out,
3910
0
                            NotificationsSubstreamState::OPEN_MAX_VALUE,
3911
0
                            SubstreamId::MAX,
3912
0
                        ),
3913
0
                )
3914
0
                .next()
3915
0
                .map(|(_, _, _, _, substream_id)| *substream_id);
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18queue_notifications_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18queue_notifications_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18queue_notifications_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18queue_notifications_0B1b_
3916
            // If we are "gossip-connected" but no open transaction/grandpa substream exists, we
3917
            // silently discard the notification.
3918
            // TODO: this is a questionable behavior
3919
0
            let Some(id) = id else { return Ok(()) };
3920
0
            id
3921
        };
3922
3923
0
        match self.inner.queue_notification(substream_id, notification) {
3924
0
            Ok(()) => Ok(()),
3925
            Err(collection::QueueNotificationError::QueueFull) => {
3926
0
                Err(QueueNotificationError::QueueFull)
3927
            }
3928
        }
3929
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE18queue_notificationB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18queue_notificationB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE18queue_notificationB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18queue_notificationB19_
3930
3931
0
    fn recognize_protocol(&self, protocol_name: &str) -> Result<Protocol, ()> {
3932
0
        Ok(match codec::decode_protocol_name(protocol_name)? {
3933
0
            codec::ProtocolName::Identify => Protocol::Identify,
3934
0
            codec::ProtocolName::Ping => Protocol::Ping,
3935
            codec::ProtocolName::BlockAnnounces {
3936
0
                genesis_hash,
3937
0
                fork_id,
3938
0
            } => Protocol::Notifications(NotificationsProtocol::BlockAnnounces {
3939
0
                chain_index: *self
3940
0
                    .chains_by_protocol_info
3941
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocol0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocol0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocol0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocol0B1b_
3942
0
                    .ok_or(())?,
3943
            }),
3944
            codec::ProtocolName::Transactions {
3945
0
                genesis_hash,
3946
0
                fork_id,
3947
0
            } => Protocol::Notifications(NotificationsProtocol::Transactions {
3948
0
                chain_index: *self
3949
0
                    .chains_by_protocol_info
3950
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols_0B1b_
3951
0
                    .ok_or(())?,
3952
            }),
3953
            codec::ProtocolName::Grandpa {
3954
0
                genesis_hash,
3955
0
                fork_id,
3956
0
            } => Protocol::Notifications(NotificationsProtocol::Grandpa {
3957
0
                chain_index: *self
3958
0
                    .chains_by_protocol_info
3959
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols0_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols0_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols0_0B1b_
3960
0
                    .ok_or(())?,
3961
            }),
3962
            codec::ProtocolName::Sync {
3963
0
                genesis_hash,
3964
0
                fork_id,
3965
0
            } => Protocol::Sync {
3966
0
                chain_index: *self
3967
0
                    .chains_by_protocol_info
3968
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols1_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols1_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols1_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols1_0B1b_
3969
0
                    .ok_or(())?,
3970
            },
3971
            codec::ProtocolName::Light {
3972
0
                genesis_hash,
3973
0
                fork_id,
3974
0
            } => Protocol::LightUnknown {
3975
0
                chain_index: *self
3976
0
                    .chains_by_protocol_info
3977
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols2_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols2_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols2_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols2_0B1b_
3978
0
                    .ok_or(())?,
3979
            },
3980
            codec::ProtocolName::Kad {
3981
0
                genesis_hash,
3982
0
                fork_id,
3983
0
            } => Protocol::Kad {
3984
0
                chain_index: *self
3985
0
                    .chains_by_protocol_info
3986
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols3_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols3_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols3_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols3_0B1b_
3987
0
                    .ok_or(())?,
3988
            },
3989
            codec::ProtocolName::SyncWarp {
3990
0
                genesis_hash,
3991
0
                fork_id,
3992
0
            } => Protocol::SyncWarp {
3993
0
                chain_index: *self
3994
0
                    .chains_by_protocol_info
3995
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols4_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols4_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols4_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols4_0B1b_
3996
0
                    .ok_or(())?,
3997
            },
3998
            codec::ProtocolName::State {
3999
0
                genesis_hash,
4000
0
                fork_id,
4001
0
            } => Protocol::State {
4002
0
                chain_index: *self
4003
0
                    .chains_by_protocol_info
4004
0
                    .get(&(genesis_hash, fork_id.map(|fork_id| fork_id.to_owned())))
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols5_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocols5_0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE18recognize_protocols5_0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocols5_0B1b_
4005
0
                    .ok_or(())?,
4006
            },
4007
        })
4008
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE18recognize_protocolB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE18recognize_protocolB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE18recognize_protocolB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE18recognize_protocolB19_
4009
4010
    /// Returns the [`PeerIndex`] of the given [`PeerId`], inserting it if isn't present in the
4011
    /// list yet.
4012
0
    fn peer_index_or_insert(&mut self, peer_id: PeerId) -> PeerIndex {
4013
0
        debug_assert_eq!(self.peers.len(), self.peers_by_peer_id.len());
4014
0
        match self.peers_by_peer_id.entry(peer_id) {
4015
0
            hashbrown::hash_map::Entry::Occupied(e) => *e.get(),
4016
0
            hashbrown::hash_map::Entry::Vacant(e) => {
4017
0
                let peer_index = PeerIndex(self.peers.insert(e.key().clone()));
4018
0
                *e.insert(peer_index)
4019
            }
4020
        }
4021
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE20peer_index_or_insertB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE20peer_index_or_insertB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE20peer_index_or_insertB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE20peer_index_or_insertB19_
4022
4023
    /// Checks whether the given [`PeerIndex`] is still in use, and if no removes it from
4024
    /// [`ChainNetwork::peers`].
4025
0
    fn try_clean_up_peer(&mut self, peer_index: PeerIndex) {
4026
0
        if self
4027
0
            .connections_by_peer_id
4028
0
            .range(
4029
0
                (peer_index, collection::ConnectionId::MIN)
4030
0
                    ..=(peer_index, collection::ConnectionId::MAX),
4031
0
            )
4032
0
            .next()
4033
0
            .is_some()
4034
        {
4035
0
            return;
4036
0
        }
4037
0
4038
0
        if self
4039
0
            .gossip_desired_peers
4040
0
            .range(
4041
0
                (peer_index, GossipKind::ConsensusTransactions, usize::MIN)
4042
0
                    ..=(peer_index, GossipKind::ConsensusTransactions, usize::MAX),
4043
0
            )
4044
0
            .next()
4045
0
            .is_some()
4046
        {
4047
0
            return;
4048
0
        }
4049
0
4050
0
        let peer_id = self.peers.remove(peer_index.0);
4051
0
        let _was_in = self.peers_by_peer_id.remove(&peer_id);
4052
0
        debug_assert_eq!(_was_in, Some(peer_index));
4053
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE17try_clean_up_peerB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE17try_clean_up_peerB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE17try_clean_up_peerB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE17try_clean_up_peerB19_
4054
4055
    /// Returns the maximum allowed size (in bytes) of the handshake of the given protocol.
4056
0
    fn notifications_protocol_max_handshake_size(&self, protocol: NotificationsProtocol) -> usize {
4057
0
        // TODO: these numbers are arbitrary, must be made to match Substrate
4058
0
        match protocol {
4059
0
            NotificationsProtocol::BlockAnnounces { .. } => 64 * 1024,
4060
0
            NotificationsProtocol::Transactions { .. } => 4,
4061
0
            NotificationsProtocol::Grandpa { .. } => 32,
4062
        }
4063
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE41notifications_protocol_max_handshake_sizeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE41notifications_protocol_max_handshake_sizeB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE41notifications_protocol_max_handshake_sizeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE41notifications_protocol_max_handshake_sizeB19_
4064
4065
    /// Returns the maximum allowed size (in bytes) of a notification of the given protocol.
4066
0
    fn notifications_protocol_max_notification_size(
4067
0
        &self,
4068
0
        _protocol: NotificationsProtocol,
4069
0
    ) -> usize {
4070
0
        // TODO: this number is arbitrary, must be made to match Substrate
4071
0
        1024 * 1024 // TODO:
4072
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE44notifications_protocol_max_notification_sizeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE44notifications_protocol_max_notification_sizeB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE44notifications_protocol_max_notification_sizeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE44notifications_protocol_max_notification_sizeB19_
4073
4074
    /// Returns the timeout allowed for the remote to send back the handshake of the given
4075
    /// protocol.
4076
0
    fn notifications_protocol_handshake_timeout(
4077
0
        &self,
4078
0
        _protocol: NotificationsProtocol,
4079
0
    ) -> Duration {
4080
0
        Duration::from_secs(10)
4081
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE40notifications_protocol_handshake_timeoutB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE40notifications_protocol_handshake_timeoutB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE40notifications_protocol_handshake_timeoutB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE40notifications_protocol_handshake_timeoutB19_
4082
4083
    /// Builds the handshake to send to the remote when opening a notifications protocol.
4084
0
    fn notifications_protocol_handshake(&self, protocol: NotificationsProtocol) -> Vec<u8> {
4085
0
        let handshake = match protocol {
4086
0
            NotificationsProtocol::BlockAnnounces { chain_index } => {
4087
0
                codec::encode_block_announces_handshake(
4088
0
                    codec::BlockAnnouncesHandshakeRef {
4089
0
                        best_hash: &self.chains[chain_index].best_hash,
4090
0
                        best_number: self.chains[chain_index].best_number,
4091
0
                        role: self.chains[chain_index].role,
4092
0
                        genesis_hash: &self.chains[chain_index].genesis_hash,
4093
0
                    },
4094
0
                    self.chains[chain_index].block_number_bytes,
4095
0
                )
4096
0
                .fold(Vec::new(), |mut a, b| {
4097
0
                    a.extend_from_slice(b.as_ref());
4098
0
                    a
4099
0
                })
Unexecuted instantiation: _RNCNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB7_12ChainNetworkpppE32notifications_protocol_handshake0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32notifications_protocol_handshake0B26_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkpppE32notifications_protocol_handshake0Bb_
Unexecuted instantiation: _RNCNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB7_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtBb_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32notifications_protocol_handshake0B1b_
4100
            }
4101
0
            NotificationsProtocol::Transactions { .. } => Vec::new(),
4102
0
            NotificationsProtocol::Grandpa { chain_index } => {
4103
0
                self.chains[chain_index].role.scale_encoding().to_vec()
4104
            }
4105
        };
4106
4107
0
        debug_assert!(handshake.len() <= self.notifications_protocol_max_handshake_size(protocol));
4108
0
        handshake
4109
0
    }
Unexecuted instantiation: _RNvMs0_NtNtCsN16ciHI6Qf_7smoldot7network7serviceINtB5_12ChainNetworkpppE32notifications_protocol_handshakeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationE32notifications_protocol_handshakeB24_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkpppE32notifications_protocol_handshakeB9_
Unexecuted instantiation: _RNvMs0_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantE32notifications_protocol_handshakeB19_
4110
}
4111
4112
impl<TChain, TConn, TNow> ops::Index<ChainId> for ChainNetwork<TChain, TConn, TNow> {
4113
    type Output = TChain;
4114
4115
147
    fn index(&self, index: ChainId) -> &Self::Output {
4116
147
        &self.chains[index.0].user_data
4117
147
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot7network7services1_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_7ChainIdE5indexB9_
Unexecuted instantiation: _RNvXs1_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationEINtNtNtB4x_3ops5index5IndexNtB5_7ChainIdE5indexB24_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot7network7services1_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_7ChainIdE5indexB9_
_RNvXs1_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB5_7ChainIdE5indexB19_
Line
Count
Source
4115
147
    fn index(&self, index: ChainId) -> &Self::Output {
4116
147
        &self.chains[index.0].user_data
4117
147
    }
4118
}
4119
4120
impl<TChain, TConn, TNow> ops::IndexMut<ChainId> for ChainNetwork<TChain, TConn, TNow> {
4121
0
    fn index_mut(&mut self, index: ChainId) -> &mut Self::Output {
4122
0
        &mut self.chains[index.0].user_data
4123
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot7network7services2_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_7ChainIdE9index_mutB9_
Unexecuted instantiation: _RNvXs2_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationEINtNtNtB4x_3ops5index8IndexMutNtB5_7ChainIdE9index_mutB24_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot7network7services2_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtB5_7ChainIdE9index_mutB9_
4124
}
4125
4126
impl<TChain, TConn, TNow> ops::Index<ConnectionId> for ChainNetwork<TChain, TConn, TNow> {
4127
    type Output = TConn;
4128
4129
0
    fn index(&self, index: ConnectionId) -> &Self::Output {
4130
0
        &self.inner[index].user_data
4131
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot7network7services3_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtNtNtB9_6libp2p10collection12ConnectionIdE5indexB9_
Unexecuted instantiation: _RNvXs3_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkINtNtCsih6EgvAwZF2_13smoldot_light15network_service5ChainNtNtCsDDUKWWCHAU_18smoldot_light_wasm8platform11PlatformRefEINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsaYZPK01V26L_4core4time8DurationEINtNtNtB4x_3ops5index5IndexNtB3D_12ConnectionIdE5indexB24_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot7network7services3_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtNtNtB9_6libp2p10collection12ConnectionIdE5indexB9_
Unexecuted instantiation: _RNvXs3_NtNtCseuYC0Zibziv_7smoldot7network7serviceINtB5_12ChainNetworkNtNtCsiUjFBJteJ7x_17smoldot_full_node15network_service5ChainINtCsldkcb8n7qNv_13async_channel6SenderNtNtNtB9_6libp2p10collection23CoordinatorToConnectionENtNtCsbpXXxgr6u8g_3std4time7InstantEINtNtNtCsaYZPK01V26L_4core3ops5index5IndexNtB2I_12ConnectionIdE5indexB19_
4132
}
4133
4134
impl<TChain, TConn, TNow> ops::IndexMut<ConnectionId> for ChainNetwork<TChain, TConn, TNow> {
4135
0
    fn index_mut(&mut self, index: ConnectionId) -> &mut Self::Output {
4136
0
        &mut self.inner[index].user_data
4137
0
    }
Unexecuted instantiation: _RNvXININtNtCsN16ciHI6Qf_7smoldot7network7services4_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtNtNtB9_6libp2p10collection12ConnectionIdE9index_mutB9_
Unexecuted instantiation: _RNvXININtNtCseuYC0Zibziv_7smoldot7network7services4_0pppEINtB5_12ChainNetworkpppEINtNtNtCsaYZPK01V26L_4core3ops5index8IndexMutNtNtNtB9_6libp2p10collection12ConnectionIdE9index_mutB9_
4138
}
4139
4140
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
4141
pub enum GossipKind {
4142
    ConsensusTransactions,
4143
}
4144
4145
/// Error returned by [`ChainNetwork::add_chain`].
4146
0
#[derive(Debug, derive_more::Display, Clone)]
Unexecuted instantiation: _RNvXs1k_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_13AddChainErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1k_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_13AddChainErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4147
pub enum AddChainError {
4148
    /// The genesis hash and fork id are identical to the ones of an existing chain.
4149
    #[display(fmt = "Genesis hash and fork id are identical to the ones of an existing chain.")]
4150
    Duplicate {
4151
        /// Identifier of the chain that uses the same genesis hash and fork id.
4152
        existing_identical: ChainId,
4153
    },
4154
}
4155
4156
/// Error returned by [`ChainNetwork::remove_chain`].
4157
0
#[derive(Debug, derive_more::Display, Clone)]
Unexecuted instantiation: _RNvXs1n_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_16RemoveChainErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1n_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_16RemoveChainErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4158
pub enum RemoveChainError {
4159
    /// Chain is still in use.
4160
    InUse,
4161
}
4162
4163
/// Event generated by [`ChainNetwork::next_event`].
4164
#[derive(Debug)]
4165
pub enum Event<TConn> {
4166
    /// A connection that was added with [`ChainNetwork::add_single_stream_connection`] or
4167
    /// [`ChainNetwork::add_multi_stream_connection`] has now finished its handshake phase.
4168
    /// Its [`PeerId`] is now known which certainty.
4169
    HandshakeFinished {
4170
        /// Identifier of the connection.
4171
        id: ConnectionId,
4172
        /// Parameter that was passed to [`ChainNetwork::add_single_stream_connection`] or
4173
        /// [`ChainNetwork::add_multi_stream_connection`].
4174
        expected_peer_id: Option<PeerId>,
4175
        /// Actual [`PeerId`] of the connection.
4176
        peer_id: PeerId,
4177
    },
4178
4179
    /// A connection has shut down before finishing its handshake.
4180
    PreHandshakeDisconnected {
4181
        /// Identifier of the connection.
4182
        id: ConnectionId,
4183
        /// Parameter that was passed to [`ChainNetwork::add_single_stream_connection`] or
4184
        /// [`ChainNetwork::add_multi_stream_connection`].
4185
        address: Vec<u8>,
4186
        /// Parameter that was passed to [`ChainNetwork::add_single_stream_connection`] or
4187
        /// [`ChainNetwork::add_multi_stream_connection`].
4188
        expected_peer_id: Option<PeerId>,
4189
        /// User data that was passed to [`ChainNetwork::add_single_stream_connection`] or
4190
        /// [`ChainNetwork::add_multi_stream_connection`].
4191
        user_data: TConn,
4192
    },
4193
4194
    /// A connection has shut down after finishing its handshake.
4195
    Disconnected {
4196
        /// Identifier of the connection.
4197
        id: ConnectionId,
4198
        /// Parameter that was passed to [`ChainNetwork::add_single_stream_connection`] or
4199
        /// [`ChainNetwork::add_multi_stream_connection`].
4200
        address: Vec<u8>,
4201
        /// Peer that was connected.
4202
        peer_id: PeerId,
4203
        /// User data that was passed to [`ChainNetwork::add_single_stream_connection`] or
4204
        /// [`ChainNetwork::add_multi_stream_connection`].
4205
        user_data: TConn,
4206
    },
4207
4208
    /// The ping of a connection has been measured.
4209
    PingOutSuccess {
4210
        /// Identifier of the connection.
4211
        id: ConnectionId,
4212
        /// [`PeerId`] of the connection.
4213
        peer_id: PeerId,
4214
        /// Time between sending the ping and receiving the pong.
4215
        ping_time: Duration,
4216
    },
4217
4218
    /// Now connected to the given peer for gossiping purposes.
4219
    ///
4220
    /// This event can only happen as a result of a call to [`ChainNetwork::gossip_open`].
4221
    GossipConnected {
4222
        /// Peer we are now connected to.
4223
        peer_id: PeerId,
4224
        /// Chain of the gossip connection.
4225
        chain_id: ChainId,
4226
        /// Which kind of gossip link is concerned.
4227
        kind: GossipKind,
4228
        /// Role the node reports playing on the network.
4229
        role: Role,
4230
        /// Height of the best block according to this node.
4231
        best_number: u64,
4232
        /// Hash of the best block according to this node.
4233
        best_hash: [u8; 32],
4234
    },
4235
4236
    /// An attempt has been made to open the given chain, but something wrong happened.
4237
    ///
4238
    /// This event can only happen as a result of a call to [`ChainNetwork::gossip_open`].
4239
    GossipOpenFailed {
4240
        /// Peer concerned by the event.
4241
        peer_id: PeerId,
4242
        /// Chain of the gossip connection.
4243
        chain_id: ChainId,
4244
        /// Which kind of gossip link is concerned.
4245
        kind: GossipKind,
4246
        /// Problem that happened.
4247
        error: GossipConnectError,
4248
    },
4249
4250
    /// No longer connected to the given peer for gossiping purposes.
4251
    GossipDisconnected {
4252
        /// Peer we are no longer connected to.
4253
        peer_id: PeerId,
4254
        /// Chain of the gossip connection.
4255
        chain_id: ChainId,
4256
        /// Which kind of gossip link is concerned.
4257
        kind: GossipKind,
4258
    },
4259
4260
    /// A peer would like to open a gossiping link with the local node.
4261
    // TODO: document what to do
4262
    // TODO: include handshake content?
4263
    GossipInDesired {
4264
        /// Peer concerned by the event.
4265
        peer_id: PeerId,
4266
        /// Chain of the gossip connection.
4267
        chain_id: ChainId,
4268
        /// Which kind of gossip link is concerned.
4269
        kind: GossipKind,
4270
    },
4271
4272
    /// A previously-emitted [`Event::GossipInDesired`] is no longer relevant as the peer has
4273
    /// stopped the opening attempt.
4274
    GossipInDesiredCancel {
4275
        /// Peer concerned by the event.
4276
        peer_id: PeerId,
4277
        /// Chain of the gossip connection.
4278
        chain_id: ChainId,
4279
        /// Which kind of gossip link is concerned.
4280
        kind: GossipKind,
4281
    },
4282
4283
    /// An outgoing request has finished, either successfully or not.
4284
    RequestResult {
4285
        /// Peer that has answered the request.
4286
        peer_id: PeerId,
4287
        /// Index of the chain the request relates to.
4288
        chain_id: ChainId,
4289
        /// Identifier of the request that was returned by the function that started the request.
4290
        substream_id: SubstreamId,
4291
        /// Outcome of the request.
4292
        response: RequestResult,
4293
    },
4294
4295
    /// Received a new block announce from a peer.
4296
    ///
4297
    /// Can only happen after a [`Event::GossipConnected`] with the given [`PeerId`] and [`ChainId`]
4298
    /// combination has happened.
4299
    BlockAnnounce {
4300
        /// Identity of the sender of the block announce.
4301
        peer_id: PeerId,
4302
        /// Index of the chain the block relates to.
4303
        chain_id: ChainId,
4304
        announce: EncodedBlockAnnounce,
4305
    },
4306
4307
    /// Received a GrandPa neighbor packet from the network. This contains an update to the
4308
    /// finality state of the given peer.
4309
    ///
4310
    /// Can only happen after a [`Event::GossipConnected`] with the given [`PeerId`] and [`ChainId`]
4311
    /// combination has happened.
4312
    GrandpaNeighborPacket {
4313
        /// Identity of the sender of the message.
4314
        peer_id: PeerId,
4315
        /// Index of the chain the message relates to.
4316
        chain_id: ChainId,
4317
        /// State of the remote.
4318
        state: GrandpaState,
4319
    },
4320
4321
    /// Received a GrandPa commit message from the network.
4322
    ///
4323
    /// Can only happen after a [`Event::GossipConnected`] with the given [`PeerId`] and [`ChainId`]
4324
    /// combination has happened.
4325
    GrandpaCommitMessage {
4326
        /// Identity of the sender of the message.
4327
        peer_id: PeerId,
4328
        /// Index of the chain the commit message relates to.
4329
        chain_id: ChainId,
4330
        message: EncodedGrandpaCommitMessage,
4331
    },
4332
4333
    /// Error in the protocol in a connection, such as failure to decode a message. This event
4334
    /// doesn't have any consequence on the health of the connection, and is purely for diagnostic
4335
    /// purposes.
4336
    // TODO: review the concept of protocol error
4337
    ProtocolError {
4338
        /// Peer that has caused the protocol error.
4339
        peer_id: PeerId,
4340
        /// Error that happened.
4341
        error: ProtocolError,
4342
    },
4343
4344
    /// A remote has sent a request for identification information.
4345
    ///
4346
    /// You are strongly encouraged to call [`ChainNetwork::respond_identify`].
4347
    IdentifyRequestIn {
4348
        /// Remote that has sent the request.
4349
        peer_id: PeerId,
4350
        /// Identifier of the request. Necessary to send back the answer.
4351
        substream_id: SubstreamId,
4352
    },
4353
4354
    /// A remote has sent a request for blocks.
4355
    ///
4356
    /// Can only happen for chains where [`ChainConfig::allow_inbound_block_requests`] is `true`.
4357
    ///
4358
    /// You are strongly encouraged to call [`ChainNetwork::respond_blocks`].
4359
    BlocksRequestIn {
4360
        /// Remote that has sent the request.
4361
        peer_id: PeerId,
4362
        /// Index of the chain concerned by the request.
4363
        chain_id: ChainId,
4364
        /// Information about the request.
4365
        config: codec::BlocksRequestConfig,
4366
        /// Identifier of the request. Necessary to send back the answer.
4367
        substream_id: SubstreamId,
4368
    },
4369
4370
    /// A remote is no longer interested in the response to a request.
4371
    ///
4372
    /// Calling [`ChainNetwork::respond_identify`], [`ChainNetwork::respond_blocks`], or similar
4373
    /// will now panic.
4374
    RequestInCancel {
4375
        /// Identifier of the request.
4376
        ///
4377
        /// This [`SubstreamId`] is considered dead and no longer valid.
4378
        substream_id: SubstreamId,
4379
    },
4380
    /*Transactions {
4381
        peer_id: PeerId,
4382
        transactions: EncodedTransactions,
4383
    }*/
4384
}
4385
4386
/// See [`Event::ProtocolError`].
4387
// TODO: reexport these error types
4388
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1r_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_13ProtocolErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1r_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_13ProtocolErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4389
pub enum ProtocolError {
4390
    /// Error in an incoming substream.
4391
    #[display(fmt = "Error in an incoming substream: {_0}")]
4392
    InboundError(InboundError),
4393
    /// Error while decoding the handshake of the block announces substream.
4394
    #[display(fmt = "Error while decoding the handshake of the block announces substream: {_0}")]
4395
    BadBlockAnnouncesHandshake(BlockAnnouncesHandshakeDecodeError),
4396
    /// Error while decoding a received block announce.
4397
    #[display(fmt = "Error while decoding a received block announce: {_0}")]
4398
    BadBlockAnnounce(codec::DecodeBlockAnnounceError),
4399
    /// Error while decoding a received Grandpa notification.
4400
    #[display(fmt = "Error while decoding a received Grandpa notification: {_0}")]
4401
    BadGrandpaNotification(codec::DecodeGrandpaNotificationError),
4402
    /// Received an invalid identify request.
4403
    BadIdentifyRequest,
4404
    /// Error while decoding a received blocks request.
4405
    #[display(fmt = "Error while decoding a received blocks request: {_0}")]
4406
    BadBlocksRequest(codec::DecodeBlockRequestError),
4407
}
4408
4409
/// Error potentially returned by [`ChainNetwork::gossip_open`].
4410
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs1u_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_15OpenGossipErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1u_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_15OpenGossipErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4411
pub enum OpenGossipError {
4412
    /// No healthy established connection is available to open the link.
4413
    NoConnection,
4414
    /// There already is a pending or fully opened gossip link with the given peer.
4415
    AlreadyOpened,
4416
}
4417
4418
/// Error potentially returned by [`ChainNetwork::gossip_close`].
4419
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs1x_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_16CloseGossipErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1x_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_16CloseGossipErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4420
pub enum CloseGossipError {
4421
    /// There exists no outgoing nor ingoing attempt at a gossip link.
4422
    NotOpen,
4423
}
4424
4425
/// Error potentially returned when starting a request.
4426
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs1A_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_17StartRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1A_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_17StartRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4427
pub enum StartRequestError {
4428
    /// There is no valid connection to the given peer on which the request can be started.
4429
    NoConnection,
4430
}
4431
4432
/// Error potentially returned when starting a request that might be too large.
4433
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs1D_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_30StartRequestMaybeTooLargeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1D_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_30StartRequestMaybeTooLargeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4434
pub enum StartRequestMaybeTooLargeError {
4435
    /// There is no valid connection to the given peer on which the request can be started.
4436
    NoConnection,
4437
    /// Size of the request is over maximum allowed by the protocol.
4438
    RequestTooLarge,
4439
}
4440
4441
impl From<StartRequestError> for StartRequestMaybeTooLargeError {
4442
0
    fn from(err: StartRequestError) -> StartRequestMaybeTooLargeError {
4443
0
        match err {
4444
0
            StartRequestError::NoConnection => StartRequestMaybeTooLargeError::NoConnection,
4445
0
        }
4446
0
    }
Unexecuted instantiation: _RNvXs5_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_30StartRequestMaybeTooLargeErrorINtNtCsaYZPK01V26L_4core7convert4FromNtB5_17StartRequestErrorE4from
Unexecuted instantiation: _RNvXs5_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_30StartRequestMaybeTooLargeErrorINtNtCsaYZPK01V26L_4core7convert4FromNtB5_17StartRequestErrorE4from
4447
}
4448
4449
/// Response to an outgoing request.
4450
///
4451
/// See [`Event::RequestResult`̀].
4452
#[derive(Debug)]
4453
pub enum RequestResult {
4454
    Blocks(Result<Vec<codec::BlockData>, BlocksRequestError>),
4455
    GrandpaWarpSync(Result<EncodedGrandpaWarpSyncResponse, GrandpaWarpSyncRequestError>),
4456
    State(Result<EncodedStateResponse, StateRequestError>),
4457
    StorageProof(Result<EncodedMerkleProof, StorageProofRequestError>),
4458
    CallProof(Result<EncodedMerkleProof, CallProofRequestError>),
4459
    KademliaFindNode(Result<Vec<(peer_id::PeerId, Vec<Vec<u8>>)>, KademliaFindNodeError>),
4460
}
4461
4462
/// Error returned by [`ChainNetwork::start_blocks_request`].
4463
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1G_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_18BlocksRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1G_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_18BlocksRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4464
pub enum BlocksRequestError {
4465
    /// Error while waiting for the response from the peer.
4466
    #[display(fmt = "{_0}")]
4467
    Request(RequestError),
4468
    /// Error while decoding the response returned by the peer.
4469
    #[display(fmt = "Response decoding error: {_0}")]
4470
    Decode(codec::DecodeBlockResponseError),
4471
}
4472
4473
/// Error returned by [`ChainNetwork::start_storage_proof_request`].
4474
0
#[derive(Debug, derive_more::Display, Clone)]
Unexecuted instantiation: _RNvXs1I_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_24StorageProofRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1I_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_24StorageProofRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4475
pub enum StorageProofRequestError {
4476
    #[display(fmt = "{_0}")]
4477
    Request(RequestError),
4478
    #[display(fmt = "Response decoding error: {_0}")]
4479
    Decode(codec::DecodeStorageCallProofResponseError),
4480
    /// The remote is incapable of answering this specific request.
4481
    RemoteCouldntAnswer,
4482
}
4483
4484
/// Error returned by [`ChainNetwork::start_call_proof_request`].
4485
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs1M_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_21CallProofRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1M_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_21CallProofRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4486
pub enum CallProofRequestError {
4487
    #[display(fmt = "{_0}")]
4488
    Request(RequestError),
4489
    #[display(fmt = "Response decoding error: {_0}")]
4490
    Decode(codec::DecodeStorageCallProofResponseError),
4491
    /// The remote is incapable of answering this specific request.
4492
    RemoteCouldntAnswer,
4493
}
4494
4495
impl CallProofRequestError {
4496
    /// Returns `true` if this is caused by networking issues, as opposed to a consensus-related
4497
    /// issue.
4498
0
    pub fn is_network_problem(&self) -> bool {
4499
0
        match self {
4500
0
            CallProofRequestError::Request(_) => true,
4501
0
            CallProofRequestError::Decode(_) => false,
4502
0
            CallProofRequestError::RemoteCouldntAnswer => true,
4503
        }
4504
0
    }
Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_21CallProofRequestError18is_network_problem
Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_21CallProofRequestError18is_network_problem
4505
}
4506
4507
/// Error returned by [`ChainNetwork::start_grandpa_warp_sync_request`].
4508
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1O_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_27GrandpaWarpSyncRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1O_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_27GrandpaWarpSyncRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4509
pub enum GrandpaWarpSyncRequestError {
4510
    #[display(fmt = "{_0}")]
4511
    Request(RequestError),
4512
    #[display(fmt = "Response decoding error: {_0}")]
4513
    Decode(codec::DecodeGrandpaWarpSyncResponseError),
4514
}
4515
4516
/// Error returned by [`ChainNetwork::start_state_request`].
4517
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1Q_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_17StateRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1Q_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_17StateRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4518
pub enum StateRequestError {
4519
    #[display(fmt = "{_0}")]
4520
    Request(RequestError),
4521
    #[display(fmt = "Response decoding error: {_0}")]
4522
    Decode(codec::DecodeStateResponseError),
4523
}
4524
4525
/// Error during [`ChainNetwork::start_kademlia_find_node_request`].
4526
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1S_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_21KademliaFindNodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1S_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_21KademliaFindNodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4527
pub enum KademliaFindNodeError {
4528
    /// Error during the request.
4529
    #[display(fmt = "{_0}")]
4530
    RequestFailed(RequestError),
4531
    /// Failed to decode the response.
4532
    #[display(fmt = "Response decoding error: {_0}")]
4533
    DecodeError(codec::DecodeFindNodeResponseError),
4534
}
4535
4536
/// Error potentially returned when queueing a notification.
4537
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs1U_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_22QueueNotificationErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1U_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_22QueueNotificationErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4538
pub enum QueueNotificationError {
4539
    /// There is no valid substream to the given peer on which the notification can be sent.
4540
    NoConnection,
4541
    /// Queue of notifications with that peer is full.
4542
    QueueFull,
4543
}
4544
4545
/// Undecoded but valid block announce.
4546
#[derive(Clone)]
4547
pub struct EncodedBlockAnnounce {
4548
    message: Vec<u8>,
4549
    block_number_bytes: usize,
4550
}
4551
4552
impl EncodedBlockAnnounce {
4553
    /// Returns the decoded version of the announcement.
4554
0
    pub fn decode(&self) -> codec::BlockAnnounceRef {
4555
0
        codec::decode_block_announce(&self.message, self.block_number_bytes).unwrap()
4556
0
    }
Unexecuted instantiation: _RNvMs7_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_20EncodedBlockAnnounce6decode
Unexecuted instantiation: _RNvMs7_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_20EncodedBlockAnnounce6decode
4557
}
4558
4559
impl fmt::Debug for EncodedBlockAnnounce {
4560
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4561
0
        fmt::Debug::fmt(&self.decode(), f)
4562
0
    }
Unexecuted instantiation: _RNvXs8_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_20EncodedBlockAnnounceNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs8_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_20EncodedBlockAnnounceNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4563
}
4564
4565
/// Undecoded but valid Merkle proof.
4566
#[derive(Clone)]
4567
pub struct EncodedMerkleProof(Vec<u8>, codec::StorageOrCallProof);
4568
4569
impl EncodedMerkleProof {
4570
    /// Returns the SCALE-encoded Merkle proof.
4571
0
    pub fn decode(&self) -> &[u8] {
4572
0
        codec::decode_storage_or_call_proof_response(self.1, &self.0)
4573
0
            .unwrap()
4574
0
            .unwrap()
4575
0
    }
Unexecuted instantiation: _RNvMs9_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_18EncodedMerkleProof6decode
Unexecuted instantiation: _RNvMs9_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_18EncodedMerkleProof6decode
4576
}
4577
4578
impl fmt::Debug for EncodedMerkleProof {
4579
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4580
0
        fmt::Debug::fmt(&self.decode(), f)
4581
0
    }
Unexecuted instantiation: _RNvXsa_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_18EncodedMerkleProofNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXsa_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_18EncodedMerkleProofNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4582
}
4583
4584
/// Undecoded but valid GrandPa warp sync response.
4585
#[derive(Clone)]
4586
pub struct EncodedGrandpaWarpSyncResponse {
4587
    message: Vec<u8>,
4588
    block_number_bytes: usize,
4589
}
4590
4591
impl EncodedGrandpaWarpSyncResponse {
4592
    /// Returns the encoded bytes of the warp sync message.
4593
0
    pub fn as_encoded(&self) -> &[u8] {
4594
0
        &self.message
4595
0
    }
Unexecuted instantiation: _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponse10as_encoded
Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponse10as_encoded
4596
4597
    /// Returns the decoded version of the warp sync message.
4598
0
    pub fn decode(&self) -> codec::GrandpaWarpSyncResponse {
4599
0
        match codec::decode_grandpa_warp_sync_response(&self.message, self.block_number_bytes) {
4600
0
            Ok(msg) => msg,
4601
0
            _ => unreachable!(),
4602
        }
4603
0
    }
Unexecuted instantiation: _RNvMsb_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponse6decode
Unexecuted instantiation: _RNvMsb_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponse6decode
4604
}
4605
4606
impl fmt::Debug for EncodedGrandpaWarpSyncResponse {
4607
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4608
0
        fmt::Debug::fmt(&self.decode(), f)
4609
0
    }
Unexecuted instantiation: _RNvXsc_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXsc_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_30EncodedGrandpaWarpSyncResponseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4610
}
4611
4612
/// Undecoded but valid state response.
4613
// TODO: merge with EncodedMerkleProof?
4614
#[derive(Clone)]
4615
pub struct EncodedStateResponse(Vec<u8>);
4616
4617
impl EncodedStateResponse {
4618
    /// Returns the Merkle proof of the state response.
4619
0
    pub fn decode(&self) -> &[u8] {
4620
0
        match codec::decode_state_response(&self.0) {
4621
0
            Ok(r) => r,
4622
0
            Err(_) => unreachable!(),
4623
        }
4624
0
    }
Unexecuted instantiation: _RNvMsd_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_20EncodedStateResponse6decode
Unexecuted instantiation: _RNvMsd_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_20EncodedStateResponse6decode
4625
}
4626
4627
impl fmt::Debug for EncodedStateResponse {
4628
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4629
0
        fmt::Debug::fmt(&self.decode(), f)
4630
0
    }
Unexecuted instantiation: _RNvXse_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_20EncodedStateResponseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXse_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_20EncodedStateResponseNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4631
}
4632
4633
#[derive(Debug, Copy, Clone)]
4634
// TODO: link to some doc about how GrandPa works: what is a round, what is the set id, etc.
4635
pub struct GrandpaState {
4636
    pub round_number: u64,
4637
    /// Set of authorities that will be used by the node to try finalize the children of the block
4638
    /// of [`GrandpaState::commit_finalized_height`].
4639
    pub set_id: u64,
4640
    /// Height of the highest block considered final by the node.
4641
    pub commit_finalized_height: u64,
4642
}
4643
4644
/// Undecoded but valid block announce handshake.
4645
pub struct EncodedBlockAnnounceHandshake {
4646
    handshake: Vec<u8>,
4647
    block_number_bytes: usize,
4648
}
4649
4650
impl EncodedBlockAnnounceHandshake {
4651
    /// Returns the decoded version of the handshake.
4652
0
    pub fn decode(&self) -> codec::BlockAnnouncesHandshakeRef {
4653
0
        codec::decode_block_announces_handshake(self.block_number_bytes, &self.handshake).unwrap()
4654
0
    }
Unexecuted instantiation: _RNvMsf_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_29EncodedBlockAnnounceHandshake6decode
Unexecuted instantiation: _RNvMsf_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_29EncodedBlockAnnounceHandshake6decode
4655
}
4656
4657
impl fmt::Debug for EncodedBlockAnnounceHandshake {
4658
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4659
0
        fmt::Debug::fmt(&self.decode(), f)
4660
0
    }
Unexecuted instantiation: _RNvXsg_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_29EncodedBlockAnnounceHandshakeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXsg_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_29EncodedBlockAnnounceHandshakeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4661
}
4662
4663
/// Error that can happen when trying to open an outbound block announces notifications substream.
4664
0
#[derive(Debug, Clone, derive_more::Display)]
Unexecuted instantiation: _RNvXs24_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB6_18GossipConnectErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs24_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB6_18GossipConnectErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
4665
pub enum GossipConnectError {
4666
    /// Error in the underlying protocol.
4667
    #[display(fmt = "{_0}")]
4668
    Substream(NotificationsOutErr),
4669
    /// Error decoding the block announces handshake.
4670
    HandshakeDecode(BlockAnnouncesHandshakeDecodeError),
4671
    /// Mismatch between the genesis hash of the remote and the local genesis hash.
4672
    #[display(fmt = "Mismatch between the genesis hash of the remote and the local genesis hash")]
4673
    GenesisMismatch {
4674
        /// Hash of the genesis block of the chain according to the local node.
4675
        local_genesis: [u8; 32],
4676
        /// Hash of the genesis block of the chain according to the remote node.
4677
        remote_genesis: [u8; 32],
4678
    },
4679
}
4680
4681
/// Undecoded but valid GrandPa commit message.
4682
#[derive(Clone)]
4683
pub struct EncodedGrandpaCommitMessage {
4684
    message: Vec<u8>,
4685
    block_number_bytes: usize,
4686
}
4687
4688
impl EncodedGrandpaCommitMessage {
4689
    /// Returns the encoded bytes of the commit message.
4690
0
    pub fn into_encoded(mut self) -> Vec<u8> {
4691
0
        // Skip the first byte because `self.message` is a `GrandpaNotificationRef`.
4692
0
        self.message.remove(0);
4693
0
        self.message
4694
0
    }
Unexecuted instantiation: _RNvMsh_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage12into_encoded
Unexecuted instantiation: _RNvMsh_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage12into_encoded
4695
4696
    /// Returns the encoded bytes of the commit message.
4697
0
    pub fn as_encoded(&self) -> &[u8] {
4698
0
        // Skip the first byte because `self.message` is a `GrandpaNotificationRef`.
4699
0
        &self.message[1..]
4700
0
    }
Unexecuted instantiation: _RNvMsh_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage10as_encoded
Unexecuted instantiation: _RNvMsh_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage10as_encoded
4701
4702
    /// Returns the decoded version of the commit message.
4703
0
    pub fn decode(&self) -> codec::CommitMessageRef {
4704
0
        match codec::decode_grandpa_notification(&self.message, self.block_number_bytes) {
4705
0
            Ok(codec::GrandpaNotificationRef::Commit(msg)) => msg,
4706
0
            _ => unreachable!(),
4707
        }
4708
0
    }
Unexecuted instantiation: _RNvMsh_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage6decode
Unexecuted instantiation: _RNvMsh_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessage6decode
4709
}
4710
4711
impl fmt::Debug for EncodedGrandpaCommitMessage {
4712
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4713
0
        fmt::Debug::fmt(&self.decode(), f)
4714
0
    }
Unexecuted instantiation: _RNvXsi_NtNtCsN16ciHI6Qf_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessageNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXsi_NtNtCseuYC0Zibziv_7smoldot7network7serviceNtB5_27EncodedGrandpaCommitMessageNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt
4715
}