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