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/executor/host/runtime_version.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
//! Wasm runtimes can optionally contain a custom section (as defined in the official WebAssembly
19
//! core specification).
20
//!
21
//! This module is dedicated to finding the custom sections containing the runtime version.
22
23
use crate::executor::host;
24
25
use alloc::vec::Vec;
26
use core::{fmt, ops, str};
27
28
pub use super::TrieEntryVersion;
29
30
/// Tries to find the custom section containing the runtime version and checks its validity.
31
152
pub fn find_embedded_runtime_version(
32
152
    binary_wasm_module: &[u8],
33
152
) -> Result<Option<CoreVersion>, FindEmbeddedRuntimeVersionError> {
34
147
    let (runtime_version_content, runtime_apis_content) =
35
152
        match find_encoded_embedded_runtime_version_apis(binary_wasm_module) {
36
            Ok(EmbeddedRuntimeVersionApis {
37
147
                runtime_version_content: Some(v),
38
147
                runtime_apis_content: Some(a),
39
147
            }) => (v, a),
40
            Ok(EmbeddedRuntimeVersionApis {
41
                runtime_version_content: None,
42
                runtime_apis_content: None,
43
1
            }) => return Ok(None),
44
2
            Ok(_) => return Err(FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch),
45
2
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::FindSections(err)),
46
        };
47
48
147
    let mut decoded_runtime_version = match decode(runtime_version_content) {
49
147
        Ok(d) => d,
50
0
        Err(()) => return Err(FindEmbeddedRuntimeVersionError::RuntimeVersionDecode),
51
    };
52
53
    decoded_runtime_version.apis =
54
147
        match CoreVersionApisRefIter::from_slice_no_length(runtime_apis_content) {
55
147
            Ok(d) => d,
56
0
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)),
57
        };
58
59
147
    Ok(Some(CoreVersion(
60
147
        decoded_runtime_version.scale_encoding_vec(),
61
147
    )))
62
152
}
_RNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version29find_embedded_runtime_version
Line
Count
Source
31
66
pub fn find_embedded_runtime_version(
32
66
    binary_wasm_module: &[u8],
33
66
) -> Result<Option<CoreVersion>, FindEmbeddedRuntimeVersionError> {
34
61
    let (runtime_version_content, runtime_apis_content) =
35
66
        match find_encoded_embedded_runtime_version_apis(binary_wasm_module) {
36
            Ok(EmbeddedRuntimeVersionApis {
37
61
                runtime_version_content: Some(v),
38
61
                runtime_apis_content: Some(a),
39
61
            }) => (v, a),
40
            Ok(EmbeddedRuntimeVersionApis {
41
                runtime_version_content: None,
42
                runtime_apis_content: None,
43
1
            }) => return Ok(None),
44
2
            Ok(_) => return Err(FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch),
45
2
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::FindSections(err)),
46
        };
47
48
61
    let mut decoded_runtime_version = match decode(runtime_version_content) {
49
61
        Ok(d) => d,
50
0
        Err(()) => return Err(FindEmbeddedRuntimeVersionError::RuntimeVersionDecode),
51
    };
52
53
    decoded_runtime_version.apis =
54
61
        match CoreVersionApisRefIter::from_slice_no_length(runtime_apis_content) {
55
61
            Ok(d) => d,
56
0
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)),
57
        };
58
59
61
    Ok(Some(CoreVersion(
60
61
        decoded_runtime_version.scale_encoding_vec(),
61
61
    )))
62
66
}
_RNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version29find_embedded_runtime_version
Line
Count
Source
31
86
pub fn find_embedded_runtime_version(
32
86
    binary_wasm_module: &[u8],
33
86
) -> Result<Option<CoreVersion>, FindEmbeddedRuntimeVersionError> {
34
86
    let (runtime_version_content, runtime_apis_content) =
35
86
        match find_encoded_embedded_runtime_version_apis(binary_wasm_module) {
36
            Ok(EmbeddedRuntimeVersionApis {
37
86
                runtime_version_content: Some(v),
38
86
                runtime_apis_content: Some(a),
39
86
            }) => (v, a),
40
            Ok(EmbeddedRuntimeVersionApis {
41
                runtime_version_content: None,
42
                runtime_apis_content: None,
43
0
            }) => return Ok(None),
44
0
            Ok(_) => return Err(FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch),
45
0
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::FindSections(err)),
46
        };
47
48
86
    let mut decoded_runtime_version = match decode(runtime_version_content) {
49
86
        Ok(d) => d,
50
0
        Err(()) => return Err(FindEmbeddedRuntimeVersionError::RuntimeVersionDecode),
51
    };
52
53
    decoded_runtime_version.apis =
54
86
        match CoreVersionApisRefIter::from_slice_no_length(runtime_apis_content) {
55
86
            Ok(d) => d,
56
0
            Err(err) => return Err(FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)),
57
        };
58
59
86
    Ok(Some(CoreVersion(
60
86
        decoded_runtime_version.scale_encoding_vec(),
61
86
    )))
62
86
}
63
64
/// Error returned by [`find_embedded_runtime_version`].
65
#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
66
pub enum FindEmbeddedRuntimeVersionError {
67
    /// Error while finding the custom section.
68
    #[display("{_0}")]
69
    FindSections(FindEncodedEmbeddedRuntimeVersionApisError),
70
    /// Only one of the two desired custom sections is present.
71
    CustomSectionsPresenceMismatch,
72
    /// Error while decoding the runtime version.
73
    RuntimeVersionDecode,
74
    /// Error while decoding the runtime APIs.
75
    #[display("{_0}")]
76
    RuntimeApisDecode(CoreVersionApisFromSliceErr),
77
}
78
79
/// Returns by [`find_encoded_embedded_runtime_version_apis`].
80
#[derive(Debug, Copy, Clone)]
81
pub struct EmbeddedRuntimeVersionApis<'a> {
82
    /// Content of the `runtime_version` section, if any was found.
83
    pub runtime_version_content: Option<&'a [u8]>,
84
    /// Content of the `runtime_apis` section, if any was found.
85
    pub runtime_apis_content: Option<&'a [u8]>,
86
}
87
88
/// Tries to find the custom sections containing the runtime version and APIs.
89
///
90
/// This function does not attempt to decode the content of the custom sections.
91
152
pub fn find_encoded_embedded_runtime_version_apis(
92
152
    binary_wasm_module: &[u8],
93
152
) -> Result<EmbeddedRuntimeVersionApis, FindEncodedEmbeddedRuntimeVersionApisError> {
94
152
    let mut parser =
95
152
        nom::combinator::all_consuming(nom::combinator::complete(nom::sequence::preceded(
96
152
            (
97
152
                nom::bytes::streaming::tag(&b"\0asm"[..]),
98
152
                nom::bytes::streaming::tag(&[0x1, 0x0, 0x0, 0x0][..]),
99
152
            ),
100
152
            nom::multi::fold_many0(
101
152
                nom::combinator::complete(wasm_section),
102
150
                || (None, None),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apis0B9_
Line
Count
Source
102
64
                || (None, None),
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apis0B9_
Line
Count
Source
102
86
                || (None, None),
103
1.70k
                move |prev_found, in_section| {
104
1.70k
                    match (prev_found, in_section) {
105
                        // Not a custom section.
106
1.21k
                        (prev_found, None) => prev_found,
107
108
                        // We found a custom section with a name that interests us, but we already
109
                        // parsed a custom section with that same name earlier. Continue with the
110
                        // value that was parsed earlier.
111
                        (
112
0
                            prev_found @ (Some(_), _),
113
                            Some(WasmSection {
114
235
                                name: b"runtime_version",
115
                                ..
116
                            }),
117
0
                        ) => prev_found,
118
                        (
119
0
                            prev_found @ (_, Some(_)),
120
                            Some(WasmSection {
121
278
                                name: b"runtime_apis",
122
                                ..
123
                            }),
124
0
                        ) => prev_found,
125
126
                        // Found a custom section that interests us, and we didn't find one
127
                        // before.
128
                        (
129
147
                            (None, prev_rt_apis),
130
                            Some(WasmSection {
131
253
                                name: b"runtime_version",
132
147
                                content,
133
                            }),
134
147
                        ) => (Some(content), prev_rt_apis),
135
                        (
136
149
                            (prev_rt_version, None),
137
                            Some(WasmSection {
138
156
                                name: b"runtime_apis",
139
149
                                content,
140
                            }),
141
149
                        ) => (prev_rt_version, Some(content)),
142
143
                        // Found a custom section with a name that doesn't interest us.
144
192
                        (prev_found, Some(_)) => prev_found,
145
                    }
146
1.70k
                },
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apiss_0B9_
Line
Count
Source
103
582
                move |prev_found, in_section| {
104
582
                    match (prev_found, in_section) {
105
                        // Not a custom section.
106
438
                        (prev_found, None) => prev_found,
107
108
                        // We found a custom section with a name that interests us, but we already
109
                        // parsed a custom section with that same name earlier. Continue with the
110
                        // value that was parsed earlier.
111
                        (
112
0
                            prev_found @ (Some(_), _),
113
                            Some(WasmSection {
114
63
                                name: b"runtime_version",
115
                                ..
116
                            }),
117
0
                        ) => prev_found,
118
                        (
119
0
                            prev_found @ (_, Some(_)),
120
                            Some(WasmSection {
121
20
                                name: b"runtime_apis",
122
                                ..
123
                            }),
124
0
                        ) => prev_found,
125
126
                        // Found a custom section that interests us, and we didn't find one
127
                        // before.
128
                        (
129
61
                            (None, prev_rt_apis),
130
                            Some(WasmSection {
131
81
                                name: b"runtime_version",
132
61
                                content,
133
                            }),
134
61
                        ) => (Some(content), prev_rt_apis),
135
                        (
136
63
                            (prev_rt_version, None),
137
                            Some(WasmSection {
138
70
                                name: b"runtime_apis",
139
63
                                content,
140
                            }),
141
63
                        ) => (prev_rt_version, Some(content)),
142
143
                        // Found a custom section with a name that doesn't interest us.
144
20
                        (prev_found, Some(_)) => prev_found,
145
                    }
146
582
                },
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apiss_0B9_
Line
Count
Source
103
1.11k
                move |prev_found, in_section| {
104
1.11k
                    match (prev_found, in_section) {
105
                        // Not a custom section.
106
774
                        (prev_found, None) => prev_found,
107
108
                        // We found a custom section with a name that interests us, but we already
109
                        // parsed a custom section with that same name earlier. Continue with the
110
                        // value that was parsed earlier.
111
                        (
112
0
                            prev_found @ (Some(_), _),
113
                            Some(WasmSection {
114
172
                                name: b"runtime_version",
115
                                ..
116
                            }),
117
0
                        ) => prev_found,
118
                        (
119
0
                            prev_found @ (_, Some(_)),
120
                            Some(WasmSection {
121
258
                                name: b"runtime_apis",
122
                                ..
123
                            }),
124
0
                        ) => prev_found,
125
126
                        // Found a custom section that interests us, and we didn't find one
127
                        // before.
128
                        (
129
86
                            (None, prev_rt_apis),
130
                            Some(WasmSection {
131
172
                                name: b"runtime_version",
132
86
                                content,
133
                            }),
134
86
                        ) => (Some(content), prev_rt_apis),
135
                        (
136
86
                            (prev_rt_version, None),
137
                            Some(WasmSection {
138
86
                                name: b"runtime_apis",
139
86
                                content,
140
                            }),
141
86
                        ) => (prev_rt_version, Some(content)),
142
143
                        // Found a custom section with a name that doesn't interest us.
144
172
                        (prev_found, Some(_)) => prev_found,
145
                    }
146
1.11k
                },
147
            ),
148
        )));
149
150
150
    let (runtime_version_content, runtime_apis_content) =
151
152
        match nom::Parser::parse(&mut parser, binary_wasm_module) {
152
150
            Ok((_, content)) => content,
153
2
            Err(_) => return Err(FindEncodedEmbeddedRuntimeVersionApisError::FailedToParse),
154
        };
155
156
150
    Ok(EmbeddedRuntimeVersionApis {
157
150
        runtime_version_content,
158
150
        runtime_apis_content,
159
150
    })
160
152
}
_RNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apis
Line
Count
Source
91
66
pub fn find_encoded_embedded_runtime_version_apis(
92
66
    binary_wasm_module: &[u8],
93
66
) -> Result<EmbeddedRuntimeVersionApis, FindEncodedEmbeddedRuntimeVersionApisError> {
94
66
    let mut parser =
95
66
        nom::combinator::all_consuming(nom::combinator::complete(nom::sequence::preceded(
96
66
            (
97
66
                nom::bytes::streaming::tag(&b"\0asm"[..]),
98
66
                nom::bytes::streaming::tag(&[0x1, 0x0, 0x0, 0x0][..]),
99
66
            ),
100
66
            nom::multi::fold_many0(
101
66
                nom::combinator::complete(wasm_section),
102
                || (None, None),
103
                move |prev_found, in_section| {
104
                    match (prev_found, in_section) {
105
                        // Not a custom section.
106
                        (prev_found, None) => prev_found,
107
108
                        // We found a custom section with a name that interests us, but we already
109
                        // parsed a custom section with that same name earlier. Continue with the
110
                        // value that was parsed earlier.
111
                        (
112
                            prev_found @ (Some(_), _),
113
                            Some(WasmSection {
114
                                name: b"runtime_version",
115
                                ..
116
                            }),
117
                        ) => prev_found,
118
                        (
119
                            prev_found @ (_, Some(_)),
120
                            Some(WasmSection {
121
                                name: b"runtime_apis",
122
                                ..
123
                            }),
124
                        ) => prev_found,
125
126
                        // Found a custom section that interests us, and we didn't find one
127
                        // before.
128
                        (
129
                            (None, prev_rt_apis),
130
                            Some(WasmSection {
131
                                name: b"runtime_version",
132
                                content,
133
                            }),
134
                        ) => (Some(content), prev_rt_apis),
135
                        (
136
                            (prev_rt_version, None),
137
                            Some(WasmSection {
138
                                name: b"runtime_apis",
139
                                content,
140
                            }),
141
                        ) => (prev_rt_version, Some(content)),
142
143
                        // Found a custom section with a name that doesn't interest us.
144
                        (prev_found, Some(_)) => prev_found,
145
                    }
146
                },
147
            ),
148
        )));
149
150
64
    let (runtime_version_content, runtime_apis_content) =
151
66
        match nom::Parser::parse(&mut parser, binary_wasm_module) {
152
64
            Ok((_, content)) => content,
153
2
            Err(_) => return Err(FindEncodedEmbeddedRuntimeVersionApisError::FailedToParse),
154
        };
155
156
64
    Ok(EmbeddedRuntimeVersionApis {
157
64
        runtime_version_content,
158
64
        runtime_apis_content,
159
64
    })
160
66
}
_RNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version42find_encoded_embedded_runtime_version_apis
Line
Count
Source
91
86
pub fn find_encoded_embedded_runtime_version_apis(
92
86
    binary_wasm_module: &[u8],
93
86
) -> Result<EmbeddedRuntimeVersionApis, FindEncodedEmbeddedRuntimeVersionApisError> {
94
86
    let mut parser =
95
86
        nom::combinator::all_consuming(nom::combinator::complete(nom::sequence::preceded(
96
86
            (
97
86
                nom::bytes::streaming::tag(&b"\0asm"[..]),
98
86
                nom::bytes::streaming::tag(&[0x1, 0x0, 0x0, 0x0][..]),
99
86
            ),
100
86
            nom::multi::fold_many0(
101
86
                nom::combinator::complete(wasm_section),
102
                || (None, None),
103
                move |prev_found, in_section| {
104
                    match (prev_found, in_section) {
105
                        // Not a custom section.
106
                        (prev_found, None) => prev_found,
107
108
                        // We found a custom section with a name that interests us, but we already
109
                        // parsed a custom section with that same name earlier. Continue with the
110
                        // value that was parsed earlier.
111
                        (
112
                            prev_found @ (Some(_), _),
113
                            Some(WasmSection {
114
                                name: b"runtime_version",
115
                                ..
116
                            }),
117
                        ) => prev_found,
118
                        (
119
                            prev_found @ (_, Some(_)),
120
                            Some(WasmSection {
121
                                name: b"runtime_apis",
122
                                ..
123
                            }),
124
                        ) => prev_found,
125
126
                        // Found a custom section that interests us, and we didn't find one
127
                        // before.
128
                        (
129
                            (None, prev_rt_apis),
130
                            Some(WasmSection {
131
                                name: b"runtime_version",
132
                                content,
133
                            }),
134
                        ) => (Some(content), prev_rt_apis),
135
                        (
136
                            (prev_rt_version, None),
137
                            Some(WasmSection {
138
                                name: b"runtime_apis",
139
                                content,
140
                            }),
141
                        ) => (prev_rt_version, Some(content)),
142
143
                        // Found a custom section with a name that doesn't interest us.
144
                        (prev_found, Some(_)) => prev_found,
145
                    }
146
                },
147
            ),
148
        )));
149
150
86
    let (runtime_version_content, runtime_apis_content) =
151
86
        match nom::Parser::parse(&mut parser, binary_wasm_module) {
152
86
            Ok((_, content)) => content,
153
0
            Err(_) => return Err(FindEncodedEmbeddedRuntimeVersionApisError::FailedToParse),
154
        };
155
156
86
    Ok(EmbeddedRuntimeVersionApis {
157
86
        runtime_version_content,
158
86
        runtime_apis_content,
159
86
    })
160
86
}
161
162
/// Error returned by [`find_encoded_embedded_runtime_version_apis`].
163
#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
164
pub enum FindEncodedEmbeddedRuntimeVersionApisError {
165
    /// Failed to parse Wasm binary.
166
    FailedToParse,
167
}
168
169
/// Error while executing `Core_version`.
170
#[derive(Debug, derive_more::Display, derive_more::Error, Clone)]
171
pub enum CoreVersionError {
172
    /// Error while decoding the output.
173
    Decode,
174
    /// Error while starting the execution of the `Core_version` function.
175
    #[display("Error while starting the execution of the `Core_version` function: {_0}")]
176
    Start(host::StartErr),
177
    /// Error during the execution of the `Core_version` function.
178
    #[display("Error during the execution of the `Core_version` function: {_0}")]
179
    Run(host::Error),
180
    /// `Core_version` used a host function that is forbidden in this context.
181
    ForbiddenHostFunction,
182
}
183
184
/// Buffer storing the SCALE-encoded core version.
185
#[derive(Debug, Clone, PartialEq, Eq)]
186
pub struct CoreVersion(Vec<u8>);
187
188
impl CoreVersion {
189
3
    pub fn from_slice(input: Vec<u8>) -> Result<Self, Vec<u8>> {
190
3
        if decode(&input).is_err() {
191
0
            return Err(input);
192
3
        }
193
194
3
        Ok(CoreVersion(input))
195
3
    }
_RNvMNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB2_11CoreVersion10from_slice
Line
Count
Source
189
3
    pub fn from_slice(input: Vec<u8>) -> Result<Self, Vec<u8>> {
190
3
        if decode(&input).is_err() {
191
0
            return Err(input);
192
3
        }
193
194
3
        Ok(CoreVersion(input))
195
3
    }
Unexecuted instantiation: _RNvMNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB2_11CoreVersion10from_slice
196
197
233
    pub fn decode(&self) -> CoreVersionRef {
198
233
        decode(&self.0).unwrap()
199
233
    }
_RNvMNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB2_11CoreVersion6decode
Line
Count
Source
197
21
    pub fn decode(&self) -> CoreVersionRef {
198
21
        decode(&self.0).unwrap()
199
21
    }
_RNvMNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB2_11CoreVersion6decode
Line
Count
Source
197
212
    pub fn decode(&self) -> CoreVersionRef {
198
212
        decode(&self.0).unwrap()
199
212
    }
200
}
201
202
impl AsRef<[u8]> for CoreVersion {
203
0
    fn as_ref(&self) -> &[u8] {
204
0
        &self.0
205
0
    }
Unexecuted instantiation: _RNvXs_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB4_11CoreVersionINtNtCs1p5UDGgVI4d_4core7convert5AsRefShE6as_ref
Unexecuted instantiation: _RNvXs_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB4_11CoreVersionINtNtCs1p5UDGgVI4d_4core7convert5AsRefShE6as_ref
206
}
207
208
/// Runtime specification, once decoded.
209
// TODO: explain these fields
210
#[derive(Debug, Clone, PartialEq, Eq)]
211
pub struct CoreVersionRef<'a> {
212
    pub spec_name: &'a str,
213
    pub impl_name: &'a str,
214
    pub authoring_version: u32,
215
    pub spec_version: u32,
216
    pub impl_version: u32,
217
218
    /// List of "API"s that the runtime supports.
219
    ///
220
    /// Each API corresponds to a certain list of runtime entry points.
221
    ///
222
    /// This field can thus be used in order to determine which runtime entry points are
223
    /// available.
224
    pub apis: CoreVersionApisRefIter<'a>,
225
226
    /// Arbitrary version number corresponding to the transactions encoding version.
227
    ///
228
    /// Whenever this version number changes, all transactions encoding generated earlier are
229
    /// invalidated and should be regenerated.
230
    ///
231
    /// Older versions of Substrate didn't provide this field. `None` if the field is missing.
232
    pub transaction_version: Option<u32>,
233
234
    /// Version number of the state trie encoding version.
235
    ///
236
    /// Version 0 corresponds to a different trie encoding than version 1.
237
    ///
238
    /// This field has been added to Substrate on 24th December 2021. Older versions of Substrate
239
    /// didn't provide this field, in which case it will contain `None`.
240
    ///
241
    /// `None` should be interpreted the same way as `Some(0)`.
242
    pub state_version: Option<TrieEntryVersion>,
243
}
244
245
impl CoreVersionRef<'_> {
246
    /// Returns the SCALE encoding of this data structure.
247
147
    pub fn scale_encoding_vec(&self) -> Vec<u8> {
248
        // See https://spec.polkadot.network/#defn-rt-core-version
249
250
147
        let num_apis = self.apis.clone().count();
251
252
        // Reserve enough capacity for the various calls to `extend` below.
253
        // This is only a reasonable estimate, as we assume 2 bytes for the SCALE-compact-encoded
254
        // lengths. In the case of very very very long names, the capacity might be too low.
255
147
        let mut out = Vec::<u8>::with_capacity(
256
147
            2 + self.spec_name.len() + 2 + self.impl_name.len() + 4 + 4 + 4 + num_apis * 12 + 4 + 1,
257
        );
258
259
147
        out.extend(crate::util::encode_scale_compact_usize(self.spec_name.len()).as_ref());
260
147
        out.extend(self.spec_name.as_bytes());
261
262
147
        out.extend(crate::util::encode_scale_compact_usize(self.impl_name.len()).as_ref());
263
147
        out.extend(self.impl_name.as_bytes());
264
265
147
        out.extend(self.authoring_version.to_le_bytes());
266
147
        out.extend(self.spec_version.to_le_bytes());
267
147
        out.extend(self.impl_version.to_le_bytes());
268
269
147
        out.extend(crate::util::encode_scale_compact_usize(num_apis).as_ref());
270
945
        for api in 
self.apis147
.
clone147
() {
271
945
            out.extend(api.name_hash);
272
945
            out.extend(api.version.to_le_bytes());
273
945
        }
274
275
147
        if let Some(transaction_version) = self.transaction_version {
276
147
            out.extend(transaction_version.to_le_bytes());
277
147
        
}0
278
279
        // TODO: it's not supposed to be allowed to have a CoreVersionRef with a state_version but no transaction_version; the CoreVersionRef struct lets you do that because it was initially designed only for decoding
280
147
        if let Some(
state_version61
) = self.state_version {
281
61
            out.extend(u8::from(state_version).to_le_bytes());
282
86
        }
283
284
147
        out
285
147
    }
_RNvMs0_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_14CoreVersionRef18scale_encoding_vec
Line
Count
Source
247
61
    pub fn scale_encoding_vec(&self) -> Vec<u8> {
248
        // See https://spec.polkadot.network/#defn-rt-core-version
249
250
61
        let num_apis = self.apis.clone().count();
251
252
        // Reserve enough capacity for the various calls to `extend` below.
253
        // This is only a reasonable estimate, as we assume 2 bytes for the SCALE-compact-encoded
254
        // lengths. In the case of very very very long names, the capacity might be too low.
255
61
        let mut out = Vec::<u8>::with_capacity(
256
61
            2 + self.spec_name.len() + 2 + self.impl_name.len() + 4 + 4 + 4 + num_apis * 12 + 4 + 1,
257
        );
258
259
61
        out.extend(crate::util::encode_scale_compact_usize(self.spec_name.len()).as_ref());
260
61
        out.extend(self.spec_name.as_bytes());
261
262
61
        out.extend(crate::util::encode_scale_compact_usize(self.impl_name.len()).as_ref());
263
61
        out.extend(self.impl_name.as_bytes());
264
265
61
        out.extend(self.authoring_version.to_le_bytes());
266
61
        out.extend(self.spec_version.to_le_bytes());
267
61
        out.extend(self.impl_version.to_le_bytes());
268
269
61
        out.extend(crate::util::encode_scale_compact_usize(num_apis).as_ref());
270
85
        for api in 
self.apis61
.
clone61
() {
271
85
            out.extend(api.name_hash);
272
85
            out.extend(api.version.to_le_bytes());
273
85
        }
274
275
61
        if let Some(transaction_version) = self.transaction_version {
276
61
            out.extend(transaction_version.to_le_bytes());
277
61
        
}0
278
279
        // TODO: it's not supposed to be allowed to have a CoreVersionRef with a state_version but no transaction_version; the CoreVersionRef struct lets you do that because it was initially designed only for decoding
280
61
        if let Some(state_version) = self.state_version {
281
61
            out.extend(u8::from(state_version).to_le_bytes());
282
61
        
}0
283
284
61
        out
285
61
    }
_RNvMs0_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_14CoreVersionRef18scale_encoding_vec
Line
Count
Source
247
86
    pub fn scale_encoding_vec(&self) -> Vec<u8> {
248
        // See https://spec.polkadot.network/#defn-rt-core-version
249
250
86
        let num_apis = self.apis.clone().count();
251
252
        // Reserve enough capacity for the various calls to `extend` below.
253
        // This is only a reasonable estimate, as we assume 2 bytes for the SCALE-compact-encoded
254
        // lengths. In the case of very very very long names, the capacity might be too low.
255
86
        let mut out = Vec::<u8>::with_capacity(
256
86
            2 + self.spec_name.len() + 2 + self.impl_name.len() + 4 + 4 + 4 + num_apis * 12 + 4 + 1,
257
        );
258
259
86
        out.extend(crate::util::encode_scale_compact_usize(self.spec_name.len()).as_ref());
260
86
        out.extend(self.spec_name.as_bytes());
261
262
86
        out.extend(crate::util::encode_scale_compact_usize(self.impl_name.len()).as_ref());
263
86
        out.extend(self.impl_name.as_bytes());
264
265
86
        out.extend(self.authoring_version.to_le_bytes());
266
86
        out.extend(self.spec_version.to_le_bytes());
267
86
        out.extend(self.impl_version.to_le_bytes());
268
269
86
        out.extend(crate::util::encode_scale_compact_usize(num_apis).as_ref());
270
860
        for api in 
self.apis86
.
clone86
() {
271
860
            out.extend(api.name_hash);
272
860
            out.extend(api.version.to_le_bytes());
273
860
        }
274
275
86
        if let Some(transaction_version) = self.transaction_version {
276
86
            out.extend(transaction_version.to_le_bytes());
277
86
        
}0
278
279
        // TODO: it's not supposed to be allowed to have a CoreVersionRef with a state_version but no transaction_version; the CoreVersionRef struct lets you do that because it was initially designed only for decoding
280
86
        if let Some(
state_version0
) = self.state_version {
281
0
            out.extend(u8::from(state_version).to_le_bytes());
282
86
        }
283
284
86
        out
285
86
    }
286
}
287
288
/// Iterator to a list of APIs. See [`CoreVersionRef::apis`].
289
#[derive(Clone)]
290
pub struct CoreVersionApisRefIter<'a> {
291
    inner: &'a [u8],
292
}
293
294
impl<'a> CoreVersionApisRefIter<'a> {
295
    /// Decodes a SCALE-encoded list of APIs.
296
    ///
297
    /// The input slice isn't expected to contain the number of APIs.
298
147
    pub fn from_slice_no_length(input: &'a [u8]) -> Result<Self, CoreVersionApisFromSliceErr> {
299
147
        let result: Result<_, nom::Err<nom::error::Error<&[u8]>>> = nom::Parser::parse(
300
147
            &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
301
147
                nom::combinator::recognize(nom::multi::fold_many0(
302
147
                    nom::combinator::complete(core_version_api),
303
0
                    || {},
Unexecuted instantiation: _RNCNvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB7_22CoreVersionApisRefIter20from_slice_no_length0Bd_
Unexecuted instantiation: _RNCNvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB7_22CoreVersionApisRefIter20from_slice_no_length0Bd_
304
                    |(), _| (),
305
                )),
306
147
                |inner| CoreVersionApisRefIter { inner },
_RNCNvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB7_22CoreVersionApisRefIter20from_slice_no_lengths0_0Bd_
Line
Count
Source
306
61
                |inner| CoreVersionApisRefIter { inner },
_RNCNvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB7_22CoreVersionApisRefIter20from_slice_no_lengths0_0Bd_
Line
Count
Source
306
86
                |inner| CoreVersionApisRefIter { inner },
307
            ))),
308
147
            input,
309
        );
310
311
147
        match result {
312
147
            Ok((_, me)) => Ok(me),
313
0
            Err(_) => Err(CoreVersionApisFromSliceErr()),
314
        }
315
147
    }
_RNvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIter20from_slice_no_length
Line
Count
Source
298
61
    pub fn from_slice_no_length(input: &'a [u8]) -> Result<Self, CoreVersionApisFromSliceErr> {
299
61
        let result: Result<_, nom::Err<nom::error::Error<&[u8]>>> = nom::Parser::parse(
300
61
            &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
301
61
                nom::combinator::recognize(nom::multi::fold_many0(
302
61
                    nom::combinator::complete(core_version_api),
303
                    || {},
304
                    |(), _| (),
305
                )),
306
                |inner| CoreVersionApisRefIter { inner },
307
            ))),
308
61
            input,
309
        );
310
311
61
        match result {
312
61
            Ok((_, me)) => Ok(me),
313
0
            Err(_) => Err(CoreVersionApisFromSliceErr()),
314
        }
315
61
    }
_RNvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIter20from_slice_no_length
Line
Count
Source
298
86
    pub fn from_slice_no_length(input: &'a [u8]) -> Result<Self, CoreVersionApisFromSliceErr> {
299
86
        let result: Result<_, nom::Err<nom::error::Error<&[u8]>>> = nom::Parser::parse(
300
86
            &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
301
86
                nom::combinator::recognize(nom::multi::fold_many0(
302
86
                    nom::combinator::complete(core_version_api),
303
                    || {},
304
                    |(), _| (),
305
                )),
306
                |inner| CoreVersionApisRefIter { inner },
307
            ))),
308
86
            input,
309
        );
310
311
86
        match result {
312
86
            Ok((_, me)) => Ok(me),
313
0
            Err(_) => Err(CoreVersionApisFromSliceErr()),
314
        }
315
86
    }
316
317
    /// Tries to find within this iterator the given API, and if found returns the version number.
318
    ///
319
    /// If multiple API versions are found, the highest one is returned.
320
    ///
321
    /// > **Note**: If you start iterating (for example by calling `next()`) then call this
322
    /// >           function, the search will only be performed on the rest of the iterator,
323
    /// >           which is typically not what you want. Preferably always call this function
324
    /// >           on a fresh iterator.
325
0
    pub fn find_version(&self, api: &str) -> Option<u32> {
326
0
        self.find_versions([api])[0]
327
0
    }
Unexecuted instantiation: _RNvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIter12find_version
Unexecuted instantiation: _RNvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIter12find_version
328
329
    /// Similar to [`CoreVersionApisRefIter::find_version`], but allows passing multiple API names
330
    /// at once. This is more optimized if multiple API names are to be queried.
331
43
    pub fn find_versions<const N: usize>(&self, apis: [&str; N]) -> [Option<u32>; N] {
332
129
        let 
hashed43
=
core::array::from_fn::<_, N, _>43
(|n| hash_api_name(apis[n]));
_RNCINvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB8_22CoreVersionApisRefIter13find_versionsKj3_E0Be_
Line
Count
Source
332
3
        let hashed = core::array::from_fn::<_, N, _>(|n| hash_api_name(apis[n]));
Unexecuted instantiation: _RNCINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB8_22CoreVersionApisRefIter13find_versionsKj1_E0Be_
_RNCINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB8_22CoreVersionApisRefIter13find_versionsKj3_E0Be_
Line
Count
Source
332
126
        let hashed = core::array::from_fn::<_, N, _>(|n| hash_api_name(apis[n]));
333
43
        let mut out = [None; N];
334
335
432
        for api in 
self43
.
clone43
() {
336
1.29k
            for (n, expected) in 
hashed432
.
iter432
().
enumerate432
() {
337
1.29k
                if *expected == api.name_hash {
338
86
                    match out[n] {
339
0
                        Some(ref mut v) if *v < api.version => *v = api.version,
340
0
                        Some(_) => {}
341
86
                        ref mut v @ None => *v = Some(api.version),
342
                    }
343
1.21k
                }
344
            }
345
        }
346
347
43
        out
348
43
    }
_RINvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter13find_versionsKj3_EBc_
Line
Count
Source
331
1
    pub fn find_versions<const N: usize>(&self, apis: [&str; N]) -> [Option<u32>; N] {
332
1
        let hashed = core::array::from_fn::<_, N, _>(|n| hash_api_name(apis[n]));
333
1
        let mut out = [None; N];
334
335
12
        for api in 
self1
.
clone1
() {
336
36
            for (n, expected) in 
hashed12
.
iter12
().
enumerate12
() {
337
36
                if *expected == api.name_hash {
338
2
                    match out[n] {
339
0
                        Some(ref mut v) if *v < api.version => *v = api.version,
340
0
                        Some(_) => {}
341
2
                        ref mut v @ None => *v = Some(api.version),
342
                    }
343
34
                }
344
            }
345
        }
346
347
1
        out
348
1
    }
Unexecuted instantiation: _RINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter13find_versionsKj1_EBc_
_RINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter13find_versionsKj3_EBc_
Line
Count
Source
331
42
    pub fn find_versions<const N: usize>(&self, apis: [&str; N]) -> [Option<u32>; N] {
332
42
        let hashed = core::array::from_fn::<_, N, _>(|n| hash_api_name(apis[n]));
333
42
        let mut out = [None; N];
334
335
420
        for api in 
self42
.
clone42
() {
336
1.26k
            for (n, expected) in 
hashed420
.
iter420
().
enumerate420
() {
337
1.26k
                if *expected == api.name_hash {
338
84
                    match out[n] {
339
0
                        Some(ref mut v) if *v < api.version => *v = api.version,
340
0
                        Some(_) => {}
341
84
                        ref mut v @ None => *v = Some(api.version),
342
                    }
343
1.17k
                }
344
            }
345
        }
346
347
42
        out
348
42
    }
349
350
    /// Returns `true` if this iterator contains the API with the given name and its version is in
351
    /// the provided range.
352
    ///
353
    /// > **Note**: If you start iterating (for example by calling `next()`) then call this
354
    /// >           function, the search will only be performed on the rest of the iterator,
355
    /// >           which is typically not what you want. Preferably always call this function
356
    /// >           on a fresh iterator.
357
0
    pub fn contains(&self, api_name: &str, version_number: impl ops::RangeBounds<u32>) -> bool {
358
0
        self.contains_hashed(&hash_api_name(api_name), version_number)
359
0
    }
Unexecuted instantiation: _RINvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter8containspEBc_
Unexecuted instantiation: _RINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter8containspEBc_
360
361
    /// Similar to [`CoreVersionApisRefIter::contains`], but allows passing the hash of the
362
    /// API name instead of its unhashed version.
363
0
    pub fn contains_hashed(
364
0
        &self,
365
0
        api_name_hash: &[u8; 8],
366
0
        version_number: impl ops::RangeBounds<u32>,
367
0
    ) -> bool {
368
0
        self.clone()
369
0
            .any(|api| api.name_hash == *api_name_hash && version_number.contains(&api.version))
Unexecuted instantiation: _RNCINvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB8_22CoreVersionApisRefIter15contains_hashedpE0Be_
Unexecuted instantiation: _RNCINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB8_22CoreVersionApisRefIter15contains_hashedpE0Be_
370
0
    }
Unexecuted instantiation: _RINvMs1_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter15contains_hashedpEBc_
Unexecuted instantiation: _RINvMs1_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB6_22CoreVersionApisRefIter15contains_hashedpEBc_
371
}
372
373
impl Iterator for CoreVersionApisRefIter<'_> {
374
    type Item = CoreVersionApi;
375
376
2.67k
    fn next(&mut self) -> Option<Self::Item> {
377
2.67k
        if self.inner.is_empty() {
378
338
            return None;
379
2.33k
        }
380
381
2.33k
        match core_version_api::<nom::error::Error<&[u8]>>(self.inner) {
382
2.33k
            Ok((rest, item)) => {
383
2.33k
                self.inner = rest;
384
2.33k
                Some(item)
385
            }
386
387
            // The content is always checked to be valid before creating a
388
            // `CoreVersionApisRefIter`.
389
0
            Err(_) => unreachable!(),
390
        }
391
2.67k
    }
_RNvXs2_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
376
305
    fn next(&mut self) -> Option<Self::Item> {
377
305
        if self.inner.is_empty() {
378
123
            return None;
379
182
        }
380
381
182
        match core_version_api::<nom::error::Error<&[u8]>>(self.inner) {
382
182
            Ok((rest, item)) => {
383
182
                self.inner = rest;
384
182
                Some(item)
385
            }
386
387
            // The content is always checked to be valid before creating a
388
            // `CoreVersionApisRefIter`.
389
0
            Err(_) => unreachable!(),
390
        }
391
305
    }
_RNvXs2_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtNtNtCs1p5UDGgVI4d_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
376
2.36k
    fn next(&mut self) -> Option<Self::Item> {
377
2.36k
        if self.inner.is_empty() {
378
215
            return None;
379
2.15k
        }
380
381
2.15k
        match core_version_api::<nom::error::Error<&[u8]>>(self.inner) {
382
2.15k
            Ok((rest, item)) => {
383
2.15k
                self.inner = rest;
384
2.15k
                Some(item)
385
            }
386
387
            // The content is always checked to be valid before creating a
388
            // `CoreVersionApisRefIter`.
389
0
            Err(_) => unreachable!(),
390
        }
391
2.36k
    }
392
}
393
394
impl PartialEq for CoreVersionApisRefIter<'_> {
395
0
    fn eq(&self, other: &Self) -> bool {
396
0
        let mut a = self.clone();
397
0
        let mut b = other.clone();
398
        loop {
399
0
            match (a.next(), b.next()) {
400
0
                (Some(a), Some(b)) if a == b => {}
401
0
                (None, None) => return true,
402
0
                _ => return false,
403
            }
404
        }
405
0
    }
Unexecuted instantiation: _RNvXs3_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtCs1p5UDGgVI4d_4core3cmp9PartialEq2eq
Unexecuted instantiation: _RNvXs3_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtCs1p5UDGgVI4d_4core3cmp9PartialEq2eq
406
}
407
408
impl Eq for CoreVersionApisRefIter<'_> {}
409
410
impl fmt::Debug for CoreVersionApisRefIter<'_> {
411
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412
0
        f.debug_list().entries(self.clone()).finish()
413
0
    }
Unexecuted instantiation: _RNvXs5_NtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
Unexecuted instantiation: _RNvXs5_NtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_versionNtB5_22CoreVersionApisRefIterNtNtCs1p5UDGgVI4d_4core3fmt5Debug3fmt
414
}
415
416
/// Error potentially returned by [`CoreVersionApisRefIter::from_slice_no_length`].
417
#[derive(Debug, Clone, derive_more::Display, derive_more::Error)]
418
#[display("Error decoding core version APIs")]
419
pub struct CoreVersionApisFromSliceErr();
420
421
/// Hashes the name of an API in order to be able to compare it to [`CoreVersionApi::name_hash`].
422
129
pub fn hash_api_name(api_name: &str) -> [u8; 8] {
423
129
    let result = blake2_rfc::blake2b::blake2b(8, &[], api_name.as_bytes());
424
129
    result.as_bytes().try_into().unwrap()
425
129
}
_RNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version13hash_api_name
Line
Count
Source
422
3
pub fn hash_api_name(api_name: &str) -> [u8; 8] {
423
3
    let result = blake2_rfc::blake2b::blake2b(8, &[], api_name.as_bytes());
424
3
    result.as_bytes().try_into().unwrap()
425
3
}
_RNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version13hash_api_name
Line
Count
Source
422
126
pub fn hash_api_name(api_name: &str) -> [u8; 8] {
423
126
    let result = blake2_rfc::blake2b::blake2b(8, &[], api_name.as_bytes());
424
126
    result.as_bytes().try_into().unwrap()
425
126
}
426
427
/// One API that the runtime supports.
428
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
429
pub struct CoreVersionApi {
430
    /// BLAKE2 hash of length 8 of the name of the API.
431
    ///
432
    /// > **Note**: Available APIs can be found by searching for `decl_runtime_apis!` in the
433
    /// >           Substrate code base. The value stored in this field is the BLAKE2 hash of
434
    /// >           length 8 of the trait name declared within `decl_runtime_apis!`.
435
    pub name_hash: [u8; 8],
436
437
    /// Version of the module. Typical values are `1`, `2`, `3`, ...
438
    pub version: u32,
439
}
440
441
383
fn decode(scale_encoded: &[u8]) -> Result<CoreVersionRef, ()> {
442
    // See https://spec.polkadot.network/#defn-rt-core-version
443
383
    let result: nom::IResult<_, _> = nom::Parser::parse(
444
383
        &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
445
            (
446
                crate::util::nom_string_decode,
447
                crate::util::nom_string_decode,
448
                nom::number::streaming::le_u32,
449
                nom::number::streaming::le_u32,
450
                nom::number::streaming::le_u32,
451
                core_version_apis,
452
383
                nom::branch::alt((
453
383
                    nom::combinator::complete(nom::combinator::map(
454
                        nom::number::streaming::le_u32,
455
                        Some,
456
                    )),
457
383
                    nom::combinator::map(nom::combinator::eof, |_| None),
458
                )),
459
383
                nom::branch::alt((
460
383
                    nom::combinator::complete(nom::combinator::map(
461
383
                        nom::bytes::streaming::tag(&[0][..]),
462
58
                        |_| Some(TrieEntryVersion::V0),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version6decodes_0B9_
Line
Count
Source
462
58
                        |_| Some(TrieEntryVersion::V0),
Unexecuted instantiation: _RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version6decodes_0B9_
463
                    )),
464
383
                    nom::combinator::complete(nom::combinator::map(
465
383
                        nom::bytes::streaming::tag(&[1][..]),
466
18
                        |_| Some(TrieEntryVersion::V1),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version6decodes0_0B9_
Line
Count
Source
466
18
                        |_| Some(TrieEntryVersion::V1),
Unexecuted instantiation: _RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version6decodes0_0B9_
467
                    )),
468
383
                    nom::combinator::map(nom::combinator::eof, |_| None),
469
                )),
470
            ),
471
            |(
472
                spec_name,
473
                impl_name,
474
                authoring_version,
475
                spec_version,
476
                impl_version,
477
                apis,
478
                transaction_version,
479
                state_version,
480
            )| CoreVersionRef {
481
383
                spec_name,
482
383
                impl_name,
483
383
                authoring_version,
484
383
                spec_version,
485
383
                impl_version,
486
383
                apis,
487
383
                transaction_version,
488
383
                state_version,
489
383
            },
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version6decodes2_0B9_
Line
Count
Source
481
85
                spec_name,
482
85
                impl_name,
483
85
                authoring_version,
484
85
                spec_version,
485
85
                impl_version,
486
85
                apis,
487
85
                transaction_version,
488
85
                state_version,
489
85
            },
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version6decodes2_0B9_
Line
Count
Source
481
298
                spec_name,
482
298
                impl_name,
483
298
                authoring_version,
484
298
                spec_version,
485
298
                impl_version,
486
298
                apis,
487
298
                transaction_version,
488
298
                state_version,
489
298
            },
490
        ))),
491
383
        scale_encoded,
492
    );
493
494
0
    match result {
495
383
        Ok((_, out)) => Ok(out),
496
0
        Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(()),
497
0
        Err(_) => unreachable!(),
498
    }
499
383
}
_RNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version6decode
Line
Count
Source
441
85
fn decode(scale_encoded: &[u8]) -> Result<CoreVersionRef, ()> {
442
    // See https://spec.polkadot.network/#defn-rt-core-version
443
85
    let result: nom::IResult<_, _> = nom::Parser::parse(
444
85
        &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
445
            (
446
                crate::util::nom_string_decode,
447
                crate::util::nom_string_decode,
448
                nom::number::streaming::le_u32,
449
                nom::number::streaming::le_u32,
450
                nom::number::streaming::le_u32,
451
                core_version_apis,
452
85
                nom::branch::alt((
453
85
                    nom::combinator::complete(nom::combinator::map(
454
                        nom::number::streaming::le_u32,
455
                        Some,
456
                    )),
457
85
                    nom::combinator::map(nom::combinator::eof, |_| None),
458
                )),
459
85
                nom::branch::alt((
460
85
                    nom::combinator::complete(nom::combinator::map(
461
85
                        nom::bytes::streaming::tag(&[0][..]),
462
                        |_| Some(TrieEntryVersion::V0),
463
                    )),
464
85
                    nom::combinator::complete(nom::combinator::map(
465
85
                        nom::bytes::streaming::tag(&[1][..]),
466
                        |_| Some(TrieEntryVersion::V1),
467
                    )),
468
85
                    nom::combinator::map(nom::combinator::eof, |_| None),
469
                )),
470
            ),
471
            |(
472
                spec_name,
473
                impl_name,
474
                authoring_version,
475
                spec_version,
476
                impl_version,
477
                apis,
478
                transaction_version,
479
                state_version,
480
            )| CoreVersionRef {
481
                spec_name,
482
                impl_name,
483
                authoring_version,
484
                spec_version,
485
                impl_version,
486
                apis,
487
                transaction_version,
488
                state_version,
489
            },
490
        ))),
491
85
        scale_encoded,
492
    );
493
494
0
    match result {
495
85
        Ok((_, out)) => Ok(out),
496
0
        Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(()),
497
0
        Err(_) => unreachable!(),
498
    }
499
85
}
_RNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version6decode
Line
Count
Source
441
298
fn decode(scale_encoded: &[u8]) -> Result<CoreVersionRef, ()> {
442
    // See https://spec.polkadot.network/#defn-rt-core-version
443
298
    let result: nom::IResult<_, _> = nom::Parser::parse(
444
298
        &mut nom::combinator::all_consuming(nom::combinator::complete(nom::combinator::map(
445
            (
446
                crate::util::nom_string_decode,
447
                crate::util::nom_string_decode,
448
                nom::number::streaming::le_u32,
449
                nom::number::streaming::le_u32,
450
                nom::number::streaming::le_u32,
451
                core_version_apis,
452
298
                nom::branch::alt((
453
298
                    nom::combinator::complete(nom::combinator::map(
454
                        nom::number::streaming::le_u32,
455
                        Some,
456
                    )),
457
298
                    nom::combinator::map(nom::combinator::eof, |_| None),
458
                )),
459
298
                nom::branch::alt((
460
298
                    nom::combinator::complete(nom::combinator::map(
461
298
                        nom::bytes::streaming::tag(&[0][..]),
462
                        |_| Some(TrieEntryVersion::V0),
463
                    )),
464
298
                    nom::combinator::complete(nom::combinator::map(
465
298
                        nom::bytes::streaming::tag(&[1][..]),
466
                        |_| Some(TrieEntryVersion::V1),
467
                    )),
468
298
                    nom::combinator::map(nom::combinator::eof, |_| None),
469
                )),
470
            ),
471
            |(
472
                spec_name,
473
                impl_name,
474
                authoring_version,
475
                spec_version,
476
                impl_version,
477
                apis,
478
                transaction_version,
479
                state_version,
480
            )| CoreVersionRef {
481
                spec_name,
482
                impl_name,
483
                authoring_version,
484
                spec_version,
485
                impl_version,
486
                apis,
487
                transaction_version,
488
                state_version,
489
            },
490
        ))),
491
298
        scale_encoded,
492
    );
493
494
0
    match result {
495
298
        Ok((_, out)) => Ok(out),
496
0
        Err(nom::Err::Error(_) | nom::Err::Failure(_)) => Err(()),
497
0
        Err(_) => unreachable!(),
498
    }
499
298
}
500
501
383
fn core_version_apis<'a, E: nom::error::ParseError<&'a [u8]>>(
502
383
    bytes: &'a [u8],
503
383
) -> nom::IResult<&'a [u8], CoreVersionApisRefIter<'a>, E> {
504
383
    nom::Parser::parse(
505
383
        &mut nom::combinator::map(
506
383
            nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
507
383
                nom::combinator::recognize(nom::multi::fold_many_m_n(
508
383
                    num_elems,
509
383
                    num_elems,
510
                    core_version_api,
511
0
                    || {},
Unexecuted instantiation: _RNCNCINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version17core_version_apispE00Bc_
Unexecuted instantiation: _RNCNCINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version17core_version_apispE00Bc_
512
                    |(), _| (),
513
                ))
514
383
            }),
_RNCINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEE0Ba_
Line
Count
Source
506
85
            nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
507
85
                nom::combinator::recognize(nom::multi::fold_many_m_n(
508
85
                    num_elems,
509
85
                    num_elems,
510
                    core_version_api,
511
                    || {},
512
                    |(), _| (),
513
                ))
514
85
            }),
_RNCINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEE0Ba_
Line
Count
Source
506
298
            nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
507
298
                nom::combinator::recognize(nom::multi::fold_many_m_n(
508
298
                    num_elems,
509
298
                    num_elems,
510
                    core_version_api,
511
                    || {},
512
                    |(), _| (),
513
                ))
514
298
            }),
515
383
            |inner| CoreVersionApisRefIter { inner },
_RNCINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEs_0Ba_
Line
Count
Source
515
85
            |inner| CoreVersionApisRefIter { inner },
_RNCINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEs_0Ba_
Line
Count
Source
515
298
            |inner| CoreVersionApisRefIter { inner },
516
        ),
517
383
        bytes,
518
    )
519
383
}
_RINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEB8_
Line
Count
Source
501
85
fn core_version_apis<'a, E: nom::error::ParseError<&'a [u8]>>(
502
85
    bytes: &'a [u8],
503
85
) -> nom::IResult<&'a [u8], CoreVersionApisRefIter<'a>, E> {
504
85
    nom::Parser::parse(
505
85
        &mut nom::combinator::map(
506
85
            nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
507
                nom::combinator::recognize(nom::multi::fold_many_m_n(
508
                    num_elems,
509
                    num_elems,
510
                    core_version_api,
511
                    || {},
512
                    |(), _| (),
513
                ))
514
            }),
515
            |inner| CoreVersionApisRefIter { inner },
516
        ),
517
85
        bytes,
518
    )
519
85
}
_RINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version17core_version_apisINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEB8_
Line
Count
Source
501
298
fn core_version_apis<'a, E: nom::error::ParseError<&'a [u8]>>(
502
298
    bytes: &'a [u8],
503
298
) -> nom::IResult<&'a [u8], CoreVersionApisRefIter<'a>, E> {
504
298
    nom::Parser::parse(
505
298
        &mut nom::combinator::map(
506
298
            nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
507
                nom::combinator::recognize(nom::multi::fold_many_m_n(
508
                    num_elems,
509
                    num_elems,
510
                    core_version_api,
511
                    || {},
512
                    |(), _| (),
513
                ))
514
            }),
515
            |inner| CoreVersionApisRefIter { inner },
516
        ),
517
298
        bytes,
518
    )
519
298
}
520
521
5.81k
fn core_version_api<'a, E: nom::error::ParseError<&'a [u8]>>(
522
5.81k
    bytes: &'a [u8],
523
5.81k
) -> nom::IResult<&'a [u8], CoreVersionApi, E> {
524
5.81k
    nom::Parser::parse(
525
5.81k
        &mut nom::combinator::map(
526
5.81k
            (
527
5.81k
                nom::bytes::streaming::take(8u32),
528
5.81k
                nom::number::streaming::le_u32,
529
5.81k
            ),
530
            move |(name, version)| CoreVersionApi {
531
5.66k
                name_hash: <[u8; 8]>::try_from(name).unwrap(),
532
5.66k
                version,
533
5.66k
            },
_RNCINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version16core_version_apiINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEE0Ba_
Line
Count
Source
531
536
                name_hash: <[u8; 8]>::try_from(name).unwrap(),
532
536
                version,
533
536
            },
_RNCINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version16core_version_apiINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEE0Ba_
Line
Count
Source
531
5.13k
                name_hash: <[u8; 8]>::try_from(name).unwrap(),
532
5.13k
                version,
533
5.13k
            },
534
        ),
535
5.81k
        bytes,
536
    )
537
5.81k
}
_RINvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version16core_version_apiINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEB8_
Line
Count
Source
521
597
fn core_version_api<'a, E: nom::error::ParseError<&'a [u8]>>(
522
597
    bytes: &'a [u8],
523
597
) -> nom::IResult<&'a [u8], CoreVersionApi, E> {
524
597
    nom::Parser::parse(
525
597
        &mut nom::combinator::map(
526
597
            (
527
597
                nom::bytes::streaming::take(8u32),
528
597
                nom::number::streaming::le_u32,
529
597
            ),
530
            move |(name, version)| CoreVersionApi {
531
                name_hash: <[u8; 8]>::try_from(name).unwrap(),
532
                version,
533
            },
534
        ),
535
597
        bytes,
536
    )
537
597
}
_RINvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version16core_version_apiINtNtCsfjEU5fc64iO_3nom5error5ErrorRShEEB8_
Line
Count
Source
521
5.21k
fn core_version_api<'a, E: nom::error::ParseError<&'a [u8]>>(
522
5.21k
    bytes: &'a [u8],
523
5.21k
) -> nom::IResult<&'a [u8], CoreVersionApi, E> {
524
5.21k
    nom::Parser::parse(
525
5.21k
        &mut nom::combinator::map(
526
5.21k
            (
527
5.21k
                nom::bytes::streaming::take(8u32),
528
5.21k
                nom::number::streaming::le_u32,
529
5.21k
            ),
530
            move |(name, version)| CoreVersionApi {
531
                name_hash: <[u8; 8]>::try_from(name).unwrap(),
532
                version,
533
            },
534
        ),
535
5.21k
        bytes,
536
    )
537
5.21k
}
538
539
struct WasmSection<'a> {
540
    name: &'a [u8],
541
    content: &'a [u8],
542
}
543
544
/// Parses a Wasm section. If it is a custom section, returns its name and content.
545
1.85k
fn wasm_section(bytes: &[u8]) -> nom::IResult<&[u8], Option<WasmSection>> {
546
1.85k
    nom::Parser::parse(
547
1.85k
        &mut nom::branch::alt((
548
1.85k
            nom::combinator::map(
549
1.85k
                nom::combinator::map_parser(
550
1.85k
                    nom::sequence::preceded(
551
1.85k
                        nom::bytes::streaming::tag(&[0][..]),
552
1.85k
                        nom::multi::length_data(nom::combinator::map_opt(
553
                            crate::util::leb128::nom_leb128_u64,
554
488
                            |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version12wasm_section0B9_
Line
Count
Source
554
144
                            |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version12wasm_section0B9_
Line
Count
Source
554
344
                            |n| u32::try_from(n).ok(),
555
                        )),
556
                    ),
557
                    (
558
1.85k
                        nom::multi::length_data(nom::combinator::map_opt(
559
                            crate::util::leb128::nom_leb128_u64,
560
488
                            |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version12wasm_sections_0B9_
Line
Count
Source
560
144
                            |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version12wasm_sections_0B9_
Line
Count
Source
560
344
                            |n| u32::try_from(n).ok(),
561
                        )),
562
                        nom::combinator::rest,
563
                    ),
564
                ),
565
488
                |(name, content)| Some(WasmSection { name, content }),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version12wasm_sections0_0B9_
Line
Count
Source
565
144
                |(name, content)| Some(WasmSection { name, content }),
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version12wasm_sections0_0B9_
Line
Count
Source
565
344
                |(name, content)| Some(WasmSection { name, content }),
566
            ),
567
1.85k
            nom::combinator::map(
568
                (
569
                    nom::number::streaming::u8,
570
1.85k
                    nom::multi::length_data(nom::combinator::map_opt(
571
                        crate::util::leb128::nom_leb128_u64,
572
1.21k
                        |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version12wasm_sections1_0B9_
Line
Count
Source
572
438
                        |n| u32::try_from(n).ok(),
_RNCNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version12wasm_sections1_0B9_
Line
Count
Source
572
774
                        |n| u32::try_from(n).ok(),
573
                    )),
574
                ),
575
                |_| None,
576
            ),
577
        )),
578
1.85k
        bytes,
579
    )
580
1.85k
}
_RNvNtNtNtCsjlkOsLH0Zfj_7smoldot8executor4host15runtime_version12wasm_section
Line
Count
Source
545
646
fn wasm_section(bytes: &[u8]) -> nom::IResult<&[u8], Option<WasmSection>> {
546
646
    nom::Parser::parse(
547
646
        &mut nom::branch::alt((
548
646
            nom::combinator::map(
549
646
                nom::combinator::map_parser(
550
646
                    nom::sequence::preceded(
551
646
                        nom::bytes::streaming::tag(&[0][..]),
552
646
                        nom::multi::length_data(nom::combinator::map_opt(
553
                            crate::util::leb128::nom_leb128_u64,
554
                            |n| u32::try_from(n).ok(),
555
                        )),
556
                    ),
557
                    (
558
646
                        nom::multi::length_data(nom::combinator::map_opt(
559
                            crate::util::leb128::nom_leb128_u64,
560
                            |n| u32::try_from(n).ok(),
561
                        )),
562
                        nom::combinator::rest,
563
                    ),
564
                ),
565
                |(name, content)| Some(WasmSection { name, content }),
566
            ),
567
646
            nom::combinator::map(
568
                (
569
                    nom::number::streaming::u8,
570
646
                    nom::multi::length_data(nom::combinator::map_opt(
571
                        crate::util::leb128::nom_leb128_u64,
572
                        |n| u32::try_from(n).ok(),
573
                    )),
574
                ),
575
                |_| None,
576
            ),
577
        )),
578
646
        bytes,
579
    )
580
646
}
_RNvNtNtNtCsc1ywvx6YAnK_7smoldot8executor4host15runtime_version12wasm_section
Line
Count
Source
545
1.20k
fn wasm_section(bytes: &[u8]) -> nom::IResult<&[u8], Option<WasmSection>> {
546
1.20k
    nom::Parser::parse(
547
1.20k
        &mut nom::branch::alt((
548
1.20k
            nom::combinator::map(
549
1.20k
                nom::combinator::map_parser(
550
1.20k
                    nom::sequence::preceded(
551
1.20k
                        nom::bytes::streaming::tag(&[0][..]),
552
1.20k
                        nom::multi::length_data(nom::combinator::map_opt(
553
                            crate::util::leb128::nom_leb128_u64,
554
                            |n| u32::try_from(n).ok(),
555
                        )),
556
                    ),
557
                    (
558
1.20k
                        nom::multi::length_data(nom::combinator::map_opt(
559
                            crate::util::leb128::nom_leb128_u64,
560
                            |n| u32::try_from(n).ok(),
561
                        )),
562
                        nom::combinator::rest,
563
                    ),
564
                ),
565
                |(name, content)| Some(WasmSection { name, content }),
566
            ),
567
1.20k
            nom::combinator::map(
568
                (
569
                    nom::number::streaming::u8,
570
1.20k
                    nom::multi::length_data(nom::combinator::map_opt(
571
                        crate::util::leb128::nom_leb128_u64,
572
                        |n| u32::try_from(n).ok(),
573
                    )),
574
                ),
575
                |_| None,
576
            ),
577
        )),
578
1.20k
        bytes,
579
    )
580
1.20k
}