Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/full-node/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
#![deny(rustdoc::broken_intra_doc_links)]
19
// TODO: #![deny(unused_crate_dependencies)] doesn't work because some deps are used only by the binary, figure if this can be fixed?
20
21
use futures_util::{future, StreamExt as _};
22
use rand::RngCore as _;
23
use smol::lock::Mutex;
24
use smoldot::{
25
    chain, chain_spec,
26
    database::full_sqlite,
27
    executor, header,
28
    identity::keystore,
29
    informant::HashDisplay,
30
    libp2p::{
31
        connection, multiaddr,
32
        peer_id::{self, PeerId},
33
    },
34
    trie,
35
};
36
use std::{array, borrow::Cow, io, iter, mem, net::SocketAddr, path::PathBuf, sync::Arc};
37
38
mod consensus_service;
39
mod database_thread;
40
mod jaeger_service;
41
mod json_rpc_service;
42
mod network_service;
43
mod util;
44
45
pub struct Config<'a> {
46
    /// Chain to connect to.
47
    pub chain: ChainConfig<'a>,
48
    /// If [`Config::chain`] contains a parachain, this field contains the configuration of the
49
    /// relay chain.
50
    pub relay_chain: Option<ChainConfig<'a>>,
51
    /// Ed25519 private key of network identity.
52
    pub libp2p_key: Box<[u8; 32]>,
53
    /// List of addresses to listen on.
54
    pub listen_addresses: Vec<multiaddr::Multiaddr>,
55
    /// Function that can be used to spawn background tasks.
56
    ///
57
    /// The tasks passed as parameter must be executed until they shut down.
58
    pub tasks_executor: Arc<dyn Fn(future::BoxFuture<'static, ()>) + Send + Sync>,
59
    /// Function called whenever a part of the node wants to notify of something.
60
    pub log_callback: Arc<dyn LogCallback + Send + Sync>,
61
    /// Address of a Jaeger agent to send traces to. If `None`, do not send Jaeger traces.
62
    pub jaeger_agent: Option<SocketAddr>,
63
}
64
65
/// See [`ChainConfig::json_rpc_listen`].
66
#[derive(Debug, Clone)]
67
pub struct JsonRpcListenConfig {
68
    /// Bind point of the JSON-RPC server.
69
    pub address: SocketAddr,
70
    /// Maximum number of JSON-RPC clients that can be connected at the same time.
71
    pub max_json_rpc_clients: u32,
72
}
73
74
/// Allow generating logs.
75
///
76
/// Implemented on closures.
77
///
78
/// > **Note**: The `log` crate isn't used because dependencies complete pollute the logs.
79
pub trait LogCallback {
80
    /// Add a log entry.
81
    fn log(&self, log_level: LogLevel, message: String);
82
}
83
84
impl<T: ?Sized + Fn(LogLevel, String)> LogCallback for T {
85
42
    fn log(&self, log_level: LogLevel, message: String) {
86
42
        (*self)(log_level, message)
87
42
    }
_RNvXCsiUjFBJteJ7x_17smoldot_full_nodeNCNCNvCsiLzmwikkc22_14json_rpc_basics_30send_request_errs_if_malformed0s_0NtB2_11LogCallback3logBF_
Line
Count
Source
85
2
    fn log(&self, log_level: LogLevel, message: String) {
86
2
        (*self)(log_level, message)
87
2
    }
_RNvXCsiUjFBJteJ7x_17smoldot_full_nodeNCNCNvCsiLzmwikkc22_14json_rpc_basics_37send_request_works_if_unknown_request0s_0NtB2_11LogCallback3logBF_
Line
Count
Source
85
2
    fn log(&self, log_level: LogLevel, message: String) {
86
2
        (*self)(log_level, message)
87
2
    }
Unexecuted instantiation: _RNvXINICsiUjFBJteJ7x_17smoldot_full_node0pEpNtB5_11LogCallback3logB5_
Unexecuted instantiation: _RNvXCsiUjFBJteJ7x_17smoldot_full_nodeNCNCNvCscDgN54JpMGG_6authors_21basic_block_generated0s_0NtB2_11LogCallback3logBF_
_RNvXCsiUjFBJteJ7x_17smoldot_full_nodeNCNCNvCsibGXYHQB8Ea_25json_rpc_general_requests12start_client0s_0NtB2_11LogCallback3logBF_
Line
Count
Source
85
38
    fn log(&self, log_level: LogLevel, message: String) {
86
38
        (*self)(log_level, message)
87
38
    }
Unexecuted instantiation: _RNvXINICshBwayKnNXDT_17smoldot_full_node0pEpNtB5_11LogCallback3logB5_
88
}
89
90
/// Log level of a log entry.
91
#[derive(Debug)]
92
pub enum LogLevel {
93
    Error = 1,
94
    Warn = 2,
95
    Info = 3,
96
    Debug = 4,
97
    Trace = 5,
98
}
99
100
#[derive(Debug)]
101
pub struct ChainConfig<'a> {
102
    /// Specification of the chain.
103
    pub chain_spec: Cow<'a, [u8]>,
104
    /// Identity and address of nodes to try to connect to on startup.
105
    pub additional_bootnodes: Vec<(peer_id::PeerId, multiaddr::Multiaddr)>,
106
    /// List of secret phrases to insert in the keystore of the node. Used to author blocks.
107
    // TODO: also automatically add the same keys through ed25519?
108
    pub keystore_memory: Vec<Box<[u8; 64]>>,
109
    /// Path to the SQLite database. If `None`, the database is opened in memory.
110
    pub sqlite_database_path: Option<PathBuf>,
111
    /// Maximum size, in bytes, of the cache SQLite uses.
112
    pub sqlite_cache_size: usize,
113
    /// Path to the directory where cryptographic keys are stored on disk.
114
    ///
115
    /// If `None`, no keys are stored in disk.
116
    pub keystore_path: Option<PathBuf>,
117
    /// Configuration of the JSON-RPC server. If `None`, no TCP server is started.
118
    pub json_rpc_listen: Option<JsonRpcListenConfig>,
119
}
120
121
/// Running client. As long as this object is alive, the client reads/writes the database and has
122
/// a JSON-RPC server open.
123
pub struct Client {
124
    json_rpc_service: json_rpc_service::JsonRpcService,
125
    relay_chain_json_rpc_service: Option<json_rpc_service::JsonRpcService>,
126
    consensus_service: Arc<consensus_service::ConsensusService>,
127
    relay_chain_consensus_service: Option<Arc<consensus_service::ConsensusService>>,
128
    network_service: Arc<network_service::NetworkService>,
129
    network_known_best: Arc<Mutex<Option<u64>>>,
130
}
131
132
impl Client {
133
    /// Returns the address the JSON-RPC server is listening on.
134
    ///
135
    /// Returns `None` if and only if [`ChainConfig::json_rpc_listen`] was `None`
136
    /// in [`Config::chain`].
137
0
    pub fn json_rpc_server_addr(&self) -> Option<SocketAddr> {
138
0
        self.json_rpc_service.listen_addr()
139
0
    }
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client20json_rpc_server_addr
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client20json_rpc_server_addr
140
141
    /// Returns the address the relay chain JSON-RPC server is listening on.
142
    ///
143
    /// Returns `None` if and only if [`Config::relay_chain`] was `None` or if
144
    /// [`ChainConfig::json_rpc_listen`] was `None` in [`Config::relay_chain`].
145
0
    pub fn relay_chain_json_rpc_server_addr(&self) -> Option<SocketAddr> {
146
0
        self.relay_chain_json_rpc_service
147
0
            .as_ref()
148
0
            .and_then(|j| j.listen_addr())
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client32relay_chain_json_rpc_server_addr0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client32relay_chain_json_rpc_server_addr0B6_
149
0
    }
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client32relay_chain_json_rpc_server_addr
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client32relay_chain_json_rpc_server_addr
150
151
    /// Returns the best block according to the networking.
152
0
    pub async fn network_known_best(&self) -> Option<u64> {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client18network_known_best
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client18network_known_best
153
0
        *self.network_known_best.lock().await
154
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client18network_known_best0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client18network_known_best0B6_
155
156
    /// Returns the current total number of peers of the client.
157
    // TODO: weird API
158
0
    pub async fn num_peers(&self) -> u64 {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client9num_peers
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client9num_peers
159
0
        u64::try_from(self.network_service.num_total_peers().await).unwrap_or(u64::MAX)
160
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client9num_peers0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client9num_peers0B6_
161
162
    /// Returns the current total number of network connections of the client.
163
    // TODO: weird API
164
0
    pub async fn num_network_connections(&self) -> u64 {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client23num_network_connections
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client23num_network_connections
165
0
        u64::try_from(self.network_service.num_connections().await).unwrap_or(u64::MAX)
166
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client23num_network_connections0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client23num_network_connections0B6_
167
168
    // TODO: not the best API
169
0
    pub async fn sync_state(&self) -> consensus_service::SyncState {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client10sync_state
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client10sync_state
170
0
        self.consensus_service.sync_state().await
171
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client10sync_state0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client10sync_state0B6_
172
173
    // TODO: not the best API
174
0
    pub async fn relay_chain_sync_state(&self) -> Option<consensus_service::SyncState> {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client22relay_chain_sync_state
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client22relay_chain_sync_state
175
0
        if let Some(s) = &self.relay_chain_consensus_service {
176
0
            Some(s.sync_state().await)
177
        } else {
178
0
            None
179
        }
180
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client22relay_chain_sync_state0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client22relay_chain_sync_state0B6_
181
182
    /// Adds a JSON-RPC request to the queue of requests of the virtual endpoint of the chain.
183
    ///
184
    /// The virtual endpoint doesn't have any limit.
185
25
    pub fn send_json_rpc_request(&self, request: String) {
186
25
        self.json_rpc_service.send_request(request)
187
25
    }
_RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client21send_json_rpc_request
Line
Count
Source
185
25
    pub fn send_json_rpc_request(&self, request: String) {
186
25
        self.json_rpc_service.send_request(request)
187
25
    }
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client21send_json_rpc_request
188
189
    /// Returns the new JSON-RPC response or notification for requests sent using
190
    /// [`Client::send_json_rpc_request`].
191
    ///
192
    /// If this function is called multiple times simultaneously, only one invocation will receive
193
    /// each response. Which one is unspecified.
194
25
    pub async fn next_json_rpc_response(&self) -> String {
_RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client22next_json_rpc_response
Line
Count
Source
194
25
    pub async fn next_json_rpc_response(&self) -> String {
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client22next_json_rpc_response
195
25
        self.json_rpc_service.next_response().
await14
196
25
    }
_RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client22next_json_rpc_response0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
194
2
    pub async fn next_json_rpc_response(&self) -> String {
195
2
        self.json_rpc_service.next_response().
await1
196
2
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client22next_json_rpc_response0B6_
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client22next_json_rpc_response0CscDgN54JpMGG_6author
_RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client22next_json_rpc_response0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
194
23
    pub async fn next_json_rpc_response(&self) -> String {
195
23
        self.json_rpc_service.next_response().
await13
196
23
    }
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client22next_json_rpc_response0B6_
197
198
    /// Adds a JSON-RPC request to the queue of requests of the virtual endpoint of the
199
    /// relay chain.
200
    ///
201
    /// The virtual endpoint doesn't have any limit.
202
0
    pub fn relay_chain_send_json_rpc_request(
203
0
        &self,
204
0
        request: String,
205
0
    ) -> Result<(), RelayChainSendJsonRpcRequestError> {
206
0
        let Some(relay_chain_json_rpc_service) = &self.relay_chain_json_rpc_service else {
207
0
            return Err(RelayChainSendJsonRpcRequestError::NoRelayChain);
208
        };
209
210
0
        relay_chain_json_rpc_service.send_request(request);
211
0
        Ok(())
212
0
    }
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client33relay_chain_send_json_rpc_request
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client33relay_chain_send_json_rpc_request
213
214
    /// Returns the new JSON-RPC response or notification for requests sent using
215
    /// [`Client::relay_chain_send_json_rpc_request`].
216
    ///
217
    /// If this function is called multiple times simultaneously, only one invocation will receive
218
    /// each response. Which one is unspecified.
219
    ///
220
    /// If [`Config::relay_chain`] was `None`, this function waits indefinitely.
221
0
    pub async fn relay_chain_next_json_rpc_response(&self) -> String {
Unexecuted instantiation: _RNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB4_6Client34relay_chain_next_json_rpc_response
Unexecuted instantiation: _RNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB4_6Client34relay_chain_next_json_rpc_response
222
0
        if let Some(relay_chain_json_rpc_service) = &self.relay_chain_json_rpc_service {
223
0
            relay_chain_json_rpc_service.next_response().await
224
        } else {
225
0
            future::pending().await
226
        }
227
0
    }
Unexecuted instantiation: _RNCNvMs_CsiUjFBJteJ7x_17smoldot_full_nodeNtB6_6Client34relay_chain_next_json_rpc_response0B6_
Unexecuted instantiation: _RNCNvMs_CshBwayKnNXDT_17smoldot_full_nodeNtB6_6Client34relay_chain_next_json_rpc_response0B6_
228
}
229
230
/// Error potentially returned by [`start`].
231
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs5_CsiUjFBJteJ7x_17smoldot_full_nodeNtB5_10StartErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs5_CshBwayKnNXDT_17smoldot_full_nodeNtB5_10StartErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
232
pub enum StartError {
233
    /// Failed to parse the chain specification.
234
    ChainSpecParse(chain_spec::ParseError),
235
    /// Error building the chain information of the genesis block.
236
    InvalidGenesisInformation(chain_spec::FromGenesisStorageError),
237
    /// Failed to parse the chain specification of the relay chain.
238
    RelayChainSpecParse(chain_spec::ParseError),
239
    /// Error building the chain information of the genesis block of the relay chain.
240
    InvalidRelayGenesisInformation(chain_spec::FromGenesisStorageError),
241
    /// Error initializing the networking service.
242
    NetworkInit(network_service::InitError),
243
    /// Error initializing the JSON-RPC service.
244
    JsonRpcServiceInit(json_rpc_service::InitError),
245
    /// Error initializing the JSON-RPC service of the relay chain.
246
    RelayChainJsonRpcServiceInit(json_rpc_service::InitError),
247
    ConsensusServiceInit(consensus_service::InitError),
248
    RelayChainConsensusServiceInit(consensus_service::InitError),
249
    /// Error initializing the keystore of the chain.
250
    KeystoreInit(io::Error),
251
    /// Error initializing the keystore of the relay chain.
252
    RelayChainKeystoreInit(io::Error),
253
    /// Error initializing the Jaeger service.
254
    JaegerInit(io::Error),
255
}
256
257
/// Error potentially returned by [`Client::relay_chain_send_json_rpc_request`].
258
0
#[derive(Debug, derive_more::Display)]
Unexecuted instantiation: _RNvXs7_CsiUjFBJteJ7x_17smoldot_full_nodeNtB5_33RelayChainSendJsonRpcRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs7_CshBwayKnNXDT_17smoldot_full_nodeNtB5_33RelayChainSendJsonRpcRequestErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
259
pub enum RelayChainSendJsonRpcRequestError {
260
    /// There is no relay chain to send the JSON-RPC request to.
261
    NoRelayChain,
262
}
263
264
/// Runs the node using the given configuration.
265
// TODO: this function has several code paths that panic instead of returning an error; it is especially unclear what to do in case of database corruption, given that a database corruption would crash the node later on anyway
266
21
pub async fn start(mut config: Config<'_>) -> Result<Client, StartError> {
_RNvCsiUjFBJteJ7x_17smoldot_full_node5start
Line
Count
Source
266
21
pub async fn start(mut config: Config<'_>) -> Result<Client, StartError> {
Unexecuted instantiation: _RNvCshBwayKnNXDT_17smoldot_full_node5start
267
21
    let chain_spec = {
268
21
        chain_spec::ChainSpec::from_json_bytes(&config.chain.chain_spec)
269
21
            .map_err(StartError::ChainSpecParse)
?0
270
    };
271
272
    // TODO: don't just throw away the runtime
273
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
274
21
    let genesis_chain_information = chain_spec
275
21
        .to_chain_information()
276
21
        .map_err(StartError::InvalidGenesisInformation)
?0
277
        .0;
278
279
21
    let relay_chain_spec = match &config.relay_chain {
280
0
        Some(cfg) => Some(
281
0
            chain_spec::ChainSpec::from_json_bytes(&cfg.chain_spec)
282
0
                .map_err(StartError::RelayChainSpecParse)?,
283
        ),
284
21
        None => None,
285
    };
286
287
    // TODO: don't just throw away the runtime
288
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
289
21
    let relay_genesis_chain_information = match &relay_chain_spec {
290
0
        Some(r) => Some(
291
0
            r.to_chain_information()
292
0
                .map_err(StartError::InvalidRelayGenesisInformation)?
293
                .0,
294
        ),
295
21
        None => None,
296
    };
297
298
    // The `protocolId` field of chain specifications is deprecated. Print a warning.
299
21
    if chain_spec.protocol_id().is_some() {
300
0
        config.log_callback.log(
301
0
            LogLevel::Warn,
302
0
            format!("chain-spec-has-protocol-id; chain={}", chain_spec.id()),
303
0
        );
304
21
    }
305
21
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
306
0
        if relay_chain_spec.protocol_id().is_some() {
307
0
            config.log_callback.log(
308
0
                LogLevel::Warn,
309
0
                format!(
310
0
                    "chain-spec-has-protocol-id; chain={}",
311
0
                    relay_chain_spec.id()
312
0
                ),
313
0
            );
314
0
        }
315
21
    }
316
317
    // The `telemetryEndpoints` field of chain specifications isn't supported.
318
21
    if chain_spec.telemetry_endpoints().count() != 0 {
319
0
        config.log_callback.log(
320
0
            LogLevel::Warn,
321
0
            format!(
322
0
                "chain-spec-has-telemetry-endpoints; chain={}",
323
0
                chain_spec.id()
324
0
            ),
325
0
        );
326
21
    }
327
21
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
328
0
        if relay_chain_spec.telemetry_endpoints().count() != 0 {
329
0
            config.log_callback.log(
330
0
                LogLevel::Warn,
331
0
                format!(
332
0
                    "chain-spec-has-telemetry-endpoints; chain={}",
333
0
                    relay_chain_spec.id()
334
0
                ),
335
0
            );
336
0
        }
337
21
    }
338
339
    // Printing the SQLite version number can be useful for debugging purposes for example in case
340
    // a query fails.
341
21
    config.log_callback.log(
342
21
        LogLevel::Debug,
343
21
        format!("sqlite-version; version={}", full_sqlite::sqlite_version()),
344
21
    );
345
346
21
    let (database, database_existed) = {
347
21
        let (db, existed) = open_database(
348
21
            &chain_spec,
349
21
            genesis_chain_information.as_ref(),
350
21
            config.chain.sqlite_database_path,
351
21
            config.chain.sqlite_cache_size,
352
21
        )
353
0
        .await;
354
355
21
        (Arc::new(database_thread::DatabaseThread::from(db)), existed)
356
    };
357
358
21
    let relay_chain_database = if let Some(
relay_chain0
) = &config.relay_chain {
359
        Some(Arc::new(database_thread::DatabaseThread::from(
360
0
            open_database(
361
0
                relay_chain_spec.as_ref().unwrap(),
362
0
                relay_genesis_chain_information.as_ref().unwrap().as_ref(),
363
0
                relay_chain.sqlite_database_path.clone(),
364
0
                relay_chain.sqlite_cache_size,
365
0
            )
366
0
            .await
367
            .0,
368
        )))
369
    } else {
370
21
        None
371
    };
372
373
21
    let database_finalized_block_hash = database
374
21
        .with_database(|db| db.finalized_block_hash().unwrap())
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start00CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
374
2
        .with_database(|db| db.finalized_block_hash().unwrap())
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start00B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start00CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start00CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
374
19
        .with_database(|db| db.finalized_block_hash().unwrap())
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start00B5_
375
21
        .await;
376
21
    let database_finalized_block_number = header::decode(
377
21
        &database
378
21
            .with_database(move |db| {
379
21
                db.block_scale_encoded_header(&database_finalized_block_hash)
380
21
                    .unwrap()
381
21
                    .unwrap()
382
21
            })
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
378
2
            .with_database(move |db| {
379
2
                db.block_scale_encoded_header(&database_finalized_block_hash)
380
2
                    .unwrap()
381
2
                    .unwrap()
382
2
            })
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
378
19
            .with_database(move |db| {
379
19
                db.block_scale_encoded_header(&database_finalized_block_hash)
380
19
                    .unwrap()
381
19
                    .unwrap()
382
19
            })
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s_0B5_
383
21
            .await,
384
21
        chain_spec.block_number_bytes().into(),
385
21
    )
386
21
    .unwrap()
387
21
    .number;
388
21
389
21
    let noise_key = {
390
21
        let mut noise_static_key = zeroize::Zeroizing::new([0u8; 32]);
391
21
        rand::thread_rng().fill_bytes(&mut *noise_static_key);
392
21
        connection::NoiseKey::new(&config.libp2p_key, &noise_static_key)
393
21
    };
394
21
    zeroize::Zeroize::zeroize(&mut *config.libp2p_key);
395
21
    let local_peer_id =
396
21
        peer_id::PublicKey::Ed25519(*noise_key.libp2p_public_ed25519_key()).into_peer_id();
397
21
398
21
    let genesis_block_hash = genesis_chain_information
399
21
        .as_ref()
400
21
        .finalized_block_header
401
21
        .hash(chain_spec.block_number_bytes().into());
402
403
21
    let jaeger_service = jaeger_service::JaegerService::new(jaeger_service::Config {
404
21
        tasks_executor: &mut |task| 
(config.tasks_executor)(task)0
,
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s0_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s0_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s0_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s0_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s0_0B5_
405
21
        service_name: local_peer_id.to_string(),
406
21
        jaeger_agent: config.jaeger_agent,
407
21
    })
408
0
    .await
409
21
    .map_err(StartError::JaegerInit)
?0
;
410
411
21
    let (network_service, network_service_chain_ids, network_events_receivers) =
412
        network_service::NetworkService::new(network_service::Config {
413
21
            listen_addresses: config.listen_addresses,
414
21
            num_events_receivers: 2 + if relay_chain_database.is_some() { 
10
} else { 0 },
415
            chains: iter::once(network_service::ChainConfig {
416
21
                log_name: chain_spec.id().to_owned(),
417
21
                fork_id: chain_spec.fork_id().map(|n| 
n.to_owned()0
),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s1_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s1_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s1_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s1_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s1_0B5_
418
21
                block_number_bytes: usize::from(chain_spec.block_number_bytes()),
419
21
                database: database.clone(),
420
0
                grandpa_protocol_finalized_block_height: if matches!(
421
21
                    genesis_chain_information.as_ref().finality,
422
                    chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
423
                ) {
424
                    Some({
425
21
                        let block_number_bytes = chain_spec.block_number_bytes();
426
21
                        database
427
21
                            .with_database(move |database| {
428
21
                                let hash = database.finalized_block_hash().unwrap();
429
21
                                let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
430
21
                                header::decode(&header, block_number_bytes.into(),).unwrap().number
431
21
                            })
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s2_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
427
2
                            .with_database(move |database| {
428
2
                                let hash = database.finalized_block_hash().unwrap();
429
2
                                let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
430
2
                                header::decode(&header, block_number_bytes.into(),).unwrap().number
431
2
                            })
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s2_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s2_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s2_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
427
19
                            .with_database(move |database| {
428
19
                                let hash = database.finalized_block_hash().unwrap();
429
19
                                let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
430
19
                                header::decode(&header, block_number_bytes.into(),).unwrap().number
431
19
                            })
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s2_0B5_
432
21
                            .await
433
                    })
434
                } else {
435
0
                    None
436
                },
437
21
                genesis_block_hash,
438
21
                best_block: {
439
21
                    let block_number_bytes = chain_spec.block_number_bytes();
440
21
                    database
441
21
                        .with_database(move |database| {
442
21
                            let hash = database.finalized_block_hash().unwrap();
443
21
                            let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
444
21
                            let number = header::decode(&header, block_number_bytes.into(),).unwrap().number;
445
21
                            (number, hash)
446
21
                        })
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s3_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
441
2
                        .with_database(move |database| {
442
2
                            let hash = database.finalized_block_hash().unwrap();
443
2
                            let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
444
2
                            let number = header::decode(&header, block_number_bytes.into(),).unwrap().number;
445
2
                            (number, hash)
446
2
                        })
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s3_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s3_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s3_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
441
19
                        .with_database(move |database| {
442
19
                            let hash = database.finalized_block_hash().unwrap();
443
19
                            let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
444
19
                            let number = header::decode(&header, block_number_bytes.into(),).unwrap().number;
445
19
                            (number, hash)
446
19
                        })
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s3_0B5_
447
21
                        .await
448
                },
449
                max_in_peers: 25,
450
                max_slots: 15,
451
                bootstrap_nodes: {
452
21
                    let mut list = Vec::with_capacity(
453
21
                        chain_spec.boot_nodes().len() + config.chain.additional_bootnodes.len(),
454
21
                    );
455
456
21
                    for 
node0
in chain_spec.boot_nodes() {
457
0
                        match node {
458
0
                            chain_spec::Bootnode::UnrecognizedFormat(raw) => {
459
0
                                config.log_callback.log(
460
0
                                    LogLevel::Warn,
461
0
                                    format!("bootnode-unrecognized-addr; value={:?}", raw),
462
0
                                );
463
0
                            }
464
0
                            chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
465
0
                                let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
466
0
                                    Ok(a) => a,
467
                                    Err(_) => {
468
0
                                        config.log_callback.log(
469
0
                                            LogLevel::Warn,
470
0
                                            format!("bootnode-unrecognized-addr; value={:?}", multiaddr),
471
0
                                        );
472
0
                                        continue;
473
                                    },
474
                                };
475
0
                                let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
476
0
                                list.push((peer_id, multiaddr));
477
                            }
478
                        }
479
                    }
480
481
21
                    list.extend(config.chain.additional_bootnodes);
482
21
                    list
483
                },
484
            })
485
            .chain(
486
21
                if let Some(
relay_chains_specs0
) = &relay_chain_spec {
487
                    Some(network_service::ChainConfig {
488
0
                        log_name: relay_chains_specs.id().to_owned(),
489
0
                        fork_id: relay_chains_specs.fork_id().map(|n| n.to_owned()),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s4_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s4_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s4_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s4_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s4_0B5_
490
0
                        block_number_bytes: usize::from(relay_chains_specs.block_number_bytes()),
491
0
                        database: relay_chain_database.clone().unwrap(),
492
0
                        grandpa_protocol_finalized_block_height: if matches!(
493
0
                            genesis_chain_information.as_ref().finality,
494
                            chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
495
                        ) {
496
0
                            Some(relay_chain_database
497
0
                                .as_ref()
498
0
                                .unwrap()
499
0
                                .with_database({
500
0
                                    let block_number_bytes = chain_spec.block_number_bytes();
501
0
                                    move |db| {
502
0
                                        let hash = db.finalized_block_hash().unwrap();
503
0
                                        let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
504
0
                                        header::decode(&header, block_number_bytes.into()).unwrap().number
505
0
                                    }
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s5_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s5_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s5_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s5_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s5_0B5_
506
0
                                })
507
0
                                .await)
508
                        } else {
509
0
                            None
510
                        },
511
0
                        genesis_block_hash: relay_genesis_chain_information
512
0
                            .as_ref()
513
0
                            .unwrap()
514
0
                            .as_ref().finalized_block_header
515
0
                            .hash(chain_spec.block_number_bytes().into(),),
516
0
                        best_block: relay_chain_database
517
0
                            .as_ref()
518
0
                            .unwrap()
519
0
                            .with_database({
520
0
                                let block_number_bytes = chain_spec.block_number_bytes();
521
0
                                move |db| {
522
0
                                    let hash = db.finalized_block_hash().unwrap();
523
0
                                    let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
524
0
                                    let number = header::decode(&header, block_number_bytes.into()).unwrap().number;
525
0
                                    (number, hash)
526
0
                                }
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s6_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s6_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s6_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s6_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s6_0B5_
527
0
                            })
528
0
                            .await,
529
                        max_in_peers: 25,
530
                        max_slots: 15,
531
                        bootstrap_nodes: {
532
0
                            let mut list =
533
0
                                Vec::with_capacity(relay_chains_specs.boot_nodes().len());
534
0
                            for node in relay_chains_specs.boot_nodes() {
535
0
                                match node {
536
0
                                    chain_spec::Bootnode::UnrecognizedFormat(raw) => {
537
0
                                        config.log_callback.log(
538
0
                                            LogLevel::Warn,
539
0
                                            format!("relay-chain-bootnode-unrecognized-addr; value={:?}", raw),
540
0
                                        );
541
0
                                    }
542
0
                                    chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
543
0
                                        let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
544
0
                                            Ok(a) => a,
545
                                            Err(_) => {
546
0
                                                config.log_callback.log(
547
0
                                                    LogLevel::Warn,
548
0
                                                    format!("relay-chain-bootnode-unrecognized-addr; value={:?}", multiaddr),
549
0
                                                );
550
0
                                                continue;
551
                                            }
552
                                        };
553
0
                                        let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
554
0
                                        list.push((peer_id, multiaddr));
555
                                    }
556
                                }
557
                            }
558
0
                            list
559
                        },
560
                    })
561
                } else {
562
21
                    None
563
                }
564
21
                .into_iter(),
565
21
            )
566
21
            .collect(),
567
21
            identify_agent_version: concat!(env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION")).to_owned(),
568
21
            noise_key,
569
21
            tasks_executor: {
570
21
                let executor = config.tasks_executor.clone();
571
21
                Box::new(move |task| executor(task))
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s7_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
571
2
                Box::new(move |task| executor(task))
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s7_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s7_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s7_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
571
19
                Box::new(move |task| executor(task))
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s7_0B5_
572
21
            },
573
21
            log_callback: config.log_callback.clone(),
574
21
            jaeger_service: jaeger_service.clone(),
575
        })
576
0
        .await
577
21
        .map_err(StartError::NetworkInit)
?0
;
578
579
21
    let mut network_events_receivers = network_events_receivers.into_iter();
580
581
21
    let keystore = Arc::new({
582
21
        let mut keystore = keystore::Keystore::new(config.chain.keystore_path, rand::random())
583
0
            .await
584
21
            .map_err(StartError::KeystoreInit)
?0
;
585
21
        for 
mut private_key0
in config.chain.keystore_memory {
586
0
            keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
587
0
            zeroize::Zeroize::zeroize(&mut *private_key);
588
0
        }
589
21
        keystore
590
    });
591
592
21
    let consensus_service = consensus_service::ConsensusService::new(consensus_service::Config {
593
21
        tasks_executor: {
594
21
            let executor = config.tasks_executor.clone();
595
21
            Box::new(move |task| executor(task))
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s8_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
595
2
            Box::new(move |task| executor(task))
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s8_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s8_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s8_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
595
19
            Box::new(move |task| executor(task))
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s8_0B5_
596
21
        },
597
21
        log_callback: config.log_callback.clone(),
598
21
        genesis_block_hash,
599
21
        network_events_receiver: network_events_receivers.next().unwrap(),
600
21
        network_service: (network_service.clone(), network_service_chain_ids[0]),
601
21
        database: database.clone(),
602
21
        block_number_bytes: usize::from(chain_spec.block_number_bytes()),
603
21
        keystore,
604
21
        jaeger_service: jaeger_service.clone(),
605
21
        slot_duration_author_ratio: 43691_u16,
606
21
    })
607
21
    .await
608
21
    .map_err(StartError::ConsensusServiceInit)
?0
;
609
610
21
    let relay_chain_consensus_service = if let Some(
relay_chain_database0
) = &relay_chain_database {
611
        Some(
612
            consensus_service::ConsensusService::new(consensus_service::Config {
613
                tasks_executor: {
614
0
                    let executor = config.tasks_executor.clone();
615
0
                    Box::new(move |task| executor(task))
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s9_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s9_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s9_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0s9_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0s9_0B5_
616
0
                },
617
0
                log_callback: config.log_callback.clone(),
618
0
                genesis_block_hash: relay_genesis_chain_information
619
0
                    .as_ref()
620
0
                    .unwrap()
621
0
                    .as_ref()
622
0
                    .finalized_block_header
623
0
                    .hash(usize::from(
624
0
                        relay_chain_spec.as_ref().unwrap().block_number_bytes(),
625
0
                    )),
626
0
                network_events_receiver: network_events_receivers.next().unwrap(),
627
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
628
0
                database: relay_chain_database.clone(),
629
0
                block_number_bytes: usize::from(
630
0
                    relay_chain_spec.as_ref().unwrap().block_number_bytes(),
631
0
                ),
632
                keystore: Arc::new({
633
0
                    let mut keystore = keystore::Keystore::new(
634
0
                        config.relay_chain.as_ref().unwrap().keystore_path.clone(),
635
0
                        rand::random(),
636
0
                    )
637
0
                    .await
638
0
                    .map_err(StartError::RelayChainKeystoreInit)?;
639
0
                    for mut private_key in
640
0
                        mem::take(&mut config.relay_chain.as_mut().unwrap().keystore_memory)
641
0
                    {
642
0
                        keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
643
0
                        zeroize::Zeroize::zeroize(&mut *private_key);
644
0
                    }
645
0
                    keystore
646
0
                }),
647
0
                jaeger_service, // TODO: consider passing a different jaeger service with a different service name
648
                slot_duration_author_ratio: 43691_u16,
649
            })
650
0
            .await
651
0
            .map_err(StartError::RelayChainConsensusServiceInit)?,
652
        )
653
    } else {
654
21
        None
655
    };
656
657
    // Start the JSON-RPC service.
658
    // It only needs to be kept alive in order to function.
659
    //
660
    // Note that initialization can fail if, for example, the port is already occupied. It is
661
    // preferable to fail to start the node altogether rather than make the user believe that they
662
    // are connected to the JSON-RPC endpoint of the node while they are in reality connected to
663
    // something else.
664
21
    let json_rpc_service = json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
665
21
        tasks_executor: config.tasks_executor.clone(),
666
21
        log_callback: config.log_callback.clone(),
667
21
        database,
668
21
        consensus_service: consensus_service.clone(),
669
21
        network_service: (network_service.clone(), network_service_chain_ids[0]),
670
21
        bind_address: config.chain.json_rpc_listen.as_ref().map(|cfg| 
cfg.address0
),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sa_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sa_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sa_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sa_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0sa_0B5_
671
21
        max_parallel_requests: 32,
672
21
        max_json_rpc_clients: config
673
21
            .chain
674
21
            .json_rpc_listen
675
21
            .map_or(0, |cfg| 
cfg.max_json_rpc_clients0
),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sb_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sb_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sb_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sb_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0sb_0B5_
676
21
        chain_name: chain_spec.name().to_owned(),
677
21
        chain_type: chain_spec.chain_type().to_owned(),
678
21
        chain_properties_json: chain_spec.properties().to_owned(),
679
21
        chain_is_live: chain_spec.has_live_network(),
680
21
        genesis_block_hash: genesis_chain_information
681
21
            .as_ref()
682
21
            .finalized_block_header
683
21
            .hash(usize::from(chain_spec.block_number_bytes())),
684
21
    })
685
0
    .await
686
21
    .map_err(StartError::JsonRpcServiceInit)
?0
;
687
688
    // Start the JSON-RPC service of the relay chain.
689
    // See remarks above.
690
21
    let relay_chain_json_rpc_service = if let Some(
relay_chain_cfg0
) = config.relay_chain {
691
0
        let relay_chain_spec = relay_chain_spec.as_ref().unwrap();
692
0
        Some(
693
0
            json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
694
0
                tasks_executor: config.tasks_executor.clone(),
695
0
                log_callback: config.log_callback.clone(),
696
0
                database: relay_chain_database.clone().unwrap(),
697
0
                consensus_service: relay_chain_consensus_service.clone().unwrap(),
698
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
699
0
                bind_address: relay_chain_cfg
700
0
                    .json_rpc_listen
701
0
                    .as_ref()
702
0
                    .map(|cfg| cfg.address),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sc_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sc_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sc_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sc_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0sc_0B5_
703
0
                max_parallel_requests: 32,
704
0
                max_json_rpc_clients: relay_chain_cfg
705
0
                    .json_rpc_listen
706
0
                    .map_or(0, |cfg| cfg.max_json_rpc_clients),
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sd_0CsiLzmwikkc22_14json_rpc_basic
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sd_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sd_0CscDgN54JpMGG_6author
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0sd_0CsibGXYHQB8Ea_25json_rpc_general_requests
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0sd_0B5_
707
0
                chain_name: relay_chain_spec.name().to_owned(),
708
0
                chain_type: relay_chain_spec.chain_type().to_owned(),
709
0
                chain_properties_json: relay_chain_spec.properties().to_owned(),
710
0
                chain_is_live: relay_chain_spec.has_live_network(),
711
0
                genesis_block_hash: relay_genesis_chain_information
712
0
                    .as_ref()
713
0
                    .unwrap()
714
0
                    .as_ref()
715
0
                    .finalized_block_header
716
0
                    .hash(usize::from(relay_chain_spec.block_number_bytes())),
717
0
            })
718
0
            .await
719
0
            .map_err(StartError::JsonRpcServiceInit)?,
720
        )
721
    } else {
722
21
        None
723
    };
724
725
    // Spawn the task printing the informant.
726
    // This is not just a dummy task that just prints on the output, but is actually the main
727
    // task that holds everything else alive. Without it, all the services that we have created
728
    // above would be cleanly dropped and nothing would happen.
729
    // For this reason, it must be spawned even if no informant is started, in which case we simply
730
    // inhibit the printing.
731
21
    let network_known_best = Arc::new(Mutex::new(None));
732
21
    (config.tasks_executor)(Box::pin({
733
21
        let mut main_network_events_receiver = network_events_receivers.next().unwrap();
734
21
        let network_service_chain_id = network_service_chain_ids[0];
735
21
        let network_known_best = network_known_best.clone();
736
21
737
21
        // TODO: shut down this task if the client stops?
738
21
        async move {
739
            loop {
740
21
                let 
network_event0
= main_network_events_receiver.next().
await0
.
unwrap()0
;
741
0
                let mut network_known_best = network_known_best.lock().await;
742
743
0
                match network_event {
744
                    network_service::Event::BlockAnnounce {
745
0
                        chain_id,
746
0
                        scale_encoded_header,
747
                        ..
748
0
                    } if chain_id == network_service_chain_id => match (
749
0
                        *network_known_best,
750
0
                        header::decode(
751
0
                            &scale_encoded_header,
752
0
                            usize::from(chain_spec.block_number_bytes()),
753
0
                        ),
754
                    ) {
755
0
                        (Some(n), Ok(header)) if n >= header.number => {}
756
0
                        (_, Ok(header)) => *network_known_best = Some(header.number),
757
0
                        (_, Err(_)) => {
758
0
                            // Do nothing if the block is invalid. This is just for the
759
0
                            // informant and not for consensus-related purposes.
760
0
                        }
761
                    },
762
                    network_service::Event::Connected {
763
0
                        chain_id,
764
0
                        best_block_number,
765
                        ..
766
0
                    } if chain_id == network_service_chain_id => match *network_known_best {
767
0
                        Some(n) if n >= best_block_number => {}
768
0
                        _ => *network_known_best = Some(best_block_number),
769
                    },
770
0
                    _ => {}
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0se_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
738
2
        async move {
739
            loop {
740
2
                let 
network_event0
= main_network_events_receiver.next().
await0
.
unwrap()0
;
741
0
                let mut network_known_best = network_known_best.lock().await;
742
743
0
                match network_event {
744
                    network_service::Event::BlockAnnounce {
745
0
                        chain_id,
746
0
                        scale_encoded_header,
747
                        ..
748
0
                    } if chain_id == network_service_chain_id => match (
749
0
                        *network_known_best,
750
0
                        header::decode(
751
0
                            &scale_encoded_header,
752
0
                            usize::from(chain_spec.block_number_bytes()),
753
0
                        ),
754
                    ) {
755
0
                        (Some(n), Ok(header)) if n >= header.number => {}
756
0
                        (_, Ok(header)) => *network_known_best = Some(header.number),
757
0
                        (_, Err(_)) => {
758
0
                            // Do nothing if the block is invalid. This is just for the
759
0
                            // informant and not for consensus-related purposes.
760
0
                        }
761
                    },
762
                    network_service::Event::Connected {
763
0
                        chain_id,
764
0
                        best_block_number,
765
                        ..
766
0
                    } if chain_id == network_service_chain_id => match *network_known_best {
767
0
                        Some(n) if n >= best_block_number => {}
768
0
                        _ => *network_known_best = Some(best_block_number),
769
                    },
770
0
                    _ => {}
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0se_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0se_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0se_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
738
19
        async move {
739
            loop {
740
19
                let 
network_event0
= main_network_events_receiver.next().
await0
.
unwrap()0
;
741
0
                let mut network_known_best = network_known_best.lock().await;
742
743
0
                match network_event {
744
                    network_service::Event::BlockAnnounce {
745
0
                        chain_id,
746
0
                        scale_encoded_header,
747
                        ..
748
0
                    } if chain_id == network_service_chain_id => match (
749
0
                        *network_known_best,
750
0
                        header::decode(
751
0
                            &scale_encoded_header,
752
0
                            usize::from(chain_spec.block_number_bytes()),
753
0
                        ),
754
                    ) {
755
0
                        (Some(n), Ok(header)) if n >= header.number => {}
756
0
                        (_, Ok(header)) => *network_known_best = Some(header.number),
757
0
                        (_, Err(_)) => {
758
0
                            // Do nothing if the block is invalid. This is just for the
759
0
                            // informant and not for consensus-related purposes.
760
0
                        }
761
                    },
762
                    network_service::Event::Connected {
763
0
                        chain_id,
764
0
                        best_block_number,
765
                        ..
766
0
                    } if chain_id == network_service_chain_id => match *network_known_best {
767
0
                        Some(n) if n >= best_block_number => {}
768
0
                        _ => *network_known_best = Some(best_block_number),
769
                    },
770
0
                    _ => {}
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node5start0se_0B5_
771
                }
772
            }
773
21
        }
774
21
    }));
775
21
776
21
    config.log_callback.log(
777
21
        LogLevel::Info,
778
21
        format!(
779
21
            "successful-initialization; local_peer_id={}; database_is_new={:?}; \
780
21
                finalized_block_hash={}; finalized_block_number={}",
781
21
            local_peer_id,
782
21
            !database_existed,
783
21
            HashDisplay(&database_finalized_block_hash),
784
21
            database_finalized_block_number
785
21
        ),
786
21
    );
787
21
788
21
    debug_assert!(network_events_receivers.next().is_none());
789
21
    Ok(Client {
790
21
        consensus_service,
791
21
        relay_chain_consensus_service,
792
21
        json_rpc_service,
793
21
        relay_chain_json_rpc_service,
794
21
        network_service,
795
21
        network_known_best,
796
21
    })
797
21
}
_RNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
266
2
pub async fn start(mut config: Config<'_>) -> Result<Client, StartError> {
267
2
    let chain_spec = {
268
2
        chain_spec::ChainSpec::from_json_bytes(&config.chain.chain_spec)
269
2
            .map_err(StartError::ChainSpecParse)
?0
270
    };
271
272
    // TODO: don't just throw away the runtime
273
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
274
2
    let genesis_chain_information = chain_spec
275
2
        .to_chain_information()
276
2
        .map_err(StartError::InvalidGenesisInformation)
?0
277
        .0;
278
279
2
    let relay_chain_spec = match &config.relay_chain {
280
0
        Some(cfg) => Some(
281
0
            chain_spec::ChainSpec::from_json_bytes(&cfg.chain_spec)
282
0
                .map_err(StartError::RelayChainSpecParse)?,
283
        ),
284
2
        None => None,
285
    };
286
287
    // TODO: don't just throw away the runtime
288
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
289
2
    let relay_genesis_chain_information = match &relay_chain_spec {
290
0
        Some(r) => Some(
291
0
            r.to_chain_information()
292
0
                .map_err(StartError::InvalidRelayGenesisInformation)?
293
                .0,
294
        ),
295
2
        None => None,
296
    };
297
298
    // The `protocolId` field of chain specifications is deprecated. Print a warning.
299
2
    if chain_spec.protocol_id().is_some() {
300
0
        config.log_callback.log(
301
0
            LogLevel::Warn,
302
0
            format!("chain-spec-has-protocol-id; chain={}", chain_spec.id()),
303
0
        );
304
2
    }
305
2
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
306
0
        if relay_chain_spec.protocol_id().is_some() {
307
0
            config.log_callback.log(
308
0
                LogLevel::Warn,
309
0
                format!(
310
0
                    "chain-spec-has-protocol-id; chain={}",
311
0
                    relay_chain_spec.id()
312
0
                ),
313
0
            );
314
0
        }
315
2
    }
316
317
    // The `telemetryEndpoints` field of chain specifications isn't supported.
318
2
    if chain_spec.telemetry_endpoints().count() != 0 {
319
0
        config.log_callback.log(
320
0
            LogLevel::Warn,
321
0
            format!(
322
0
                "chain-spec-has-telemetry-endpoints; chain={}",
323
0
                chain_spec.id()
324
0
            ),
325
0
        );
326
2
    }
327
2
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
328
0
        if relay_chain_spec.telemetry_endpoints().count() != 0 {
329
0
            config.log_callback.log(
330
0
                LogLevel::Warn,
331
0
                format!(
332
0
                    "chain-spec-has-telemetry-endpoints; chain={}",
333
0
                    relay_chain_spec.id()
334
0
                ),
335
0
            );
336
0
        }
337
2
    }
338
339
    // Printing the SQLite version number can be useful for debugging purposes for example in case
340
    // a query fails.
341
2
    config.log_callback.log(
342
2
        LogLevel::Debug,
343
2
        format!("sqlite-version; version={}", full_sqlite::sqlite_version()),
344
2
    );
345
346
2
    let (database, database_existed) = {
347
2
        let (db, existed) = open_database(
348
2
            &chain_spec,
349
2
            genesis_chain_information.as_ref(),
350
2
            config.chain.sqlite_database_path,
351
2
            config.chain.sqlite_cache_size,
352
2
        )
353
0
        .await;
354
355
2
        (Arc::new(database_thread::DatabaseThread::from(db)), existed)
356
    };
357
358
2
    let relay_chain_database = if let Some(
relay_chain0
) = &config.relay_chain {
359
        Some(Arc::new(database_thread::DatabaseThread::from(
360
0
            open_database(
361
0
                relay_chain_spec.as_ref().unwrap(),
362
0
                relay_genesis_chain_information.as_ref().unwrap().as_ref(),
363
0
                relay_chain.sqlite_database_path.clone(),
364
0
                relay_chain.sqlite_cache_size,
365
0
            )
366
0
            .await
367
            .0,
368
        )))
369
    } else {
370
2
        None
371
    };
372
373
2
    let database_finalized_block_hash = database
374
2
        .with_database(|db| db.finalized_block_hash().unwrap())
375
2
        .await;
376
2
    let database_finalized_block_number = header::decode(
377
2
        &database
378
2
            .with_database(move |db| {
379
                db.block_scale_encoded_header(&database_finalized_block_hash)
380
                    .unwrap()
381
                    .unwrap()
382
2
            })
383
2
            .await,
384
2
        chain_spec.block_number_bytes().into(),
385
2
    )
386
2
    .unwrap()
387
2
    .number;
388
2
389
2
    let noise_key = {
390
2
        let mut noise_static_key = zeroize::Zeroizing::new([0u8; 32]);
391
2
        rand::thread_rng().fill_bytes(&mut *noise_static_key);
392
2
        connection::NoiseKey::new(&config.libp2p_key, &noise_static_key)
393
2
    };
394
2
    zeroize::Zeroize::zeroize(&mut *config.libp2p_key);
395
2
    let local_peer_id =
396
2
        peer_id::PublicKey::Ed25519(*noise_key.libp2p_public_ed25519_key()).into_peer_id();
397
2
398
2
    let genesis_block_hash = genesis_chain_information
399
2
        .as_ref()
400
2
        .finalized_block_header
401
2
        .hash(chain_spec.block_number_bytes().into());
402
403
2
    let jaeger_service = jaeger_service::JaegerService::new(jaeger_service::Config {
404
2
        tasks_executor: &mut |task| (config.tasks_executor)(task),
405
2
        service_name: local_peer_id.to_string(),
406
2
        jaeger_agent: config.jaeger_agent,
407
2
    })
408
0
    .await
409
2
    .map_err(StartError::JaegerInit)
?0
;
410
411
2
    let (network_service, network_service_chain_ids, network_events_receivers) =
412
        network_service::NetworkService::new(network_service::Config {
413
2
            listen_addresses: config.listen_addresses,
414
2
            num_events_receivers: 2 + if relay_chain_database.is_some() { 
10
} else { 0 },
415
            chains: iter::once(network_service::ChainConfig {
416
2
                log_name: chain_spec.id().to_owned(),
417
2
                fork_id: chain_spec.fork_id().map(|n| n.to_owned()),
418
2
                block_number_bytes: usize::from(chain_spec.block_number_bytes()),
419
2
                database: database.clone(),
420
0
                grandpa_protocol_finalized_block_height: if matches!(
421
2
                    genesis_chain_information.as_ref().finality,
422
                    chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
423
                ) {
424
                    Some({
425
2
                        let block_number_bytes = chain_spec.block_number_bytes();
426
2
                        database
427
2
                            .with_database(move |database| {
428
                                let hash = database.finalized_block_hash().unwrap();
429
                                let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
430
                                header::decode(&header, block_number_bytes.into(),).unwrap().number
431
2
                            })
432
2
                            .await
433
                    })
434
                } else {
435
0
                    None
436
                },
437
2
                genesis_block_hash,
438
2
                best_block: {
439
2
                    let block_number_bytes = chain_spec.block_number_bytes();
440
2
                    database
441
2
                        .with_database(move |database| {
442
                            let hash = database.finalized_block_hash().unwrap();
443
                            let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
444
                            let number = header::decode(&header, block_number_bytes.into(),).unwrap().number;
445
                            (number, hash)
446
2
                        })
447
2
                        .await
448
                },
449
                max_in_peers: 25,
450
                max_slots: 15,
451
                bootstrap_nodes: {
452
2
                    let mut list = Vec::with_capacity(
453
2
                        chain_spec.boot_nodes().len() + config.chain.additional_bootnodes.len(),
454
2
                    );
455
456
2
                    for 
node0
in chain_spec.boot_nodes() {
457
0
                        match node {
458
0
                            chain_spec::Bootnode::UnrecognizedFormat(raw) => {
459
0
                                config.log_callback.log(
460
0
                                    LogLevel::Warn,
461
0
                                    format!("bootnode-unrecognized-addr; value={:?}", raw),
462
0
                                );
463
0
                            }
464
0
                            chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
465
0
                                let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
466
0
                                    Ok(a) => a,
467
                                    Err(_) => {
468
0
                                        config.log_callback.log(
469
0
                                            LogLevel::Warn,
470
0
                                            format!("bootnode-unrecognized-addr; value={:?}", multiaddr),
471
0
                                        );
472
0
                                        continue;
473
                                    },
474
                                };
475
0
                                let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
476
0
                                list.push((peer_id, multiaddr));
477
                            }
478
                        }
479
                    }
480
481
2
                    list.extend(config.chain.additional_bootnodes);
482
2
                    list
483
                },
484
            })
485
            .chain(
486
2
                if let Some(
relay_chains_specs0
) = &relay_chain_spec {
487
                    Some(network_service::ChainConfig {
488
0
                        log_name: relay_chains_specs.id().to_owned(),
489
0
                        fork_id: relay_chains_specs.fork_id().map(|n| n.to_owned()),
490
0
                        block_number_bytes: usize::from(relay_chains_specs.block_number_bytes()),
491
0
                        database: relay_chain_database.clone().unwrap(),
492
0
                        grandpa_protocol_finalized_block_height: if matches!(
493
0
                            genesis_chain_information.as_ref().finality,
494
                            chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
495
                        ) {
496
0
                            Some(relay_chain_database
497
0
                                .as_ref()
498
0
                                .unwrap()
499
0
                                .with_database({
500
0
                                    let block_number_bytes = chain_spec.block_number_bytes();
501
0
                                    move |db| {
502
                                        let hash = db.finalized_block_hash().unwrap();
503
                                        let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
504
                                        header::decode(&header, block_number_bytes.into()).unwrap().number
505
0
                                    }
506
0
                                })
507
0
                                .await)
508
                        } else {
509
0
                            None
510
                        },
511
0
                        genesis_block_hash: relay_genesis_chain_information
512
0
                            .as_ref()
513
0
                            .unwrap()
514
0
                            .as_ref().finalized_block_header
515
0
                            .hash(chain_spec.block_number_bytes().into(),),
516
0
                        best_block: relay_chain_database
517
0
                            .as_ref()
518
0
                            .unwrap()
519
0
                            .with_database({
520
0
                                let block_number_bytes = chain_spec.block_number_bytes();
521
0
                                move |db| {
522
                                    let hash = db.finalized_block_hash().unwrap();
523
                                    let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
524
                                    let number = header::decode(&header, block_number_bytes.into()).unwrap().number;
525
                                    (number, hash)
526
0
                                }
527
0
                            })
528
0
                            .await,
529
                        max_in_peers: 25,
530
                        max_slots: 15,
531
                        bootstrap_nodes: {
532
0
                            let mut list =
533
0
                                Vec::with_capacity(relay_chains_specs.boot_nodes().len());
534
0
                            for node in relay_chains_specs.boot_nodes() {
535
0
                                match node {
536
0
                                    chain_spec::Bootnode::UnrecognizedFormat(raw) => {
537
0
                                        config.log_callback.log(
538
0
                                            LogLevel::Warn,
539
0
                                            format!("relay-chain-bootnode-unrecognized-addr; value={:?}", raw),
540
0
                                        );
541
0
                                    }
542
0
                                    chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
543
0
                                        let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
544
0
                                            Ok(a) => a,
545
                                            Err(_) => {
546
0
                                                config.log_callback.log(
547
0
                                                    LogLevel::Warn,
548
0
                                                    format!("relay-chain-bootnode-unrecognized-addr; value={:?}", multiaddr),
549
0
                                                );
550
0
                                                continue;
551
                                            }
552
                                        };
553
0
                                        let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
554
0
                                        list.push((peer_id, multiaddr));
555
                                    }
556
                                }
557
                            }
558
0
                            list
559
                        },
560
                    })
561
                } else {
562
2
                    None
563
                }
564
2
                .into_iter(),
565
2
            )
566
2
            .collect(),
567
2
            identify_agent_version: concat!(env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION")).to_owned(),
568
2
            noise_key,
569
2
            tasks_executor: {
570
2
                let executor = config.tasks_executor.clone();
571
2
                Box::new(move |task| executor(task))
572
2
            },
573
2
            log_callback: config.log_callback.clone(),
574
2
            jaeger_service: jaeger_service.clone(),
575
        })
576
0
        .await
577
2
        .map_err(StartError::NetworkInit)
?0
;
578
579
2
    let mut network_events_receivers = network_events_receivers.into_iter();
580
581
2
    let keystore = Arc::new({
582
2
        let mut keystore = keystore::Keystore::new(config.chain.keystore_path, rand::random())
583
0
            .await
584
2
            .map_err(StartError::KeystoreInit)
?0
;
585
2
        for 
mut private_key0
in config.chain.keystore_memory {
586
0
            keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
587
0
            zeroize::Zeroize::zeroize(&mut *private_key);
588
0
        }
589
2
        keystore
590
    });
591
592
2
    let consensus_service = consensus_service::ConsensusService::new(consensus_service::Config {
593
2
        tasks_executor: {
594
2
            let executor = config.tasks_executor.clone();
595
2
            Box::new(move |task| executor(task))
596
2
        },
597
2
        log_callback: config.log_callback.clone(),
598
2
        genesis_block_hash,
599
2
        network_events_receiver: network_events_receivers.next().unwrap(),
600
2
        network_service: (network_service.clone(), network_service_chain_ids[0]),
601
2
        database: database.clone(),
602
2
        block_number_bytes: usize::from(chain_spec.block_number_bytes()),
603
2
        keystore,
604
2
        jaeger_service: jaeger_service.clone(),
605
2
        slot_duration_author_ratio: 43691_u16,
606
2
    })
607
2
    .await
608
2
    .map_err(StartError::ConsensusServiceInit)
?0
;
609
610
2
    let relay_chain_consensus_service = if let Some(
relay_chain_database0
) = &relay_chain_database {
611
        Some(
612
            consensus_service::ConsensusService::new(consensus_service::Config {
613
                tasks_executor: {
614
0
                    let executor = config.tasks_executor.clone();
615
0
                    Box::new(move |task| executor(task))
616
0
                },
617
0
                log_callback: config.log_callback.clone(),
618
0
                genesis_block_hash: relay_genesis_chain_information
619
0
                    .as_ref()
620
0
                    .unwrap()
621
0
                    .as_ref()
622
0
                    .finalized_block_header
623
0
                    .hash(usize::from(
624
0
                        relay_chain_spec.as_ref().unwrap().block_number_bytes(),
625
0
                    )),
626
0
                network_events_receiver: network_events_receivers.next().unwrap(),
627
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
628
0
                database: relay_chain_database.clone(),
629
0
                block_number_bytes: usize::from(
630
0
                    relay_chain_spec.as_ref().unwrap().block_number_bytes(),
631
0
                ),
632
                keystore: Arc::new({
633
0
                    let mut keystore = keystore::Keystore::new(
634
0
                        config.relay_chain.as_ref().unwrap().keystore_path.clone(),
635
0
                        rand::random(),
636
0
                    )
637
0
                    .await
638
0
                    .map_err(StartError::RelayChainKeystoreInit)?;
639
0
                    for mut private_key in
640
0
                        mem::take(&mut config.relay_chain.as_mut().unwrap().keystore_memory)
641
0
                    {
642
0
                        keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
643
0
                        zeroize::Zeroize::zeroize(&mut *private_key);
644
0
                    }
645
0
                    keystore
646
0
                }),
647
0
                jaeger_service, // TODO: consider passing a different jaeger service with a different service name
648
                slot_duration_author_ratio: 43691_u16,
649
            })
650
0
            .await
651
0
            .map_err(StartError::RelayChainConsensusServiceInit)?,
652
        )
653
    } else {
654
2
        None
655
    };
656
657
    // Start the JSON-RPC service.
658
    // It only needs to be kept alive in order to function.
659
    //
660
    // Note that initialization can fail if, for example, the port is already occupied. It is
661
    // preferable to fail to start the node altogether rather than make the user believe that they
662
    // are connected to the JSON-RPC endpoint of the node while they are in reality connected to
663
    // something else.
664
2
    let json_rpc_service = json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
665
2
        tasks_executor: config.tasks_executor.clone(),
666
2
        log_callback: config.log_callback.clone(),
667
2
        database,
668
2
        consensus_service: consensus_service.clone(),
669
2
        network_service: (network_service.clone(), network_service_chain_ids[0]),
670
2
        bind_address: config.chain.json_rpc_listen.as_ref().map(|cfg| cfg.address),
671
2
        max_parallel_requests: 32,
672
2
        max_json_rpc_clients: config
673
2
            .chain
674
2
            .json_rpc_listen
675
2
            .map_or(0, |cfg| cfg.max_json_rpc_clients),
676
2
        chain_name: chain_spec.name().to_owned(),
677
2
        chain_type: chain_spec.chain_type().to_owned(),
678
2
        chain_properties_json: chain_spec.properties().to_owned(),
679
2
        chain_is_live: chain_spec.has_live_network(),
680
2
        genesis_block_hash: genesis_chain_information
681
2
            .as_ref()
682
2
            .finalized_block_header
683
2
            .hash(usize::from(chain_spec.block_number_bytes())),
684
2
    })
685
0
    .await
686
2
    .map_err(StartError::JsonRpcServiceInit)
?0
;
687
688
    // Start the JSON-RPC service of the relay chain.
689
    // See remarks above.
690
2
    let relay_chain_json_rpc_service = if let Some(
relay_chain_cfg0
) = config.relay_chain {
691
0
        let relay_chain_spec = relay_chain_spec.as_ref().unwrap();
692
0
        Some(
693
0
            json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
694
0
                tasks_executor: config.tasks_executor.clone(),
695
0
                log_callback: config.log_callback.clone(),
696
0
                database: relay_chain_database.clone().unwrap(),
697
0
                consensus_service: relay_chain_consensus_service.clone().unwrap(),
698
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
699
0
                bind_address: relay_chain_cfg
700
0
                    .json_rpc_listen
701
0
                    .as_ref()
702
0
                    .map(|cfg| cfg.address),
703
0
                max_parallel_requests: 32,
704
0
                max_json_rpc_clients: relay_chain_cfg
705
0
                    .json_rpc_listen
706
0
                    .map_or(0, |cfg| cfg.max_json_rpc_clients),
707
0
                chain_name: relay_chain_spec.name().to_owned(),
708
0
                chain_type: relay_chain_spec.chain_type().to_owned(),
709
0
                chain_properties_json: relay_chain_spec.properties().to_owned(),
710
0
                chain_is_live: relay_chain_spec.has_live_network(),
711
0
                genesis_block_hash: relay_genesis_chain_information
712
0
                    .as_ref()
713
0
                    .unwrap()
714
0
                    .as_ref()
715
0
                    .finalized_block_header
716
0
                    .hash(usize::from(relay_chain_spec.block_number_bytes())),
717
0
            })
718
0
            .await
719
0
            .map_err(StartError::JsonRpcServiceInit)?,
720
        )
721
    } else {
722
2
        None
723
    };
724
725
    // Spawn the task printing the informant.
726
    // This is not just a dummy task that just prints on the output, but is actually the main
727
    // task that holds everything else alive. Without it, all the services that we have created
728
    // above would be cleanly dropped and nothing would happen.
729
    // For this reason, it must be spawned even if no informant is started, in which case we simply
730
    // inhibit the printing.
731
2
    let network_known_best = Arc::new(Mutex::new(None));
732
2
    (config.tasks_executor)(Box::pin({
733
2
        let mut main_network_events_receiver = network_events_receivers.next().unwrap();
734
2
        let network_service_chain_id = network_service_chain_ids[0];
735
2
        let network_known_best = network_known_best.clone();
736
2
737
2
        // TODO: shut down this task if the client stops?
738
2
        async move {
739
            loop {
740
                let network_event = main_network_events_receiver.next().await.unwrap();
741
                let mut network_known_best = network_known_best.lock().await;
742
743
                match network_event {
744
                    network_service::Event::BlockAnnounce {
745
                        chain_id,
746
                        scale_encoded_header,
747
                        ..
748
                    } if chain_id == network_service_chain_id => match (
749
                        *network_known_best,
750
                        header::decode(
751
                            &scale_encoded_header,
752
                            usize::from(chain_spec.block_number_bytes()),
753
                        ),
754
                    ) {
755
                        (Some(n), Ok(header)) if n >= header.number => {}
756
                        (_, Ok(header)) => *network_known_best = Some(header.number),
757
                        (_, Err(_)) => {
758
                            // Do nothing if the block is invalid. This is just for the
759
                            // informant and not for consensus-related purposes.
760
                        }
761
                    },
762
                    network_service::Event::Connected {
763
                        chain_id,
764
                        best_block_number,
765
                        ..
766
                    } if chain_id == network_service_chain_id => match *network_known_best {
767
                        Some(n) if n >= best_block_number => {}
768
                        _ => *network_known_best = Some(best_block_number),
769
                    },
770
                    _ => {}
771
                }
772
            }
773
2
        }
774
2
    }));
775
2
776
2
    config.log_callback.log(
777
2
        LogLevel::Info,
778
2
        format!(
779
2
            "successful-initialization; local_peer_id={}; database_is_new={:?}; \
780
2
                finalized_block_hash={}; finalized_block_number={}",
781
2
            local_peer_id,
782
2
            !database_existed,
783
2
            HashDisplay(&database_finalized_block_hash),
784
2
            database_finalized_block_number
785
2
        ),
786
2
    );
787
2
788
2
    debug_assert!(network_events_receivers.next().is_none());
789
2
    Ok(Client {
790
2
        consensus_service,
791
2
        relay_chain_consensus_service,
792
2
        json_rpc_service,
793
2
        relay_chain_json_rpc_service,
794
2
        network_service,
795
2
        network_known_best,
796
2
    })
797
2
}
Unexecuted instantiation: _RNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0B3_
Unexecuted instantiation: _RNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0CscDgN54JpMGG_6author
_RNCNvCsiUjFBJteJ7x_17smoldot_full_node5start0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
266
19
pub async fn start(mut config: Config<'_>) -> Result<Client, StartError> {
267
19
    let chain_spec = {
268
19
        chain_spec::ChainSpec::from_json_bytes(&config.chain.chain_spec)
269
19
            .map_err(StartError::ChainSpecParse)
?0
270
    };
271
272
    // TODO: don't just throw away the runtime
273
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
274
19
    let genesis_chain_information = chain_spec
275
19
        .to_chain_information()
276
19
        .map_err(StartError::InvalidGenesisInformation)
?0
277
        .0;
278
279
19
    let relay_chain_spec = match &config.relay_chain {
280
0
        Some(cfg) => Some(
281
0
            chain_spec::ChainSpec::from_json_bytes(&cfg.chain_spec)
282
0
                .map_err(StartError::RelayChainSpecParse)?,
283
        ),
284
19
        None => None,
285
    };
286
287
    // TODO: don't just throw away the runtime
288
    // TODO: building the genesis chain information is pretty expensive and we throw away most of the information
289
19
    let relay_genesis_chain_information = match &relay_chain_spec {
290
0
        Some(r) => Some(
291
0
            r.to_chain_information()
292
0
                .map_err(StartError::InvalidRelayGenesisInformation)?
293
                .0,
294
        ),
295
19
        None => None,
296
    };
297
298
    // The `protocolId` field of chain specifications is deprecated. Print a warning.
299
19
    if chain_spec.protocol_id().is_some() {
300
0
        config.log_callback.log(
301
0
            LogLevel::Warn,
302
0
            format!("chain-spec-has-protocol-id; chain={}", chain_spec.id()),
303
0
        );
304
19
    }
305
19
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
306
0
        if relay_chain_spec.protocol_id().is_some() {
307
0
            config.log_callback.log(
308
0
                LogLevel::Warn,
309
0
                format!(
310
0
                    "chain-spec-has-protocol-id; chain={}",
311
0
                    relay_chain_spec.id()
312
0
                ),
313
0
            );
314
0
        }
315
19
    }
316
317
    // The `telemetryEndpoints` field of chain specifications isn't supported.
318
19
    if chain_spec.telemetry_endpoints().count() != 0 {
319
0
        config.log_callback.log(
320
0
            LogLevel::Warn,
321
0
            format!(
322
0
                "chain-spec-has-telemetry-endpoints; chain={}",
323
0
                chain_spec.id()
324
0
            ),
325
0
        );
326
19
    }
327
19
    if let Some(
relay_chain_spec0
) = &relay_chain_spec {
328
0
        if relay_chain_spec.telemetry_endpoints().count() != 0 {
329
0
            config.log_callback.log(
330
0
                LogLevel::Warn,
331
0
                format!(
332
0
                    "chain-spec-has-telemetry-endpoints; chain={}",
333
0
                    relay_chain_spec.id()
334
0
                ),
335
0
            );
336
0
        }
337
19
    }
338
339
    // Printing the SQLite version number can be useful for debugging purposes for example in case
340
    // a query fails.
341
19
    config.log_callback.log(
342
19
        LogLevel::Debug,
343
19
        format!("sqlite-version; version={}", full_sqlite::sqlite_version()),
344
19
    );
345
346
19
    let (database, database_existed) = {
347
19
        let (db, existed) = open_database(
348
19
            &chain_spec,
349
19
            genesis_chain_information.as_ref(),
350
19
            config.chain.sqlite_database_path,
351
19
            config.chain.sqlite_cache_size,
352
19
        )
353
0
        .await;
354
355
19
        (Arc::new(database_thread::DatabaseThread::from(db)), existed)
356
    };
357
358
19
    let relay_chain_database = if let Some(
relay_chain0
) = &config.relay_chain {
359
        Some(Arc::new(database_thread::DatabaseThread::from(
360
0
            open_database(
361
0
                relay_chain_spec.as_ref().unwrap(),
362
0
                relay_genesis_chain_information.as_ref().unwrap().as_ref(),
363
0
                relay_chain.sqlite_database_path.clone(),
364
0
                relay_chain.sqlite_cache_size,
365
0
            )
366
0
            .await
367
            .0,
368
        )))
369
    } else {
370
19
        None
371
    };
372
373
19
    let database_finalized_block_hash = database
374
19
        .with_database(|db| db.finalized_block_hash().unwrap())
375
19
        .await;
376
19
    let database_finalized_block_number = header::decode(
377
19
        &database
378
19
            .with_database(move |db| {
379
                db.block_scale_encoded_header(&database_finalized_block_hash)
380
                    .unwrap()
381
                    .unwrap()
382
19
            })
383
19
            .await,
384
19
        chain_spec.block_number_bytes().into(),
385
19
    )
386
19
    .unwrap()
387
19
    .number;
388
19
389
19
    let noise_key = {
390
19
        let mut noise_static_key = zeroize::Zeroizing::new([0u8; 32]);
391
19
        rand::thread_rng().fill_bytes(&mut *noise_static_key);
392
19
        connection::NoiseKey::new(&config.libp2p_key, &noise_static_key)
393
19
    };
394
19
    zeroize::Zeroize::zeroize(&mut *config.libp2p_key);
395
19
    let local_peer_id =
396
19
        peer_id::PublicKey::Ed25519(*noise_key.libp2p_public_ed25519_key()).into_peer_id();
397
19
398
19
    let genesis_block_hash = genesis_chain_information
399
19
        .as_ref()
400
19
        .finalized_block_header
401
19
        .hash(chain_spec.block_number_bytes().into());
402
403
19
    let jaeger_service = jaeger_service::JaegerService::new(jaeger_service::Config {
404
19
        tasks_executor: &mut |task| (config.tasks_executor)(task),
405
19
        service_name: local_peer_id.to_string(),
406
19
        jaeger_agent: config.jaeger_agent,
407
19
    })
408
0
    .await
409
19
    .map_err(StartError::JaegerInit)
?0
;
410
411
19
    let (network_service, network_service_chain_ids, network_events_receivers) =
412
        network_service::NetworkService::new(network_service::Config {
413
19
            listen_addresses: config.listen_addresses,
414
19
            num_events_receivers: 2 + if relay_chain_database.is_some() { 
10
} else { 0 },
415
            chains: iter::once(network_service::ChainConfig {
416
19
                log_name: chain_spec.id().to_owned(),
417
19
                fork_id: chain_spec.fork_id().map(|n| n.to_owned()),
418
19
                block_number_bytes: usize::from(chain_spec.block_number_bytes()),
419
19
                database: database.clone(),
420
0
                grandpa_protocol_finalized_block_height: if matches!(
421
19
                    genesis_chain_information.as_ref().finality,
422
                    chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
423
                ) {
424
                    Some({
425
19
                        let block_number_bytes = chain_spec.block_number_bytes();
426
19
                        database
427
19
                            .with_database(move |database| {
428
                                let hash = database.finalized_block_hash().unwrap();
429
                                let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
430
                                header::decode(&header, block_number_bytes.into(),).unwrap().number
431
19
                            })
432
19
                            .await
433
                    })
434
                } else {
435
0
                    None
436
                },
437
19
                genesis_block_hash,
438
19
                best_block: {
439
19
                    let block_number_bytes = chain_spec.block_number_bytes();
440
19
                    database
441
19
                        .with_database(move |database| {
442
                            let hash = database.finalized_block_hash().unwrap();
443
                            let header = database.block_scale_encoded_header(&hash).unwrap().unwrap();
444
                            let number = header::decode(&header, block_number_bytes.into(),).unwrap().number;
445
                            (number, hash)
446
19
                        })
447
19
                        .await
448
                },
449
                max_in_peers: 25,
450
                max_slots: 15,
451
                bootstrap_nodes: {
452
19
                    let mut list = Vec::with_capacity(
453
19
                        chain_spec.boot_nodes().len() + config.chain.additional_bootnodes.len(),
454
19
                    );
455
456
19
                    for 
node0
in chain_spec.boot_nodes() {
457
0
                        match node {
458
0
                            chain_spec::Bootnode::UnrecognizedFormat(raw) => {
459
0
                                config.log_callback.log(
460
0
                                    LogLevel::Warn,
461
0
                                    format!("bootnode-unrecognized-addr; value={:?}", raw),
462
0
                                );
463
0
                            }
464
0
                            chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
465
0
                                let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
466
0
                                    Ok(a) => a,
467
                                    Err(_) => {
468
0
                                        config.log_callback.log(
469
0
                                            LogLevel::Warn,
470
0
                                            format!("bootnode-unrecognized-addr; value={:?}", multiaddr),
471
0
                                        );
472
0
                                        continue;
473
                                    },
474
                                };
475
0
                                let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
476
0
                                list.push((peer_id, multiaddr));
477
                            }
478
                        }
479
                    }
480
481
19
                    list.extend(config.chain.additional_bootnodes);
482
19
                    list
483
                },
484
            })
485
            .chain(
486
19
                if let Some(
relay_chains_specs0
) = &relay_chain_spec {
487
                    Some(network_service::ChainConfig {
488
0
                        log_name: relay_chains_specs.id().to_owned(),
489
0
                        fork_id: relay_chains_specs.fork_id().map(|n| n.to_owned()),
490
0
                        block_number_bytes: usize::from(relay_chains_specs.block_number_bytes()),
491
0
                        database: relay_chain_database.clone().unwrap(),
492
0
                        grandpa_protocol_finalized_block_height: if matches!(
493
0
                            genesis_chain_information.as_ref().finality,
494
                            chain::chain_information::ChainInformationFinalityRef::Grandpa { .. }
495
                        ) {
496
0
                            Some(relay_chain_database
497
0
                                .as_ref()
498
0
                                .unwrap()
499
0
                                .with_database({
500
0
                                    let block_number_bytes = chain_spec.block_number_bytes();
501
0
                                    move |db| {
502
                                        let hash = db.finalized_block_hash().unwrap();
503
                                        let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
504
                                        header::decode(&header, block_number_bytes.into()).unwrap().number
505
0
                                    }
506
0
                                })
507
0
                                .await)
508
                        } else {
509
0
                            None
510
                        },
511
0
                        genesis_block_hash: relay_genesis_chain_information
512
0
                            .as_ref()
513
0
                            .unwrap()
514
0
                            .as_ref().finalized_block_header
515
0
                            .hash(chain_spec.block_number_bytes().into(),),
516
0
                        best_block: relay_chain_database
517
0
                            .as_ref()
518
0
                            .unwrap()
519
0
                            .with_database({
520
0
                                let block_number_bytes = chain_spec.block_number_bytes();
521
0
                                move |db| {
522
                                    let hash = db.finalized_block_hash().unwrap();
523
                                    let header = db.block_scale_encoded_header(&hash).unwrap().unwrap();
524
                                    let number = header::decode(&header, block_number_bytes.into()).unwrap().number;
525
                                    (number, hash)
526
0
                                }
527
0
                            })
528
0
                            .await,
529
                        max_in_peers: 25,
530
                        max_slots: 15,
531
                        bootstrap_nodes: {
532
0
                            let mut list =
533
0
                                Vec::with_capacity(relay_chains_specs.boot_nodes().len());
534
0
                            for node in relay_chains_specs.boot_nodes() {
535
0
                                match node {
536
0
                                    chain_spec::Bootnode::UnrecognizedFormat(raw) => {
537
0
                                        config.log_callback.log(
538
0
                                            LogLevel::Warn,
539
0
                                            format!("relay-chain-bootnode-unrecognized-addr; value={:?}", raw),
540
0
                                        );
541
0
                                    }
542
0
                                    chain_spec::Bootnode::Parsed { multiaddr, peer_id } => {
543
0
                                        let multiaddr: multiaddr::Multiaddr = match multiaddr.parse() {
544
0
                                            Ok(a) => a,
545
                                            Err(_) => {
546
0
                                                config.log_callback.log(
547
0
                                                    LogLevel::Warn,
548
0
                                                    format!("relay-chain-bootnode-unrecognized-addr; value={:?}", multiaddr),
549
0
                                                );
550
0
                                                continue;
551
                                            }
552
                                        };
553
0
                                        let peer_id = PeerId::from_bytes(peer_id.to_vec()).unwrap();
554
0
                                        list.push((peer_id, multiaddr));
555
                                    }
556
                                }
557
                            }
558
0
                            list
559
                        },
560
                    })
561
                } else {
562
19
                    None
563
                }
564
19
                .into_iter(),
565
19
            )
566
19
            .collect(),
567
19
            identify_agent_version: concat!(env!("CARGO_PKG_NAME"), " ", env!("CARGO_PKG_VERSION")).to_owned(),
568
19
            noise_key,
569
19
            tasks_executor: {
570
19
                let executor = config.tasks_executor.clone();
571
19
                Box::new(move |task| executor(task))
572
19
            },
573
19
            log_callback: config.log_callback.clone(),
574
19
            jaeger_service: jaeger_service.clone(),
575
        })
576
0
        .await
577
19
        .map_err(StartError::NetworkInit)
?0
;
578
579
19
    let mut network_events_receivers = network_events_receivers.into_iter();
580
581
19
    let keystore = Arc::new({
582
19
        let mut keystore = keystore::Keystore::new(config.chain.keystore_path, rand::random())
583
0
            .await
584
19
            .map_err(StartError::KeystoreInit)
?0
;
585
19
        for 
mut private_key0
in config.chain.keystore_memory {
586
0
            keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
587
0
            zeroize::Zeroize::zeroize(&mut *private_key);
588
0
        }
589
19
        keystore
590
    });
591
592
19
    let consensus_service = consensus_service::ConsensusService::new(consensus_service::Config {
593
19
        tasks_executor: {
594
19
            let executor = config.tasks_executor.clone();
595
19
            Box::new(move |task| executor(task))
596
19
        },
597
19
        log_callback: config.log_callback.clone(),
598
19
        genesis_block_hash,
599
19
        network_events_receiver: network_events_receivers.next().unwrap(),
600
19
        network_service: (network_service.clone(), network_service_chain_ids[0]),
601
19
        database: database.clone(),
602
19
        block_number_bytes: usize::from(chain_spec.block_number_bytes()),
603
19
        keystore,
604
19
        jaeger_service: jaeger_service.clone(),
605
19
        slot_duration_author_ratio: 43691_u16,
606
19
    })
607
19
    .await
608
19
    .map_err(StartError::ConsensusServiceInit)
?0
;
609
610
19
    let relay_chain_consensus_service = if let Some(
relay_chain_database0
) = &relay_chain_database {
611
        Some(
612
            consensus_service::ConsensusService::new(consensus_service::Config {
613
                tasks_executor: {
614
0
                    let executor = config.tasks_executor.clone();
615
0
                    Box::new(move |task| executor(task))
616
0
                },
617
0
                log_callback: config.log_callback.clone(),
618
0
                genesis_block_hash: relay_genesis_chain_information
619
0
                    .as_ref()
620
0
                    .unwrap()
621
0
                    .as_ref()
622
0
                    .finalized_block_header
623
0
                    .hash(usize::from(
624
0
                        relay_chain_spec.as_ref().unwrap().block_number_bytes(),
625
0
                    )),
626
0
                network_events_receiver: network_events_receivers.next().unwrap(),
627
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
628
0
                database: relay_chain_database.clone(),
629
0
                block_number_bytes: usize::from(
630
0
                    relay_chain_spec.as_ref().unwrap().block_number_bytes(),
631
0
                ),
632
                keystore: Arc::new({
633
0
                    let mut keystore = keystore::Keystore::new(
634
0
                        config.relay_chain.as_ref().unwrap().keystore_path.clone(),
635
0
                        rand::random(),
636
0
                    )
637
0
                    .await
638
0
                    .map_err(StartError::RelayChainKeystoreInit)?;
639
0
                    for mut private_key in
640
0
                        mem::take(&mut config.relay_chain.as_mut().unwrap().keystore_memory)
641
0
                    {
642
0
                        keystore.insert_sr25519_memory(keystore::KeyNamespace::all(), &private_key);
643
0
                        zeroize::Zeroize::zeroize(&mut *private_key);
644
0
                    }
645
0
                    keystore
646
0
                }),
647
0
                jaeger_service, // TODO: consider passing a different jaeger service with a different service name
648
                slot_duration_author_ratio: 43691_u16,
649
            })
650
0
            .await
651
0
            .map_err(StartError::RelayChainConsensusServiceInit)?,
652
        )
653
    } else {
654
19
        None
655
    };
656
657
    // Start the JSON-RPC service.
658
    // It only needs to be kept alive in order to function.
659
    //
660
    // Note that initialization can fail if, for example, the port is already occupied. It is
661
    // preferable to fail to start the node altogether rather than make the user believe that they
662
    // are connected to the JSON-RPC endpoint of the node while they are in reality connected to
663
    // something else.
664
19
    let json_rpc_service = json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
665
19
        tasks_executor: config.tasks_executor.clone(),
666
19
        log_callback: config.log_callback.clone(),
667
19
        database,
668
19
        consensus_service: consensus_service.clone(),
669
19
        network_service: (network_service.clone(), network_service_chain_ids[0]),
670
19
        bind_address: config.chain.json_rpc_listen.as_ref().map(|cfg| cfg.address),
671
19
        max_parallel_requests: 32,
672
19
        max_json_rpc_clients: config
673
19
            .chain
674
19
            .json_rpc_listen
675
19
            .map_or(0, |cfg| cfg.max_json_rpc_clients),
676
19
        chain_name: chain_spec.name().to_owned(),
677
19
        chain_type: chain_spec.chain_type().to_owned(),
678
19
        chain_properties_json: chain_spec.properties().to_owned(),
679
19
        chain_is_live: chain_spec.has_live_network(),
680
19
        genesis_block_hash: genesis_chain_information
681
19
            .as_ref()
682
19
            .finalized_block_header
683
19
            .hash(usize::from(chain_spec.block_number_bytes())),
684
19
    })
685
0
    .await
686
19
    .map_err(StartError::JsonRpcServiceInit)
?0
;
687
688
    // Start the JSON-RPC service of the relay chain.
689
    // See remarks above.
690
19
    let relay_chain_json_rpc_service = if let Some(
relay_chain_cfg0
) = config.relay_chain {
691
0
        let relay_chain_spec = relay_chain_spec.as_ref().unwrap();
692
0
        Some(
693
0
            json_rpc_service::JsonRpcService::new(json_rpc_service::Config {
694
0
                tasks_executor: config.tasks_executor.clone(),
695
0
                log_callback: config.log_callback.clone(),
696
0
                database: relay_chain_database.clone().unwrap(),
697
0
                consensus_service: relay_chain_consensus_service.clone().unwrap(),
698
0
                network_service: (network_service.clone(), network_service_chain_ids[1]),
699
0
                bind_address: relay_chain_cfg
700
0
                    .json_rpc_listen
701
0
                    .as_ref()
702
0
                    .map(|cfg| cfg.address),
703
0
                max_parallel_requests: 32,
704
0
                max_json_rpc_clients: relay_chain_cfg
705
0
                    .json_rpc_listen
706
0
                    .map_or(0, |cfg| cfg.max_json_rpc_clients),
707
0
                chain_name: relay_chain_spec.name().to_owned(),
708
0
                chain_type: relay_chain_spec.chain_type().to_owned(),
709
0
                chain_properties_json: relay_chain_spec.properties().to_owned(),
710
0
                chain_is_live: relay_chain_spec.has_live_network(),
711
0
                genesis_block_hash: relay_genesis_chain_information
712
0
                    .as_ref()
713
0
                    .unwrap()
714
0
                    .as_ref()
715
0
                    .finalized_block_header
716
0
                    .hash(usize::from(relay_chain_spec.block_number_bytes())),
717
0
            })
718
0
            .await
719
0
            .map_err(StartError::JsonRpcServiceInit)?,
720
        )
721
    } else {
722
19
        None
723
    };
724
725
    // Spawn the task printing the informant.
726
    // This is not just a dummy task that just prints on the output, but is actually the main
727
    // task that holds everything else alive. Without it, all the services that we have created
728
    // above would be cleanly dropped and nothing would happen.
729
    // For this reason, it must be spawned even if no informant is started, in which case we simply
730
    // inhibit the printing.
731
19
    let network_known_best = Arc::new(Mutex::new(None));
732
19
    (config.tasks_executor)(Box::pin({
733
19
        let mut main_network_events_receiver = network_events_receivers.next().unwrap();
734
19
        let network_service_chain_id = network_service_chain_ids[0];
735
19
        let network_known_best = network_known_best.clone();
736
19
737
19
        // TODO: shut down this task if the client stops?
738
19
        async move {
739
            loop {
740
                let network_event = main_network_events_receiver.next().await.unwrap();
741
                let mut network_known_best = network_known_best.lock().await;
742
743
                match network_event {
744
                    network_service::Event::BlockAnnounce {
745
                        chain_id,
746
                        scale_encoded_header,
747
                        ..
748
                    } if chain_id == network_service_chain_id => match (
749
                        *network_known_best,
750
                        header::decode(
751
                            &scale_encoded_header,
752
                            usize::from(chain_spec.block_number_bytes()),
753
                        ),
754
                    ) {
755
                        (Some(n), Ok(header)) if n >= header.number => {}
756
                        (_, Ok(header)) => *network_known_best = Some(header.number),
757
                        (_, Err(_)) => {
758
                            // Do nothing if the block is invalid. This is just for the
759
                            // informant and not for consensus-related purposes.
760
                        }
761
                    },
762
                    network_service::Event::Connected {
763
                        chain_id,
764
                        best_block_number,
765
                        ..
766
                    } if chain_id == network_service_chain_id => match *network_known_best {
767
                        Some(n) if n >= best_block_number => {}
768
                        _ => *network_known_best = Some(best_block_number),
769
                    },
770
                    _ => {}
771
                }
772
            }
773
19
        }
774
19
    }));
775
19
776
19
    config.log_callback.log(
777
19
        LogLevel::Info,
778
19
        format!(
779
19
            "successful-initialization; local_peer_id={}; database_is_new={:?}; \
780
19
                finalized_block_hash={}; finalized_block_number={}",
781
19
            local_peer_id,
782
19
            !database_existed,
783
19
            HashDisplay(&database_finalized_block_hash),
784
19
            database_finalized_block_number
785
19
        ),
786
19
    );
787
19
788
19
    debug_assert!(network_events_receivers.next().is_none());
789
19
    Ok(Client {
790
19
        consensus_service,
791
19
        relay_chain_consensus_service,
792
19
        json_rpc_service,
793
19
        relay_chain_json_rpc_service,
794
19
        network_service,
795
19
        network_known_best,
796
19
    })
797
19
}
Unexecuted instantiation: _RNCNvCshBwayKnNXDT_17smoldot_full_node5start0B3_
798
799
/// Opens the database from the file system, or create a new database if none is found.
800
///
801
/// If `db_path` is `None`, open the database in memory instead.
802
///
803
/// The returned boolean is `true` if the database existed before.
804
///
805
/// # Panic
806
///
807
/// Panics if the database can't be open. This function is expected to be called from the `main`
808
/// function.
809
///
810
21
async fn open_database(
811
21
    chain_spec: &chain_spec::ChainSpec,
812
21
    genesis_chain_information: chain::chain_information::ChainInformationRef<'_>,
813
21
    db_path: Option<PathBuf>,
814
21
    sqlite_cache_size: usize,
815
21
) -> (full_sqlite::SqliteFullDatabase, bool) {
_RNvCsiUjFBJteJ7x_17smoldot_full_node13open_database
Line
Count
Source
810
21
async fn open_database(
811
21
    chain_spec: &chain_spec::ChainSpec,
812
21
    genesis_chain_information: chain::chain_information::ChainInformationRef<'_>,
813
21
    db_path: Option<PathBuf>,
814
21
    sqlite_cache_size: usize,
815
21
) -> (full_sqlite::SqliteFullDatabase, bool) {
Unexecuted instantiation: _RNvCshBwayKnNXDT_17smoldot_full_node13open_database
816
21
    // The `unwrap()` here can panic for example in case of access denied.
817
21
    match full_sqlite::open(full_sqlite::Config {
818
21
        block_number_bytes: chain_spec.block_number_bytes().into(),
819
21
        cache_size: sqlite_cache_size,
820
21
        ty: if let Some(
path0
) = &db_path {
821
0
            full_sqlite::ConfigTy::Disk {
822
0
                path,
823
0
                memory_map_size: 1000000000, // TODO: make configurable
824
0
            }
825
        } else {
826
21
            full_sqlite::ConfigTy::Memory
827
        },
828
    })
829
21
    .unwrap()
830
    {
831
        // Database already exists and contains data.
832
0
        full_sqlite::DatabaseOpen::Open(database) => {
833
0
            if database.block_hash_by_number(0).unwrap().next().unwrap()
834
0
                != genesis_chain_information
835
0
                    .finalized_block_header
836
0
                    .hash(chain_spec.block_number_bytes().into())
837
            {
838
0
                panic!("Mismatch between database and chain specification. Shutting down node.");
839
0
            }
840
0
841
0
            (database, true)
842
        }
843
844
        // The database doesn't exist or is empty.
845
21
        full_sqlite::DatabaseOpen::Empty(empty) => {
846
21
            let genesis_storage = chain_spec.genesis_storage().into_genesis_items().unwrap(); // TODO: return error instead
847
21
848
21
            // In order to determine the state_version of the genesis block, we need to compile
849
21
            // the runtime.
850
21
            // TODO: return errors instead of panicking
851
21
            // TODO: consider not throwing away the runtime
852
21
            let state_version = executor::host::HostVmPrototype::new(executor::host::Config {
853
21
                module: genesis_storage.value(b":code").unwrap(),
854
21
                heap_pages: executor::storage_heap_pages_to_value(
855
21
                    genesis_storage.value(b":heappages"),
856
21
                )
857
21
                .unwrap(),
858
21
                exec_hint: executor::vm::ExecHint::ValidateAndExecuteOnce,
859
21
                allow_unresolved_imports: true,
860
21
            })
861
21
            .unwrap()
862
21
            .runtime_version()
863
21
            .decode()
864
21
            .state_version
865
21
            .map(u8::from)
866
21
            .unwrap_or(0);
867
868
            // The chain specification only contains trie nodes that have a storage value attached
869
            // to them, while the database needs to know all trie nodes (including branch nodes).
870
            // The good news is that we can determine the latter from the former, which we do
871
            // here.
872
            // TODO: consider moving this block to the chain spec module
873
            // TODO: poorly optimized
874
21
            let mut trie_structure = {
875
21
                let mut trie_structure = trie::trie_structure::TrieStructure::new();
876
735
                for (key, value) in 
genesis_storage.iter()21
{
877
735
                    match trie_structure.node(trie::bytes_to_nibbles(key.iter().copied())) {
878
735
                        trie::trie_structure::Entry::Vacant(e) => {
879
735
                            e.insert_storage_value().insert(
880
735
                                (Some(value), None::<trie::trie_node::MerkleValueOutput>),
881
735
                                (None, None),
882
735
                            );
883
735
                        }
884
                        trie::trie_structure::Entry::Occupied(
885
0
                            trie::trie_structure::NodeAccess::Branch(mut e),
886
0
                        ) => {
887
0
                            *e.user_data() = (Some(value), None);
888
0
                            e.insert_storage_value();
889
0
                        }
890
                        trie::trie_structure::Entry::Occupied(
891
                            trie::trie_structure::NodeAccess::Storage(_),
892
                        ) => {
893
                            // Duplicate entry.
894
0
                            panic!() // TODO: don't panic?
895
                        }
896
                    }
897
                }
898
899
                // Calculate the Merkle values of the nodes.
900
1.00k
                for node_index in trie_structure
901
21
                    .iter_ordered()
902
21
                    .collect::<Vec<_>>()
903
21
                    .into_iter()
904
21
                    .rev()
905
                {
906
1.00k
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
907
1.00k
908
16.1k
                    let children = core::array::from_fn::<_, 16, _>(|n| {
909
16.1k
                        node_access
910
16.1k
                            .child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
911
16.1k
                            .map(|mut child| 
child.user_data().1.as_ref().unwrap().clone()987
)
_RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database000CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
911
94
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
Unexecuted instantiation: _RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database000B7_
Unexecuted instantiation: _RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database000CscDgN54JpMGG_6author
_RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database000CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
911
893
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
Unexecuted instantiation: _RNCNCNCNvCshBwayKnNXDT_17smoldot_full_node13open_database000B7_
912
16.1k
                    });
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database00CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
908
1.53k
                    let children = core::array::from_fn::<_, 16, _>(|n| {
909
1.53k
                        node_access
910
1.53k
                            .child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
911
1.53k
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
912
1.53k
                    });
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database00B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database00CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database00CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
908
14.5k
                    let children = core::array::from_fn::<_, 16, _>(|n| {
909
14.5k
                        node_access
910
14.5k
                            .child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
911
14.5k
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
912
14.5k
                    });
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node13open_database00B5_
913
1.00k
914
1.00k
                    let is_root_node = node_access.is_root_node();
915
1.00k
                    let partial_key = node_access.partial_key().collect::<Vec<_>>().into_iter();
916
917
                    // We have to hash the storage value ahead of time if necessary due to borrow
918
                    // checking difficulties.
919
1.00k
                    let storage_value_hashed =
920
1.00k
                        match (node_access.user_data().0.as_ref(), state_version) {
921
0
                            (Some(v), 1) => {
922
0
                                if v.len() >= 33 {
923
0
                                    Some(blake2_rfc::blake2b::blake2b(32, &[], v))
924
                                } else {
925
0
                                    None
926
                                }
927
                            }
928
1.00k
                            _ => None,
929
                        };
930
1.00k
                    let storage_value = match (
931
1.00k
                        node_access.user_data().0.as_ref(),
932
1.00k
                        storage_value_hashed.as_ref(),
933
                    ) {
934
0
                        (_, Some(storage_value_hashed)) => trie::trie_node::StorageValue::Hashed(
935
0
                            <&[u8; 32]>::try_from(storage_value_hashed.as_bytes()).unwrap(),
936
0
                        ),
937
735
                        (Some(v), None) => trie::trie_node::StorageValue::Unhashed(&v[..]),
938
273
                        (None, _) => trie::trie_node::StorageValue::None,
939
                    };
940
941
1.00k
                    let merkle_value = trie::trie_node::calculate_merkle_value(
942
1.00k
                        trie::trie_node::Decoded {
943
1.00k
                            children,
944
1.00k
                            partial_key,
945
1.00k
                            storage_value,
946
1.00k
                        },
947
1.00k
                        trie::HashFunction::Blake2,
948
1.00k
                        is_root_node,
949
1.00k
                    )
950
1.00k
                    .unwrap();
951
1.00k
952
1.00k
                    node_access.into_user_data().1 = Some(merkle_value);
953
                }
954
955
21
                trie_structure
956
21
            };
957
21
958
21
            // Build the iterator of trie nodes.
959
21
            let genesis_storage_full_trie = trie_structure
960
21
                .iter_unordered()
961
21
                .collect::<Vec<_>>()
962
21
                .into_iter()
963
1.00k
                .map(|node_index| {
964
1.00k
                    let (storage_value, Some(merkle_value)) = &trie_structure[node_index] else {
965
0
                        unreachable!()
966
                    };
967
                    // Cloning to solve borrow checker restriction. // TODO: optimize?
968
1.00k
                    let storage_value = if let Some(
storage_value735
) = storage_value {
969
                        // TODO: child tries support?
970
735
                        full_sqlite::InsertTrieNodeStorageValue::Value {
971
735
                            value: Cow::Owned(storage_value.to_vec()),
972
735
                            references_merkle_value: false,
973
735
                        }
974
                    } else {
975
273
                        full_sqlite::InsertTrieNodeStorageValue::NoValue
976
                    };
977
1.00k
                    let merkle_value = merkle_value.as_ref().to_owned();
978
1.00k
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
979
1.00k
980
1.00k
                    full_sqlite::InsertTrieNode {
981
1.00k
                        storage_value,
982
1.00k
                        merkle_value: Cow::Owned(merkle_value),
983
16.1k
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
16.1k
                            let child_index =
985
16.1k
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
16.1k
                            node_access.child(child_index).map(|mut child| {
987
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
16.1k
                            })
_RNCNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_000CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
986
94
                            node_access.child(child_index).map(|mut child| {
987
94
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
94
                            })
Unexecuted instantiation: _RNCNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_000B9_
Unexecuted instantiation: _RNCNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_000CscDgN54JpMGG_6author
_RNCNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_000CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
986
893
                            node_access.child(child_index).map(|mut child| {
987
893
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
893
                            })
Unexecuted instantiation: _RNCNCNCNCNvCshBwayKnNXDT_17smoldot_full_node13open_database0s_000B9_
989
16.1k
                        }),
_RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_00CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
983
1.53k
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
1.53k
                            let child_index =
985
1.53k
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
1.53k
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
1.53k
                            })
989
1.53k
                        }),
Unexecuted instantiation: _RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_00B7_
Unexecuted instantiation: _RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_00CscDgN54JpMGG_6author
_RNCNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_00CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
983
14.5k
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
14.5k
                            let child_index =
985
14.5k
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
14.5k
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
14.5k
                            })
989
14.5k
                        }),
Unexecuted instantiation: _RNCNCNCNvCshBwayKnNXDT_17smoldot_full_node13open_database0s_00B7_
990
1.00k
                        partial_key_nibbles: Cow::Owned(
991
1.00k
                            node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
992
1.00k
                        ),
993
1.00k
                    }
994
1.00k
                });
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
963
96
                .map(|node_index| {
964
96
                    let (storage_value, Some(merkle_value)) = &trie_structure[node_index] else {
965
0
                        unreachable!()
966
                    };
967
                    // Cloning to solve borrow checker restriction. // TODO: optimize?
968
96
                    let storage_value = if let Some(
storage_value70
) = storage_value {
969
                        // TODO: child tries support?
970
70
                        full_sqlite::InsertTrieNodeStorageValue::Value {
971
70
                            value: Cow::Owned(storage_value.to_vec()),
972
70
                            references_merkle_value: false,
973
70
                        }
974
                    } else {
975
26
                        full_sqlite::InsertTrieNodeStorageValue::NoValue
976
                    };
977
96
                    let merkle_value = merkle_value.as_ref().to_owned();
978
96
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
979
96
980
96
                    full_sqlite::InsertTrieNode {
981
96
                        storage_value,
982
96
                        merkle_value: Cow::Owned(merkle_value),
983
96
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
                            let child_index =
985
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
                            })
989
96
                        }),
990
96
                        partial_key_nibbles: Cow::Owned(
991
96
                            node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
992
96
                        ),
993
96
                    }
994
96
                });
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_0B5_
Unexecuted instantiation: _RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_0CscDgN54JpMGG_6author
_RNCNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0s_0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
963
912
                .map(|node_index| {
964
912
                    let (storage_value, Some(merkle_value)) = &trie_structure[node_index] else {
965
0
                        unreachable!()
966
                    };
967
                    // Cloning to solve borrow checker restriction. // TODO: optimize?
968
912
                    let storage_value = if let Some(
storage_value665
) = storage_value {
969
                        // TODO: child tries support?
970
665
                        full_sqlite::InsertTrieNodeStorageValue::Value {
971
665
                            value: Cow::Owned(storage_value.to_vec()),
972
665
                            references_merkle_value: false,
973
665
                        }
974
                    } else {
975
247
                        full_sqlite::InsertTrieNodeStorageValue::NoValue
976
                    };
977
912
                    let merkle_value = merkle_value.as_ref().to_owned();
978
912
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
979
912
980
912
                    full_sqlite::InsertTrieNode {
981
912
                        storage_value,
982
912
                        merkle_value: Cow::Owned(merkle_value),
983
912
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
                            let child_index =
985
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
                            })
989
912
                        }),
990
912
                        partial_key_nibbles: Cow::Owned(
991
912
                            node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
992
912
                        ),
993
912
                    }
994
912
                });
Unexecuted instantiation: _RNCNCNvCshBwayKnNXDT_17smoldot_full_node13open_database0s_0B5_
995
21
996
21
            // The finalized block is the genesis block. As such, it has an empty body and
997
21
            // no justification.
998
21
            let database = empty
999
21
                .initialize(
1000
21
                    &genesis_chain_information
1001
21
                        .finalized_block_header
1002
21
                        .scale_encoding_vec(chain_spec.block_number_bytes().into()),
1003
21
                    iter::empty(),
1004
21
                    None,
1005
21
                )
1006
21
                .unwrap();
1007
21
            database
1008
21
                .insert_trie_nodes(genesis_storage_full_trie, state_version)
1009
21
                .unwrap();
1010
21
            (database, false)
1011
        }
1012
    }
1013
21
}
_RNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0CsiLzmwikkc22_14json_rpc_basic
Line
Count
Source
815
2
) -> (full_sqlite::SqliteFullDatabase, bool) {
816
2
    // The `unwrap()` here can panic for example in case of access denied.
817
2
    match full_sqlite::open(full_sqlite::Config {
818
2
        block_number_bytes: chain_spec.block_number_bytes().into(),
819
2
        cache_size: sqlite_cache_size,
820
2
        ty: if let Some(
path0
) = &db_path {
821
0
            full_sqlite::ConfigTy::Disk {
822
0
                path,
823
0
                memory_map_size: 1000000000, // TODO: make configurable
824
0
            }
825
        } else {
826
2
            full_sqlite::ConfigTy::Memory
827
        },
828
    })
829
2
    .unwrap()
830
    {
831
        // Database already exists and contains data.
832
0
        full_sqlite::DatabaseOpen::Open(database) => {
833
0
            if database.block_hash_by_number(0).unwrap().next().unwrap()
834
0
                != genesis_chain_information
835
0
                    .finalized_block_header
836
0
                    .hash(chain_spec.block_number_bytes().into())
837
            {
838
0
                panic!("Mismatch between database and chain specification. Shutting down node.");
839
0
            }
840
0
841
0
            (database, true)
842
        }
843
844
        // The database doesn't exist or is empty.
845
2
        full_sqlite::DatabaseOpen::Empty(empty) => {
846
2
            let genesis_storage = chain_spec.genesis_storage().into_genesis_items().unwrap(); // TODO: return error instead
847
2
848
2
            // In order to determine the state_version of the genesis block, we need to compile
849
2
            // the runtime.
850
2
            // TODO: return errors instead of panicking
851
2
            // TODO: consider not throwing away the runtime
852
2
            let state_version = executor::host::HostVmPrototype::new(executor::host::Config {
853
2
                module: genesis_storage.value(b":code").unwrap(),
854
2
                heap_pages: executor::storage_heap_pages_to_value(
855
2
                    genesis_storage.value(b":heappages"),
856
2
                )
857
2
                .unwrap(),
858
2
                exec_hint: executor::vm::ExecHint::ValidateAndExecuteOnce,
859
2
                allow_unresolved_imports: true,
860
2
            })
861
2
            .unwrap()
862
2
            .runtime_version()
863
2
            .decode()
864
2
            .state_version
865
2
            .map(u8::from)
866
2
            .unwrap_or(0);
867
868
            // The chain specification only contains trie nodes that have a storage value attached
869
            // to them, while the database needs to know all trie nodes (including branch nodes).
870
            // The good news is that we can determine the latter from the former, which we do
871
            // here.
872
            // TODO: consider moving this block to the chain spec module
873
            // TODO: poorly optimized
874
2
            let mut trie_structure = {
875
2
                let mut trie_structure = trie::trie_structure::TrieStructure::new();
876
70
                for (key, value) in 
genesis_storage.iter()2
{
877
70
                    match trie_structure.node(trie::bytes_to_nibbles(key.iter().copied())) {
878
70
                        trie::trie_structure::Entry::Vacant(e) => {
879
70
                            e.insert_storage_value().insert(
880
70
                                (Some(value), None::<trie::trie_node::MerkleValueOutput>),
881
70
                                (None, None),
882
70
                            );
883
70
                        }
884
                        trie::trie_structure::Entry::Occupied(
885
0
                            trie::trie_structure::NodeAccess::Branch(mut e),
886
0
                        ) => {
887
0
                            *e.user_data() = (Some(value), None);
888
0
                            e.insert_storage_value();
889
0
                        }
890
                        trie::trie_structure::Entry::Occupied(
891
                            trie::trie_structure::NodeAccess::Storage(_),
892
                        ) => {
893
                            // Duplicate entry.
894
0
                            panic!() // TODO: don't panic?
895
                        }
896
                    }
897
                }
898
899
                // Calculate the Merkle values of the nodes.
900
96
                for node_index in trie_structure
901
2
                    .iter_ordered()
902
2
                    .collect::<Vec<_>>()
903
2
                    .into_iter()
904
2
                    .rev()
905
                {
906
96
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
907
96
908
96
                    let children = core::array::from_fn::<_, 16, _>(|n| {
909
                        node_access
910
                            .child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
911
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
912
96
                    });
913
96
914
96
                    let is_root_node = node_access.is_root_node();
915
96
                    let partial_key = node_access.partial_key().collect::<Vec<_>>().into_iter();
916
917
                    // We have to hash the storage value ahead of time if necessary due to borrow
918
                    // checking difficulties.
919
96
                    let storage_value_hashed =
920
96
                        match (node_access.user_data().0.as_ref(), state_version) {
921
0
                            (Some(v), 1) => {
922
0
                                if v.len() >= 33 {
923
0
                                    Some(blake2_rfc::blake2b::blake2b(32, &[], v))
924
                                } else {
925
0
                                    None
926
                                }
927
                            }
928
96
                            _ => None,
929
                        };
930
96
                    let storage_value = match (
931
96
                        node_access.user_data().0.as_ref(),
932
96
                        storage_value_hashed.as_ref(),
933
                    ) {
934
0
                        (_, Some(storage_value_hashed)) => trie::trie_node::StorageValue::Hashed(
935
0
                            <&[u8; 32]>::try_from(storage_value_hashed.as_bytes()).unwrap(),
936
0
                        ),
937
70
                        (Some(v), None) => trie::trie_node::StorageValue::Unhashed(&v[..]),
938
26
                        (None, _) => trie::trie_node::StorageValue::None,
939
                    };
940
941
96
                    let merkle_value = trie::trie_node::calculate_merkle_value(
942
96
                        trie::trie_node::Decoded {
943
96
                            children,
944
96
                            partial_key,
945
96
                            storage_value,
946
96
                        },
947
96
                        trie::HashFunction::Blake2,
948
96
                        is_root_node,
949
96
                    )
950
96
                    .unwrap();
951
96
952
96
                    node_access.into_user_data().1 = Some(merkle_value);
953
                }
954
955
2
                trie_structure
956
2
            };
957
2
958
2
            // Build the iterator of trie nodes.
959
2
            let genesis_storage_full_trie = trie_structure
960
2
                .iter_unordered()
961
2
                .collect::<Vec<_>>()
962
2
                .into_iter()
963
2
                .map(|node_index| {
964
                    let (storage_value, Some(merkle_value)) = &trie_structure[node_index] else {
965
                        unreachable!()
966
                    };
967
                    // Cloning to solve borrow checker restriction. // TODO: optimize?
968
                    let storage_value = if let Some(storage_value) = storage_value {
969
                        // TODO: child tries support?
970
                        full_sqlite::InsertTrieNodeStorageValue::Value {
971
                            value: Cow::Owned(storage_value.to_vec()),
972
                            references_merkle_value: false,
973
                        }
974
                    } else {
975
                        full_sqlite::InsertTrieNodeStorageValue::NoValue
976
                    };
977
                    let merkle_value = merkle_value.as_ref().to_owned();
978
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
979
980
                    full_sqlite::InsertTrieNode {
981
                        storage_value,
982
                        merkle_value: Cow::Owned(merkle_value),
983
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
                            let child_index =
985
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
                            })
989
                        }),
990
                        partial_key_nibbles: Cow::Owned(
991
                            node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
992
                        ),
993
                    }
994
2
                });
995
2
996
2
            // The finalized block is the genesis block. As such, it has an empty body and
997
2
            // no justification.
998
2
            let database = empty
999
2
                .initialize(
1000
2
                    &genesis_chain_information
1001
2
                        .finalized_block_header
1002
2
                        .scale_encoding_vec(chain_spec.block_number_bytes().into()),
1003
2
                    iter::empty(),
1004
2
                    None,
1005
2
                )
1006
2
                .unwrap();
1007
2
            database
1008
2
                .insert_trie_nodes(genesis_storage_full_trie, state_version)
1009
2
                .unwrap();
1010
2
            (database, false)
1011
        }
1012
    }
1013
2
}
Unexecuted instantiation: _RNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0B3_
Unexecuted instantiation: _RNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0CscDgN54JpMGG_6author
_RNCNvCsiUjFBJteJ7x_17smoldot_full_node13open_database0CsibGXYHQB8Ea_25json_rpc_general_requests
Line
Count
Source
815
19
) -> (full_sqlite::SqliteFullDatabase, bool) {
816
19
    // The `unwrap()` here can panic for example in case of access denied.
817
19
    match full_sqlite::open(full_sqlite::Config {
818
19
        block_number_bytes: chain_spec.block_number_bytes().into(),
819
19
        cache_size: sqlite_cache_size,
820
19
        ty: if let Some(
path0
) = &db_path {
821
0
            full_sqlite::ConfigTy::Disk {
822
0
                path,
823
0
                memory_map_size: 1000000000, // TODO: make configurable
824
0
            }
825
        } else {
826
19
            full_sqlite::ConfigTy::Memory
827
        },
828
    })
829
19
    .unwrap()
830
    {
831
        // Database already exists and contains data.
832
0
        full_sqlite::DatabaseOpen::Open(database) => {
833
0
            if database.block_hash_by_number(0).unwrap().next().unwrap()
834
0
                != genesis_chain_information
835
0
                    .finalized_block_header
836
0
                    .hash(chain_spec.block_number_bytes().into())
837
            {
838
0
                panic!("Mismatch between database and chain specification. Shutting down node.");
839
0
            }
840
0
841
0
            (database, true)
842
        }
843
844
        // The database doesn't exist or is empty.
845
19
        full_sqlite::DatabaseOpen::Empty(empty) => {
846
19
            let genesis_storage = chain_spec.genesis_storage().into_genesis_items().unwrap(); // TODO: return error instead
847
19
848
19
            // In order to determine the state_version of the genesis block, we need to compile
849
19
            // the runtime.
850
19
            // TODO: return errors instead of panicking
851
19
            // TODO: consider not throwing away the runtime
852
19
            let state_version = executor::host::HostVmPrototype::new(executor::host::Config {
853
19
                module: genesis_storage.value(b":code").unwrap(),
854
19
                heap_pages: executor::storage_heap_pages_to_value(
855
19
                    genesis_storage.value(b":heappages"),
856
19
                )
857
19
                .unwrap(),
858
19
                exec_hint: executor::vm::ExecHint::ValidateAndExecuteOnce,
859
19
                allow_unresolved_imports: true,
860
19
            })
861
19
            .unwrap()
862
19
            .runtime_version()
863
19
            .decode()
864
19
            .state_version
865
19
            .map(u8::from)
866
19
            .unwrap_or(0);
867
868
            // The chain specification only contains trie nodes that have a storage value attached
869
            // to them, while the database needs to know all trie nodes (including branch nodes).
870
            // The good news is that we can determine the latter from the former, which we do
871
            // here.
872
            // TODO: consider moving this block to the chain spec module
873
            // TODO: poorly optimized
874
19
            let mut trie_structure = {
875
19
                let mut trie_structure = trie::trie_structure::TrieStructure::new();
876
665
                for (key, value) in 
genesis_storage.iter()19
{
877
665
                    match trie_structure.node(trie::bytes_to_nibbles(key.iter().copied())) {
878
665
                        trie::trie_structure::Entry::Vacant(e) => {
879
665
                            e.insert_storage_value().insert(
880
665
                                (Some(value), None::<trie::trie_node::MerkleValueOutput>),
881
665
                                (None, None),
882
665
                            );
883
665
                        }
884
                        trie::trie_structure::Entry::Occupied(
885
0
                            trie::trie_structure::NodeAccess::Branch(mut e),
886
0
                        ) => {
887
0
                            *e.user_data() = (Some(value), None);
888
0
                            e.insert_storage_value();
889
0
                        }
890
                        trie::trie_structure::Entry::Occupied(
891
                            trie::trie_structure::NodeAccess::Storage(_),
892
                        ) => {
893
                            // Duplicate entry.
894
0
                            panic!() // TODO: don't panic?
895
                        }
896
                    }
897
                }
898
899
                // Calculate the Merkle values of the nodes.
900
912
                for node_index in trie_structure
901
19
                    .iter_ordered()
902
19
                    .collect::<Vec<_>>()
903
19
                    .into_iter()
904
19
                    .rev()
905
                {
906
912
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
907
912
908
912
                    let children = core::array::from_fn::<_, 16, _>(|n| {
909
                        node_access
910
                            .child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
911
                            .map(|mut child| child.user_data().1.as_ref().unwrap().clone())
912
912
                    });
913
912
914
912
                    let is_root_node = node_access.is_root_node();
915
912
                    let partial_key = node_access.partial_key().collect::<Vec<_>>().into_iter();
916
917
                    // We have to hash the storage value ahead of time if necessary due to borrow
918
                    // checking difficulties.
919
912
                    let storage_value_hashed =
920
912
                        match (node_access.user_data().0.as_ref(), state_version) {
921
0
                            (Some(v), 1) => {
922
0
                                if v.len() >= 33 {
923
0
                                    Some(blake2_rfc::blake2b::blake2b(32, &[], v))
924
                                } else {
925
0
                                    None
926
                                }
927
                            }
928
912
                            _ => None,
929
                        };
930
912
                    let storage_value = match (
931
912
                        node_access.user_data().0.as_ref(),
932
912
                        storage_value_hashed.as_ref(),
933
                    ) {
934
0
                        (_, Some(storage_value_hashed)) => trie::trie_node::StorageValue::Hashed(
935
0
                            <&[u8; 32]>::try_from(storage_value_hashed.as_bytes()).unwrap(),
936
0
                        ),
937
665
                        (Some(v), None) => trie::trie_node::StorageValue::Unhashed(&v[..]),
938
247
                        (None, _) => trie::trie_node::StorageValue::None,
939
                    };
940
941
912
                    let merkle_value = trie::trie_node::calculate_merkle_value(
942
912
                        trie::trie_node::Decoded {
943
912
                            children,
944
912
                            partial_key,
945
912
                            storage_value,
946
912
                        },
947
912
                        trie::HashFunction::Blake2,
948
912
                        is_root_node,
949
912
                    )
950
912
                    .unwrap();
951
912
952
912
                    node_access.into_user_data().1 = Some(merkle_value);
953
                }
954
955
19
                trie_structure
956
19
            };
957
19
958
19
            // Build the iterator of trie nodes.
959
19
            let genesis_storage_full_trie = trie_structure
960
19
                .iter_unordered()
961
19
                .collect::<Vec<_>>()
962
19
                .into_iter()
963
19
                .map(|node_index| {
964
                    let (storage_value, Some(merkle_value)) = &trie_structure[node_index] else {
965
                        unreachable!()
966
                    };
967
                    // Cloning to solve borrow checker restriction. // TODO: optimize?
968
                    let storage_value = if let Some(storage_value) = storage_value {
969
                        // TODO: child tries support?
970
                        full_sqlite::InsertTrieNodeStorageValue::Value {
971
                            value: Cow::Owned(storage_value.to_vec()),
972
                            references_merkle_value: false,
973
                        }
974
                    } else {
975
                        full_sqlite::InsertTrieNodeStorageValue::NoValue
976
                    };
977
                    let merkle_value = merkle_value.as_ref().to_owned();
978
                    let mut node_access = trie_structure.node_by_index(node_index).unwrap();
979
980
                    full_sqlite::InsertTrieNode {
981
                        storage_value,
982
                        merkle_value: Cow::Owned(merkle_value),
983
                        children_merkle_values: array::from_fn::<_, 16, _>(|n| {
984
                            let child_index =
985
                                trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
986
                            node_access.child(child_index).map(|mut child| {
987
                                Cow::Owned(child.user_data().1.as_ref().unwrap().as_ref().to_vec())
988
                            })
989
                        }),
990
                        partial_key_nibbles: Cow::Owned(
991
                            node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
992
                        ),
993
                    }
994
19
                });
995
19
996
19
            // The finalized block is the genesis block. As such, it has an empty body and
997
19
            // no justification.
998
19
            let database = empty
999
19
                .initialize(
1000
19
                    &genesis_chain_information
1001
19
                        .finalized_block_header
1002
19
                        .scale_encoding_vec(chain_spec.block_number_bytes().into()),
1003
19
                    iter::empty(),
1004
19
                    None,
1005
19
                )
1006
19
                .unwrap();
1007
19
            database
1008
19
                .insert_trie_nodes(genesis_storage_full_trie, state_version)
1009
19
                .unwrap();
1010
19
            (database, false)
1011
        }
1012
    }
1013
19
}
Unexecuted instantiation: _RNCNvCshBwayKnNXDT_17smoldot_full_node13open_database0B3_