Coverage Report

Created: 2025-07-01 09:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/__w/smoldot/smoldot/repo/lib/src/header.rs
Line
Count
Source
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
//! Parsing SCALE-encoded header.
19
//!
20
//! Each block of a chain is composed of two parts: its header, and its body.
21
//!
22
//! The header of a block consists in a list of hard coded fields such as the parent block's hash
23
//! or the block number, and a variable-sized list of log items.
24
//!
25
//! The standard format of a block header is the
26
//! [SCALE encoding](https://docs.substrate.io/v3/advanced/scale-codec). It is typically
27
//! under this encoding that block headers are for example transferred over the network or stored
28
//! in the database. Use the [`decode`] function in order to decompose a SCALE-encoded header
29
//! into a usable [`HeaderRef`].
30
//!
31
//! # Example
32
//!
33
//! ```
34
//! // Example encoded header.
35
//! let scale_encoded_header: &[u8] = &[
36
//!     246, 90, 76, 223, 195, 230, 202, 111, 120, 197, 6, 9, 90, 164, 170, 8, 194, 57, 184, 75,
37
//!     95, 67, 240, 169, 62, 244, 171, 95, 237, 85, 86, 1, 122, 169, 8, 0, 138, 149, 72, 185, 56,
38
//!     62, 30, 76, 117, 134, 123, 62, 4, 132, 23, 143, 200, 150, 171, 42, 63, 19, 173, 21, 89, 98,
39
//!     38, 175, 43, 132, 69, 75, 96, 168, 82, 108, 19, 182, 130, 230, 161, 43, 7, 225, 20, 229,
40
//!     92, 103, 57, 188, 151, 170, 16, 8, 126, 122, 98, 131, 121, 43, 181, 19, 180, 228, 8, 6, 66,
41
//!     65, 66, 69, 181, 1, 3, 1, 0, 0, 0, 250, 8, 207, 15, 0, 0, 0, 0, 86, 157, 105, 202, 151,
42
//!     254, 95, 169, 249, 150, 219, 194, 195, 143, 181, 39, 43, 87, 179, 157, 152, 191, 40, 255,
43
//!     23, 66, 18, 249, 93, 170, 58, 15, 178, 210, 130, 18, 66, 244, 232, 119, 74, 190, 92, 145,
44
//!     33, 192, 195, 176, 125, 217, 124, 33, 167, 97, 64, 63, 149, 200, 220, 191, 64, 134, 232, 9,
45
//!     3, 178, 186, 150, 130, 105, 25, 148, 218, 35, 208, 226, 112, 85, 184, 237, 23, 243, 86, 81,
46
//!     27, 127, 188, 223, 162, 244, 26, 77, 234, 116, 24, 11, 5, 66, 65, 66, 69, 1, 1, 112, 68,
47
//!     111, 83, 145, 78, 98, 96, 247, 64, 179, 237, 113, 175, 125, 177, 110, 39, 185, 55, 156,
48
//!     197, 177, 225, 226, 90, 238, 223, 115, 193, 185, 35, 67, 216, 98, 25, 55, 225, 224, 19, 43,
49
//!     255, 226, 125, 22, 160, 33, 182, 222, 213, 150, 40, 108, 108, 124, 254, 140, 228, 155, 29,
50
//!     250, 193, 65, 140,
51
//! ];
52
//!
53
//! // Decoding the header can panic if it is malformed. Do not unwrap if, for example, the
54
//! // header has been received from a remote!
55
//! // The second parameter is specific to each chain and corresponds to the number of bytes
56
//! // that are used to encode block numbers. This value is also necessary when calculating
57
//! // the hash of the header or encoding it.
58
//! let decoded_header = smoldot::header::decode(&scale_encoded_header, 4).unwrap();
59
//!
60
//! println!("Block hash: {:?}", decoded_header.hash(4));
61
//! println!("Header number: {}", decoded_header.number);
62
//! println!("Parent block hash: {:?}", decoded_header.parent_hash);
63
//! for item in decoded_header.digest.logs() {
64
//!     println!("Digest item: {:?}", item);
65
//! }
66
//!
67
//! // Call `scale_encoding` to produce the header encoding.
68
//! let reencoded: Vec<u8> = decoded_header
69
//!     .scale_encoding(4)
70
//!     .fold(Vec::new(), |mut a, b| { a.extend_from_slice(b.as_ref()); a });
71
//! assert_eq!(reencoded, scale_encoded_header);
72
//! ```
73
74
// TODO: consider rewriting the encoding into a more legible style
75
76
use crate::{trie, util};
77
78
use alloc::{vec, vec::Vec};
79
use core::{fmt, iter, slice};
80
81
mod aura;
82
mod babe;
83
mod grandpa;
84
mod tests;
85
86
pub use aura::*;
87
pub use babe::*;
88
pub use grandpa::*;
89
90
/// Returns a hash of a SCALE-encoded header.
91
///
92
/// Does not verify the validity of the header.
93
1.07k
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
1.07k
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
1.07k
}
_RINvNtCsjlkOsLH0Zfj_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEEB4_
Line
Count
Source
93
5
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
5
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
5
}
_RINvNtCsjlkOsLH0Zfj_7smoldot6header30hash_from_scale_encoded_headerRShEB4_
Line
Count
Source
93
1.02k
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
1.02k
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
1.02k
}
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEECscoAnRPySggw_6author
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRShECscoAnRPySggw_6author
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRShECsfFWJyR6nd6r_17smoldot_full_node
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEEB4_
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRShECs7snhGEhbuap_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEECs7snhGEhbuap_18smoldot_light_wasm
_RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEECsjyNE3yDMkgA_14json_rpc_basic
Line
Count
Source
93
2
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
2
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
2
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRShECsjyNE3yDMkgA_14json_rpc_basic
Line
Count
Source
93
2
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
2
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
2
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRShECs4VrkfB1pvQ3_25json_rpc_general_requests
Line
Count
Source
93
19
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
19
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
19
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header30hash_from_scale_encoded_headerRINtNtCsaFPxhswmqCN_5alloc3vec3VechEECs4VrkfB1pvQ3_25json_rpc_general_requests
Line
Count
Source
93
19
pub fn hash_from_scale_encoded_header(header: impl AsRef<[u8]>) -> [u8; 32] {
94
19
    hash_from_scale_encoded_header_vectored(iter::once(header))
95
19
}
96
97
/// Returns a hash of a SCALE-encoded header.
98
///
99
/// Must be passed a list of buffers, which, when concatenated, form the SCALE-encoded header.
100
///
101
/// Does not verify the validity of the header.
102
1.14k
pub fn hash_from_scale_encoded_header_vectored(
103
1.14k
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
1.14k
) -> [u8; 32] {
105
1.14k
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
2.61k
    for 
buf1.46k
in header {
107
1.46k
        hasher.update(buf.as_ref());
108
1.46k
    }
109
110
1.14k
    let result = hasher.finalize();
111
1.14k
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
1.14k
    let mut out = [0; 32];
114
1.14k
    out.copy_from_slice(result.as_bytes());
115
1.14k
    out
116
1.14k
}
_RINvNtCsjlkOsLH0Zfj_7smoldot6header39hash_from_scale_encoded_header_vectoredINtCsfDbbEgL1j7J_6either6EitherIB1d_RShINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EEIB1d_B1P_IB1d_INtNtCsaFPxhswmqCN_5alloc3vec3VechEB1M_EEEINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters5chain5ChainINtNtB3F_3map3MapIB3B_IB3B_IB3B_INtNtNtB3H_7sources4once4OnceB1H_EB4Y_EB4Y_EB4Y_ENcNtB1c_4Left0EIB4t_IB3B_IB4Z_B2G_EINtNtB3F_7flatten7FlatMapNtB2_8LogsIterIB4t_INtNtNtB3J_5array4iter8IntoIterB2P_Kj2_ENcNtB2G_5Right0ENCNvMs2_B2_NtB2_9DigestRef14scale_encoding0EENcNtB1c_5Right0EEEB4_
Line
Count
Source
102
11
pub fn hash_from_scale_encoded_header_vectored(
103
11
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
11
) -> [u8; 32] {
105
11
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
90
    for 
buf79
in header {
107
79
        hasher.update(buf.as_ref());
108
79
    }
109
110
11
    let result = hasher.finalize();
111
11
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
11
    let mut out = [0; 32];
114
11
    out.copy_from_slice(result.as_bytes());
115
11
    out
116
11
}
_RINvNtCsjlkOsLH0Zfj_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EEB4_
Line
Count
Source
102
5
pub fn hash_from_scale_encoded_header_vectored(
103
5
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
5
) -> [u8; 32] {
105
5
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
10
    for 
buf5
in header {
107
5
        hasher.update(buf.as_ref());
108
5
    }
109
110
5
    let result = hasher.finalize();
111
5
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
5
    let mut out = [0; 32];
114
5
    out.copy_from_slice(result.as_bytes());
115
5
    out
116
5
}
_RINvNtCsjlkOsLH0Zfj_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EEB4_
Line
Count
Source
102
1.02k
pub fn hash_from_scale_encoded_header_vectored(
103
1.02k
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
1.02k
) -> [u8; 32] {
105
1.02k
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
2.05k
    for 
buf1.02k
in header {
107
1.02k
        hasher.update(buf.as_ref());
108
1.02k
    }
109
110
1.02k
    let result = hasher.finalize();
111
1.02k
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
1.02k
    let mut out = [0; 32];
114
1.02k
    out.copy_from_slice(result.as_bytes());
115
1.02k
    out
116
1.02k
}
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECscoAnRPySggw_6author
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECscoAnRPySggw_6author
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECsfFWJyR6nd6r_17smoldot_full_node
_RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredINtCsfDbbEgL1j7J_6either6EitherIB1d_RShINtNtCsh2B47LN1tya_8arrayvec8arrayvec8ArrayVechKj9_EEIB1d_B1P_IB1d_INtNtCsaFPxhswmqCN_5alloc3vec3VechEB1M_EEEINtNtNtNtCs1p5UDGgVI4d_4core4iter8adapters5chain5ChainINtNtB3F_3map3MapIB3B_IB3B_IB3B_INtNtNtB3H_7sources4once4OnceB1H_EB4Y_EB4Y_EB4Y_ENcNtB1c_4Left0EIB4t_IB3B_IB4Z_B2G_EINtNtB3F_7flatten7FlatMapNtB2_8LogsIterIB4t_INtNtNtB3J_5array4iter8IntoIterB2P_Kj2_ENcNtB2G_5Right0ENCNvMs2_B2_NtB2_9DigestRef14scale_encoding0EENcNtB1c_5Right0EEEB4_
Line
Count
Source
102
63
pub fn hash_from_scale_encoded_header_vectored(
103
63
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
63
) -> [u8; 32] {
105
63
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
378
    for 
buf315
in header {
107
315
        hasher.update(buf.as_ref());
108
315
    }
109
110
63
    let result = hasher.finalize();
111
63
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
63
    let mut out = [0; 32];
114
63
    out.copy_from_slice(result.as_bytes());
115
63
    out
116
63
}
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EEB4_
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECs7snhGEhbuap_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECs7snhGEhbuap_18smoldot_light_wasm
_RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECsjyNE3yDMkgA_14json_rpc_basic
Line
Count
Source
102
2
pub fn hash_from_scale_encoded_header_vectored(
103
2
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
2
) -> [u8; 32] {
105
2
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
4
    for 
buf2
in header {
107
2
        hasher.update(buf.as_ref());
108
2
    }
109
110
2
    let result = hasher.finalize();
111
2
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
2
    let mut out = [0; 32];
114
2
    out.copy_from_slice(result.as_bytes());
115
2
    out
116
2
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECsjyNE3yDMkgA_14json_rpc_basic
Line
Count
Source
102
2
pub fn hash_from_scale_encoded_header_vectored(
103
2
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
2
) -> [u8; 32] {
105
2
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
4
    for 
buf2
in header {
107
2
        hasher.update(buf.as_ref());
108
2
    }
109
110
2
    let result = hasher.finalize();
111
2
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
2
    let mut out = [0; 32];
114
2
    out.copy_from_slice(result.as_bytes());
115
2
    out
116
2
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRINtNtCsaFPxhswmqCN_5alloc3vec3VechEINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECs4VrkfB1pvQ3_25json_rpc_general_requests
Line
Count
Source
102
19
pub fn hash_from_scale_encoded_header_vectored(
103
19
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
19
) -> [u8; 32] {
105
19
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
38
    for 
buf19
in header {
107
19
        hasher.update(buf.as_ref());
108
19
    }
109
110
19
    let result = hasher.finalize();
111
19
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
19
    let mut out = [0; 32];
114
19
    out.copy_from_slice(result.as_bytes());
115
19
    out
116
19
}
_RINvNtCsc1ywvx6YAnK_7smoldot6header39hash_from_scale_encoded_header_vectoredRShINtNtNtNtCs1p5UDGgVI4d_4core4iter7sources4once4OnceB1c_EECs4VrkfB1pvQ3_25json_rpc_general_requests
Line
Count
Source
102
19
pub fn hash_from_scale_encoded_header_vectored(
103
19
    header: impl Iterator<Item = impl AsRef<[u8]>>,
104
19
) -> [u8; 32] {
105
19
    let mut hasher = blake2_rfc::blake2b::Blake2b::with_key(32, &[]);
106
38
    for 
buf19
in header {
107
19
        hasher.update(buf.as_ref());
108
19
    }
109
110
19
    let result = hasher.finalize();
111
19
    debug_assert_eq!(result.as_bytes().len(), 32);
112
113
19
    let mut out = [0; 32];
114
19
    out.copy_from_slice(result.as_bytes());
115
19
    out
116
19
}
117
118
/// Returns the value appropriate for [`Header::extrinsics_root`]. Must be passed the list of
119
/// transactions in that block.
120
0
pub fn extrinsics_root(transactions: &[impl AsRef<[u8]>]) -> [u8; 32] {
121
    // The extrinsics root is always calculated with V0 of the trie.
122
0
    trie::ordered_root(
123
0
        trie::TrieEntryVersion::V0,
124
0
        trie::HashFunction::Blake2,
125
0
        transactions,
126
    )
127
0
}
Unexecuted instantiation: _RINvNtCsjlkOsLH0Zfj_7smoldot6header15extrinsics_rootpEB4_
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header15extrinsics_rootINtNtCsaFPxhswmqCN_5alloc3vec3VechEECscoAnRPySggw_6author
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header15extrinsics_rootpEB4_
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header15extrinsics_rootINtNtCsaFPxhswmqCN_5alloc3vec3VechEECs7snhGEhbuap_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header15extrinsics_rootINtNtCsaFPxhswmqCN_5alloc3vec3VechEECsjyNE3yDMkgA_14json_rpc_basic
Unexecuted instantiation: _RINvNtCsc1ywvx6YAnK_7smoldot6header15extrinsics_rootINtNtCsaFPxhswmqCN_5alloc3vec3VechEECs4VrkfB1pvQ3_25json_rpc_general_requests
128
129
/// Attempt to decode the given SCALE-encoded header.
130
1.51k
pub fn decode(scale_encoded: &[u8], block_number_bytes: usize) -> Result<HeaderRef, Error> {
131
1.51k
    let (
header1.51k
,
remainder1.51k
) = decode_partial(scale_encoded, block_number_bytes)
?1
;
132
1.51k
    if !remainder.is_empty() {
133
0
        return Err(Error::TooLong);
134
1.51k
    }
135
136
1.51k
    Ok(header)
137
1.51k
}
_RNvNtCsjlkOsLH0Zfj_7smoldot6header6decode
Line
Count
Source
130
1.05k
pub fn decode(scale_encoded: &[u8], block_number_bytes: usize) -> Result<HeaderRef, Error> {
131
1.05k
    let (
header1.04k
,
remainder1.04k
) = decode_partial(scale_encoded, block_number_bytes)
?1
;
132
1.04k
    if !remainder.is_empty() {
133
0
        return Err(Error::TooLong);
134
1.04k
    }
135
136
1.04k
    Ok(header)
137
1.05k
}
_RNvNtCsc1ywvx6YAnK_7smoldot6header6decode
Line
Count
Source
130
464
pub fn decode(scale_encoded: &[u8], block_number_bytes: usize) -> Result<HeaderRef, Error> {
131
464
    let (header, remainder) = decode_partial(scale_encoded, block_number_bytes)
?0
;
132
464
    if !remainder.is_empty() {
133
0
        return Err(Error::TooLong);
134
464
    }
135
136
464
    Ok(header)
137
464
}
138
139
/// Attempt to decode the given SCALE-encoded header.
140
///
141
/// Contrary to [`decode`], doesn't return an error if the slice is too long but returns the
142
/// remainder.
143
1.51k
pub fn decode_partial(
144
1.51k
    mut scale_encoded: &[u8],
145
1.51k
    block_number_bytes: usize,
146
1.51k
) -> Result<(HeaderRef, &[u8]), Error> {
147
1.51k
    if scale_encoded.len() < 32 + 1 {
148
0
        return Err(Error::TooShort);
149
1.51k
    }
150
151
1.51k
    let parent_hash: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
152
1.51k
    scale_encoded = &scale_encoded[32..];
153
154
1.51k
    let (mut scale_encoded, number) =
155
1.51k
        crate::util::nom_scale_compact_u64::<nom::error::Error<&[u8]>>(scale_encoded)
156
1.51k
            .map_err(|_| Error::BlockNumberDecodeError)
?0
;
157
158
1.51k
    if scale_encoded.len() < 32 + 32 + 1 {
159
0
        return Err(Error::TooShort);
160
1.51k
    }
161
162
1.51k
    let state_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
163
1.51k
    scale_encoded = &scale_encoded[32..];
164
1.51k
    let extrinsics_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
165
1.51k
    scale_encoded = &scale_encoded[32..];
166
167
1.51k
    let (
digest1.51k
,
remainder1.51k
) = DigestRef::from_scale_bytes(scale_encoded, block_number_bytes)
?1
;
168
169
1.51k
    let header = HeaderRef {
170
1.51k
        parent_hash,
171
1.51k
        number,
172
1.51k
        state_root,
173
1.51k
        extrinsics_root,
174
1.51k
        digest,
175
1.51k
    };
176
177
1.51k
    Ok((header, remainder))
178
1.51k
}
_RNvNtCsjlkOsLH0Zfj_7smoldot6header14decode_partial
Line
Count
Source
143
1.05k
pub fn decode_partial(
144
1.05k
    mut scale_encoded: &[u8],
145
1.05k
    block_number_bytes: usize,
146
1.05k
) -> Result<(HeaderRef, &[u8]), Error> {
147
1.05k
    if scale_encoded.len() < 32 + 1 {
148
0
        return Err(Error::TooShort);
149
1.05k
    }
150
151
1.05k
    let parent_hash: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
152
1.05k
    scale_encoded = &scale_encoded[32..];
153
154
1.05k
    let (mut scale_encoded, number) =
155
1.05k
        crate::util::nom_scale_compact_u64::<nom::error::Error<&[u8]>>(scale_encoded)
156
1.05k
            .map_err(|_| Error::BlockNumberDecodeError)
?0
;
157
158
1.05k
    if scale_encoded.len() < 32 + 32 + 1 {
159
0
        return Err(Error::TooShort);
160
1.05k
    }
161
162
1.05k
    let state_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
163
1.05k
    scale_encoded = &scale_encoded[32..];
164
1.05k
    let extrinsics_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
165
1.05k
    scale_encoded = &scale_encoded[32..];
166
167
1.05k
    let (
digest1.04k
,
remainder1.04k
) = DigestRef::from_scale_bytes(scale_encoded, block_number_bytes)
?1
;
168
169
1.04k
    let header = HeaderRef {
170
1.04k
        parent_hash,
171
1.04k
        number,
172
1.04k
        state_root,
173
1.04k
        extrinsics_root,
174
1.04k
        digest,
175
1.04k
    };
176
177
1.04k
    Ok((header, remainder))
178
1.05k
}
_RNvNtCsc1ywvx6YAnK_7smoldot6header14decode_partial
Line
Count
Source
143
464
pub fn decode_partial(
144
464
    mut scale_encoded: &[u8],
145
464
    block_number_bytes: usize,
146
464
) -> Result<(HeaderRef, &[u8]), Error> {
147
464
    if scale_encoded.len() < 32 + 1 {
148
0
        return Err(Error::TooShort);
149
464
    }
150
151
464
    let parent_hash: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
152
464
    scale_encoded = &scale_encoded[32..];
153
154
464
    let (mut scale_encoded, number) =
155
464
        crate::util::nom_scale_compact_u64::<nom::error::Error<&[u8]>>(scale_encoded)
156
464
            .map_err(|_| Error::BlockNumberDecodeError)
?0
;
157
158
464
    if scale_encoded.len() < 32 + 32 + 1 {
159
0
        return Err(Error::TooShort);
160
464
    }
161
162
464
    let state_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
163
464
    scale_encoded = &scale_encoded[32..];
164
464
    let extrinsics_root: &[u8; 32] = TryFrom::try_from(&scale_encoded[0..32]).unwrap();
165
464
    scale_encoded = &scale_encoded[32..];
166
167
464
    let (digest, remainder) = DigestRef::from_scale_bytes(scale_encoded, block_number_bytes)
?0
;
168
169
464
    let header = HeaderRef {
170
464
        parent_hash,
171
464
        number,
172
464
        state_root,
173
464
        extrinsics_root,
174
464
        digest,
175
464
    };
176
177
464
    Ok((header, remainder))
178
464
}
179
180
/// Potential error when decoding a header.
181
#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
182
pub enum Error {
183
    /// Header is not long enough.
184
    TooShort,
185
    /// Header is too long.
186
    TooLong,
187
    /// Error while decoding the block number.
188
    BlockNumberDecodeError,
189
    /// Error while decoding the digest length.
190
    DigestLenDecodeError,
191
    /// Error while decoding a digest log item length.
192
    DigestItemLenDecodeError,
193
    /// Error while decoding a digest item.
194
    DigestItemDecodeError,
195
    /// Digest log item with an unrecognized type.
196
    #[display("Digest log with an unrecognized type {unknown_type}")]
197
    UnknownDigestLogType {
198
        /// Identifier of the type.
199
        unknown_type: u8,
200
    },
201
    /// Found a seal that isn't the last item in the list.
202
    SealIsntLastItem,
203
    /// Bad length of an AURA seal.
204
    BadAuraSealLength,
205
    BadAuraConsensusRefType,
206
    BadAuraAuthoritiesListLen,
207
    /// There are multiple Aura pre-runtime digests in the block header.
208
    MultipleAuraPreRuntimeDigests,
209
    /// Bad length of a BABE seal.
210
    BadBabeSealLength,
211
    BadBabePreDigestRefType,
212
    BadBabeConsensusRefType,
213
    BadBabeNextConfigVersion,
214
    /// There are multiple Babe pre-runtime digests in the block header.
215
    MultipleBabePreRuntimeDigests,
216
    /// There are multiple Babe epoch descriptor digests in the block header.
217
    MultipleBabeEpochDescriptors,
218
    /// There are multiple Babe configuration descriptor digests in the block header.
219
    MultipleBabeConfigDescriptors,
220
    /// There are multiple runtime environment updated digests in the block header.
221
    MutipleRuntimeEnvironmentUpdated,
222
    /// Found a Babe configuration change digest without an epoch change digest.
223
    UnexpectedBabeConfigDescriptor,
224
    GrandpaConsensusLogDecodeError,
225
    /// Proof-of-work consensus algorithm is intentionally not supported for ideological reasons.
226
    PowIdeologicallyNotSupported,
227
}
228
229
/// Header of a block, after decoding.
230
///
231
/// Note that the information in there are not guaranteed to be exact. The exactness of the
232
/// information depends on the context.
233
#[derive(Debug, Clone)]
234
pub struct HeaderRef<'a> {
235
    /// Hash of the parent block stored in the header.
236
    pub parent_hash: &'a [u8; 32],
237
    /// Block number stored in the header.
238
    pub number: u64,
239
    /// The state trie Merkle root
240
    pub state_root: &'a [u8; 32],
241
    /// The Merkle root of the extrinsics.
242
    ///
243
    /// You can use the [`extrinsics_root`] function to compute this value.
244
    pub extrinsics_root: &'a [u8; 32],
245
    /// List of auxiliary data appended to the block header.
246
    pub digest: DigestRef<'a>,
247
}
248
249
impl<'a> HeaderRef<'a> {
250
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
251
    /// encoding of the header.
252
1.19k
    pub fn scale_encoding(
253
1.19k
        &self,
254
1.19k
        block_number_bytes: usize,
255
1.19k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
256
1.19k
        self.scale_encoding_before_digest().map(either::Left).chain(
257
1.19k
            self.digest
258
1.19k
                .scale_encoding(block_number_bytes)
259
1.19k
                .map(either::Right),
260
        )
261
1.19k
    }
_RNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB2_9HeaderRef14scale_encoding
Line
Count
Source
252
1.04k
    pub fn scale_encoding(
253
1.04k
        &self,
254
1.04k
        block_number_bytes: usize,
255
1.04k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
256
1.04k
        self.scale_encoding_before_digest().map(either::Left).chain(
257
1.04k
            self.digest
258
1.04k
                .scale_encoding(block_number_bytes)
259
1.04k
                .map(either::Right),
260
        )
261
1.04k
    }
_RNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB2_9HeaderRef14scale_encoding
Line
Count
Source
252
147
    pub fn scale_encoding(
253
147
        &self,
254
147
        block_number_bytes: usize,
255
147
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
256
147
        self.scale_encoding_before_digest().map(either::Left).chain(
257
147
            self.digest
258
147
                .scale_encoding(block_number_bytes)
259
147
                .map(either::Right),
260
        )
261
147
    }
262
263
    /// Same as [`HeaderRef::scale_encoding`], but with an extra digest item added to the end of
264
    /// the list.
265
    ///
266
    /// > **Note**: Keep in mind that this can produce a potentially invalid header, for example
267
    /// >           if the digest contains duplicate items that shouldn't be duplicate.
268
0
    pub fn scale_encoding_with_extra_digest_item(
269
0
        &self,
270
0
        block_number_bytes: usize,
271
0
        extra_item: DigestItemRef<'a>,
272
0
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
273
0
        self.scale_encoding_before_digest().map(either::Left).chain(
274
0
            self.digest
275
0
                .scale_encoding_with_extra_item(block_number_bytes, extra_item)
276
0
                .map(either::Right),
277
        )
278
0
    }
Unexecuted instantiation: _RNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB2_9HeaderRef37scale_encoding_with_extra_digest_item
Unexecuted instantiation: _RNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB2_9HeaderRef37scale_encoding_with_extra_digest_item
279
280
1.19k
    fn scale_encoding_before_digest(
281
1.19k
        &self,
282
1.19k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
283
1.19k
        iter::once(either::Left(&self.parent_hash[..]))
284
1.19k
            .chain(iter::once(either::Right(util::encode_scale_compact_u64(
285
1.19k
                self.number,
286
1.19k
            ))))
287
1.19k
            .chain(iter::once(either::Left(&self.state_root[..])))
288
1.19k
            .chain(iter::once(either::Left(&self.extrinsics_root[..])))
289
1.19k
    }
_RNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB2_9HeaderRef28scale_encoding_before_digest
Line
Count
Source
280
1.04k
    fn scale_encoding_before_digest(
281
1.04k
        &self,
282
1.04k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
283
1.04k
        iter::once(either::Left(&self.parent_hash[..]))
284
1.04k
            .chain(iter::once(either::Right(util::encode_scale_compact_u64(
285
1.04k
                self.number,
286
1.04k
            ))))
287
1.04k
            .chain(iter::once(either::Left(&self.state_root[..])))
288
1.04k
            .chain(iter::once(either::Left(&self.extrinsics_root[..])))
289
1.04k
    }
_RNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB2_9HeaderRef28scale_encoding_before_digest
Line
Count
Source
280
147
    fn scale_encoding_before_digest(
281
147
        &self,
282
147
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
283
147
        iter::once(either::Left(&self.parent_hash[..]))
284
147
            .chain(iter::once(either::Right(util::encode_scale_compact_u64(
285
147
                self.number,
286
147
            ))))
287
147
            .chain(iter::once(either::Left(&self.state_root[..])))
288
147
            .chain(iter::once(either::Left(&self.extrinsics_root[..])))
289
147
    }
290
291
    /// Equivalent to [`HeaderRef::scale_encoding`] but returns the data in a `Vec`.
292
1.11k
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
293
        // We assume that an average header should be less than this size.
294
        // At the time of writing of this comment, the average Westend/Polkadot/Kusama block
295
        // header is 288 bytes, and the average parachain block is 186 bytes. Some blocks
296
        // (the epoch transition blocks in particular) have a much larger header, but considering
297
        // that they are the vast minority we don't care so much about that.
298
        const CAP: usize = 1024;
299
300
1.11k
        self.scale_encoding(block_number_bytes)
301
5.63k
            .
fold1.11k
(
Vec::with_capacity1.11k
(CAP), |mut a, b| {
302
5.63k
                a.extend_from_slice(b.as_ref());
303
5.63k
                a
304
5.63k
            })
_RNCNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB4_9HeaderRef18scale_encoding_vec0B6_
Line
Count
Source
301
5.21k
            .fold(Vec::with_capacity(CAP), |mut a, b| {
302
5.21k
                a.extend_from_slice(b.as_ref());
303
5.21k
                a
304
5.21k
            })
_RNCNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB4_9HeaderRef18scale_encoding_vec0B6_
Line
Count
Source
301
420
            .fold(Vec::with_capacity(CAP), |mut a, b| {
302
420
                a.extend_from_slice(b.as_ref());
303
420
                a
304
420
            })
305
1.11k
    }
_RNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB2_9HeaderRef18scale_encoding_vec
Line
Count
Source
292
1.03k
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
293
        // We assume that an average header should be less than this size.
294
        // At the time of writing of this comment, the average Westend/Polkadot/Kusama block
295
        // header is 288 bytes, and the average parachain block is 186 bytes. Some blocks
296
        // (the epoch transition blocks in particular) have a much larger header, but considering
297
        // that they are the vast minority we don't care so much about that.
298
        const CAP: usize = 1024;
299
300
1.03k
        self.scale_encoding(block_number_bytes)
301
1.03k
            .fold(Vec::with_capacity(CAP), |mut a, b| {
302
                a.extend_from_slice(b.as_ref());
303
                a
304
            })
305
1.03k
    }
_RNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB2_9HeaderRef18scale_encoding_vec
Line
Count
Source
292
84
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
293
        // We assume that an average header should be less than this size.
294
        // At the time of writing of this comment, the average Westend/Polkadot/Kusama block
295
        // header is 288 bytes, and the average parachain block is 186 bytes. Some blocks
296
        // (the epoch transition blocks in particular) have a much larger header, but considering
297
        // that they are the vast minority we don't care so much about that.
298
        const CAP: usize = 1024;
299
300
84
        self.scale_encoding(block_number_bytes)
301
84
            .fold(Vec::with_capacity(CAP), |mut a, b| {
302
                a.extend_from_slice(b.as_ref());
303
                a
304
            })
305
84
    }
306
307
    /// Builds the hash of the header.
308
74
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
309
74
        hash_from_scale_encoded_header_vectored(self.scale_encoding(block_number_bytes))
310
74
    }
_RNvMNtCsjlkOsLH0Zfj_7smoldot6headerNtB2_9HeaderRef4hash
Line
Count
Source
308
11
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
309
11
        hash_from_scale_encoded_header_vectored(self.scale_encoding(block_number_bytes))
310
11
    }
_RNvMNtCsc1ywvx6YAnK_7smoldot6headerNtB2_9HeaderRef4hash
Line
Count
Source
308
63
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
309
63
        hash_from_scale_encoded_header_vectored(self.scale_encoding(block_number_bytes))
310
63
    }
311
}
312
313
impl<'a> From<&'a Header> for HeaderRef<'a> {
314
365
    fn from(a: &'a Header) -> HeaderRef<'a> {
315
365
        HeaderRef {
316
365
            parent_hash: &a.parent_hash,
317
365
            number: a.number,
318
365
            state_root: &a.state_root,
319
365
            extrinsics_root: &a.extrinsics_root,
320
365
            digest: (&a.digest).into(),
321
365
        }
322
365
    }
_RNvXs_NtCsjlkOsLH0Zfj_7smoldot6headerNtB4_9HeaderRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB4_6HeaderE4from
Line
Count
Source
314
8
    fn from(a: &'a Header) -> HeaderRef<'a> {
315
8
        HeaderRef {
316
8
            parent_hash: &a.parent_hash,
317
8
            number: a.number,
318
8
            state_root: &a.state_root,
319
8
            extrinsics_root: &a.extrinsics_root,
320
8
            digest: (&a.digest).into(),
321
8
        }
322
8
    }
_RNvXs_NtCsc1ywvx6YAnK_7smoldot6headerNtB4_9HeaderRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB4_6HeaderE4from
Line
Count
Source
314
357
    fn from(a: &'a Header) -> HeaderRef<'a> {
315
357
        HeaderRef {
316
357
            parent_hash: &a.parent_hash,
317
357
            number: a.number,
318
357
            state_root: &a.state_root,
319
357
            extrinsics_root: &a.extrinsics_root,
320
357
            digest: (&a.digest).into(),
321
357
        }
322
357
    }
323
}
324
325
/// Header of a block, after decoding.
326
///
327
/// Note that the information in there are not guaranteed to be exact. The exactness of the
328
/// information depends on the context.
329
#[derive(Debug, Clone)]
330
pub struct Header {
331
    /// Hash of the parent block stored in the header.
332
    pub parent_hash: [u8; 32],
333
    /// Block number stored in the header.
334
    pub number: u64,
335
    /// The state trie Merkle root
336
    pub state_root: [u8; 32],
337
    /// The Merkle root of the extrinsics.
338
    ///
339
    /// You can use the [`extrinsics_root`] function to compute this value.
340
    pub extrinsics_root: [u8; 32],
341
    /// List of auxiliary data appended to the block header.
342
    pub digest: Digest,
343
}
344
345
impl Header {
346
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
347
    /// encoding of the header.
348
0
    pub fn scale_encoding(
349
0
        &self,
350
0
        block_number_bytes: usize,
351
0
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone> + Clone {
352
0
        HeaderRef::from(self).scale_encoding(block_number_bytes)
353
0
    }
Unexecuted instantiation: _RNvMs0_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Header14scale_encoding
Unexecuted instantiation: _RNvMs0_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Header14scale_encoding
354
355
    /// Equivalent to [`Header::scale_encoding`] but returns the data in a `Vec`.
356
23
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
357
23
        HeaderRef::from(self).scale_encoding_vec(block_number_bytes)
358
23
    }
_RNvMs0_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Header18scale_encoding_vec
Line
Count
Source
356
2
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
357
2
        HeaderRef::from(self).scale_encoding_vec(block_number_bytes)
358
2
    }
_RNvMs0_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Header18scale_encoding_vec
Line
Count
Source
356
21
    pub fn scale_encoding_vec(&self, block_number_bytes: usize) -> Vec<u8> {
357
21
        HeaderRef::from(self).scale_encoding_vec(block_number_bytes)
358
21
    }
359
360
    /// Builds the hash of the header.
361
23
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
362
23
        HeaderRef::from(self).hash(block_number_bytes)
363
23
    }
_RNvMs0_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Header4hash
Line
Count
Source
361
2
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
362
2
        HeaderRef::from(self).hash(block_number_bytes)
363
2
    }
_RNvMs0_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Header4hash
Line
Count
Source
361
21
    pub fn hash(&self, block_number_bytes: usize) -> [u8; 32] {
362
21
        HeaderRef::from(self).hash(block_number_bytes)
363
21
    }
364
}
365
366
impl<'a> From<HeaderRef<'a>> for Header {
367
45
    fn from(a: HeaderRef<'a>) -> Header {
368
45
        Header {
369
45
            parent_hash: *a.parent_hash,
370
45
            number: a.number,
371
45
            state_root: *a.state_root,
372
45
            extrinsics_root: *a.extrinsics_root,
373
45
            digest: a.digest.into(),
374
45
        }
375
45
    }
_RNvXs1_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6HeaderINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_9HeaderRefE4from
Line
Count
Source
367
3
    fn from(a: HeaderRef<'a>) -> Header {
368
3
        Header {
369
3
            parent_hash: *a.parent_hash,
370
3
            number: a.number,
371
3
            state_root: *a.state_root,
372
3
            extrinsics_root: *a.extrinsics_root,
373
3
            digest: a.digest.into(),
374
3
        }
375
3
    }
_RNvXs1_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6HeaderINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_9HeaderRefE4from
Line
Count
Source
367
42
    fn from(a: HeaderRef<'a>) -> Header {
368
42
        Header {
369
42
            parent_hash: *a.parent_hash,
370
42
            number: a.number,
371
42
            state_root: *a.state_root,
372
42
            extrinsics_root: *a.extrinsics_root,
373
42
            digest: a.digest.into(),
374
42
        }
375
42
    }
376
}
377
378
/// Generic header digest.
379
#[derive(Clone)]
380
pub struct DigestRef<'a> {
381
    /// Actual source of digest items.
382
    inner: DigestRefInner<'a>,
383
    /// Index of the [`DigestItemRef::AuraSeal`] item, if any.
384
    aura_seal_index: Option<usize>,
385
    /// Index of the [`DigestItemRef::AuraPreDigest`] item, if any.
386
    aura_predigest_index: Option<usize>,
387
    /// Index of the [`DigestItemRef::BabeSeal`] item, if any.
388
    babe_seal_index: Option<usize>,
389
    /// Index of the [`DigestItemRef::BabePreDigest`] item, if any.
390
    babe_predigest_index: Option<usize>,
391
    /// Index of the [`DigestItemRef::BabeConsensus`] item containing a
392
    /// [`BabeConsensusLogRef::NextEpochData`], if any.
393
    babe_next_epoch_data_index: Option<usize>,
394
    /// Index of the [`DigestItemRef::BabeConsensus`] item containing a
395
    /// [`BabeConsensusLogRef::NextConfigData`], if any.
396
    babe_next_config_data_index: Option<usize>,
397
    /// `true` if there is a [`DigestItemRef::RuntimeEnvironmentUpdated`] item.
398
    has_runtime_environment_updated: bool,
399
}
400
401
#[derive(Clone)]
402
enum DigestRefInner<'a> {
403
    /// Source of data is an undecoded slice of bytes.
404
    Undecoded {
405
        /// Number of log items in the header.
406
        /// Must always match the actual number of items in [`DigestRefInner::Undecoded::digest`].
407
        /// The validity must be verified before a [`DigestRef`] object is instantiated.
408
        digest_logs_len: usize,
409
        /// Encoded digest. Its validity must be verified before a [`DigestRef`] object is
410
        /// instantiated.
411
        digest: &'a [u8],
412
        /// Number of bytes used to encode block numbers in headers.
413
        block_number_bytes: usize,
414
    },
415
    Parsed(&'a [DigestItem]),
416
}
417
418
impl<'a> DigestRef<'a> {
419
    /// Returns a digest with empty logs.
420
1.05k
    pub fn empty() -> DigestRef<'a> {
421
1.05k
        DigestRef {
422
1.05k
            inner: DigestRefInner::Parsed(&[]),
423
1.05k
            aura_seal_index: None,
424
1.05k
            aura_predigest_index: None,
425
1.05k
            babe_seal_index: None,
426
1.05k
            babe_predigest_index: None,
427
1.05k
            babe_next_epoch_data_index: None,
428
1.05k
            babe_next_config_data_index: None,
429
1.05k
            has_runtime_environment_updated: false,
430
1.05k
        }
431
1.05k
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef5empty
Line
Count
Source
420
1.03k
    pub fn empty() -> DigestRef<'a> {
421
1.03k
        DigestRef {
422
1.03k
            inner: DigestRefInner::Parsed(&[]),
423
1.03k
            aura_seal_index: None,
424
1.03k
            aura_predigest_index: None,
425
1.03k
            babe_seal_index: None,
426
1.03k
            babe_predigest_index: None,
427
1.03k
            babe_next_epoch_data_index: None,
428
1.03k
            babe_next_config_data_index: None,
429
1.03k
            has_runtime_environment_updated: false,
430
1.03k
        }
431
1.03k
    }
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef5empty
Line
Count
Source
420
21
    pub fn empty() -> DigestRef<'a> {
421
21
        DigestRef {
422
21
            inner: DigestRefInner::Parsed(&[]),
423
21
            aura_seal_index: None,
424
21
            aura_predigest_index: None,
425
21
            babe_seal_index: None,
426
21
            babe_predigest_index: None,
427
21
            babe_next_epoch_data_index: None,
428
21
            babe_next_config_data_index: None,
429
21
            has_runtime_environment_updated: false,
430
21
        }
431
21
    }
432
433
    /// Returns true if the list has any item that belong to the Aura consensus engine.
434
    ///
435
    /// This function is `O(n)` over the number of log items.
436
4
    pub fn has_any_aura(&self) -> bool {
437
10
        
self.logs()4
.
any4
(|l| l.is_aura())
_RNCNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_9DigestRef12has_any_aura0B9_
Line
Count
Source
437
10
        self.logs().any(|l| l.is_aura())
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef12has_any_aura0B9_
438
4
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef12has_any_aura
Line
Count
Source
436
4
    pub fn has_any_aura(&self) -> bool {
437
4
        self.logs().any(|l| l.is_aura())
438
4
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef12has_any_aura
439
440
    /// Returns true if the list has any item that belong to the Babe consensus engine.
441
    ///
442
    /// This function is `O(n)` over the number of log items.
443
42
    pub fn has_any_babe(&self) -> bool {
444
42
        self.logs().any(|l| 
l0
.
is_babe0
())
Unexecuted instantiation: _RNCNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_9DigestRef12has_any_babe0B9_
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef12has_any_babe0B9_
445
42
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef12has_any_babe
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef12has_any_babe
Line
Count
Source
443
42
    pub fn has_any_babe(&self) -> bool {
444
42
        self.logs().any(|l| l.is_babe())
445
42
    }
446
447
    /// Returns true if the list has any item that belong to the Grandpa finality engine.
448
    ///
449
    /// This function is `O(n)` over the number of log items.
450
0
    pub fn has_any_grandpa(&self) -> bool {
451
0
        self.logs().any(|l| l.is_grandpa())
Unexecuted instantiation: _RNCNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_9DigestRef15has_any_grandpa0B9_
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef15has_any_grandpa0B9_
452
0
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef15has_any_grandpa
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef15has_any_grandpa
453
454
    /// Returns the Aura seal digest item, if any.
455
42
    pub fn aura_seal(&self) -> Option<&'a [u8; 64]> {
456
42
        if let Some(
aura_seal_index0
) = self.aura_seal_index {
457
0
            if let DigestItemRef::AuraSeal(seal) = self.logs().nth(aura_seal_index).unwrap() {
458
0
                Some(seal)
459
            } else {
460
0
                unreachable!()
461
            }
462
        } else {
463
42
            None
464
        }
465
42
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef9aura_seal
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef9aura_seal
Line
Count
Source
455
42
    pub fn aura_seal(&self) -> Option<&'a [u8; 64]> {
456
42
        if let Some(
aura_seal_index0
) = self.aura_seal_index {
457
0
            if let DigestItemRef::AuraSeal(seal) = self.logs().nth(aura_seal_index).unwrap() {
458
0
                Some(seal)
459
            } else {
460
0
                unreachable!()
461
            }
462
        } else {
463
42
            None
464
        }
465
42
    }
466
467
    /// Returns the Aura pre-runtime digest item, if any.
468
42
    pub fn aura_pre_runtime(&self) -> Option<AuraPreDigest> {
469
42
        if let Some(
aura_predigest_index0
) = self.aura_predigest_index {
470
0
            if let DigestItemRef::AuraPreDigest(item) =
471
0
                self.logs().nth(aura_predigest_index).unwrap()
472
            {
473
0
                Some(item)
474
            } else {
475
0
                unreachable!()
476
            }
477
        } else {
478
42
            None
479
        }
480
42
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef16aura_pre_runtime
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef16aura_pre_runtime
Line
Count
Source
468
42
    pub fn aura_pre_runtime(&self) -> Option<AuraPreDigest> {
469
42
        if let Some(
aura_predigest_index0
) = self.aura_predigest_index {
470
0
            if let DigestItemRef::AuraPreDigest(item) =
471
0
                self.logs().nth(aura_predigest_index).unwrap()
472
            {
473
0
                Some(item)
474
            } else {
475
0
                unreachable!()
476
            }
477
        } else {
478
42
            None
479
        }
480
42
    }
481
482
    /// Returns the Babe seal digest item, if any.
483
4
    pub fn babe_seal(&self) -> Option<&'a [u8; 64]> {
484
4
        if let Some(babe_seal_index) = self.babe_seal_index {
485
4
            if let DigestItemRef::BabeSeal(seal) = self.logs().nth(babe_seal_index).unwrap() {
486
4
                Some(seal)
487
            } else {
488
0
                unreachable!()
489
            }
490
        } else {
491
0
            None
492
        }
493
4
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef9babe_seal
Line
Count
Source
483
4
    pub fn babe_seal(&self) -> Option<&'a [u8; 64]> {
484
4
        if let Some(babe_seal_index) = self.babe_seal_index {
485
4
            if let DigestItemRef::BabeSeal(seal) = self.logs().nth(babe_seal_index).unwrap() {
486
4
                Some(seal)
487
            } else {
488
0
                unreachable!()
489
            }
490
        } else {
491
0
            None
492
        }
493
4
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef9babe_seal
494
495
    /// Returns the Babe pre-runtime digest item, if any.
496
6
    pub fn babe_pre_runtime(&self) -> Option<BabePreDigestRef<'a>> {
497
6
        if let Some(babe_predigest_index) = self.babe_predigest_index {
498
6
            if let DigestItemRef::BabePreDigest(item) =
499
6
                self.logs().nth(babe_predigest_index).unwrap()
500
            {
501
6
                Some(item)
502
            } else {
503
0
                unreachable!()
504
            }
505
        } else {
506
0
            None
507
        }
508
6
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef16babe_pre_runtime
Line
Count
Source
496
6
    pub fn babe_pre_runtime(&self) -> Option<BabePreDigestRef<'a>> {
497
6
        if let Some(babe_predigest_index) = self.babe_predigest_index {
498
6
            if let DigestItemRef::BabePreDigest(item) =
499
6
                self.logs().nth(babe_predigest_index).unwrap()
500
            {
501
6
                Some(item)
502
            } else {
503
0
                unreachable!()
504
            }
505
        } else {
506
0
            None
507
        }
508
6
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef16babe_pre_runtime
509
510
    /// Returns the Babe epoch information stored in the header, if any.
511
    ///
512
    /// It is guaranteed that a configuration change is present only if an epoch change is
513
    /// present too.
514
8
    pub fn babe_epoch_information(&self) -> Option<(BabeNextEpochRef<'a>, Option<BabeNextConfig>)> {
515
8
        if let Some(
babe_next_epoch_data_index4
) = self.babe_next_epoch_data_index {
516
4
            if let DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(epoch)) =
517
4
                self.logs().nth(babe_next_epoch_data_index).unwrap()
518
            {
519
4
                if let Some(
babe_next_config_data_index0
) = self.babe_next_config_data_index {
520
                    if let DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(
521
0
                        config,
522
0
                    )) = self.logs().nth(babe_next_config_data_index).unwrap()
523
                    {
524
0
                        Some((epoch, Some(config)))
525
                    } else {
526
0
                        panic!()
527
                    }
528
                } else {
529
4
                    Some((epoch, None))
530
                }
531
            } else {
532
0
                unreachable!()
533
            }
534
        } else {
535
4
            debug_assert!(self.babe_next_config_data_index.is_none());
536
4
            None
537
        }
538
8
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef22babe_epoch_information
Line
Count
Source
514
8
    pub fn babe_epoch_information(&self) -> Option<(BabeNextEpochRef<'a>, Option<BabeNextConfig>)> {
515
8
        if let Some(
babe_next_epoch_data_index4
) = self.babe_next_epoch_data_index {
516
4
            if let DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(epoch)) =
517
4
                self.logs().nth(babe_next_epoch_data_index).unwrap()
518
            {
519
4
                if let Some(
babe_next_config_data_index0
) = self.babe_next_config_data_index {
520
                    if let DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(
521
0
                        config,
522
0
                    )) = self.logs().nth(babe_next_config_data_index).unwrap()
523
                    {
524
0
                        Some((epoch, Some(config)))
525
                    } else {
526
0
                        panic!()
527
                    }
528
                } else {
529
4
                    Some((epoch, None))
530
                }
531
            } else {
532
0
                unreachable!()
533
            }
534
        } else {
535
4
            debug_assert!(self.babe_next_config_data_index.is_none());
536
4
            None
537
        }
538
8
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef22babe_epoch_information
539
540
    /// Returns `true` if there is a [`DigestItemRef::RuntimeEnvironmentUpdated`] item.
541
0
    pub fn has_runtime_environment_updated(&self) -> bool {
542
0
        self.has_runtime_environment_updated
543
0
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef31has_runtime_environment_updated
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef31has_runtime_environment_updated
544
545
    /// If the last element of the list is a seal, removes it from the [`DigestRef`].
546
4
    pub fn pop_seal(&mut self) -> Option<Seal<'a>> {
547
4
        let seal_pos = self.babe_seal_index.or(self.aura_seal_index)
?0
;
548
549
4
        match &mut self.inner {
550
0
            DigestRefInner::Parsed(list) => {
551
0
                debug_assert!(!list.is_empty());
552
0
                debug_assert_eq!(seal_pos, list.len() - 1);
553
554
0
                let item = &list[seal_pos];
555
0
                *list = &list[..seal_pos];
556
557
0
                match item {
558
0
                    DigestItem::AuraSeal(seal) => Some(Seal::Aura(seal)),
559
0
                    DigestItem::BabeSeal(seal) => Some(Seal::Babe(seal)),
560
0
                    _ => unreachable!(),
561
                }
562
            }
563
564
            DigestRefInner::Undecoded {
565
4
                digest,
566
4
                digest_logs_len,
567
4
                block_number_bytes,
568
            } => {
569
4
                debug_assert_eq!(seal_pos, *digest_logs_len - 1);
570
571
4
                let mut iter = LogsIter {
572
4
                    inner: LogsIterInner::Undecoded {
573
4
                        pointer: digest,
574
4
                        remaining_len: *digest_logs_len,
575
4
                        block_number_bytes: *block_number_bytes,
576
4
                    },
577
4
                };
578
4
                for _ in 0..seal_pos {
579
6
                    let _item = iter.next();
580
6
                    debug_assert!(_item.is_some());
581
                }
582
583
                if let LogsIterInner::Undecoded {
584
4
                    pointer,
585
4
                    remaining_len,
586
                    ..
587
4
                } = iter.inner
588
                {
589
4
                    *digest_logs_len -= 1;
590
4
                    *digest = &digest[..digest.len() - pointer.len()];
591
4
                    self.babe_seal_index = None;
592
4
                    debug_assert_eq!(remaining_len, 1);
593
                } else {
594
0
                    unreachable!()
595
                }
596
597
4
                match iter.next() {
598
0
                    Some(DigestItemRef::AuraSeal(seal)) => Some(Seal::Aura(seal)),
599
4
                    Some(DigestItemRef::BabeSeal(seal)) => Some(Seal::Babe(seal)),
600
0
                    _ => unreachable!(),
601
                }
602
            }
603
        }
604
4
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef8pop_seal
Line
Count
Source
546
4
    pub fn pop_seal(&mut self) -> Option<Seal<'a>> {
547
4
        let seal_pos = self.babe_seal_index.or(self.aura_seal_index)
?0
;
548
549
4
        match &mut self.inner {
550
0
            DigestRefInner::Parsed(list) => {
551
0
                debug_assert!(!list.is_empty());
552
0
                debug_assert_eq!(seal_pos, list.len() - 1);
553
554
0
                let item = &list[seal_pos];
555
0
                *list = &list[..seal_pos];
556
557
0
                match item {
558
0
                    DigestItem::AuraSeal(seal) => Some(Seal::Aura(seal)),
559
0
                    DigestItem::BabeSeal(seal) => Some(Seal::Babe(seal)),
560
0
                    _ => unreachable!(),
561
                }
562
            }
563
564
            DigestRefInner::Undecoded {
565
4
                digest,
566
4
                digest_logs_len,
567
4
                block_number_bytes,
568
            } => {
569
4
                debug_assert_eq!(seal_pos, *digest_logs_len - 1);
570
571
4
                let mut iter = LogsIter {
572
4
                    inner: LogsIterInner::Undecoded {
573
4
                        pointer: digest,
574
4
                        remaining_len: *digest_logs_len,
575
4
                        block_number_bytes: *block_number_bytes,
576
4
                    },
577
4
                };
578
4
                for _ in 0..seal_pos {
579
6
                    let _item = iter.next();
580
6
                    debug_assert!(_item.is_some());
581
                }
582
583
                if let LogsIterInner::Undecoded {
584
4
                    pointer,
585
4
                    remaining_len,
586
                    ..
587
4
                } = iter.inner
588
                {
589
4
                    *digest_logs_len -= 1;
590
4
                    *digest = &digest[..digest.len() - pointer.len()];
591
4
                    self.babe_seal_index = None;
592
4
                    debug_assert_eq!(remaining_len, 1);
593
                } else {
594
0
                    unreachable!()
595
                }
596
597
4
                match iter.next() {
598
0
                    Some(DigestItemRef::AuraSeal(seal)) => Some(Seal::Aura(seal)),
599
4
                    Some(DigestItemRef::BabeSeal(seal)) => Some(Seal::Babe(seal)),
600
0
                    _ => unreachable!(),
601
                }
602
            }
603
        }
604
4
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef8pop_seal
605
606
    /// Returns an iterator to the log items in this digest.
607
2.49k
    pub fn logs(&self) -> LogsIter<'a> {
608
        LogsIter {
609
2.49k
            inner: match self.inner {
610
2.40k
                DigestRefInner::Parsed(list) => LogsIterInner::Decoded(list.iter()),
611
                DigestRefInner::Undecoded {
612
91
                    digest,
613
91
                    digest_logs_len,
614
91
                    block_number_bytes,
615
91
                } => LogsIterInner::Undecoded {
616
91
                    pointer: digest,
617
91
                    remaining_len: digest_logs_len,
618
91
                    block_number_bytes,
619
91
                },
620
            },
621
        }
622
2.49k
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef4logs
Line
Count
Source
607
2.11k
    pub fn logs(&self) -> LogsIter<'a> {
608
        LogsIter {
609
2.11k
            inner: match self.inner {
610
2.07k
                DigestRefInner::Parsed(list) => LogsIterInner::Decoded(list.iter()),
611
                DigestRefInner::Undecoded {
612
47
                    digest,
613
47
                    digest_logs_len,
614
47
                    block_number_bytes,
615
47
                } => LogsIterInner::Undecoded {
616
47
                    pointer: digest,
617
47
                    remaining_len: digest_logs_len,
618
47
                    block_number_bytes,
619
47
                },
620
            },
621
        }
622
2.11k
    }
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef4logs
Line
Count
Source
607
380
    pub fn logs(&self) -> LogsIter<'a> {
608
        LogsIter {
609
380
            inner: match self.inner {
610
336
                DigestRefInner::Parsed(list) => LogsIterInner::Decoded(list.iter()),
611
                DigestRefInner::Undecoded {
612
44
                    digest,
613
44
                    digest_logs_len,
614
44
                    block_number_bytes,
615
44
                } => LogsIterInner::Undecoded {
616
44
                    pointer: digest,
617
44
                    remaining_len: digest_logs_len,
618
44
                    block_number_bytes,
619
44
                },
620
            },
621
        }
622
380
    }
623
624
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
625
    /// encoding of the digest items.
626
1.19k
    pub fn scale_encoding(
627
1.19k
        &self,
628
1.19k
        block_number_bytes: usize,
629
1.19k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
630
1.19k
        let encoded_len = util::encode_scale_compact_usize(self.logs().len());
631
1.19k
        iter::once(either::Left(encoded_len)).chain(
632
1.19k
            self.logs()
633
1.19k
                .flat_map(move |v| 
v41
.
scale_encoding41
(
block_number_bytes41
).
map41
(either::Right)),
_RNCNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_9DigestRef14scale_encoding0B9_
Line
Count
Source
633
41
                .flat_map(move |v| v.scale_encoding(block_number_bytes).map(either::Right)),
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef14scale_encoding0CscoAnRPySggw_6author
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef14scale_encoding0B9_
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef14scale_encoding0Cs7snhGEhbuap_18smoldot_light_wasm
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef14scale_encoding0CsjyNE3yDMkgA_14json_rpc_basic
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef14scale_encoding0Cs4VrkfB1pvQ3_25json_rpc_general_requests
634
        )
635
1.19k
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef14scale_encoding
Line
Count
Source
626
1.04k
    pub fn scale_encoding(
627
1.04k
        &self,
628
1.04k
        block_number_bytes: usize,
629
1.04k
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
630
1.04k
        let encoded_len = util::encode_scale_compact_usize(self.logs().len());
631
1.04k
        iter::once(either::Left(encoded_len)).chain(
632
1.04k
            self.logs()
633
1.04k
                .flat_map(move |v| v.scale_encoding(block_number_bytes).map(either::Right)),
634
        )
635
1.04k
    }
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef14scale_encoding
Line
Count
Source
626
147
    pub fn scale_encoding(
627
147
        &self,
628
147
        block_number_bytes: usize,
629
147
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
630
147
        let encoded_len = util::encode_scale_compact_usize(self.logs().len());
631
147
        iter::once(either::Left(encoded_len)).chain(
632
147
            self.logs()
633
147
                .flat_map(move |v| v.scale_encoding(block_number_bytes).map(either::Right)),
634
        )
635
147
    }
636
637
    /// Same as [`DigestRef::scale_encoding`], but with an extra item added to the end of the list.
638
0
    pub fn scale_encoding_with_extra_item(
639
0
        &self,
640
0
        block_number_bytes: usize,
641
0
        extra_item: DigestItemRef<'a>,
642
0
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
643
        // Given that `self.logs().len()` counts a number of items present in memory, and that
644
        // these items have a non-zero size, it is not possible for this value to be equal to
645
        // `usize::MAX`, as that would mean that the entire memory is completely full
646
        // of digest log items. Therefore, doing `+ 1` is also guaranteed to never overflow.
647
0
        let new_len = self.logs().len() + 1;
648
649
0
        let encoded_len = util::encode_scale_compact_usize(new_len);
650
0
        iter::once(either::Left(encoded_len)).chain(
651
0
            self.logs()
652
0
                .chain(iter::once(extra_item))
653
0
                .flat_map(move |v| v.scale_encoding(block_number_bytes).map(either::Right)),
Unexecuted instantiation: _RNCNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_9DigestRef30scale_encoding_with_extra_item0B9_
Unexecuted instantiation: _RNCNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_9DigestRef30scale_encoding_with_extra_item0B9_
654
        )
655
0
    }
Unexecuted instantiation: _RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef30scale_encoding_with_extra_item
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef30scale_encoding_with_extra_item
656
657
    /// Turns an already-decoded list of items into a [`DigestRef`].
658
    ///
659
    /// Error can happen if the list of items is invalid, for example if it contains a seal at the
660
    /// non-last position.
661
1
    pub fn from_slice(slice: &'a [DigestItem]) -> Result<Self, Error> {
662
1
        let mut aura_seal_index = None;
663
1
        let mut aura_predigest_index = None;
664
1
        let mut babe_seal_index = None;
665
1
        let mut babe_predigest_index = None;
666
1
        let mut babe_next_epoch_data_index = None;
667
1
        let mut babe_next_config_data_index = None;
668
1
        let mut has_runtime_environment_updated = false;
669
670
        // Iterate through the log items to see if anything is wrong.
671
1
        for (item_num, item) in slice.iter().enumerate() {
672
1
            match item {
673
1
                DigestItem::AuraPreDigest(_) if aura_predigest_index.is_none() => {
674
1
                    aura_predigest_index = Some(item_num);
675
1
                }
676
0
                DigestItem::AuraPreDigest(_) => return Err(Error::MultipleAuraPreRuntimeDigests),
677
0
                DigestItem::AuraConsensus(_) => {}
678
0
                DigestItem::BabePreDigest(_) if babe_predigest_index.is_none() => {
679
0
                    babe_predigest_index = Some(item_num);
680
0
                }
681
0
                DigestItem::BabePreDigest(_) => return Err(Error::MultipleBabePreRuntimeDigests),
682
                DigestItem::BabeConsensus(BabeConsensusLog::NextEpochData(_))
683
0
                    if babe_next_epoch_data_index.is_none() =>
684
0
                {
685
0
                    babe_next_epoch_data_index = Some(item_num);
686
0
                }
687
                DigestItem::BabeConsensus(BabeConsensusLog::NextEpochData(_)) => {
688
0
                    return Err(Error::MultipleBabeEpochDescriptors);
689
                }
690
                DigestItem::BabeConsensus(BabeConsensusLog::NextConfigData(_))
691
0
                    if babe_next_config_data_index.is_none() =>
692
0
                {
693
0
                    babe_next_config_data_index = Some(item_num);
694
0
                }
695
                DigestItem::BabeConsensus(BabeConsensusLog::NextConfigData(_)) => {
696
0
                    return Err(Error::MultipleBabeConfigDescriptors);
697
                }
698
0
                DigestItem::BabeConsensus(BabeConsensusLog::OnDisabled(_)) => {}
699
0
                DigestItem::GrandpaConsensus(_) => {}
700
0
                DigestItem::AuraSeal(_) if item_num == slice.len() - 1 => {
701
0
                    debug_assert!(aura_seal_index.is_none());
702
0
                    debug_assert!(babe_seal_index.is_none());
703
0
                    aura_seal_index = Some(item_num);
704
                }
705
0
                DigestItem::AuraSeal(_) => return Err(Error::SealIsntLastItem),
706
0
                DigestItem::BabeSeal(_) if item_num == slice.len() - 1 => {
707
0
                    debug_assert!(aura_seal_index.is_none());
708
0
                    debug_assert!(babe_seal_index.is_none());
709
0
                    babe_seal_index = Some(item_num);
710
                }
711
0
                DigestItem::RuntimeEnvironmentUpdated if has_runtime_environment_updated => {
712
0
                    return Err(Error::MutipleRuntimeEnvironmentUpdated);
713
                }
714
0
                DigestItem::RuntimeEnvironmentUpdated => {
715
0
                    has_runtime_environment_updated = true;
716
0
                }
717
0
                DigestItem::BabeSeal(_) => return Err(Error::SealIsntLastItem),
718
0
                DigestItem::UnknownSeal { .. } if item_num == slice.len() - 1 => {
719
0
                    debug_assert!(aura_seal_index.is_none());
720
0
                    debug_assert!(babe_seal_index.is_none());
721
                }
722
0
                DigestItem::UnknownSeal { .. } => return Err(Error::SealIsntLastItem),
723
                DigestItem::UnknownConsensus { .. }
724
                | DigestItem::UnknownPreRuntime { .. }
725
0
                | DigestItem::Other(..) => {}
726
            }
727
        }
728
729
1
        if babe_next_config_data_index.is_some() && 
babe_next_epoch_data_index0
.
is_none0
() {
730
0
            return Err(Error::UnexpectedBabeConfigDescriptor);
731
1
        }
732
733
1
        Ok(DigestRef {
734
1
            inner: DigestRefInner::Parsed(slice),
735
1
            aura_seal_index,
736
1
            aura_predigest_index,
737
1
            babe_seal_index,
738
1
            babe_predigest_index,
739
1
            babe_next_epoch_data_index,
740
1
            babe_next_config_data_index,
741
1
            has_runtime_environment_updated,
742
1
        })
743
1
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef10from_slice
Line
Count
Source
661
1
    pub fn from_slice(slice: &'a [DigestItem]) -> Result<Self, Error> {
662
1
        let mut aura_seal_index = None;
663
1
        let mut aura_predigest_index = None;
664
1
        let mut babe_seal_index = None;
665
1
        let mut babe_predigest_index = None;
666
1
        let mut babe_next_epoch_data_index = None;
667
1
        let mut babe_next_config_data_index = None;
668
1
        let mut has_runtime_environment_updated = false;
669
670
        // Iterate through the log items to see if anything is wrong.
671
1
        for (item_num, item) in slice.iter().enumerate() {
672
1
            match item {
673
1
                DigestItem::AuraPreDigest(_) if aura_predigest_index.is_none() => {
674
1
                    aura_predigest_index = Some(item_num);
675
1
                }
676
0
                DigestItem::AuraPreDigest(_) => return Err(Error::MultipleAuraPreRuntimeDigests),
677
0
                DigestItem::AuraConsensus(_) => {}
678
0
                DigestItem::BabePreDigest(_) if babe_predigest_index.is_none() => {
679
0
                    babe_predigest_index = Some(item_num);
680
0
                }
681
0
                DigestItem::BabePreDigest(_) => return Err(Error::MultipleBabePreRuntimeDigests),
682
                DigestItem::BabeConsensus(BabeConsensusLog::NextEpochData(_))
683
0
                    if babe_next_epoch_data_index.is_none() =>
684
0
                {
685
0
                    babe_next_epoch_data_index = Some(item_num);
686
0
                }
687
                DigestItem::BabeConsensus(BabeConsensusLog::NextEpochData(_)) => {
688
0
                    return Err(Error::MultipleBabeEpochDescriptors);
689
                }
690
                DigestItem::BabeConsensus(BabeConsensusLog::NextConfigData(_))
691
0
                    if babe_next_config_data_index.is_none() =>
692
0
                {
693
0
                    babe_next_config_data_index = Some(item_num);
694
0
                }
695
                DigestItem::BabeConsensus(BabeConsensusLog::NextConfigData(_)) => {
696
0
                    return Err(Error::MultipleBabeConfigDescriptors);
697
                }
698
0
                DigestItem::BabeConsensus(BabeConsensusLog::OnDisabled(_)) => {}
699
0
                DigestItem::GrandpaConsensus(_) => {}
700
0
                DigestItem::AuraSeal(_) if item_num == slice.len() - 1 => {
701
0
                    debug_assert!(aura_seal_index.is_none());
702
0
                    debug_assert!(babe_seal_index.is_none());
703
0
                    aura_seal_index = Some(item_num);
704
                }
705
0
                DigestItem::AuraSeal(_) => return Err(Error::SealIsntLastItem),
706
0
                DigestItem::BabeSeal(_) if item_num == slice.len() - 1 => {
707
0
                    debug_assert!(aura_seal_index.is_none());
708
0
                    debug_assert!(babe_seal_index.is_none());
709
0
                    babe_seal_index = Some(item_num);
710
                }
711
0
                DigestItem::RuntimeEnvironmentUpdated if has_runtime_environment_updated => {
712
0
                    return Err(Error::MutipleRuntimeEnvironmentUpdated);
713
                }
714
0
                DigestItem::RuntimeEnvironmentUpdated => {
715
0
                    has_runtime_environment_updated = true;
716
0
                }
717
0
                DigestItem::BabeSeal(_) => return Err(Error::SealIsntLastItem),
718
0
                DigestItem::UnknownSeal { .. } if item_num == slice.len() - 1 => {
719
0
                    debug_assert!(aura_seal_index.is_none());
720
0
                    debug_assert!(babe_seal_index.is_none());
721
                }
722
0
                DigestItem::UnknownSeal { .. } => return Err(Error::SealIsntLastItem),
723
                DigestItem::UnknownConsensus { .. }
724
                | DigestItem::UnknownPreRuntime { .. }
725
0
                | DigestItem::Other(..) => {}
726
            }
727
        }
728
729
1
        if babe_next_config_data_index.is_some() && 
babe_next_epoch_data_index0
.
is_none0
() {
730
0
            return Err(Error::UnexpectedBabeConfigDescriptor);
731
1
        }
732
733
1
        Ok(DigestRef {
734
1
            inner: DigestRefInner::Parsed(slice),
735
1
            aura_seal_index,
736
1
            aura_predigest_index,
737
1
            babe_seal_index,
738
1
            babe_predigest_index,
739
1
            babe_next_epoch_data_index,
740
1
            babe_next_config_data_index,
741
1
            has_runtime_environment_updated,
742
1
        })
743
1
    }
Unexecuted instantiation: _RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef10from_slice
744
745
    /// Try to decode a list of digest items, from their SCALE encoding.
746
1.51k
    fn from_scale_bytes(
747
1.51k
        scale_encoded: &'a [u8],
748
1.51k
        block_number_bytes: usize,
749
1.51k
    ) -> Result<(Self, &'a [u8]), Error> {
750
1.51k
        let (scale_encoded, digest_logs_len) =
751
1.51k
            crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(scale_encoded)
752
1.51k
                .map_err(|_| Error::DigestItemLenDecodeError)
?0
;
753
754
1.51k
        let mut aura_seal_index = None;
755
1.51k
        let mut aura_predigest_index = None;
756
1.51k
        let mut babe_seal_index = None;
757
1.51k
        let mut babe_predigest_index = None;
758
1.51k
        let mut babe_next_epoch_data_index = None;
759
1.51k
        let mut babe_next_config_data_index = None;
760
1.51k
        let mut has_runtime_environment_updated = false;
761
762
        // Iterate through the log items to see if anything is wrong.
763
1.51k
        let mut next_digest = scale_encoded;
764
1.51k
        for 
item_num68
in 0..digest_logs_len {
765
68
            let (
item67
,
next67
) = decode_item(next_digest, block_number_bytes)
?1
;
766
67
            next_digest = next;
767
768
1
            match item {
769
1
                DigestItemRef::AuraPreDigest(_) if aura_predigest_index.is_none() => {
770
1
                    aura_predigest_index = Some(item_num);
771
1
                }
772
                DigestItemRef::AuraPreDigest(_) => {
773
0
                    return Err(Error::MultipleAuraPreRuntimeDigests);
774
                }
775
0
                DigestItemRef::AuraConsensus(_) => {}
776
16
                DigestItemRef::BabePreDigest(_) if babe_predigest_index.is_none() => {
777
16
                    babe_predigest_index = Some(item_num);
778
16
                }
779
                DigestItemRef::BabePreDigest(_) => {
780
0
                    return Err(Error::MultipleBabePreRuntimeDigests);
781
                }
782
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_))
783
8
                    if babe_next_epoch_data_index.is_none() =>
784
8
                {
785
8
                    babe_next_epoch_data_index = Some(item_num);
786
8
                }
787
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_)) => {
788
0
                    return Err(Error::MultipleBabeEpochDescriptors);
789
                }
790
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_))
791
1
                    if babe_next_config_data_index.is_none() =>
792
1
                {
793
1
                    babe_next_config_data_index = Some(item_num);
794
1
                }
795
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_)) => {
796
0
                    return Err(Error::MultipleBabeConfigDescriptors);
797
                }
798
11
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::OnDisabled(_)) => {}
799
13
                DigestItemRef::GrandpaConsensus(_) => {}
800
0
                DigestItemRef::AuraSeal(_) if item_num == digest_logs_len - 1 => {
801
0
                    debug_assert!(aura_seal_index.is_none());
802
0
                    debug_assert!(babe_seal_index.is_none());
803
0
                    aura_seal_index = Some(item_num);
804
                }
805
0
                DigestItemRef::AuraSeal(_) => return Err(Error::SealIsntLastItem),
806
16
                DigestItemRef::BabeSeal(_) if item_num == digest_logs_len - 1 => {
807
16
                    debug_assert!(aura_seal_index.is_none());
808
16
                    debug_assert!(babe_seal_index.is_none());
809
16
                    babe_seal_index = Some(item_num);
810
                }
811
0
                DigestItemRef::RuntimeEnvironmentUpdated if has_runtime_environment_updated => {
812
0
                    return Err(Error::MutipleRuntimeEnvironmentUpdated);
813
                }
814
0
                DigestItemRef::RuntimeEnvironmentUpdated => {
815
0
                    has_runtime_environment_updated = true;
816
0
                }
817
0
                DigestItemRef::BabeSeal(_) => return Err(Error::SealIsntLastItem),
818
0
                DigestItemRef::UnknownSeal { .. } if item_num == digest_logs_len - 1 => {
819
0
                    debug_assert!(aura_seal_index.is_none());
820
0
                    debug_assert!(babe_seal_index.is_none());
821
                }
822
0
                DigestItemRef::UnknownSeal { .. } => return Err(Error::SealIsntLastItem),
823
                DigestItemRef::UnknownConsensus { .. }
824
                | DigestItemRef::UnknownPreRuntime { .. }
825
1
                | DigestItemRef::Other { .. } => {}
826
            }
827
        }
828
829
1.51k
        if babe_next_config_data_index.is_some() && 
babe_next_epoch_data_index1
.
is_none1
() {
830
0
            return Err(Error::UnexpectedBabeConfigDescriptor);
831
1.51k
        }
832
833
1.51k
        let out = DigestRef {
834
1.51k
            inner: DigestRefInner::Undecoded {
835
1.51k
                digest_logs_len,
836
1.51k
                digest: scale_encoded,
837
1.51k
                block_number_bytes,
838
1.51k
            },
839
1.51k
            aura_seal_index,
840
1.51k
            aura_predigest_index,
841
1.51k
            babe_seal_index,
842
1.51k
            babe_predigest_index,
843
1.51k
            babe_next_epoch_data_index,
844
1.51k
            babe_next_config_data_index,
845
1.51k
            has_runtime_environment_updated,
846
1.51k
        };
847
848
1.51k
        Ok((out, next_digest))
849
1.51k
    }
_RNvMs2_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRef16from_scale_bytes
Line
Count
Source
746
1.05k
    fn from_scale_bytes(
747
1.05k
        scale_encoded: &'a [u8],
748
1.05k
        block_number_bytes: usize,
749
1.05k
    ) -> Result<(Self, &'a [u8]), Error> {
750
1.05k
        let (scale_encoded, digest_logs_len) =
751
1.05k
            crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(scale_encoded)
752
1.05k
                .map_err(|_| Error::DigestItemLenDecodeError)
?0
;
753
754
1.05k
        let mut aura_seal_index = None;
755
1.05k
        let mut aura_predigest_index = None;
756
1.05k
        let mut babe_seal_index = None;
757
1.05k
        let mut babe_predigest_index = None;
758
1.05k
        let mut babe_next_epoch_data_index = None;
759
1.05k
        let mut babe_next_config_data_index = None;
760
1.05k
        let mut has_runtime_environment_updated = false;
761
762
        // Iterate through the log items to see if anything is wrong.
763
1.05k
        let mut next_digest = scale_encoded;
764
1.05k
        for 
item_num68
in 0..digest_logs_len {
765
68
            let (
item67
,
next67
) = decode_item(next_digest, block_number_bytes)
?1
;
766
67
            next_digest = next;
767
768
1
            match item {
769
1
                DigestItemRef::AuraPreDigest(_) if aura_predigest_index.is_none() => {
770
1
                    aura_predigest_index = Some(item_num);
771
1
                }
772
                DigestItemRef::AuraPreDigest(_) => {
773
0
                    return Err(Error::MultipleAuraPreRuntimeDigests);
774
                }
775
0
                DigestItemRef::AuraConsensus(_) => {}
776
16
                DigestItemRef::BabePreDigest(_) if babe_predigest_index.is_none() => {
777
16
                    babe_predigest_index = Some(item_num);
778
16
                }
779
                DigestItemRef::BabePreDigest(_) => {
780
0
                    return Err(Error::MultipleBabePreRuntimeDigests);
781
                }
782
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_))
783
8
                    if babe_next_epoch_data_index.is_none() =>
784
8
                {
785
8
                    babe_next_epoch_data_index = Some(item_num);
786
8
                }
787
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_)) => {
788
0
                    return Err(Error::MultipleBabeEpochDescriptors);
789
                }
790
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_))
791
1
                    if babe_next_config_data_index.is_none() =>
792
1
                {
793
1
                    babe_next_config_data_index = Some(item_num);
794
1
                }
795
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_)) => {
796
0
                    return Err(Error::MultipleBabeConfigDescriptors);
797
                }
798
11
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::OnDisabled(_)) => {}
799
13
                DigestItemRef::GrandpaConsensus(_) => {}
800
0
                DigestItemRef::AuraSeal(_) if item_num == digest_logs_len - 1 => {
801
0
                    debug_assert!(aura_seal_index.is_none());
802
0
                    debug_assert!(babe_seal_index.is_none());
803
0
                    aura_seal_index = Some(item_num);
804
                }
805
0
                DigestItemRef::AuraSeal(_) => return Err(Error::SealIsntLastItem),
806
16
                DigestItemRef::BabeSeal(_) if item_num == digest_logs_len - 1 => {
807
16
                    debug_assert!(aura_seal_index.is_none());
808
16
                    debug_assert!(babe_seal_index.is_none());
809
16
                    babe_seal_index = Some(item_num);
810
                }
811
0
                DigestItemRef::RuntimeEnvironmentUpdated if has_runtime_environment_updated => {
812
0
                    return Err(Error::MutipleRuntimeEnvironmentUpdated);
813
                }
814
0
                DigestItemRef::RuntimeEnvironmentUpdated => {
815
0
                    has_runtime_environment_updated = true;
816
0
                }
817
0
                DigestItemRef::BabeSeal(_) => return Err(Error::SealIsntLastItem),
818
0
                DigestItemRef::UnknownSeal { .. } if item_num == digest_logs_len - 1 => {
819
0
                    debug_assert!(aura_seal_index.is_none());
820
0
                    debug_assert!(babe_seal_index.is_none());
821
                }
822
0
                DigestItemRef::UnknownSeal { .. } => return Err(Error::SealIsntLastItem),
823
                DigestItemRef::UnknownConsensus { .. }
824
                | DigestItemRef::UnknownPreRuntime { .. }
825
1
                | DigestItemRef::Other { .. } => {}
826
            }
827
        }
828
829
1.04k
        if babe_next_config_data_index.is_some() && 
babe_next_epoch_data_index1
.
is_none1
() {
830
0
            return Err(Error::UnexpectedBabeConfigDescriptor);
831
1.04k
        }
832
833
1.04k
        let out = DigestRef {
834
1.04k
            inner: DigestRefInner::Undecoded {
835
1.04k
                digest_logs_len,
836
1.04k
                digest: scale_encoded,
837
1.04k
                block_number_bytes,
838
1.04k
            },
839
1.04k
            aura_seal_index,
840
1.04k
            aura_predigest_index,
841
1.04k
            babe_seal_index,
842
1.04k
            babe_predigest_index,
843
1.04k
            babe_next_epoch_data_index,
844
1.04k
            babe_next_config_data_index,
845
1.04k
            has_runtime_environment_updated,
846
1.04k
        };
847
848
1.04k
        Ok((out, next_digest))
849
1.05k
    }
_RNvMs2_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRef16from_scale_bytes
Line
Count
Source
746
464
    fn from_scale_bytes(
747
464
        scale_encoded: &'a [u8],
748
464
        block_number_bytes: usize,
749
464
    ) -> Result<(Self, &'a [u8]), Error> {
750
464
        let (scale_encoded, digest_logs_len) =
751
464
            crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(scale_encoded)
752
464
                .map_err(|_| Error::DigestItemLenDecodeError)
?0
;
753
754
464
        let mut aura_seal_index = None;
755
464
        let mut aura_predigest_index = None;
756
464
        let mut babe_seal_index = None;
757
464
        let mut babe_predigest_index = None;
758
464
        let mut babe_next_epoch_data_index = None;
759
464
        let mut babe_next_config_data_index = None;
760
464
        let mut has_runtime_environment_updated = false;
761
762
        // Iterate through the log items to see if anything is wrong.
763
464
        let mut next_digest = scale_encoded;
764
464
        for 
item_num0
in 0..digest_logs_len {
765
0
            let (item, next) = decode_item(next_digest, block_number_bytes)?;
766
0
            next_digest = next;
767
768
0
            match item {
769
0
                DigestItemRef::AuraPreDigest(_) if aura_predigest_index.is_none() => {
770
0
                    aura_predigest_index = Some(item_num);
771
0
                }
772
                DigestItemRef::AuraPreDigest(_) => {
773
0
                    return Err(Error::MultipleAuraPreRuntimeDigests);
774
                }
775
0
                DigestItemRef::AuraConsensus(_) => {}
776
0
                DigestItemRef::BabePreDigest(_) if babe_predigest_index.is_none() => {
777
0
                    babe_predigest_index = Some(item_num);
778
0
                }
779
                DigestItemRef::BabePreDigest(_) => {
780
0
                    return Err(Error::MultipleBabePreRuntimeDigests);
781
                }
782
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_))
783
0
                    if babe_next_epoch_data_index.is_none() =>
784
0
                {
785
0
                    babe_next_epoch_data_index = Some(item_num);
786
0
                }
787
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextEpochData(_)) => {
788
0
                    return Err(Error::MultipleBabeEpochDescriptors);
789
                }
790
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_))
791
0
                    if babe_next_config_data_index.is_none() =>
792
0
                {
793
0
                    babe_next_config_data_index = Some(item_num);
794
0
                }
795
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::NextConfigData(_)) => {
796
0
                    return Err(Error::MultipleBabeConfigDescriptors);
797
                }
798
0
                DigestItemRef::BabeConsensus(BabeConsensusLogRef::OnDisabled(_)) => {}
799
0
                DigestItemRef::GrandpaConsensus(_) => {}
800
0
                DigestItemRef::AuraSeal(_) if item_num == digest_logs_len - 1 => {
801
0
                    debug_assert!(aura_seal_index.is_none());
802
0
                    debug_assert!(babe_seal_index.is_none());
803
0
                    aura_seal_index = Some(item_num);
804
                }
805
0
                DigestItemRef::AuraSeal(_) => return Err(Error::SealIsntLastItem),
806
0
                DigestItemRef::BabeSeal(_) if item_num == digest_logs_len - 1 => {
807
0
                    debug_assert!(aura_seal_index.is_none());
808
0
                    debug_assert!(babe_seal_index.is_none());
809
0
                    babe_seal_index = Some(item_num);
810
                }
811
0
                DigestItemRef::RuntimeEnvironmentUpdated if has_runtime_environment_updated => {
812
0
                    return Err(Error::MutipleRuntimeEnvironmentUpdated);
813
                }
814
0
                DigestItemRef::RuntimeEnvironmentUpdated => {
815
0
                    has_runtime_environment_updated = true;
816
0
                }
817
0
                DigestItemRef::BabeSeal(_) => return Err(Error::SealIsntLastItem),
818
0
                DigestItemRef::UnknownSeal { .. } if item_num == digest_logs_len - 1 => {
819
0
                    debug_assert!(aura_seal_index.is_none());
820
0
                    debug_assert!(babe_seal_index.is_none());
821
                }
822
0
                DigestItemRef::UnknownSeal { .. } => return Err(Error::SealIsntLastItem),
823
                DigestItemRef::UnknownConsensus { .. }
824
                | DigestItemRef::UnknownPreRuntime { .. }
825
0
                | DigestItemRef::Other { .. } => {}
826
            }
827
        }
828
829
464
        if babe_next_config_data_index.is_some() && 
babe_next_epoch_data_index0
.
is_none0
() {
830
0
            return Err(Error::UnexpectedBabeConfigDescriptor);
831
464
        }
832
833
464
        let out = DigestRef {
834
464
            inner: DigestRefInner::Undecoded {
835
464
                digest_logs_len,
836
464
                digest: scale_encoded,
837
464
                block_number_bytes,
838
464
            },
839
464
            aura_seal_index,
840
464
            aura_predigest_index,
841
464
            babe_seal_index,
842
464
            babe_predigest_index,
843
464
            babe_next_epoch_data_index,
844
464
            babe_next_config_data_index,
845
464
            has_runtime_environment_updated,
846
464
        };
847
848
464
        Ok((out, next_digest))
849
464
    }
850
}
851
852
impl<'a> fmt::Debug for DigestRef<'a> {
853
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
854
0
        f.debug_list().entries(self.logs()).finish()
855
0
    }
Unexecuted instantiation: _RNvXs3_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRefNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs3_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRefNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
856
}
857
858
impl<'a> From<&'a Digest> for DigestRef<'a> {
859
365
    fn from(digest: &'a Digest) -> DigestRef<'a> {
860
365
        DigestRef {
861
365
            inner: DigestRefInner::Parsed(&digest.list),
862
365
            aura_seal_index: digest.aura_seal_index,
863
365
            aura_predigest_index: digest.aura_predigest_index,
864
365
            babe_seal_index: digest.babe_seal_index,
865
365
            babe_predigest_index: digest.babe_predigest_index,
866
365
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
867
365
            babe_next_config_data_index: digest.babe_next_config_data_index,
868
365
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
869
365
        }
870
365
    }
_RNvXs4_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_9DigestRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB5_6DigestE4from
Line
Count
Source
859
8
    fn from(digest: &'a Digest) -> DigestRef<'a> {
860
8
        DigestRef {
861
8
            inner: DigestRefInner::Parsed(&digest.list),
862
8
            aura_seal_index: digest.aura_seal_index,
863
8
            aura_predigest_index: digest.aura_predigest_index,
864
8
            babe_seal_index: digest.babe_seal_index,
865
8
            babe_predigest_index: digest.babe_predigest_index,
866
8
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
867
8
            babe_next_config_data_index: digest.babe_next_config_data_index,
868
8
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
869
8
        }
870
8
    }
_RNvXs4_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_9DigestRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB5_6DigestE4from
Line
Count
Source
859
357
    fn from(digest: &'a Digest) -> DigestRef<'a> {
860
357
        DigestRef {
861
357
            inner: DigestRefInner::Parsed(&digest.list),
862
357
            aura_seal_index: digest.aura_seal_index,
863
357
            aura_predigest_index: digest.aura_predigest_index,
864
357
            babe_seal_index: digest.babe_seal_index,
865
357
            babe_predigest_index: digest.babe_predigest_index,
866
357
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
867
357
            babe_next_config_data_index: digest.babe_next_config_data_index,
868
357
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
869
357
        }
870
357
    }
871
}
872
873
/// Seal popped using [`DigestRef::pop_seal`].
874
pub enum Seal<'a> {
875
    Aura(&'a [u8; 64]),
876
    Babe(&'a [u8; 64]),
877
}
878
879
/// Generic header digest.
880
#[derive(Clone)]
881
pub struct Digest {
882
    /// Actual list of items.
883
    list: Vec<DigestItem>,
884
    /// Index of the [`DigestItemRef::AuraSeal`] item, if any.
885
    aura_seal_index: Option<usize>,
886
    /// Index of the [`DigestItemRef::AuraPreDigest`] item, if any.
887
    aura_predigest_index: Option<usize>,
888
    /// Index of the [`DigestItemRef::BabeSeal`] item, if any.
889
    babe_seal_index: Option<usize>,
890
    /// Index of the [`DigestItemRef::BabePreDigest`] item, if any.
891
    babe_predigest_index: Option<usize>,
892
    /// Index of the [`DigestItemRef::BabeConsensus`] item containing a
893
    /// [`BabeConsensusLogRef::NextEpochData`], if any.
894
    babe_next_epoch_data_index: Option<usize>,
895
    /// Index of the [`DigestItemRef::BabeConsensus`] item containing a
896
    /// [`BabeConsensusLogRef::NextConfigData`], if any.
897
    babe_next_config_data_index: Option<usize>,
898
    /// `true` if there is a [`DigestItemRef::RuntimeEnvironmentUpdated`] item.
899
    has_runtime_environment_updated: bool,
900
}
901
902
impl Digest {
903
    /// Returns an iterator to the log items in this digest.
904
0
    pub fn logs(&self) -> LogsIter {
905
0
        DigestRef::from(self).logs()
906
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest4logs
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest4logs
907
908
    /// Returns the Aura seal digest item, if any.
909
0
    pub fn aura_seal(&self) -> Option<&[u8; 64]> {
910
0
        DigestRef::from(self).aura_seal()
911
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest9aura_seal
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest9aura_seal
912
913
    /// Returns the Babe seal digest item, if any.
914
0
    pub fn babe_seal(&self) -> Option<&[u8; 64]> {
915
0
        DigestRef::from(self).babe_seal()
916
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest9babe_seal
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest9babe_seal
917
918
    /// Returns the Babe pre-runtime digest item, if any.
919
0
    pub fn babe_pre_runtime(&self) -> Option<BabePreDigestRef> {
920
0
        DigestRef::from(self).babe_pre_runtime()
921
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest16babe_pre_runtime
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest16babe_pre_runtime
922
923
    /// Returns the Babe epoch information stored in the header, if any.
924
    ///
925
    /// It is guaranteed that a configuration change is present only if an epoch change is
926
    /// present too.
927
0
    pub fn babe_epoch_information(&self) -> Option<(BabeNextEpochRef, Option<BabeNextConfig>)> {
928
0
        DigestRef::from(self).babe_epoch_information()
929
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest22babe_epoch_information
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest22babe_epoch_information
930
931
    /// Returns `true` if there is a [`DigestItemRef::RuntimeEnvironmentUpdated`] item.
932
0
    pub fn has_runtime_environment_updated(&self) -> bool {
933
0
        self.has_runtime_environment_updated
934
0
    }
Unexecuted instantiation: _RNvMs5_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6Digest31has_runtime_environment_updated
Unexecuted instantiation: _RNvMs5_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6Digest31has_runtime_environment_updated
935
}
936
937
impl fmt::Debug for Digest {
938
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
939
0
        f.debug_list()
940
0
            .entries(self.list.iter().map(DigestItemRef::from))
941
0
            .finish()
942
0
    }
Unexecuted instantiation: _RNvXs6_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6DigestNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs6_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6DigestNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
943
}
944
945
impl<'a> From<DigestRef<'a>> for Digest {
946
47
    fn from(digest: DigestRef<'a>) -> Digest {
947
47
        Digest {
948
47
            list: digest.logs().map(Into::into).collect(),
949
47
            aura_seal_index: digest.aura_seal_index,
950
47
            aura_predigest_index: digest.aura_predigest_index,
951
47
            babe_seal_index: digest.babe_seal_index,
952
47
            babe_predigest_index: digest.babe_predigest_index,
953
47
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
954
47
            babe_next_config_data_index: digest.babe_next_config_data_index,
955
47
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
956
47
        }
957
47
    }
_RNvXs7_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_6DigestINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_9DigestRefE4from
Line
Count
Source
946
5
    fn from(digest: DigestRef<'a>) -> Digest {
947
5
        Digest {
948
5
            list: digest.logs().map(Into::into).collect(),
949
5
            aura_seal_index: digest.aura_seal_index,
950
5
            aura_predigest_index: digest.aura_predigest_index,
951
5
            babe_seal_index: digest.babe_seal_index,
952
5
            babe_predigest_index: digest.babe_predigest_index,
953
5
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
954
5
            babe_next_config_data_index: digest.babe_next_config_data_index,
955
5
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
956
5
        }
957
5
    }
_RNvXs7_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_6DigestINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_9DigestRefE4from
Line
Count
Source
946
42
    fn from(digest: DigestRef<'a>) -> Digest {
947
42
        Digest {
948
42
            list: digest.logs().map(Into::into).collect(),
949
42
            aura_seal_index: digest.aura_seal_index,
950
42
            aura_predigest_index: digest.aura_predigest_index,
951
42
            babe_seal_index: digest.babe_seal_index,
952
42
            babe_predigest_index: digest.babe_predigest_index,
953
42
            babe_next_epoch_data_index: digest.babe_next_epoch_data_index,
954
42
            babe_next_config_data_index: digest.babe_next_config_data_index,
955
42
            has_runtime_environment_updated: digest.has_runtime_environment_updated,
956
42
        }
957
42
    }
958
}
959
960
/// Iterator towards the digest log items.
961
#[derive(Clone)]
962
pub struct LogsIter<'a> {
963
    inner: LogsIterInner<'a>,
964
}
965
966
#[derive(Clone)]
967
enum LogsIterInner<'a> {
968
    Decoded(slice::Iter<'a, DigestItem>),
969
    Undecoded {
970
        /// Encoded digest.
971
        pointer: &'a [u8],
972
        /// Number of log items remaining.
973
        remaining_len: usize,
974
        /// Number of bytes used to encode block numbers in the header.
975
        block_number_bytes: usize,
976
    },
977
}
978
979
impl<'a> Iterator for LogsIter<'a> {
980
    type Item = DigestItemRef<'a>;
981
982
1.40k
    fn next(&mut self) -> Option<Self::Item> {
983
1.40k
        match &mut self.inner {
984
1.22k
            LogsIterInner::Decoded(iter) => iter.next().map(Into::into),
985
            LogsIterInner::Undecoded {
986
175
                pointer,
987
175
                remaining_len,
988
175
                block_number_bytes,
989
            } => {
990
175
                if *remaining_len == 0 {
991
68
                    return None;
992
107
                }
993
994
                // Validity is guaranteed when the `DigestRef` is constructed.
995
107
                let (item, new_pointer) = decode_item(pointer, *block_number_bytes).unwrap();
996
107
                *pointer = new_pointer;
997
107
                *remaining_len -= 1;
998
999
107
                Some(item)
1000
            }
1001
        }
1002
1.40k
    }
_RNvXs8_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_8LogsIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
982
1.17k
    fn next(&mut self) -> Option<Self::Item> {
983
1.17k
        match &mut self.inner {
984
1.04k
            LogsIterInner::Decoded(iter) => iter.next().map(Into::into),
985
            LogsIterInner::Undecoded {
986
131
                pointer,
987
131
                remaining_len,
988
131
                block_number_bytes,
989
            } => {
990
131
                if *remaining_len == 0 {
991
24
                    return None;
992
107
                }
993
994
                // Validity is guaranteed when the `DigestRef` is constructed.
995
107
                let (item, new_pointer) = decode_item(pointer, *block_number_bytes).unwrap();
996
107
                *pointer = new_pointer;
997
107
                *remaining_len -= 1;
998
999
107
                Some(item)
1000
            }
1001
        }
1002
1.17k
    }
_RNvXs8_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_8LogsIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
982
233
    fn next(&mut self) -> Option<Self::Item> {
983
233
        match &mut self.inner {
984
189
            LogsIterInner::Decoded(iter) => iter.next().map(Into::into),
985
            LogsIterInner::Undecoded {
986
44
                pointer,
987
44
                remaining_len,
988
44
                block_number_bytes,
989
            } => {
990
44
                if *remaining_len == 0 {
991
44
                    return None;
992
0
                }
993
994
                // Validity is guaranteed when the `DigestRef` is constructed.
995
0
                let (item, new_pointer) = decode_item(pointer, *block_number_bytes).unwrap();
996
0
                *pointer = new_pointer;
997
0
                *remaining_len -= 1;
998
999
0
                Some(item)
1000
            }
1001
        }
1002
233
    }
1003
1004
1.19k
    fn size_hint(&self) -> (usize, Option<usize>) {
1005
1.19k
        match &self.inner {
1006
1.18k
            LogsIterInner::Decoded(iter) => iter.size_hint(),
1007
11
            LogsIterInner::Undecoded { remaining_len, .. } => {
1008
11
                (*remaining_len, Some(*remaining_len))
1009
            }
1010
        }
1011
1.19k
    }
_RNvXs8_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_8LogsIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator9size_hint
Line
Count
Source
1004
1.04k
    fn size_hint(&self) -> (usize, Option<usize>) {
1005
1.04k
        match &self.inner {
1006
1.03k
            LogsIterInner::Decoded(iter) => iter.size_hint(),
1007
11
            LogsIterInner::Undecoded { remaining_len, .. } => {
1008
11
                (*remaining_len, Some(*remaining_len))
1009
            }
1010
        }
1011
1.04k
    }
_RNvXs8_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_8LogsIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator9size_hint
Line
Count
Source
1004
147
    fn size_hint(&self) -> (usize, Option<usize>) {
1005
147
        match &self.inner {
1006
147
            LogsIterInner::Decoded(iter) => iter.size_hint(),
1007
0
            LogsIterInner::Undecoded { remaining_len, .. } => {
1008
0
                (*remaining_len, Some(*remaining_len))
1009
            }
1010
        }
1011
147
    }
1012
}
1013
1014
impl<'a> ExactSizeIterator for LogsIter<'a> {}
1015
1016
// TODO: document
1017
#[derive(Debug, PartialEq, Eq, Clone)]
1018
pub enum DigestItemRef<'a> {
1019
    AuraPreDigest(AuraPreDigest),
1020
    /// Block signature made using the AURA consensus engine.
1021
    AuraSeal(&'a [u8; 64]),
1022
    AuraConsensus(AuraConsensusLogRef<'a>),
1023
1024
    BabePreDigest(BabePreDigestRef<'a>),
1025
    BabeConsensus(BabeConsensusLogRef<'a>),
1026
    /// Block signature made using the BABE consensus engine.
1027
    BabeSeal(&'a [u8; 64]),
1028
1029
    GrandpaConsensus(GrandpaConsensusLogRef<'a>),
1030
1031
    /// Consensus item with an engine that hasn't been recognized.
1032
    UnknownConsensus {
1033
        /// Name of the consensus engine.
1034
        engine: [u8; 4],
1035
        /// Smoldot doesn't interpret the content of the log item.
1036
        opaque: &'a [u8],
1037
    },
1038
    /// Pre-runtime item with a consensus engine that hasn't been recognized.
1039
    UnknownPreRuntime {
1040
        /// Name of the consensus engine.
1041
        engine: [u8; 4],
1042
        /// Smoldot doesn't interpret the content of the log item.
1043
        opaque: &'a [u8],
1044
    },
1045
    /// Seal using a consensus engine that hasn't been recognized.
1046
    UnknownSeal {
1047
        /// Name of the consensus engine.
1048
        engine: [u8; 4],
1049
        /// Smoldot doesn't interpret the content of the log item.
1050
        opaque: &'a [u8],
1051
    },
1052
1053
    /// Some other thing. Always ignored.
1054
    ///
1055
    /// Contrary to [`DigestItemRef::UnknownConsensus`], [`DigestItemRef::UnknownPreRuntime`], or
1056
    /// [`DigestItemRef::UnknownSeal`], this item is intentionally meant to always be ignored.
1057
    Other(&'a [u8]),
1058
1059
    /// Runtime of the chain has been updated in this block. This can include the runtime code or
1060
    /// the heap pages.
1061
    RuntimeEnvironmentUpdated,
1062
}
1063
1064
impl<'a> DigestItemRef<'a> {
1065
    /// True if the item is relevant to the Aura consensus engine.
1066
10
    pub fn is_aura(&self) -> bool {
1067
10
        matches!(
1068
10
            self,
1069
            DigestItemRef::AuraPreDigest(_)
1070
                | DigestItemRef::AuraSeal(_)
1071
                | DigestItemRef::AuraConsensus(_)
1072
        )
1073
10
    }
_RNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRef7is_aura
Line
Count
Source
1066
10
    pub fn is_aura(&self) -> bool {
1067
10
        matches!(
1068
10
            self,
1069
            DigestItemRef::AuraPreDigest(_)
1070
                | DigestItemRef::AuraSeal(_)
1071
                | DigestItemRef::AuraConsensus(_)
1072
        )
1073
10
    }
Unexecuted instantiation: _RNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRef7is_aura
1074
1075
    /// True if the item is relevant to the Babe consensus engine.
1076
0
    pub fn is_babe(&self) -> bool {
1077
0
        matches!(
1078
0
            self,
1079
            DigestItemRef::BabePreDigest(_)
1080
                | DigestItemRef::BabeConsensus(_)
1081
                | DigestItemRef::BabeSeal(_)
1082
        )
1083
0
    }
Unexecuted instantiation: _RNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRef7is_babe
Unexecuted instantiation: _RNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRef7is_babe
1084
1085
    /// True if the item is relevant to the Grandpa finality engine.
1086
0
    pub fn is_grandpa(&self) -> bool {
1087
0
        matches!(self, DigestItemRef::GrandpaConsensus(_))
1088
0
    }
Unexecuted instantiation: _RNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRef10is_grandpa
Unexecuted instantiation: _RNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRef10is_grandpa
1089
1090
    /// Decodes a SCALE-encoded digest item.
1091
0
    pub fn from_scale_encoded(bytes: &'a [u8], block_number_bytes: usize) -> Result<Self, Error> {
1092
0
        let (item, remain) = decode_item(bytes, block_number_bytes)?;
1093
0
        if !remain.is_empty() {
1094
0
            return Err(Error::TooLong);
1095
0
        }
1096
0
        Ok(item)
1097
0
    }
Unexecuted instantiation: _RNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRef18from_scale_encoded
Unexecuted instantiation: _RNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRef18from_scale_encoded
1098
1099
    /// Returns an iterator to list of buffers which, when concatenated, produces the SCALE
1100
    /// encoding of that digest item.
1101
41
    pub fn scale_encoding(
1102
41
        &self,
1103
41
        block_number_bytes: usize,
1104
41
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
1105
41
        let (item1, item2) = match *self {
1106
2
            DigestItemRef::AuraPreDigest(ref aura_pre_digest) => {
1107
2
                let encoded = aura_pre_digest
1108
2
                    .scale_encoding()
1109
2
                    .fold(Vec::new(), |mut a, b| {
1110
2
                        a.extend_from_slice(b.as_ref());
1111
2
                        a
1112
2
                    });
_RNCNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_13DigestItemRef14scale_encoding0B9_
Line
Count
Source
1109
2
                    .fold(Vec::new(), |mut a, b| {
1110
2
                        a.extend_from_slice(b.as_ref());
1111
2
                        a
1112
2
                    });
Unexecuted instantiation: _RNCNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_13DigestItemRef14scale_encoding0B9_
1113
1114
2
                let mut ret = Vec::with_capacity(12);
1115
2
                ret.push(6);
1116
2
                ret.extend_from_slice(b"aura");
1117
2
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1118
2
                (ret, either::Left(encoded))
1119
            }
1120
0
            DigestItemRef::AuraSeal(seal) => {
1121
0
                let mut ret = Vec::with_capacity(12);
1122
0
                ret.push(5);
1123
0
                ret.extend_from_slice(b"aura");
1124
0
                ret.extend_from_slice(util::encode_scale_compact_usize(64).as_ref());
1125
0
                (ret, either::Right(&seal[..]))
1126
            }
1127
0
            DigestItemRef::AuraConsensus(ref aura_consensus) => {
1128
0
                let encoded = aura_consensus
1129
0
                    .scale_encoding()
1130
0
                    .fold(Vec::new(), |mut a, b| {
1131
0
                        a.extend_from_slice(b.as_ref());
1132
0
                        a
1133
0
                    });
Unexecuted instantiation: _RNCNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_13DigestItemRef14scale_encodings_0B9_
Unexecuted instantiation: _RNCNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_13DigestItemRef14scale_encodings_0B9_
1134
1135
0
                let mut ret = Vec::with_capacity(12);
1136
0
                ret.push(4);
1137
0
                ret.extend_from_slice(b"aura");
1138
0
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1139
0
                (ret, either::Left(encoded))
1140
            }
1141
7
            DigestItemRef::BabePreDigest(ref babe_pre_digest) => {
1142
7
                let encoded = babe_pre_digest
1143
7
                    .scale_encoding()
1144
27
                    .
fold7
(
Vec::new7
(), |mut a, b| {
1145
27
                        a.extend_from_slice(b.as_ref());
1146
27
                        a
1147
27
                    });
_RNCNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_13DigestItemRef14scale_encodings0_0B9_
Line
Count
Source
1144
27
                    .fold(Vec::new(), |mut a, b| {
1145
27
                        a.extend_from_slice(b.as_ref());
1146
27
                        a
1147
27
                    });
Unexecuted instantiation: _RNCNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_13DigestItemRef14scale_encodings0_0B9_
1148
1149
7
                let mut ret = Vec::with_capacity(12);
1150
7
                ret.push(6);
1151
7
                ret.extend_from_slice(b"BABE");
1152
7
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1153
7
                (ret, either::Left(encoded))
1154
            }
1155
17
            DigestItemRef::BabeConsensus(ref babe_consensus) => {
1156
17
                let encoded = babe_consensus
1157
17
                    .scale_encoding()
1158
1.89k
                    .
fold17
(
Vec::new17
(), |mut a, b| {
1159
1.89k
                        a.extend_from_slice(b.as_ref());
1160
1.89k
                        a
1161
1.89k
                    });
_RNCNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_13DigestItemRef14scale_encodings1_0B9_
Line
Count
Source
1158
1.89k
                    .fold(Vec::new(), |mut a, b| {
1159
1.89k
                        a.extend_from_slice(b.as_ref());
1160
1.89k
                        a
1161
1.89k
                    });
Unexecuted instantiation: _RNCNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_13DigestItemRef14scale_encodings1_0B9_
1162
1163
17
                let mut ret = Vec::with_capacity(12);
1164
17
                ret.push(4);
1165
17
                ret.extend_from_slice(b"BABE");
1166
17
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1167
17
                (ret, either::Left(encoded))
1168
            }
1169
12
            DigestItemRef::GrandpaConsensus(ref gp_consensus) => {
1170
12
                let encoded =
1171
12
                    gp_consensus
1172
12
                        .scale_encoding(block_number_bytes)
1173
1.82k
                        .
fold12
(
Vec::new12
(), |mut a, b| {
1174
1.82k
                            a.extend_from_slice(b.as_ref());
1175
1.82k
                            a
1176
1.82k
                        });
_RNCNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB7_13DigestItemRef14scale_encodings2_0B9_
Line
Count
Source
1173
1.82k
                        .fold(Vec::new(), |mut a, b| {
1174
1.82k
                            a.extend_from_slice(b.as_ref());
1175
1.82k
                            a
1176
1.82k
                        });
Unexecuted instantiation: _RNCNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB7_13DigestItemRef14scale_encodings2_0B9_
1177
1178
12
                let mut ret = Vec::with_capacity(12);
1179
12
                ret.push(4);
1180
12
                ret.extend_from_slice(b"FRNK");
1181
12
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1182
12
                (ret, either::Left(encoded))
1183
            }
1184
3
            DigestItemRef::BabeSeal(seal) => {
1185
3
                let mut ret = Vec::with_capacity(12);
1186
3
                ret.push(5);
1187
3
                ret.extend_from_slice(b"BABE");
1188
3
                ret.extend_from_slice(util::encode_scale_compact_usize(64).as_ref());
1189
3
                (ret, either::Right(&seal[..]))
1190
            }
1191
0
            DigestItemRef::UnknownConsensus { engine, opaque } => {
1192
0
                let mut ret = Vec::with_capacity(12);
1193
0
                ret.push(4);
1194
0
                ret.extend_from_slice(&engine);
1195
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1196
0
                (ret, either::Right(opaque))
1197
            }
1198
0
            DigestItemRef::UnknownSeal { engine, opaque } => {
1199
0
                let mut ret = Vec::with_capacity(12);
1200
0
                ret.push(5);
1201
0
                ret.extend_from_slice(&engine);
1202
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1203
0
                (ret, either::Right(opaque))
1204
            }
1205
0
            DigestItemRef::UnknownPreRuntime { engine, opaque } => {
1206
0
                let mut ret = Vec::with_capacity(12);
1207
0
                ret.push(6);
1208
0
                ret.extend_from_slice(&engine);
1209
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1210
0
                (ret, either::Right(opaque))
1211
            }
1212
0
            DigestItemRef::Other(raw) => {
1213
0
                let mut ret = Vec::with_capacity(12);
1214
0
                ret.push(0);
1215
0
                ret.extend_from_slice(util::encode_scale_compact_usize(raw.len()).as_ref());
1216
0
                (ret, either::Right(raw))
1217
            }
1218
0
            DigestItemRef::RuntimeEnvironmentUpdated => (vec![8], either::Right(&[][..])),
1219
        };
1220
1221
41
        [either::Left(item1), item2].into_iter()
1222
41
    }
_RNvMsa_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRef14scale_encoding
Line
Count
Source
1101
41
    pub fn scale_encoding(
1102
41
        &self,
1103
41
        block_number_bytes: usize,
1104
41
    ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + use<'a>> + Clone + use<'a> {
1105
41
        let (item1, item2) = match *self {
1106
2
            DigestItemRef::AuraPreDigest(ref aura_pre_digest) => {
1107
2
                let encoded = aura_pre_digest
1108
2
                    .scale_encoding()
1109
2
                    .fold(Vec::new(), |mut a, b| {
1110
                        a.extend_from_slice(b.as_ref());
1111
                        a
1112
                    });
1113
1114
2
                let mut ret = Vec::with_capacity(12);
1115
2
                ret.push(6);
1116
2
                ret.extend_from_slice(b"aura");
1117
2
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1118
2
                (ret, either::Left(encoded))
1119
            }
1120
0
            DigestItemRef::AuraSeal(seal) => {
1121
0
                let mut ret = Vec::with_capacity(12);
1122
0
                ret.push(5);
1123
0
                ret.extend_from_slice(b"aura");
1124
0
                ret.extend_from_slice(util::encode_scale_compact_usize(64).as_ref());
1125
0
                (ret, either::Right(&seal[..]))
1126
            }
1127
0
            DigestItemRef::AuraConsensus(ref aura_consensus) => {
1128
0
                let encoded = aura_consensus
1129
0
                    .scale_encoding()
1130
0
                    .fold(Vec::new(), |mut a, b| {
1131
                        a.extend_from_slice(b.as_ref());
1132
                        a
1133
                    });
1134
1135
0
                let mut ret = Vec::with_capacity(12);
1136
0
                ret.push(4);
1137
0
                ret.extend_from_slice(b"aura");
1138
0
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1139
0
                (ret, either::Left(encoded))
1140
            }
1141
7
            DigestItemRef::BabePreDigest(ref babe_pre_digest) => {
1142
7
                let encoded = babe_pre_digest
1143
7
                    .scale_encoding()
1144
7
                    .fold(Vec::new(), |mut a, b| {
1145
                        a.extend_from_slice(b.as_ref());
1146
                        a
1147
                    });
1148
1149
7
                let mut ret = Vec::with_capacity(12);
1150
7
                ret.push(6);
1151
7
                ret.extend_from_slice(b"BABE");
1152
7
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1153
7
                (ret, either::Left(encoded))
1154
            }
1155
17
            DigestItemRef::BabeConsensus(ref babe_consensus) => {
1156
17
                let encoded = babe_consensus
1157
17
                    .scale_encoding()
1158
17
                    .fold(Vec::new(), |mut a, b| {
1159
                        a.extend_from_slice(b.as_ref());
1160
                        a
1161
                    });
1162
1163
17
                let mut ret = Vec::with_capacity(12);
1164
17
                ret.push(4);
1165
17
                ret.extend_from_slice(b"BABE");
1166
17
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1167
17
                (ret, either::Left(encoded))
1168
            }
1169
12
            DigestItemRef::GrandpaConsensus(ref gp_consensus) => {
1170
12
                let encoded =
1171
12
                    gp_consensus
1172
12
                        .scale_encoding(block_number_bytes)
1173
12
                        .fold(Vec::new(), |mut a, b| {
1174
                            a.extend_from_slice(b.as_ref());
1175
                            a
1176
                        });
1177
1178
12
                let mut ret = Vec::with_capacity(12);
1179
12
                ret.push(4);
1180
12
                ret.extend_from_slice(b"FRNK");
1181
12
                ret.extend_from_slice(util::encode_scale_compact_usize(encoded.len()).as_ref());
1182
12
                (ret, either::Left(encoded))
1183
            }
1184
3
            DigestItemRef::BabeSeal(seal) => {
1185
3
                let mut ret = Vec::with_capacity(12);
1186
3
                ret.push(5);
1187
3
                ret.extend_from_slice(b"BABE");
1188
3
                ret.extend_from_slice(util::encode_scale_compact_usize(64).as_ref());
1189
3
                (ret, either::Right(&seal[..]))
1190
            }
1191
0
            DigestItemRef::UnknownConsensus { engine, opaque } => {
1192
0
                let mut ret = Vec::with_capacity(12);
1193
0
                ret.push(4);
1194
0
                ret.extend_from_slice(&engine);
1195
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1196
0
                (ret, either::Right(opaque))
1197
            }
1198
0
            DigestItemRef::UnknownSeal { engine, opaque } => {
1199
0
                let mut ret = Vec::with_capacity(12);
1200
0
                ret.push(5);
1201
0
                ret.extend_from_slice(&engine);
1202
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1203
0
                (ret, either::Right(opaque))
1204
            }
1205
0
            DigestItemRef::UnknownPreRuntime { engine, opaque } => {
1206
0
                let mut ret = Vec::with_capacity(12);
1207
0
                ret.push(6);
1208
0
                ret.extend_from_slice(&engine);
1209
0
                ret.extend_from_slice(util::encode_scale_compact_usize(opaque.len()).as_ref());
1210
0
                (ret, either::Right(opaque))
1211
            }
1212
0
            DigestItemRef::Other(raw) => {
1213
0
                let mut ret = Vec::with_capacity(12);
1214
0
                ret.push(0);
1215
0
                ret.extend_from_slice(util::encode_scale_compact_usize(raw.len()).as_ref());
1216
0
                (ret, either::Right(raw))
1217
            }
1218
0
            DigestItemRef::RuntimeEnvironmentUpdated => (vec![8], either::Right(&[][..])),
1219
        };
1220
1221
41
        [either::Left(item1), item2].into_iter()
1222
41
    }
Unexecuted instantiation: _RNvMsa_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRef14scale_encoding
1223
}
1224
1225
impl<'a> From<&'a DigestItem> for DigestItemRef<'a> {
1226
2
    fn from(a: &'a DigestItem) -> DigestItemRef<'a> {
1227
2
        match a {
1228
2
            DigestItem::AuraPreDigest(v) => DigestItemRef::AuraPreDigest(v.clone()),
1229
0
            DigestItem::AuraConsensus(v) => DigestItemRef::AuraConsensus(v.into()),
1230
0
            DigestItem::AuraSeal(v) => DigestItemRef::AuraSeal(v),
1231
0
            DigestItem::BabePreDigest(v) => DigestItemRef::BabePreDigest(v.into()),
1232
0
            DigestItem::BabeConsensus(v) => DigestItemRef::BabeConsensus(v.into()),
1233
0
            DigestItem::BabeSeal(v) => DigestItemRef::BabeSeal(v),
1234
0
            DigestItem::GrandpaConsensus(v) => DigestItemRef::GrandpaConsensus(v.into()),
1235
0
            DigestItem::UnknownConsensus { engine, opaque } => DigestItemRef::UnknownConsensus {
1236
0
                engine: *engine,
1237
0
                opaque,
1238
0
            },
1239
0
            DigestItem::UnknownSeal { engine, opaque } => DigestItemRef::UnknownSeal {
1240
0
                engine: *engine,
1241
0
                opaque,
1242
0
            },
1243
0
            DigestItem::UnknownPreRuntime { engine, opaque } => DigestItemRef::UnknownPreRuntime {
1244
0
                engine: *engine,
1245
0
                opaque,
1246
0
            },
1247
0
            DigestItem::Other(v) => DigestItemRef::Other(v),
1248
0
            DigestItem::RuntimeEnvironmentUpdated => DigestItemRef::RuntimeEnvironmentUpdated,
1249
        }
1250
2
    }
_RNvXsb_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_13DigestItemRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB5_10DigestItemE4from
Line
Count
Source
1226
2
    fn from(a: &'a DigestItem) -> DigestItemRef<'a> {
1227
2
        match a {
1228
2
            DigestItem::AuraPreDigest(v) => DigestItemRef::AuraPreDigest(v.clone()),
1229
0
            DigestItem::AuraConsensus(v) => DigestItemRef::AuraConsensus(v.into()),
1230
0
            DigestItem::AuraSeal(v) => DigestItemRef::AuraSeal(v),
1231
0
            DigestItem::BabePreDigest(v) => DigestItemRef::BabePreDigest(v.into()),
1232
0
            DigestItem::BabeConsensus(v) => DigestItemRef::BabeConsensus(v.into()),
1233
0
            DigestItem::BabeSeal(v) => DigestItemRef::BabeSeal(v),
1234
0
            DigestItem::GrandpaConsensus(v) => DigestItemRef::GrandpaConsensus(v.into()),
1235
0
            DigestItem::UnknownConsensus { engine, opaque } => DigestItemRef::UnknownConsensus {
1236
0
                engine: *engine,
1237
0
                opaque,
1238
0
            },
1239
0
            DigestItem::UnknownSeal { engine, opaque } => DigestItemRef::UnknownSeal {
1240
0
                engine: *engine,
1241
0
                opaque,
1242
0
            },
1243
0
            DigestItem::UnknownPreRuntime { engine, opaque } => DigestItemRef::UnknownPreRuntime {
1244
0
                engine: *engine,
1245
0
                opaque,
1246
0
            },
1247
0
            DigestItem::Other(v) => DigestItemRef::Other(v),
1248
0
            DigestItem::RuntimeEnvironmentUpdated => DigestItemRef::RuntimeEnvironmentUpdated,
1249
        }
1250
2
    }
Unexecuted instantiation: _RNvXsb_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_13DigestItemRefINtNtCs1p5UDGgVI4d_4core7convert4FromRNtB5_10DigestItemE4from
1251
}
1252
1253
// TODO: document
1254
#[derive(Debug, Clone)]
1255
pub enum DigestItem {
1256
    AuraPreDigest(AuraPreDigest),
1257
    AuraConsensus(AuraConsensusLog),
1258
    /// Block signature made using the AURA consensus engine.
1259
    AuraSeal([u8; 64]),
1260
1261
    BabePreDigest(BabePreDigest),
1262
    BabeConsensus(BabeConsensusLog),
1263
    /// Block signature made using the BABE consensus engine.
1264
    BabeSeal([u8; 64]),
1265
1266
    GrandpaConsensus(GrandpaConsensusLog),
1267
1268
    /// See [`DigestItemRef::UnknownConsensus`].
1269
    UnknownConsensus {
1270
        /// Name of the consensus engine.
1271
        engine: [u8; 4],
1272
        /// Smoldot doesn't interpret the content of the log item.
1273
        opaque: Vec<u8>,
1274
    },
1275
    /// See [`DigestItemRef::UnknownPreRuntime`].
1276
    UnknownPreRuntime {
1277
        /// Name of the consensus engine.
1278
        engine: [u8; 4],
1279
        /// Smoldot doesn't interpret the content of the log item.
1280
        opaque: Vec<u8>,
1281
    },
1282
    /// See [`DigestItemRef::UnknownSeal`].
1283
    UnknownSeal {
1284
        /// Name of the consensus engine.
1285
        engine: [u8; 4],
1286
        /// Smoldot doesn't interpret the content of the log item.
1287
        opaque: Vec<u8>,
1288
    },
1289
1290
    /// Runtime of the chain has been updated in this block. This can include the runtime code or
1291
    /// the heap pages.
1292
    RuntimeEnvironmentUpdated,
1293
1294
    /// Some other thing. Always ignored.
1295
    Other(Vec<u8>),
1296
}
1297
1298
impl<'a> From<DigestItemRef<'a>> for DigestItem {
1299
4
    fn from(a: DigestItemRef<'a>) -> DigestItem {
1300
4
        match a {
1301
0
            DigestItemRef::AuraPreDigest(v) => DigestItem::AuraPreDigest(v),
1302
0
            DigestItemRef::AuraConsensus(v) => DigestItem::AuraConsensus(v.into()),
1303
0
            DigestItemRef::AuraSeal(v) => {
1304
0
                let mut seal = [0; 64];
1305
0
                seal.copy_from_slice(v);
1306
0
                DigestItem::AuraSeal(seal)
1307
            }
1308
2
            DigestItemRef::BabePreDigest(v) => DigestItem::BabePreDigest(v.into()),
1309
0
            DigestItemRef::BabeConsensus(v) => DigestItem::BabeConsensus(v.into()),
1310
2
            DigestItemRef::BabeSeal(v) => {
1311
2
                let mut seal = [0; 64];
1312
2
                seal.copy_from_slice(v);
1313
2
                DigestItem::BabeSeal(seal)
1314
            }
1315
0
            DigestItemRef::GrandpaConsensus(v) => DigestItem::GrandpaConsensus(v.into()),
1316
0
            DigestItemRef::UnknownConsensus { engine, opaque } => DigestItem::UnknownConsensus {
1317
0
                opaque: opaque.to_vec(),
1318
0
                engine,
1319
0
            },
1320
0
            DigestItemRef::UnknownSeal { engine, opaque } => DigestItem::UnknownSeal {
1321
0
                opaque: opaque.to_vec(),
1322
0
                engine,
1323
0
            },
1324
0
            DigestItemRef::UnknownPreRuntime { engine, opaque } => DigestItem::UnknownPreRuntime {
1325
0
                opaque: opaque.to_vec(),
1326
0
                engine,
1327
0
            },
1328
0
            DigestItemRef::Other(v) => DigestItem::Other(v.to_vec()),
1329
0
            DigestItemRef::RuntimeEnvironmentUpdated => DigestItem::RuntimeEnvironmentUpdated,
1330
        }
1331
4
    }
_RNvXsc_NtCsjlkOsLH0Zfj_7smoldot6headerNtB5_10DigestItemINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_13DigestItemRefE4from
Line
Count
Source
1299
4
    fn from(a: DigestItemRef<'a>) -> DigestItem {
1300
4
        match a {
1301
0
            DigestItemRef::AuraPreDigest(v) => DigestItem::AuraPreDigest(v),
1302
0
            DigestItemRef::AuraConsensus(v) => DigestItem::AuraConsensus(v.into()),
1303
0
            DigestItemRef::AuraSeal(v) => {
1304
0
                let mut seal = [0; 64];
1305
0
                seal.copy_from_slice(v);
1306
0
                DigestItem::AuraSeal(seal)
1307
            }
1308
2
            DigestItemRef::BabePreDigest(v) => DigestItem::BabePreDigest(v.into()),
1309
0
            DigestItemRef::BabeConsensus(v) => DigestItem::BabeConsensus(v.into()),
1310
2
            DigestItemRef::BabeSeal(v) => {
1311
2
                let mut seal = [0; 64];
1312
2
                seal.copy_from_slice(v);
1313
2
                DigestItem::BabeSeal(seal)
1314
            }
1315
0
            DigestItemRef::GrandpaConsensus(v) => DigestItem::GrandpaConsensus(v.into()),
1316
0
            DigestItemRef::UnknownConsensus { engine, opaque } => DigestItem::UnknownConsensus {
1317
0
                opaque: opaque.to_vec(),
1318
0
                engine,
1319
0
            },
1320
0
            DigestItemRef::UnknownSeal { engine, opaque } => DigestItem::UnknownSeal {
1321
0
                opaque: opaque.to_vec(),
1322
0
                engine,
1323
0
            },
1324
0
            DigestItemRef::UnknownPreRuntime { engine, opaque } => DigestItem::UnknownPreRuntime {
1325
0
                opaque: opaque.to_vec(),
1326
0
                engine,
1327
0
            },
1328
0
            DigestItemRef::Other(v) => DigestItem::Other(v.to_vec()),
1329
0
            DigestItemRef::RuntimeEnvironmentUpdated => DigestItem::RuntimeEnvironmentUpdated,
1330
        }
1331
4
    }
Unexecuted instantiation: _RNvXsc_NtCsc1ywvx6YAnK_7smoldot6headerNtB5_10DigestItemINtNtCs1p5UDGgVI4d_4core7convert4FromNtB5_13DigestItemRefE4from
1332
}
1333
1334
/// Decodes a single digest log item. On success, returns the item and the data that remains
1335
/// after the item.
1336
175
fn decode_item(
1337
175
    mut slice: &[u8],
1338
175
    block_number_bytes: usize,
1339
175
) -> Result<(DigestItemRef, &[u8]), Error> {
1340
175
    let index = *slice.first().ok_or(Error::TooShort)
?0
;
1341
175
    slice = &slice[1..];
1342
1343
175
    match index {
1344
175
        4..=6 => {
1345
175
            if slice.len() < 4 {
1346
0
                return Err(Error::TooShort);
1347
175
            }
1348
1349
175
            let engine_id: &[u8; 4] = TryFrom::try_from(&slice[..4]).unwrap();
1350
175
            slice = &slice[4..];
1351
1352
175
            let (mut slice, len) =
1353
175
                crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(slice)
1354
175
                    .map_err(|_| Error::DigestItemLenDecodeError)
?0
;
1355
1356
175
            if slice.len() < len {
1357
0
                return Err(Error::TooShort);
1358
175
            }
1359
1360
175
            let content = &slice[..len];
1361
175
            slice = &slice[len..];
1362
1363
175
            let 
item174
= decode_item_from_parts(index, block_number_bytes, engine_id, content)
?1
;
1364
174
            Ok((item, slice))
1365
        }
1366
0
        8 => Ok((DigestItemRef::RuntimeEnvironmentUpdated, slice)),
1367
        0 => {
1368
0
            let (mut slice, len) =
1369
0
                crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(slice)
1370
0
                    .map_err(|_| Error::DigestItemLenDecodeError)?;
1371
1372
0
            if slice.len() < len {
1373
0
                return Err(Error::TooShort);
1374
0
            }
1375
1376
0
            let content = &slice[..len];
1377
0
            slice = &slice[len..];
1378
1379
0
            let item = DigestItemRef::Other(content);
1380
1381
0
            Ok((item, slice))
1382
        }
1383
0
        ty => Err(Error::UnknownDigestLogType { unknown_type: ty }),
1384
    }
1385
175
}
_RNvNtCsjlkOsLH0Zfj_7smoldot6header11decode_item
Line
Count
Source
1336
175
fn decode_item(
1337
175
    mut slice: &[u8],
1338
175
    block_number_bytes: usize,
1339
175
) -> Result<(DigestItemRef, &[u8]), Error> {
1340
175
    let index = *slice.first().ok_or(Error::TooShort)
?0
;
1341
175
    slice = &slice[1..];
1342
1343
175
    match index {
1344
175
        4..=6 => {
1345
175
            if slice.len() < 4 {
1346
0
                return Err(Error::TooShort);
1347
175
            }
1348
1349
175
            let engine_id: &[u8; 4] = TryFrom::try_from(&slice[..4]).unwrap();
1350
175
            slice = &slice[4..];
1351
1352
175
            let (mut slice, len) =
1353
175
                crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(slice)
1354
175
                    .map_err(|_| Error::DigestItemLenDecodeError)
?0
;
1355
1356
175
            if slice.len() < len {
1357
0
                return Err(Error::TooShort);
1358
175
            }
1359
1360
175
            let content = &slice[..len];
1361
175
            slice = &slice[len..];
1362
1363
175
            let 
item174
= decode_item_from_parts(index, block_number_bytes, engine_id, content)
?1
;
1364
174
            Ok((item, slice))
1365
        }
1366
0
        8 => Ok((DigestItemRef::RuntimeEnvironmentUpdated, slice)),
1367
        0 => {
1368
0
            let (mut slice, len) =
1369
0
                crate::util::nom_scale_compact_usize::<nom::error::Error<&[u8]>>(slice)
1370
0
                    .map_err(|_| Error::DigestItemLenDecodeError)?;
1371
1372
0
            if slice.len() < len {
1373
0
                return Err(Error::TooShort);
1374
0
            }
1375
1376
0
            let content = &slice[..len];
1377
0
            slice = &slice[len..];
1378
1379
0
            let item = DigestItemRef::Other(content);
1380
1381
0
            Ok((item, slice))
1382
        }
1383
0
        ty => Err(Error::UnknownDigestLogType { unknown_type: ty }),
1384
    }
1385
175
}
Unexecuted instantiation: _RNvNtCsc1ywvx6YAnK_7smoldot6header11decode_item
1386
1387
/// When we know the index, engine id, and content of an item, we can finish decoding.
1388
175
fn decode_item_from_parts<'a>(
1389
175
    index: u8,
1390
175
    block_number_bytes: usize,
1391
175
    engine_id: &'a [u8; 4],
1392
175
    content: &'a [u8],
1393
175
) -> Result<DigestItemRef<'a>, Error> {
1394
175
    Ok(match (index, engine_id) {
1395
0
        (_, b"pow_") => return Err(Error::PowIdeologicallyNotSupported),
1396
        // 4 = Consensus
1397
1
        (4, b"aura") => DigestItemRef::AuraConsensus(AuraConsensusLogRef::from_slice(content)?),
1398
51
        (4, b"BABE") => DigestItemRef::BabeConsensus(BabeConsensusLogRef::from_slice(content)
?0
),
1399
25
        (4, b"FRNK") => DigestItemRef::GrandpaConsensus(GrandpaConsensusLogRef::from_slice(
1400
25
            content,
1401
25
            block_number_bytes,
1402
0
        )?),
1403
1
        (4, engine) => DigestItemRef::UnknownConsensus {
1404
1
            engine: *engine,
1405
1
            opaque: content,
1406
1
        },
1407
        // 5 = Seal
1408
        (5, b"aura") => DigestItemRef::AuraSeal({
1409
0
            TryFrom::try_from(content).map_err(|_| Error::BadAuraSealLength)?
1410
        }),
1411
        (5, b"BABE") => DigestItemRef::BabeSeal({
1412
41
            TryFrom::try_from(content).map_err(|_| Error::BadBabeSealLength)
?0
1413
        }),
1414
0
        (5, engine) => DigestItemRef::UnknownSeal {
1415
0
            engine: *engine,
1416
0
            opaque: content,
1417
0
        },
1418
        // 6 = PreRuntime
1419
1
        (6, b"aura") => DigestItemRef::AuraPreDigest(AuraPreDigest::from_slice(content)
?0
),
1420
55
        (6, b"BABE") => DigestItemRef::BabePreDigest(BabePreDigestRef::from_slice(content)
?0
),
1421
0
        (6, engine) => DigestItemRef::UnknownPreRuntime {
1422
0
            engine: *engine,
1423
0
            opaque: content,
1424
0
        },
1425
0
        _ => unreachable!(),
1426
    })
1427
175
}
_RNvNtCsjlkOsLH0Zfj_7smoldot6header22decode_item_from_parts
Line
Count
Source
1388
175
fn decode_item_from_parts<'a>(
1389
175
    index: u8,
1390
175
    block_number_bytes: usize,
1391
175
    engine_id: &'a [u8; 4],
1392
175
    content: &'a [u8],
1393
175
) -> Result<DigestItemRef<'a>, Error> {
1394
175
    Ok(match (index, engine_id) {
1395
0
        (_, b"pow_") => return Err(Error::PowIdeologicallyNotSupported),
1396
        // 4 = Consensus
1397
1
        (4, b"aura") => DigestItemRef::AuraConsensus(AuraConsensusLogRef::from_slice(content)?),
1398
51
        (4, b"BABE") => DigestItemRef::BabeConsensus(BabeConsensusLogRef::from_slice(content)
?0
),
1399
25
        (4, b"FRNK") => DigestItemRef::GrandpaConsensus(GrandpaConsensusLogRef::from_slice(
1400
25
            content,
1401
25
            block_number_bytes,
1402
0
        )?),
1403
1
        (4, engine) => DigestItemRef::UnknownConsensus {
1404
1
            engine: *engine,
1405
1
            opaque: content,
1406
1
        },
1407
        // 5 = Seal
1408
        (5, b"aura") => DigestItemRef::AuraSeal({
1409
0
            TryFrom::try_from(content).map_err(|_| Error::BadAuraSealLength)?
1410
        }),
1411
        (5, b"BABE") => DigestItemRef::BabeSeal({
1412
41
            TryFrom::try_from(content).map_err(|_| Error::BadBabeSealLength)
?0
1413
        }),
1414
0
        (5, engine) => DigestItemRef::UnknownSeal {
1415
0
            engine: *engine,
1416
0
            opaque: content,
1417
0
        },
1418
        // 6 = PreRuntime
1419
1
        (6, b"aura") => DigestItemRef::AuraPreDigest(AuraPreDigest::from_slice(content)
?0
),
1420
55
        (6, b"BABE") => DigestItemRef::BabePreDigest(BabePreDigestRef::from_slice(content)
?0
),
1421
0
        (6, engine) => DigestItemRef::UnknownPreRuntime {
1422
0
            engine: *engine,
1423
0
            opaque: content,
1424
0
        },
1425
0
        _ => unreachable!(),
1426
    })
1427
175
}
Unexecuted instantiation: _RNvNtCsc1ywvx6YAnK_7smoldot6header22decode_item_from_parts