Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/transactions/validate.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2019-2022  Parity Technologies (UK) Ltd.
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
//! Runtime call to obtain the transactions validity status.
19
20
use crate::util;
21
22
use alloc::{borrow::ToOwned as _, vec::Vec};
23
use core::{iter, num::NonZeroU64};
24
25
mod tests;
26
27
/// Source of the transaction.
28
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29
pub enum TransactionSource {
30
    /// Transaction is already included in a block.
31
    ///
32
    /// It isn't possible to tell where the transaction is coming from, since it's already in a
33
    /// received block.
34
    InBlock,
35
36
    /// Transaction is coming from a local source.
37
    ///
38
    /// The transaction was produced internally by the node (for instance an off-chain worker).
39
    /// This transaction therefore has a higher level of trust compared to the other variants.
40
    Local,
41
42
    /// Transaction has been received externally.
43
    ///
44
    /// The transaction has been received from an "untrusted" source, such as the network or the
45
    /// JSON-RPC server.
46
    External,
47
}
48
49
/// Information concerning a valid transaction.
50
#[derive(Debug, Clone, PartialEq, Eq)]
51
pub struct ValidTransaction {
52
    /// Priority of the transaction.
53
    ///
54
    /// Priority determines the ordering of two transactions that have all
55
    /// [their required tags](ValidTransaction::requires) satisfied. Transactions with a higher
56
    /// priority should be included first.
57
    pub priority: u64,
58
59
    /// Transaction dependencies.
60
    ///
61
    /// Contains a list of so-called *tags*. The actual bytes of the tags can be compared in order
62
    /// to determine whether two tags are equal, but aren't meaningful from the client
63
    /// perspective.
64
    ///
65
    /// A non-empty list signifies that this transaction can't be included before some other
66
    /// transactions which [provide](ValidTransaction::provides) the given tags. *All* the tags
67
    /// must be fulfilled before the transaction can be included.
68
    // TODO: better type than `Vec<Vec<u8>>`? I feel like this could be a single `Vec<u8>` that is decoded on the fly?
69
    pub requires: Vec<Vec<u8>>,
70
71
    /// Tags provided by the transaction.
72
    ///
73
    /// The bytes of the tags aren't meaningful from the client's perspective, but are used to
74
    /// enforce an ordering between transactions. See [`ValidTransaction::requires`].
75
    ///
76
    /// Two transactions that have a provided tag in common are mutually exclusive, and cannot be
77
    /// both included in the same chain of blocks.
78
    ///
79
    /// Guaranteed to never be empty.
80
    // TODO: better type than `Vec<Vec<u8>>`? I feel like this could be a single `Vec<u8>` that is decoded on the fly?
81
    pub provides: Vec<Vec<u8>>,
82
83
    /// Transaction longevity.
84
    ///
85
    /// This value provides a hint of the number of blocks during which the client can assume the
86
    /// transaction to be valid. This is provided for optimization purposes, to save the client
87
    /// from re-validating every pending transaction at each new block. It is only a hint, and the
88
    /// transaction might become invalid sooner.
89
    ///
90
    /// After this period, transaction should be removed from the pool or revalidated.
91
    ///
92
    /// > **Note**: Many transactions are "mortal", meaning that they automatically become invalid
93
    /// >           after a certain number of blocks. In that case, the longevity returned by the
94
    /// >           validation function will be at most this number of blocks. The concept of
95
    /// >           mortal transactions, however, is not relevant from the client's perspective.
96
    pub longevity: NonZeroU64,
97
98
    /// A flag indicating whether the transaction should be propagated to other peers.
99
    ///
100
    /// If `false`, the transaction will still be considered for inclusion in blocks that are
101
    /// authored locally, but will not be sent to the rest of the network.
102
    ///
103
    /// > **Note**: A value of `false` is typically returned for transactions that are very heavy.
104
    pub propagate: bool,
105
}
106
107
/// An invalid transaction validity.
108
0
#[derive(Debug, derive_more::Display, Clone, PartialEq, Eq)]
Unexecuted instantiation: _RNvXsa_NtNtCsN16ciHI6Qf_7smoldot12transactions8validateNtB5_18InvalidTransactionNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsa_NtNtCseuYC0Zibziv_7smoldot12transactions8validateNtB5_18InvalidTransactionNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
109
pub enum InvalidTransaction {
110
    /// The call of the transaction is not expected.
111
    Call,
112
    /// General error to do with the inability to pay some fees (e.g. account balance too low).
113
    Payment,
114
    /// General error to do with the transaction not yet being valid (e.g. nonce too high).
115
    Future,
116
    /// General error to do with the transaction being outdated (e.g. nonce too low).
117
    Stale,
118
    /// General error to do with the transaction's proofs (e.g. signature).
119
    ///
120
    /// # Possible causes
121
    ///
122
    /// When using a signed extension that provides additional data for signing, it is required
123
    /// that the signing and the verifying side use the same additional data. Additional
124
    /// data will only be used to generate the signature, but will not be part of the transaction
125
    /// itself. As the verifying side does not know which additional data was used while signing
126
    /// it will only be able to assume a bad signature and cannot express a more meaningful error.
127
    BadProof,
128
    /// The transaction birth block is ancient.
129
    AncientBirthBlock,
130
    /// The transaction would exhaust the resources of current block.
131
    ///
132
    /// The transaction might be valid, but there are not enough resources
133
    /// left in the current block.
134
    ExhaustsResources,
135
    /// Any other custom invalid validity that is not covered by this enum.
136
    #[display(fmt = "Other reason (code: {_0})")]
137
    Custom(u8),
138
    /// An extrinsic with a Mandatory dispatch resulted in Error. This is indicative of either a
139
    /// malicious validator or a buggy `provide_inherent`. In any case, it can result in dangerously
140
    /// overweight blocks and therefore if found, invalidates the block.
141
    BadMandatory,
142
    /// A transaction with a mandatory dispatch. This is invalid; only inherent extrinsics are
143
    /// allowed to have mandatory dispatches.
144
    MandatoryDispatch,
145
}
146
147
/// An unknown transaction validity.
148
0
#[derive(Debug, derive_more::Display, Clone, PartialEq, Eq)]
Unexecuted instantiation: _RNvXsg_NtNtCsN16ciHI6Qf_7smoldot12transactions8validateNtB5_18UnknownTransactionNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsg_NtNtCseuYC0Zibziv_7smoldot12transactions8validateNtB5_18UnknownTransactionNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
149
pub enum UnknownTransaction {
150
    /// Could not lookup some information that is required to validate the transaction.
151
    CannotLookup,
152
    /// No validator found for the given unsigned transaction.
153
    NoUnsignedValidator,
154
    /// Any other custom unknown validity that is not covered by this enum.
155
    #[display(fmt = "Other reason (code: {_0})")]
156
    Custom(u8),
157
}
158
159
/// Error that can happen during the decoding.
160
0
#[derive(Debug, derive_more::Display, Clone)]
Unexecuted instantiation: _RNvXsm_NtNtCsN16ciHI6Qf_7smoldot12transactions8validateNtB5_11DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsm_NtNtCseuYC0Zibziv_7smoldot12transactions8validateNtB5_11DecodeErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
161
pub struct DecodeError();
162
163
/// Errors that can occur while checking the validity of a transaction.
164
0
#[derive(Debug, derive_more::Display, Clone, PartialEq, Eq)]
Unexecuted instantiation: _RNvXsp_NtNtCsN16ciHI6Qf_7smoldot12transactions8validateNtB5_24TransactionValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsp_NtNtCseuYC0Zibziv_7smoldot12transactions8validateNtB5_24TransactionValidityErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt
165
pub enum TransactionValidityError {
166
    /// The transaction is invalid.
167
    #[display(fmt = "Invalid transaction: {_0}")]
168
    Invalid(InvalidTransaction),
169
    /// Transaction validity can't be determined.
170
    #[display(fmt = "Transaction validity couldn't be determined: {_0}")]
171
    Unknown(UnknownTransaction),
172
}
173
174
/// Produces the input to pass to the `TaggedTransactionQueue_validate_transaction` runtime call.
175
0
pub fn validate_transaction_runtime_parameters_v2<'a>(
176
0
    scale_encoded_transaction: impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a,
177
0
    source: TransactionSource,
178
0
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a {
179
0
    validate_transaction_runtime_parameters_inner(scale_encoded_transaction, source, &[])
180
0
}
Unexecuted instantiation: _RINvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate42validate_transaction_runtime_parameters_v2ppEB6_
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot12transactions8validate42validate_transaction_runtime_parameters_v2ppEB6_
181
182
/// Produces the input to pass to the `TaggedTransactionQueue_validate_transaction` runtime call.
183
1
pub fn validate_transaction_runtime_parameters_v3<'a>(
184
1
    scale_encoded_transaction: impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a,
185
1
    source: TransactionSource,
186
1
    block_hash: &'a [u8; 32],
187
1
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a {
188
1
    validate_transaction_runtime_parameters_inner(scale_encoded_transaction, source, block_hash)
189
1
}
_RINvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate42validate_transaction_runtime_parameters_v3RINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEB6_
Line
Count
Source
183
1
pub fn validate_transaction_runtime_parameters_v3<'a>(
184
1
    scale_encoded_transaction: impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a,
185
1
    source: TransactionSource,
186
1
    block_hash: &'a [u8; 32],
187
1
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a {
188
1
    validate_transaction_runtime_parameters_inner(scale_encoded_transaction, source, block_hash)
189
1
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot12transactions8validate42validate_transaction_runtime_parameters_v3RShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot12transactions8validate42validate_transaction_runtime_parameters_v3ppEB6_
190
191
1
fn validate_transaction_runtime_parameters_inner<'a>(
192
1
    scale_encoded_transaction: impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a,
193
1
    source: TransactionSource,
194
1
    block_hash: &'a [u8],
195
1
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a {
196
    // The `TaggedTransactionQueue_validate_transaction` function expects a SCALE-encoded
197
    // `(source, tx, block_hash)`. The encoding is performed manually in order to avoid
198
    // performing redundant data copies.
199
1
    let source = match source {
200
0
        TransactionSource::InBlock => &[0],
201
0
        TransactionSource::Local => &[1],
202
1
        TransactionSource::External => &[2],
203
    };
204
205
1
    iter::once(source)
206
1
        .map(either::Left)
207
1
        .chain(
208
1
            scale_encoded_transaction
209
1
                .map(either::Right)
210
1
                .map(either::Right),
211
1
        )
212
1
        .chain(iter::once(block_hash).map(either::Left).map(either::Right))
213
1
}
_RINvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate45validate_transaction_runtime_parameters_innerRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1z_EEB6_
Line
Count
Source
191
1
fn validate_transaction_runtime_parameters_inner<'a>(
192
1
    scale_encoded_transaction: impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a,
193
1
    source: TransactionSource,
194
1
    block_hash: &'a [u8],
195
1
) -> impl Iterator<Item = impl AsRef<[u8]> + 'a> + Clone + 'a {
196
    // The `TaggedTransactionQueue_validate_transaction` function expects a SCALE-encoded
197
    // `(source, tx, block_hash)`. The encoding is performed manually in order to avoid
198
    // performing redundant data copies.
199
1
    let source = match source {
200
0
        TransactionSource::InBlock => &[0],
201
0
        TransactionSource::Local => &[1],
202
1
        TransactionSource::External => &[2],
203
    };
204
205
1
    iter::once(source)
206
1
        .map(either::Left)
207
1
        .chain(
208
1
            scale_encoded_transaction
209
1
                .map(either::Right)
210
1
                .map(either::Right),
211
1
        )
212
1
        .chain(iter::once(block_hash).map(either::Left).map(either::Right))
213
1
}
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot12transactions8validate45validate_transaction_runtime_parameters_innerRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1A_EECsDDUKWWCHAU_18smoldot_light_wasm
Unexecuted instantiation: _RINvNtNtCseuYC0Zibziv_7smoldot12transactions8validate45validate_transaction_runtime_parameters_innerppEB6_
214
215
/// Name of the runtime function to call in order to validate a transaction.
216
pub const VALIDATION_FUNCTION_NAME: &str = "TaggedTransactionQueue_validate_transaction";
217
218
/// Attempt to decode the return value of the  `TaggedTransactionQueue_validate_transaction`
219
/// runtime call.
220
0
pub fn decode_validate_transaction_return_value(
221
0
    scale_encoded: &[u8],
222
0
) -> Result<Result<ValidTransaction, TransactionValidityError>, DecodeError> {
223
0
    match nom::combinator::all_consuming(transaction_validity)(scale_encoded) {
224
0
        Ok((_, data)) => Ok(data),
225
0
        Err(_) => Err(DecodeError()),
226
    }
227
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate40decode_validate_transaction_return_value
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate40decode_validate_transaction_return_value
228
229
// `nom` parser functions can be found below.
230
231
0
fn transaction_validity(
232
0
    bytes: &[u8],
233
0
) -> nom::IResult<&[u8], Result<ValidTransaction, TransactionValidityError>> {
234
0
    nom::error::context(
235
0
        "transaction validity",
236
0
        nom::branch::alt((
237
0
            nom::combinator::map(
238
0
                nom::sequence::preceded(nom::bytes::streaming::tag(&[0]), valid_transaction),
239
0
                Ok,
240
0
            ),
241
0
            nom::combinator::map(
242
0
                nom::sequence::preceded(
243
0
                    nom::bytes::streaming::tag(&[1]),
244
0
                    transaction_validity_error,
245
0
                ),
246
0
                Err,
247
0
            ),
248
0
        )),
249
0
    )(bytes)
250
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate20transaction_validity
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate20transaction_validity
251
252
0
fn valid_transaction(bytes: &[u8]) -> nom::IResult<&[u8], ValidTransaction> {
253
0
    nom::error::context(
254
0
        "valid transaction",
255
0
        nom::combinator::map(
256
0
            nom::sequence::tuple((
257
0
                nom::number::streaming::le_u64,
258
0
                tags,
259
0
                // TODO: maybe show by strong typing the fact that the provide tags are never empty
260
0
                nom::combinator::verify(tags, |provides: &Vec<Vec<u8>>| !provides.is_empty()),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate17valid_transaction0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate17valid_transaction0B7_
261
0
                nom::combinator::map_opt(nom::number::streaming::le_u64, NonZeroU64::new),
262
0
                util::nom_bool_decode,
263
0
            )),
264
0
            |(priority, requires, provides, longevity, propagate)| ValidTransaction {
265
0
                priority,
266
0
                requires,
267
0
                provides,
268
0
                longevity,
269
0
                propagate,
270
0
            },
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate17valid_transactions_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate17valid_transactions_0B7_
271
0
        ),
272
0
    )(bytes)
273
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate17valid_transaction
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate17valid_transaction
274
275
0
fn transaction_validity_error(bytes: &[u8]) -> nom::IResult<&[u8], TransactionValidityError> {
276
0
    nom::error::context(
277
0
        "transaction validity error",
278
0
        nom::branch::alt((
279
0
            nom::combinator::map(
280
0
                nom::sequence::preceded(nom::bytes::streaming::tag(&[0]), invalid_transaction),
281
0
                TransactionValidityError::Invalid,
282
0
            ),
283
0
            nom::combinator::map(
284
0
                nom::sequence::preceded(nom::bytes::streaming::tag(&[1]), unknown_transaction),
285
0
                TransactionValidityError::Unknown,
286
0
            ),
287
0
        )),
288
0
    )(bytes)
289
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate26transaction_validity_error
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate26transaction_validity_error
290
291
0
fn invalid_transaction(bytes: &[u8]) -> nom::IResult<&[u8], InvalidTransaction> {
292
0
    nom::error::context(
293
0
        "invalid transaction",
294
0
        nom::branch::alt((
295
0
            nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| {
296
0
                InvalidTransaction::Call
297
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transaction0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transaction0B7_
298
0
            nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| {
299
0
                InvalidTransaction::Payment
300
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions_0B7_
301
0
            nom::combinator::map(nom::bytes::streaming::tag(&[2]), |_| {
302
0
                InvalidTransaction::Future
303
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions0_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions0_0B7_
304
0
            nom::combinator::map(nom::bytes::streaming::tag(&[3]), |_| {
305
0
                InvalidTransaction::Stale
306
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions1_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions1_0B7_
307
0
            nom::combinator::map(nom::bytes::streaming::tag(&[4]), |_| {
308
0
                InvalidTransaction::BadProof
309
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions2_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions2_0B7_
310
0
            nom::combinator::map(nom::bytes::streaming::tag(&[5]), |_| {
311
0
                InvalidTransaction::AncientBirthBlock
312
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions3_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions3_0B7_
313
0
            nom::combinator::map(nom::bytes::streaming::tag(&[6]), |_| {
314
0
                InvalidTransaction::ExhaustsResources
315
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions4_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions4_0B7_
316
0
            nom::combinator::map(
317
0
                nom::sequence::preceded(
318
0
                    nom::bytes::streaming::tag(&[7]),
319
0
                    nom::bytes::streaming::take(1u32),
320
0
                ),
321
0
                |n: &[u8]| InvalidTransaction::Custom(n[0]),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions5_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions5_0B7_
322
0
            ),
323
0
            nom::combinator::map(nom::bytes::streaming::tag(&[8]), |_| {
324
0
                InvalidTransaction::BadMandatory
325
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions6_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions6_0B7_
326
0
            nom::combinator::map(nom::bytes::streaming::tag(&[9]), |_| {
327
0
                InvalidTransaction::MandatoryDispatch
328
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transactions7_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transactions7_0B7_
329
0
        )),
330
0
    )(bytes)
331
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19invalid_transaction
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19invalid_transaction
332
333
0
fn unknown_transaction(bytes: &[u8]) -> nom::IResult<&[u8], UnknownTransaction> {
334
0
    nom::error::context(
335
0
        "unknown transaction",
336
0
        nom::branch::alt((
337
0
            nom::combinator::map(nom::bytes::streaming::tag(&[0]), |_| {
338
0
                UnknownTransaction::CannotLookup
339
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19unknown_transaction0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19unknown_transaction0B7_
340
0
            nom::combinator::map(nom::bytes::streaming::tag(&[1]), |_| {
341
0
                UnknownTransaction::NoUnsignedValidator
342
0
            }),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19unknown_transactions_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19unknown_transactions_0B7_
343
0
            nom::combinator::map(
344
0
                nom::sequence::preceded(
345
0
                    nom::bytes::streaming::tag(&[2]),
346
0
                    nom::bytes::streaming::take(1u32),
347
0
                ),
348
0
                |n: &[u8]| UnknownTransaction::Custom(n[0]),
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19unknown_transactions0_0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19unknown_transactions0_0B7_
349
0
            ),
350
0
        )),
351
0
    )(bytes)
352
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate19unknown_transaction
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate19unknown_transaction
353
354
0
fn tags(bytes: &[u8]) -> nom::IResult<&[u8], Vec<Vec<u8>>> {
355
0
    nom::combinator::flat_map(crate::util::nom_scale_compact_usize, |num_elems| {
356
0
        nom::multi::many_m_n(
357
0
            num_elems,
358
0
            num_elems,
359
0
            nom::combinator::map(
360
0
                nom::multi::length_data(crate::util::nom_scale_compact_usize),
361
0
                |tag| tag.to_owned(),
Unexecuted instantiation: _RNCNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate4tags00B9_
Unexecuted instantiation: _RNCNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate4tags00B9_
362
0
            ),
363
0
        )
364
0
    })(bytes)
Unexecuted instantiation: _RNCNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate4tags0B7_
Unexecuted instantiation: _RNCNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate4tags0B7_
365
0
}
Unexecuted instantiation: _RNvNtNtCsN16ciHI6Qf_7smoldot12transactions8validate4tags
Unexecuted instantiation: _RNvNtNtCseuYC0Zibziv_7smoldot12transactions8validate4tags