sp_runtime/traits/transaction_extension/mod.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! The transaction extension trait.
19
20use crate::{
21 scale_info::{MetaType, StaticTypeInfo},
22 transaction_validity::{
23 TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction,
24 },
25 DispatchResult,
26};
27use codec::{Codec, Decode, Encode};
28use impl_trait_for_tuples::impl_for_tuples;
29#[doc(hidden)]
30pub use sp_std::marker::PhantomData;
31use sp_std::{self, fmt::Debug, prelude::*};
32use sp_weights::Weight;
33use tuplex::{PopFront, PushBack};
34
35use super::{
36 DispatchInfoOf, DispatchOriginOf, Dispatchable, ExtensionPostDispatchWeightHandler,
37 PostDispatchInfoOf, RefundWeight,
38};
39
40mod as_transaction_extension;
41mod dispatch_transaction;
42#[allow(deprecated)]
43pub use as_transaction_extension::AsTransactionExtension;
44pub use dispatch_transaction::DispatchTransaction;
45
46/// Provides `Sealed` trait.
47mod private {
48 /// Special trait that prevents the implementation of some traits outside of this crate.
49 pub trait Sealed {}
50}
51
52/// The base implication in a transaction.
53///
54/// This struct is used to represent the base implication in the transaction, that is
55/// the implication not part of any transaction extensions. It usually comprises of the call and
56/// the transaction extension version.
57///
58/// The concept of implication in the transaction extension pipeline is explained in the trait
59/// documentation: [`TransactionExtension`].
60#[derive(Encode)]
61pub struct TxBaseImplication<T>(pub T);
62
63impl<T: Encode> Implication for TxBaseImplication<T> {
64 fn parts(&self) -> ImplicationParts<&impl Encode, &impl Encode, &impl Encode> {
65 ImplicationParts { base: self, explicit: &(), implicit: &() }
66 }
67}
68
69impl<T> private::Sealed for TxBaseImplication<T> {}
70
71/// The implication in a transaction.
72///
73/// The concept of implication in the transaction extension pipeline is explained in the trait
74/// documentation: [`TransactionExtension`].
75#[derive(Encode)]
76pub struct ImplicationParts<Base, Explicit, Implicit> {
77 /// The base implication, that is implication not part of any transaction extension, usually
78 /// the call and the transaction extension version.
79 pub base: Base,
80 /// The explicit implication in transaction extensions.
81 pub explicit: Explicit,
82 /// The implicit implication in transaction extensions.
83 pub implicit: Implicit,
84}
85
86impl<Base: Encode, Explicit: Encode, Implicit: Encode> Implication
87 for ImplicationParts<Base, Explicit, Implicit>
88{
89 fn parts(&self) -> ImplicationParts<&impl Encode, &impl Encode, &impl Encode> {
90 ImplicationParts { base: &self.base, explicit: &self.explicit, implicit: &self.implicit }
91 }
92}
93
94impl<Base, Explicit, Implicit> private::Sealed for ImplicationParts<Base, Explicit, Implicit> {}
95
96/// Interface of implications in the transaction extension pipeline.
97///
98/// Implications can be encoded, this is useful for checking signature on the implications.
99/// Implications can be split into parts, this allow to destructure and restructure the
100/// implications, this is useful for nested pipeline.
101///
102/// This trait is sealed, consider using [`TxBaseImplication`] and [`ImplicationParts`]
103/// implementations.
104///
105/// The concept of implication in the transaction extension pipeline is explained in the trait
106/// documentation: [`TransactionExtension`].
107pub trait Implication: Encode + private::Sealed {
108 /// Destructure the implication into its parts.
109 fn parts(&self) -> ImplicationParts<&impl Encode, &impl Encode, &impl Encode>;
110}
111
112/// Shortcut for the result value of the `validate` function.
113pub type ValidateResult<Val, Call> =
114 Result<(ValidTransaction, Val, DispatchOriginOf<Call>), TransactionValidityError>;
115
116/// Means by which a transaction may be extended. This type embodies both the data and the logic
117/// that should be additionally associated with the transaction. It should be plain old data.
118///
119/// The simplest transaction extension would be the Unit type (and empty pipeline) `()`. This
120/// executes no additional logic and implies a dispatch of the transaction's call using the
121/// inherited origin (either `None` or `Signed`, depending on whether this is a signed or general
122/// transaction).
123///
124/// Transaction extensions are capable of altering certain associated semantics:
125///
126/// - They may define the origin with which the transaction's call should be dispatched.
127/// - They may define various parameters used by the transaction queue to determine under what
128/// conditions the transaction should be retained and introduced on-chain.
129/// - They may define whether this transaction is acceptable for introduction on-chain at all.
130///
131/// Each of these semantics are defined by the `validate` function.
132///
133/// **NOTE: Transaction extensions cannot under any circumstances alter the call itself.**
134///
135/// Transaction extensions are capable of defining logic which is executed additionally to the
136/// dispatch of the call:
137///
138/// - They may define logic which must be executed prior to the dispatch of the call.
139/// - They may also define logic which must be executed after the dispatch of the call.
140///
141/// Each of these semantics are defined by the `prepare` and `post_dispatch_details` functions
142/// respectively.
143///
144/// Finally, transaction extensions may define additional data to help define the implications of
145/// the logic they introduce. This additional data may be explicitly defined by the transaction
146/// author (in which case it is included as part of the transaction body), or it may be implicitly
147/// defined by the transaction extension based around the on-chain state (which the transaction
148/// author is assumed to know). This data may be utilized by the above logic to alter how a node's
149/// transaction queue treats this transaction.
150///
151/// ## Default implementations
152///
153/// Of the 6 functions in this trait along with `TransactionExtension`, 2 of them must return a
154/// value of an associated type on success, with only `implicit` having a default implementation.
155/// This means that default implementations cannot be provided for `validate` and `prepare`.
156/// However, a macro is provided [impl_tx_ext_default](crate::impl_tx_ext_default) which is capable
157/// of generating default implementations for both of these functions. If you do not wish to
158/// introduce additional logic into the transaction pipeline, then it is recommended that you use
159/// this macro to implement these functions. Additionally, [weight](TransactionExtension::weight)
160/// can return a default value, which would mean the extension is weightless, but it is not
161/// implemented by default. Instead, implementers can explicitly choose to implement this default
162/// behavior through the same [impl_tx_ext_default](crate::impl_tx_ext_default) macro.
163///
164/// If your extension does any post-flight logic, then the functionality must be implemented in
165/// [post_dispatch_details](TransactionExtension::post_dispatch_details). This function can return
166/// the actual weight used by the extension during an entire dispatch cycle by wrapping said weight
167/// value in a `Some`. This is useful in computing fee refunds, similar to how post dispatch
168/// information is used to refund fees for calls. Alternatively, a `None` can be returned, which
169/// means that the worst case scenario weight, namely the value returned by
170/// [weight](TransactionExtension::weight), is the actual weight. This particular piece of logic
171/// is embedded in the default implementation of
172/// [post_dispatch](TransactionExtension::post_dispatch) so that the weight is assumed to be worst
173/// case scenario, but implementers of this trait can correct it with extra effort. Therefore, all
174/// users of an extension should use [post_dispatch](TransactionExtension::post_dispatch), with
175/// [post_dispatch_details](TransactionExtension::post_dispatch_details) considered an internal
176/// function.
177///
178/// ## Pipelines, Inherited Implications, and Authorized Origins
179///
180/// Requiring a single transaction extension to define all of the above semantics would be
181/// cumbersome and would lead to a lot of boilerplate. Instead, transaction extensions are
182/// aggregated into pipelines, which are tuples of transaction extensions. Each extension in the
183/// pipeline is executed in order, and the output of each extension is aggregated and/or relayed as
184/// the input to the next extension in the pipeline.
185///
186/// This ordered composition happens with all data types ([Val](TransactionExtension::Val),
187/// [Pre](TransactionExtension::Pre) and [Implicit](TransactionExtension::Implicit)) as well as
188/// all functions. There are important consequences stemming from how the composition affects the
189/// meaning of the `origin` and `implication` parameters as well as the results. Whereas the
190/// [prepare](TransactionExtension::prepare) and
191/// [post_dispatch](TransactionExtension::post_dispatch) functions are clear in their meaning, the
192/// [validate](TransactionExtension::validate) function is fairly sophisticated and warrants further
193/// explanation.
194///
195/// Firstly, the `origin` parameter. The `origin` passed into the first item in a pipeline is simply
196/// that passed into the tuple itself. It represents an authority who has authorized the implication
197/// of the transaction, as of the extension it has been passed into *and any further extensions it
198/// may pass though, all the way to, and including, the transaction's dispatch call itself. Each
199/// following item in the pipeline is passed the origin which the previous item returned. The origin
200/// returned from the final item in the pipeline is the origin which is returned by the tuple
201/// itself.
202///
203/// This means that if a constituent extension returns a different origin to the one it was called
204/// with, then (assuming no other extension changes it further) *this new origin will be used for
205/// all extensions following it in the pipeline, and will be returned from the pipeline to be used
206/// as the origin for the call's dispatch*. The call itself as well as all these extensions
207/// following may each imply consequence for this origin. We call this the *inherited implication*.
208///
209/// The *inherited implication* is the cumulated on-chain effects born by whatever origin is
210/// returned. It is expressed to the [validate](TransactionExtension::validate) function only as the
211/// `implication` argument which implements the [Encode] trait. A transaction extension may define
212/// its own implications through its own fields and the
213/// [implicit](TransactionExtension::implicit) function. This is only utilized by extensions
214/// which precede it in a pipeline or, if the transaction is an old-school signed transaction, the
215/// underlying transaction verification logic.
216///
217/// **The inherited implication passed as the `implication` parameter to
218/// [validate](TransactionExtension::validate) does not include the extension's inner data itself
219/// nor does it include the result of the extension's `implicit` function.** If you both provide an
220/// implication and rely on the implication, then you need to manually aggregate your extensions
221/// implication with the aggregated implication passed in.
222///
223/// In the post dispatch pipeline, the actual weight of each extension is accrued in the
224/// [PostDispatchInfo](PostDispatchInfoOf<Call>) of that transaction sequentially with each
225/// [post_dispatch](TransactionExtension::post_dispatch) call. This means that an extension handling
226/// transaction payment and refunds should be at the end of the pipeline in order to capture the
227/// correct amount of weight used during the call. This is because one cannot know the actual weight
228/// of an extension after post dispatch without running the post dispatch ahead of time.
229pub trait TransactionExtension<Call: Dispatchable>:
230 Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
231{
232 /// Unique identifier of this signed extension.
233 ///
234 /// This will be exposed in the metadata to identify the signed extension used in an extrinsic.
235 const IDENTIFIER: &'static str;
236
237 /// Any additional data which was known at the time of transaction construction and can be
238 /// useful in authenticating the transaction. This is determined dynamically in part from the
239 /// on-chain environment using the `implicit` function and not directly contained in the
240 /// transaction itself and therefore is considered "implicit".
241 type Implicit: Codec + StaticTypeInfo;
242
243 /// Determine any additional data which was known at the time of transaction construction and
244 /// can be useful in authenticating the transaction. The expected usage of this is to include in
245 /// any data which is signed and verified as part of transaction validation. Also perform any
246 /// pre-signature-verification checks and return an error if needed.
247 fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
248 use crate::transaction_validity::InvalidTransaction::IndeterminateImplicit;
249 Ok(Self::Implicit::decode(&mut &[][..]).map_err(|_| IndeterminateImplicit)?)
250 }
251
252 /// Returns the metadata for this extension.
253 ///
254 /// As a [`TransactionExtension`] can be a tuple of [`TransactionExtension`]s we need to return
255 /// a `Vec` that holds the metadata of each one. Each individual `TransactionExtension` must
256 /// return *exactly* one [`TransactionExtensionMetadata`].
257 ///
258 /// This method provides a default implementation that returns a vec containing a single
259 /// [`TransactionExtensionMetadata`].
260 fn metadata() -> Vec<TransactionExtensionMetadata> {
261 sp_std::vec![TransactionExtensionMetadata {
262 identifier: Self::IDENTIFIER,
263 ty: scale_info::meta_type::<Self>(),
264 implicit: scale_info::meta_type::<Self::Implicit>()
265 }]
266 }
267
268 /// The type that encodes information that can be passed from `validate` to `prepare`.
269 type Val;
270
271 /// The type that encodes information that can be passed from `prepare` to `post_dispatch`.
272 type Pre;
273
274 /// The weight consumed by executing this extension instance fully during transaction dispatch.
275 fn weight(&self, call: &Call) -> Weight;
276
277 /// Validate a transaction for the transaction queue.
278 ///
279 /// This function can be called frequently by the transaction queue to obtain transaction
280 /// validity against current state. It should perform all checks that determine a valid
281 /// transaction, that can pay for its execution and quickly eliminate ones that are stale or
282 /// incorrect.
283 ///
284 /// Parameters:
285 /// - `origin`: The origin of the transaction which this extension inherited; coming from an
286 /// "old-school" *signed transaction*, this will be a system `RawOrigin::Signed` value. If the
287 /// transaction is a "new-school" *General Transaction*, then this will be a system
288 /// `RawOrigin::None` value. If this extension is an item in a composite, then it could be
289 /// anything which was previously returned as an `origin` value in the result of a `validate`
290 /// call.
291 /// - `call`: The `Call` wrapped by this extension.
292 /// - `info`: Information concerning, and inherent to, the transaction's call.
293 /// - `len`: The total length of the encoded transaction.
294 /// - `inherited_implication`: The *implication* which this extension inherits. This is a tuple
295 /// of the transaction's call and some additional opaque-but-encodable data. Coming directly
296 /// from a transaction, the latter is [()]. However, if this extension is expressed as part of
297 /// a composite type, then the latter component is equal to any further implications to which
298 /// the returned `origin` could potentially apply. See Pipelines, Inherited Implications, and
299 /// Authorized Origins for more information.
300 ///
301 /// Returns a [ValidateResult], which is a [Result] whose success type is a tuple of
302 /// [ValidTransaction] (defining useful metadata for the transaction queue), the [Self::Val]
303 /// token of this transaction, which gets passed into [prepare](TransactionExtension::prepare),
304 /// and the origin of the transaction, which gets passed into
305 /// [prepare](TransactionExtension::prepare) and is ultimately used for dispatch.
306 fn validate(
307 &self,
308 origin: DispatchOriginOf<Call>,
309 call: &Call,
310 info: &DispatchInfoOf<Call>,
311 len: usize,
312 self_implicit: Self::Implicit,
313 inherited_implication: &impl Implication,
314 source: TransactionSource,
315 ) -> ValidateResult<Self::Val, Call>;
316
317 /// Do any pre-flight stuff for a transaction after validation.
318 ///
319 /// This is for actions which do not happen in the transaction queue but only immediately prior
320 /// to the point of dispatch on-chain. This should not return an error, since errors should
321 /// already have been identified during the [validate](TransactionExtension::validate) call. If
322 /// an error is returned, the transaction will be considered invalid but no state changes will
323 /// happen and therefore work done in [validate](TransactionExtension::validate) will not be
324 /// paid for.
325 ///
326 /// Unlike `validate`, this function may consume `self`.
327 ///
328 /// Parameters:
329 /// - `val`: `Self::Val` returned by the result of the `validate` call.
330 /// - `origin`: The origin returned by the result of the `validate` call.
331 /// - `call`: The `Call` wrapped by this extension.
332 /// - `info`: Information concerning, and inherent to, the transaction's call.
333 /// - `len`: The total length of the encoded transaction.
334 ///
335 /// Returns a [Self::Pre] value on success, which gets passed into
336 /// [post_dispatch](TransactionExtension::post_dispatch) and after the call is dispatched.
337 ///
338 /// IMPORTANT: **Checks made in validation need not be repeated here.**
339 fn prepare(
340 self,
341 val: Self::Val,
342 origin: &DispatchOriginOf<Call>,
343 call: &Call,
344 info: &DispatchInfoOf<Call>,
345 len: usize,
346 ) -> Result<Self::Pre, TransactionValidityError>;
347
348 /// Do any post-flight stuff for an extrinsic.
349 ///
350 /// `_pre` contains the output of `prepare`.
351 ///
352 /// This gets given the `DispatchResult` `_result` from the extrinsic and can, if desired,
353 /// introduce a `TransactionValidityError`, causing the block to become invalid for including
354 /// it.
355 ///
356 /// On success, the caller must return the amount of unspent weight left over by this extension
357 /// after dispatch. By default, this function returns no unspent weight, which means the entire
358 /// weight computed for the worst case scenario is consumed.
359 ///
360 /// WARNING: This function does not automatically keep track of accumulated "actual" weight.
361 /// Unless this weight is handled at the call site, use
362 /// [post_dispatch](TransactionExtension::post_dispatch)
363 /// instead.
364 ///
365 /// Parameters:
366 /// - `pre`: `Self::Pre` returned by the result of the `prepare` call prior to dispatch.
367 /// - `info`: Information concerning, and inherent to, the transaction's call.
368 /// - `post_info`: Information concerning the dispatch of the transaction's call.
369 /// - `len`: The total length of the encoded transaction.
370 /// - `result`: The result of the dispatch.
371 ///
372 /// WARNING: It is dangerous to return an error here. To do so will fundamentally invalidate the
373 /// transaction and any block that it is included in, causing the block author to not be
374 /// compensated for their work in validating the transaction or producing the block so far. It
375 /// can only be used safely when you *know* that the transaction is one that would only be
376 /// introduced by the current block author.
377 fn post_dispatch_details(
378 _pre: Self::Pre,
379 _info: &DispatchInfoOf<Call>,
380 _post_info: &PostDispatchInfoOf<Call>,
381 _len: usize,
382 _result: &DispatchResult,
383 ) -> Result<Weight, TransactionValidityError> {
384 Ok(Weight::zero())
385 }
386
387 /// A wrapper for [`post_dispatch_details`](TransactionExtension::post_dispatch_details) that
388 /// refunds the unspent weight consumed by this extension into the post dispatch information.
389 ///
390 /// If `post_dispatch_details` returns a non-zero unspent weight, which, by definition, must be
391 /// less than the worst case weight provided by [weight](TransactionExtension::weight), that
392 /// is the value refunded in `post_info`.
393 ///
394 /// If no unspent weight is reported by `post_dispatch_details`, this function assumes the worst
395 /// case weight and does not refund anything.
396 ///
397 /// For more information, look into
398 /// [post_dispatch_details](TransactionExtension::post_dispatch_details).
399 fn post_dispatch(
400 pre: Self::Pre,
401 info: &DispatchInfoOf<Call>,
402 post_info: &mut PostDispatchInfoOf<Call>,
403 len: usize,
404 result: &DispatchResult,
405 ) -> Result<(), TransactionValidityError> {
406 let unspent_weight = Self::post_dispatch_details(pre, info, &post_info, len, result)?;
407 post_info.refund(unspent_weight);
408
409 Ok(())
410 }
411
412 /// Validation logic for bare extrinsics.
413 ///
414 /// NOTE: This function will be migrated to a separate `InherentExtension` interface.
415 fn bare_validate(
416 _call: &Call,
417 _info: &DispatchInfoOf<Call>,
418 _len: usize,
419 ) -> TransactionValidity {
420 Ok(ValidTransaction::default())
421 }
422
423 /// All pre-flight logic run before dispatching bare extrinsics.
424 ///
425 /// NOTE: This function will be migrated to a separate `InherentExtension` interface.
426 fn bare_validate_and_prepare(
427 _call: &Call,
428 _info: &DispatchInfoOf<Call>,
429 _len: usize,
430 ) -> Result<(), TransactionValidityError> {
431 Ok(())
432 }
433
434 /// Post dispatch logic run after dispatching bare extrinsics.
435 ///
436 /// NOTE: This function will be migrated to a separate `InherentExtension` interface.
437 fn bare_post_dispatch(
438 _info: &DispatchInfoOf<Call>,
439 _post_info: &mut PostDispatchInfoOf<Call>,
440 _len: usize,
441 _result: &DispatchResult,
442 ) -> Result<(), TransactionValidityError> {
443 Ok(())
444 }
445}
446
447/// Helper macro to be used in a `impl TransactionExtension` block to add default implementations of
448/// `weight`, `validate`, `prepare` or any combinations of the them.
449///
450/// The macro is to be used with 2 parameters, separated by ";":
451/// - the `Call` type;
452/// - the functions for which a default implementation should be generated, separated by " ";
453/// available options are `weight`, `validate` and `prepare`.
454///
455/// Example usage:
456/// ```nocompile
457/// impl TransactionExtension<FirstCall> for EmptyExtension {
458/// type Val = ();
459/// type Pre = ();
460///
461/// impl_tx_ext_default!(FirstCall; weight validate prepare);
462/// }
463///
464/// impl TransactionExtension<SecondCall> for SimpleExtension {
465/// type Val = u32;
466/// type Pre = ();
467///
468/// fn weight(&self, _: &SecondCall) -> Weight {
469/// Weight::zero()
470/// }
471///
472/// fn validate(
473/// &self,
474/// _origin: <T as Config>::RuntimeOrigin,
475/// _call: &SecondCall,
476/// _info: &DispatchInfoOf<SecondCall>,
477/// _len: usize,
478/// _self_implicit: Self::Implicit,
479/// _inherited_implication: &impl Encode,
480/// ) -> ValidateResult<Self::Val, SecondCall> {
481/// Ok((Default::default(), 42u32, origin))
482/// }
483///
484/// impl_tx_ext_default!(SecondCall; prepare);
485/// }
486/// ```
487#[macro_export]
488macro_rules! impl_tx_ext_default {
489 ($call:ty ; , $( $rest:tt )*) => {
490 impl_tx_ext_default!{$call ; $( $rest )*}
491 };
492 ($call:ty ; validate $( $rest:tt )*) => {
493 fn validate(
494 &self,
495 origin: $crate::traits::DispatchOriginOf<$call>,
496 _call: &$call,
497 _info: &$crate::traits::DispatchInfoOf<$call>,
498 _len: usize,
499 _self_implicit: Self::Implicit,
500 _inherited_implication: &impl $crate::codec::Encode,
501 _source: $crate::transaction_validity::TransactionSource,
502 ) -> $crate::traits::ValidateResult<Self::Val, $call> {
503 Ok((Default::default(), Default::default(), origin))
504 }
505 impl_tx_ext_default!{$call ; $( $rest )*}
506 };
507 ($call:ty ; prepare $( $rest:tt )*) => {
508 fn prepare(
509 self,
510 _val: Self::Val,
511 _origin: &$crate::traits::DispatchOriginOf<$call>,
512 _call: &$call,
513 _info: &$crate::traits::DispatchInfoOf<$call>,
514 _len: usize,
515 ) -> Result<Self::Pre, $crate::transaction_validity::TransactionValidityError> {
516 Ok(Default::default())
517 }
518 impl_tx_ext_default!{$call ; $( $rest )*}
519 };
520 ($call:ty ; weight $( $rest:tt )*) => {
521 fn weight(&self, _call: &$call) -> $crate::Weight {
522 $crate::Weight::zero()
523 }
524 impl_tx_ext_default!{$call ; $( $rest )*}
525 };
526 ($call:ty ;) => {};
527}
528
529/// Information about a [`TransactionExtension`] for the runtime metadata.
530pub struct TransactionExtensionMetadata {
531 /// The unique identifier of the [`TransactionExtension`].
532 pub identifier: &'static str,
533 /// The type of the [`TransactionExtension`].
534 pub ty: MetaType,
535 /// The type of the [`TransactionExtension`] additional signed data for the payload.
536 pub implicit: MetaType,
537}
538
539#[impl_for_tuples(1, 12)]
540impl<Call: Dispatchable> TransactionExtension<Call> for Tuple {
541 const IDENTIFIER: &'static str = "Use `metadata()`!";
542 for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); );
543 fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
544 Ok(for_tuples!( ( #( Tuple.implicit()? ),* ) ))
545 }
546 fn metadata() -> Vec<TransactionExtensionMetadata> {
547 let mut ids = Vec::new();
548 for_tuples!( #( ids.extend(Tuple::metadata()); )* );
549 ids
550 }
551
552 for_tuples!( type Val = ( #( Tuple::Val ),* ); );
553 for_tuples!( type Pre = ( #( Tuple::Pre ),* ); );
554
555 fn weight(&self, call: &Call) -> Weight {
556 let mut weight = Weight::zero();
557 for_tuples!( #( weight = weight.saturating_add(Tuple.weight(call)); )* );
558 weight
559 }
560
561 fn validate(
562 &self,
563 origin: <Call as Dispatchable>::RuntimeOrigin,
564 call: &Call,
565 info: &DispatchInfoOf<Call>,
566 len: usize,
567 self_implicit: Self::Implicit,
568 inherited_implication: &impl Implication,
569 source: TransactionSource,
570 ) -> Result<
571 (ValidTransaction, Self::Val, <Call as Dispatchable>::RuntimeOrigin),
572 TransactionValidityError,
573 > {
574 let valid = ValidTransaction::default();
575 let val = ();
576 let following_explicit_implications = for_tuples!( ( #( &self.Tuple ),* ) );
577 let following_implicit_implications = self_implicit;
578
579 let implication_parts = inherited_implication.parts();
580
581 for_tuples!(#(
582 // Implication of this pipeline element not relevant for later items, so we pop it.
583 let (_item, following_explicit_implications) = following_explicit_implications.pop_front();
584 let (item_implicit, following_implicit_implications) = following_implicit_implications.pop_front();
585 let (item_valid, item_val, origin) = {
586 Tuple.validate(origin, call, info, len, item_implicit,
587 &ImplicationParts {
588 base: implication_parts.base,
589 explicit: (&following_explicit_implications, implication_parts.explicit),
590 implicit: (&following_implicit_implications, implication_parts.implicit),
591 },
592 source)?
593 };
594 let valid = valid.combine_with(item_valid);
595 let val = val.push_back(item_val);
596 )* );
597 Ok((valid, val, origin))
598 }
599
600 fn prepare(
601 self,
602 val: Self::Val,
603 origin: &<Call as Dispatchable>::RuntimeOrigin,
604 call: &Call,
605 info: &DispatchInfoOf<Call>,
606 len: usize,
607 ) -> Result<Self::Pre, TransactionValidityError> {
608 Ok(for_tuples!( ( #(
609 Tuple::prepare(self.Tuple, val.Tuple, origin, call, info, len)?
610 ),* ) ))
611 }
612
613 fn post_dispatch_details(
614 pre: Self::Pre,
615 info: &DispatchInfoOf<Call>,
616 post_info: &PostDispatchInfoOf<Call>,
617 len: usize,
618 result: &DispatchResult,
619 ) -> Result<Weight, TransactionValidityError> {
620 let mut total_unspent_weight = Weight::zero();
621 for_tuples!( #({
622 let unspent_weight = Tuple::post_dispatch_details(pre.Tuple, info, post_info, len, result)?;
623 total_unspent_weight = total_unspent_weight.saturating_add(unspent_weight);
624 })* );
625 Ok(total_unspent_weight)
626 }
627
628 fn post_dispatch(
629 pre: Self::Pre,
630 info: &DispatchInfoOf<Call>,
631 post_info: &mut PostDispatchInfoOf<Call>,
632 len: usize,
633 result: &DispatchResult,
634 ) -> Result<(), TransactionValidityError> {
635 for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result)?; )* );
636 Ok(())
637 }
638
639 fn bare_validate(call: &Call, info: &DispatchInfoOf<Call>, len: usize) -> TransactionValidity {
640 let valid = ValidTransaction::default();
641 for_tuples!(#(
642 let item_valid = Tuple::bare_validate(call, info, len)?;
643 let valid = valid.combine_with(item_valid);
644 )* );
645 Ok(valid)
646 }
647
648 fn bare_validate_and_prepare(
649 call: &Call,
650 info: &DispatchInfoOf<Call>,
651 len: usize,
652 ) -> Result<(), TransactionValidityError> {
653 for_tuples!( #( Tuple::bare_validate_and_prepare(call, info, len)?; )* );
654 Ok(())
655 }
656
657 fn bare_post_dispatch(
658 info: &DispatchInfoOf<Call>,
659 post_info: &mut PostDispatchInfoOf<Call>,
660 len: usize,
661 result: &DispatchResult,
662 ) -> Result<(), TransactionValidityError> {
663 for_tuples!( #( Tuple::bare_post_dispatch(info, post_info, len, result)?; )* );
664 Ok(())
665 }
666}
667
668impl<Call: Dispatchable> TransactionExtension<Call> for () {
669 const IDENTIFIER: &'static str = "UnitTransactionExtension";
670 type Implicit = ();
671 fn implicit(&self) -> sp_std::result::Result<Self::Implicit, TransactionValidityError> {
672 Ok(())
673 }
674 type Val = ();
675 type Pre = ();
676 fn weight(&self, _call: &Call) -> Weight {
677 Weight::zero()
678 }
679 fn validate(
680 &self,
681 origin: <Call as Dispatchable>::RuntimeOrigin,
682 _call: &Call,
683 _info: &DispatchInfoOf<Call>,
684 _len: usize,
685 _self_implicit: Self::Implicit,
686 _inherited_implication: &impl Implication,
687 _source: TransactionSource,
688 ) -> Result<
689 (ValidTransaction, (), <Call as Dispatchable>::RuntimeOrigin),
690 TransactionValidityError,
691 > {
692 Ok((ValidTransaction::default(), (), origin))
693 }
694 fn prepare(
695 self,
696 _val: (),
697 _origin: &<Call as Dispatchable>::RuntimeOrigin,
698 _call: &Call,
699 _info: &DispatchInfoOf<Call>,
700 _len: usize,
701 ) -> Result<(), TransactionValidityError> {
702 Ok(())
703 }
704}
705
706#[cfg(test)]
707mod test {
708 use super::*;
709
710 #[test]
711 fn test_implications_on_nested_structure() {
712 use scale_info::TypeInfo;
713 use std::cell::RefCell;
714
715 #[derive(Clone, Debug, Eq, PartialEq, Encode, Decode, TypeInfo)]
716 struct MockExtension {
717 also_implicit: u8,
718 explicit: u8,
719 }
720
721 const CALL_IMPLICIT: u8 = 23;
722
723 thread_local! {
724 static COUNTER: RefCell<u8> = RefCell::new(1);
725 }
726
727 impl TransactionExtension<()> for MockExtension {
728 const IDENTIFIER: &'static str = "MockExtension";
729 type Implicit = u8;
730 fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
731 Ok(self.also_implicit)
732 }
733 type Val = ();
734 type Pre = ();
735 fn weight(&self, _call: &()) -> Weight {
736 Weight::zero()
737 }
738 fn prepare(
739 self,
740 _val: Self::Val,
741 _origin: &DispatchOriginOf<()>,
742 _call: &(),
743 _info: &DispatchInfoOf<()>,
744 _len: usize,
745 ) -> Result<Self::Pre, TransactionValidityError> {
746 Ok(())
747 }
748 fn validate(
749 &self,
750 origin: DispatchOriginOf<()>,
751 _call: &(),
752 _info: &DispatchInfoOf<()>,
753 _len: usize,
754 self_implicit: Self::Implicit,
755 inherited_implication: &impl Implication,
756 _source: TransactionSource,
757 ) -> ValidateResult<Self::Val, ()> {
758 COUNTER.with(|c| {
759 let mut counter = c.borrow_mut();
760
761 assert_eq!(self_implicit, *counter);
762 assert_eq!(
763 self,
764 &MockExtension { also_implicit: *counter, explicit: *counter + 1 }
765 );
766
767 // Implications must be call then 1 to 22 then 1 to 22 odd.
768 let mut assert_implications = Vec::new();
769 assert_implications.push(CALL_IMPLICIT);
770 for i in *counter + 2..23 {
771 assert_implications.push(i);
772 }
773 for i in *counter + 2..23 {
774 if i % 2 == 1 {
775 assert_implications.push(i);
776 }
777 }
778 assert_eq!(inherited_implication.encode(), assert_implications);
779
780 *counter += 2;
781 });
782 Ok((ValidTransaction::default(), (), origin))
783 }
784 fn post_dispatch_details(
785 _pre: Self::Pre,
786 _info: &DispatchInfoOf<()>,
787 _post_info: &PostDispatchInfoOf<()>,
788 _len: usize,
789 _result: &DispatchResult,
790 ) -> Result<Weight, TransactionValidityError> {
791 Ok(Weight::zero())
792 }
793 }
794
795 // Test for one nested structure
796
797 let ext = (
798 MockExtension { also_implicit: 1, explicit: 2 },
799 MockExtension { also_implicit: 3, explicit: 4 },
800 (
801 MockExtension { also_implicit: 5, explicit: 6 },
802 MockExtension { also_implicit: 7, explicit: 8 },
803 (
804 MockExtension { also_implicit: 9, explicit: 10 },
805 MockExtension { also_implicit: 11, explicit: 12 },
806 ),
807 MockExtension { also_implicit: 13, explicit: 14 },
808 MockExtension { also_implicit: 15, explicit: 16 },
809 ),
810 MockExtension { also_implicit: 17, explicit: 18 },
811 (MockExtension { also_implicit: 19, explicit: 20 },),
812 MockExtension { also_implicit: 21, explicit: 22 },
813 );
814
815 let implicit = ext.implicit().unwrap();
816
817 let res = ext
818 .validate(
819 (),
820 &(),
821 &DispatchInfoOf::<()>::default(),
822 0,
823 implicit,
824 &TxBaseImplication(CALL_IMPLICIT),
825 TransactionSource::Local,
826 )
827 .expect("valid");
828
829 assert_eq!(res.0, ValidTransaction::default());
830
831 // Test for another nested structure
832
833 COUNTER.with(|c| {
834 *c.borrow_mut() = 1;
835 });
836
837 let ext = (
838 MockExtension { also_implicit: 1, explicit: 2 },
839 MockExtension { also_implicit: 3, explicit: 4 },
840 MockExtension { also_implicit: 5, explicit: 6 },
841 MockExtension { also_implicit: 7, explicit: 8 },
842 MockExtension { also_implicit: 9, explicit: 10 },
843 MockExtension { also_implicit: 11, explicit: 12 },
844 (
845 MockExtension { also_implicit: 13, explicit: 14 },
846 MockExtension { also_implicit: 15, explicit: 16 },
847 MockExtension { also_implicit: 17, explicit: 18 },
848 MockExtension { also_implicit: 19, explicit: 20 },
849 MockExtension { also_implicit: 21, explicit: 22 },
850 ),
851 );
852
853 let implicit = ext.implicit().unwrap();
854
855 let res = ext
856 .validate(
857 (),
858 &(),
859 &DispatchInfoOf::<()>::default(),
860 0,
861 implicit,
862 &TxBaseImplication(CALL_IMPLICIT),
863 TransactionSource::Local,
864 )
865 .expect("valid");
866
867 assert_eq!(res.0, ValidTransaction::default());
868 }
869}