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 super::{
21 DispatchInfoOf, DispatchOriginOf, Dispatchable, ExtensionPostDispatchWeightHandler,
22 PostDispatchInfoOf, RefundWeight,
23};
24use crate::{
25 scale_info::{MetaType, StaticTypeInfo},
26 transaction_validity::{
27 TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction,
28 },
29 DispatchResult,
30};
31use alloc::vec::Vec;
32use codec::{Codec, Decode, DecodeWithMemTracking, Encode};
33use core::fmt::Debug;
34#[doc(hidden)]
35pub use core::marker::PhantomData;
36use impl_trait_for_tuples::impl_for_tuples;
37use sp_weights::Weight;
38use tuplex::{PopFront, PushBack};
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 + DecodeWithMemTracking + 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 alloc::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 $crate::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 $crate::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 $crate::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 $crate::impl_tx_ext_default!{$call ; $( $rest )*}
525 };
526 ($call:ty ;) => {};
527}
528
529/// Information about a [`TransactionExtension`] for the runtime metadata.
530#[derive(Clone)]
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}