/__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 |