mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 14:41:11 +00:00
This PR reverts #2280 which introduced `TransactionExtension` to replace `SignedExtension`. As a result of the discussion [here](https://github.com/paritytech/polkadot-sdk/pull/3623#issuecomment-1986789700), the changes will be reverted for now with plans to reintroduce the concept in the future. --------- Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
This commit is contained in:
@@ -18,115 +18,81 @@
|
||||
//! Generic implementation of an extrinsic that has passed the verification
|
||||
//! stage.
|
||||
|
||||
use codec::Encode;
|
||||
|
||||
use crate::{
|
||||
traits::{
|
||||
self, transaction_extension::TransactionExtension, DispatchInfoOf, DispatchTransaction,
|
||||
Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf, ValidateUnsigned,
|
||||
self, DispatchInfoOf, Dispatchable, MaybeDisplay, Member, PostDispatchInfoOf,
|
||||
SignedExtension, ValidateUnsigned,
|
||||
},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
};
|
||||
|
||||
/// The kind of extrinsic this is, including any fields required of that kind. This is basically
|
||||
/// the full extrinsic except the `Call`.
|
||||
#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)]
|
||||
pub enum ExtrinsicFormat<AccountId, Extension> {
|
||||
/// Extrinsic is bare; it must pass either the bare forms of `TransactionExtension` or
|
||||
/// `ValidateUnsigned`, both deprecated, or alternatively a `ProvideInherent`.
|
||||
Bare,
|
||||
/// Extrinsic has a default `Origin` of `Signed(AccountId)` and must pass all
|
||||
/// `TransactionExtension`s regular checks and includes all extension data.
|
||||
Signed(AccountId, Extension),
|
||||
/// Extrinsic has a default `Origin` of `None` and must pass all `TransactionExtension`s.
|
||||
/// regular checks and includes all extension data.
|
||||
General(Extension),
|
||||
}
|
||||
|
||||
// TODO: Rename ValidateUnsigned to ValidateInherent
|
||||
// TODO: Consider changing ValidateInherent API to avoid need for duplicating validate
|
||||
// code into pre_dispatch (rename that to `prepare`).
|
||||
// TODO: New extrinsic type corresponding to `ExtrinsicFormat::General`, which is
|
||||
// unsigned but includes extension data.
|
||||
// TODO: Move usage of `signed` to `format`:
|
||||
// - Inherent instead of None.
|
||||
// - Signed(id, extension) instead of Some((id, extra)).
|
||||
// - Introduce General(extension) for one without a signature.
|
||||
|
||||
/// Definition of something that the external world might want to say; its existence implies that it
|
||||
/// has been checked and is good, particularly with regards to the signature.
|
||||
///
|
||||
/// This is typically passed into [`traits::Applyable::apply`], which should execute
|
||||
/// [`CheckedExtrinsic::function`], alongside all other bits and bobs.
|
||||
#[derive(PartialEq, Eq, Clone, sp_core::RuntimeDebug)]
|
||||
pub struct CheckedExtrinsic<AccountId, Call, Extension> {
|
||||
pub struct CheckedExtrinsic<AccountId, Call, Extra> {
|
||||
/// Who this purports to be from and the number of extrinsics have come before
|
||||
/// from the same signer, if anyone (note this is not a signature).
|
||||
pub format: ExtrinsicFormat<AccountId, Extension>,
|
||||
pub signed: Option<(AccountId, Extra)>,
|
||||
|
||||
/// The function that should be called.
|
||||
pub function: Call,
|
||||
}
|
||||
|
||||
impl<AccountId, Call, Extension, RuntimeOrigin> traits::Applyable
|
||||
for CheckedExtrinsic<AccountId, Call, Extension>
|
||||
impl<AccountId, Call, Extra, RuntimeOrigin> traits::Applyable
|
||||
for CheckedExtrinsic<AccountId, Call, Extra>
|
||||
where
|
||||
AccountId: Member + MaybeDisplay,
|
||||
Call: Member + Dispatchable<RuntimeOrigin = RuntimeOrigin> + Encode,
|
||||
Extension: TransactionExtension<Call, ()>,
|
||||
Call: Member + Dispatchable<RuntimeOrigin = RuntimeOrigin>,
|
||||
Extra: SignedExtension<AccountId = AccountId, Call = Call>,
|
||||
RuntimeOrigin: From<Option<AccountId>>,
|
||||
{
|
||||
type Call = Call;
|
||||
|
||||
fn validate<I: ValidateUnsigned<Call = Self::Call>>(
|
||||
fn validate<U: ValidateUnsigned<Call = Self::Call>>(
|
||||
&self,
|
||||
// TODO [#5006;ToDr] should source be passed to `SignedExtension`s?
|
||||
// Perhaps a change for 2.0 to avoid breaking too much APIs?
|
||||
source: TransactionSource,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
match self.format {
|
||||
ExtrinsicFormat::Bare => {
|
||||
let inherent_validation = I::validate_unsigned(source, &self.function)?;
|
||||
#[allow(deprecated)]
|
||||
let legacy_validation = Extension::validate_bare_compat(&self.function, info, len)?;
|
||||
Ok(legacy_validation.combine_with(inherent_validation))
|
||||
},
|
||||
ExtrinsicFormat::Signed(ref signer, ref extension) => {
|
||||
let origin = Some(signer.clone()).into();
|
||||
extension.validate_only(origin, &self.function, info, len).map(|x| x.0)
|
||||
},
|
||||
ExtrinsicFormat::General(ref extension) =>
|
||||
extension.validate_only(None.into(), &self.function, info, len).map(|x| x.0),
|
||||
if let Some((ref id, ref extra)) = self.signed {
|
||||
Extra::validate(extra, id, &self.function, info, len)
|
||||
} else {
|
||||
let valid = Extra::validate_unsigned(&self.function, info, len)?;
|
||||
let unsigned_validation = U::validate_unsigned(source, &self.function)?;
|
||||
Ok(valid.combine_with(unsigned_validation))
|
||||
}
|
||||
}
|
||||
|
||||
fn apply<I: ValidateUnsigned<Call = Self::Call>>(
|
||||
fn apply<U: ValidateUnsigned<Call = Self::Call>>(
|
||||
self,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>> {
|
||||
match self.format {
|
||||
ExtrinsicFormat::Bare => {
|
||||
I::pre_dispatch(&self.function)?;
|
||||
// TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension`
|
||||
// or `LegacyExtension` is removed.
|
||||
#[allow(deprecated)]
|
||||
Extension::validate_bare_compat(&self.function, info, len)?;
|
||||
#[allow(deprecated)]
|
||||
Extension::pre_dispatch_bare_compat(&self.function, info, len)?;
|
||||
let res = self.function.dispatch(None.into());
|
||||
let post_info = res.unwrap_or_else(|err| err.post_info);
|
||||
let pd_res = res.map(|_| ()).map_err(|e| e.error);
|
||||
// TODO: Remove below once `pre_dispatch_unsigned` is removed from `LegacyExtension`
|
||||
// or `LegacyExtension` is removed.
|
||||
#[allow(deprecated)]
|
||||
Extension::post_dispatch_bare_compat(info, &post_info, len, &pd_res)?;
|
||||
Ok(res)
|
||||
},
|
||||
ExtrinsicFormat::Signed(signer, extension) =>
|
||||
extension.dispatch_transaction(Some(signer).into(), self.function, info, len),
|
||||
ExtrinsicFormat::General(extension) =>
|
||||
extension.dispatch_transaction(None.into(), self.function, info, len),
|
||||
}
|
||||
let (maybe_who, maybe_pre) = if let Some((id, extra)) = self.signed {
|
||||
let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?;
|
||||
(Some(id), Some(pre))
|
||||
} else {
|
||||
Extra::pre_dispatch_unsigned(&self.function, info, len)?;
|
||||
U::pre_dispatch(&self.function)?;
|
||||
(None, None)
|
||||
};
|
||||
let res = self.function.dispatch(RuntimeOrigin::from(maybe_who));
|
||||
let post_info = match res {
|
||||
Ok(info) => info,
|
||||
Err(err) => err.post_info,
|
||||
};
|
||||
Extra::post_dispatch(
|
||||
maybe_pre,
|
||||
info,
|
||||
&post_info,
|
||||
len,
|
||||
&res.map(|_| ()).map_err(|e| e.error),
|
||||
)?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ mod unchecked_extrinsic;
|
||||
|
||||
pub use self::{
|
||||
block::{Block, BlockId, SignedBlock},
|
||||
checked_extrinsic::{CheckedExtrinsic, ExtrinsicFormat},
|
||||
checked_extrinsic::CheckedExtrinsic,
|
||||
digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId},
|
||||
era::{Era, Phase},
|
||||
header::Header,
|
||||
unchecked_extrinsic::{Preamble, SignedPayload, UncheckedExtrinsic},
|
||||
unchecked_extrinsic::{SignedPayload, UncheckedExtrinsic},
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -125,11 +125,6 @@ pub use sp_arithmetic::{
|
||||
Perquintill, Rational128, Rounding, UpperOf,
|
||||
};
|
||||
|
||||
pub use transaction_validity::{
|
||||
InvalidTransaction, TransactionSource, TransactionValidityError, UnknownTransaction,
|
||||
ValidTransaction,
|
||||
};
|
||||
|
||||
pub use either::Either;
|
||||
|
||||
/// The number of bytes of the module-specific `error` field defined in [`ModuleError`].
|
||||
@@ -448,21 +443,21 @@ impl std::fmt::Display for MultiSigner {
|
||||
impl Verify for MultiSignature {
|
||||
type Signer = MultiSigner;
|
||||
fn verify<L: Lazy<[u8]>>(&self, mut msg: L, signer: &AccountId32) -> bool {
|
||||
match self {
|
||||
Self::Ed25519(ref sig) => match ed25519::Public::from_slice(signer.as_ref()) {
|
||||
match (self, signer) {
|
||||
(Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) {
|
||||
Ok(signer) => sig.verify(msg, &signer),
|
||||
Err(()) => false,
|
||||
},
|
||||
Self::Sr25519(ref sig) => match sr25519::Public::from_slice(signer.as_ref()) {
|
||||
(Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) {
|
||||
Ok(signer) => sig.verify(msg, &signer),
|
||||
Err(()) => false,
|
||||
},
|
||||
Self::Ecdsa(ref sig) => {
|
||||
(Self::Ecdsa(ref sig), who) => {
|
||||
let m = sp_io::hashing::blake2_256(msg.get());
|
||||
match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) {
|
||||
Ok(pubkey) =>
|
||||
&sp_io::hashing::blake2_256(pubkey.as_ref()) ==
|
||||
<dyn AsRef<[u8; 32]>>::as_ref(signer),
|
||||
<dyn AsRef<[u8; 32]>>::as_ref(who),
|
||||
_ => false,
|
||||
}
|
||||
},
|
||||
@@ -949,13 +944,9 @@ impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: OpaqueExtrinsics cannot act like regular extrinsics, right?!
|
||||
impl traits::Extrinsic for OpaqueExtrinsic {
|
||||
type Call = ();
|
||||
type SignaturePayload = ();
|
||||
fn is_bare(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Print something that implements `Printable` from the runtime.
|
||||
|
||||
@@ -21,16 +21,24 @@ use crate::{
|
||||
codec::{Codec, Decode, Encode, MaxEncodedLen},
|
||||
generic,
|
||||
scale_info::TypeInfo,
|
||||
traits::{self, BlakeTwo256, Dispatchable, OpaqueKeys},
|
||||
DispatchResultWithInfo, KeyTypeId,
|
||||
traits::{
|
||||
self, Applyable, BlakeTwo256, Checkable, DispatchInfoOf, Dispatchable, OpaqueKeys,
|
||||
PostDispatchInfoOf, SignaturePayload, SignedExtension, ValidateUnsigned,
|
||||
},
|
||||
transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
|
||||
ApplyExtrinsicResultWithInfo, KeyTypeId,
|
||||
};
|
||||
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize};
|
||||
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use sp_core::{
|
||||
crypto::{key_types, ByteArray, CryptoType, Dummy},
|
||||
U256,
|
||||
};
|
||||
pub use sp_core::{sr25519, H256};
|
||||
use std::{cell::RefCell, fmt::Debug};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
fmt::{self, Debug},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
/// A dummy type which can be used instead of regular cryptographic primitives.
|
||||
///
|
||||
@@ -190,6 +198,42 @@ impl Header {
|
||||
}
|
||||
}
|
||||
|
||||
/// An opaque extrinsic wrapper type.
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)]
|
||||
pub struct ExtrinsicWrapper<Xt>(Xt);
|
||||
|
||||
impl<Xt> traits::Extrinsic for ExtrinsicWrapper<Xt> {
|
||||
type Call = ();
|
||||
type SignaturePayload = ();
|
||||
|
||||
fn is_signed(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<Xt: Encode> serde::Serialize for ExtrinsicWrapper<Xt> {
|
||||
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ::serde::Serializer,
|
||||
{
|
||||
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Xt> From<Xt> for ExtrinsicWrapper<Xt> {
|
||||
fn from(xt: Xt) -> Self {
|
||||
ExtrinsicWrapper(xt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Xt> Deref for ExtrinsicWrapper<Xt> {
|
||||
type Target = Xt;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Testing block
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, TypeInfo)]
|
||||
pub struct Block<Xt> {
|
||||
@@ -239,22 +283,139 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper over a `u64` that can be used as a `RuntimeCall`.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode, TypeInfo)]
|
||||
pub struct MockCallU64(pub u64);
|
||||
/// The signature payload of a `TestXt`.
|
||||
type TxSingaturePayload<Extra> = (u64, Extra);
|
||||
|
||||
impl Dispatchable for MockCallU64 {
|
||||
type RuntimeOrigin = u64;
|
||||
type Config = ();
|
||||
type Info = ();
|
||||
type PostInfo = ();
|
||||
fn dispatch(self, _origin: Self::RuntimeOrigin) -> DispatchResultWithInfo<Self::PostInfo> {
|
||||
Ok(())
|
||||
impl<Extra: TypeInfo> SignaturePayload for TxSingaturePayload<Extra> {
|
||||
type SignatureAddress = u64;
|
||||
type Signature = ();
|
||||
type SignatureExtra = Extra;
|
||||
}
|
||||
|
||||
/// Test transaction, tuple of (sender, call, signed_extra)
|
||||
/// with index only used if sender is some.
|
||||
///
|
||||
/// If sender is some then the transaction is signed otherwise it is unsigned.
|
||||
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
|
||||
pub struct TestXt<Call, Extra> {
|
||||
/// Signature of the extrinsic.
|
||||
pub signature: Option<TxSingaturePayload<Extra>>,
|
||||
/// Call of the extrinsic.
|
||||
pub call: Call,
|
||||
}
|
||||
|
||||
impl<Call, Extra> TestXt<Call, Extra> {
|
||||
/// Create a new `TextXt`.
|
||||
pub fn new(call: Call, signature: Option<(u64, Extra)>) -> Self {
|
||||
Self { call, signature }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for MockCallU64 {
|
||||
fn from(value: u64) -> Self {
|
||||
Self(value)
|
||||
impl<Call, Extra> Serialize for TestXt<Call, Extra>
|
||||
where
|
||||
TestXt<Call, Extra>: Encode,
|
||||
{
|
||||
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.using_encoded(|bytes| seq.serialize_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Call, Extra> Debug for TestXt<Call, Extra> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TestXt({:?}, ...)", self.signature.as_ref().map(|x| &x.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Call: Codec + Sync + Send, Context, Extra> Checkable<Context> for TestXt<Call, Extra> {
|
||||
type Checked = Self;
|
||||
fn check(self, _: &Context) -> Result<Self::Checked, TransactionValidityError> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[cfg(feature = "try-runtime")]
|
||||
fn unchecked_into_checked_i_know_what_i_am_doing(
|
||||
self,
|
||||
_: &Context,
|
||||
) -> Result<Self::Checked, TransactionValidityError> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Call: Codec + Sync + Send + TypeInfo, Extra: TypeInfo> traits::Extrinsic
|
||||
for TestXt<Call, Extra>
|
||||
{
|
||||
type Call = Call;
|
||||
type SignaturePayload = TxSingaturePayload<Extra>;
|
||||
|
||||
fn is_signed(&self) -> Option<bool> {
|
||||
Some(self.signature.is_some())
|
||||
}
|
||||
|
||||
fn new(c: Call, sig: Option<Self::SignaturePayload>) -> Option<Self> {
|
||||
Some(TestXt { signature: sig, call: c })
|
||||
}
|
||||
}
|
||||
|
||||
impl<Call, Extra> traits::ExtrinsicMetadata for TestXt<Call, Extra>
|
||||
where
|
||||
Call: Codec + Sync + Send,
|
||||
Extra: SignedExtension<AccountId = u64, Call = Call>,
|
||||
{
|
||||
type SignedExtensions = Extra;
|
||||
const VERSION: u8 = 0u8;
|
||||
}
|
||||
|
||||
impl<Origin, Call, Extra> Applyable for TestXt<Call, Extra>
|
||||
where
|
||||
Call: 'static
|
||||
+ Sized
|
||||
+ Send
|
||||
+ Sync
|
||||
+ Clone
|
||||
+ Eq
|
||||
+ Codec
|
||||
+ Debug
|
||||
+ Dispatchable<RuntimeOrigin = Origin>,
|
||||
Extra: SignedExtension<AccountId = u64, Call = Call>,
|
||||
Origin: From<Option<u64>>,
|
||||
{
|
||||
type Call = Call;
|
||||
|
||||
/// Checks to see if this is a valid *transaction*. It returns information on it if so.
|
||||
fn validate<U: ValidateUnsigned<Call = Self::Call>>(
|
||||
&self,
|
||||
source: TransactionSource,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
if let Some((ref id, ref extra)) = self.signature {
|
||||
Extra::validate(extra, id, &self.call, info, len)
|
||||
} else {
|
||||
let valid = Extra::validate_unsigned(&self.call, info, len)?;
|
||||
let unsigned_validation = U::validate_unsigned(source, &self.call)?;
|
||||
Ok(valid.combine_with(unsigned_validation))
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
|
||||
/// index and sender.
|
||||
fn apply<U: ValidateUnsigned<Call = Self::Call>>(
|
||||
self,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Self::Call>> {
|
||||
let maybe_who = if let Some((who, extra)) = self.signature {
|
||||
Extra::pre_dispatch(extra, &who, &self.call, info, len)?;
|
||||
Some(who)
|
||||
} else {
|
||||
Extra::pre_dispatch_unsigned(&self.call, info, len)?;
|
||||
U::pre_dispatch(&self.call)?;
|
||||
None
|
||||
};
|
||||
|
||||
Ok(self.call.dispatch(maybe_who.into()))
|
||||
}
|
||||
}
|
||||
|
||||
+148
-100
@@ -19,7 +19,7 @@
|
||||
|
||||
use crate::{
|
||||
generic::Digest,
|
||||
scale_info::{StaticTypeInfo, TypeInfo},
|
||||
scale_info::{MetaType, StaticTypeInfo, TypeInfo},
|
||||
transaction_validity::{
|
||||
TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
|
||||
ValidTransaction,
|
||||
@@ -52,12 +52,6 @@ use std::fmt::Display;
|
||||
#[cfg(feature = "std")]
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod transaction_extension;
|
||||
pub use transaction_extension::{
|
||||
DispatchTransaction, TransactionExtension, TransactionExtensionBase,
|
||||
TransactionExtensionInterior, TransactionExtensionMetadata, ValidateResult,
|
||||
};
|
||||
|
||||
/// A lazy value.
|
||||
pub trait Lazy<T: ?Sized> {
|
||||
/// Get a reference to the underlying value.
|
||||
@@ -1259,7 +1253,7 @@ pub trait Header:
|
||||
// that is then used to define `UncheckedExtrinsic`.
|
||||
// ```ignore
|
||||
// pub type UncheckedExtrinsic =
|
||||
// generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
|
||||
// generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
|
||||
// ```
|
||||
// This `UncheckedExtrinsic` is supplied to the `Block`.
|
||||
// ```ignore
|
||||
@@ -1329,31 +1323,19 @@ pub trait Extrinsic: Sized {
|
||||
|
||||
/// Is this `Extrinsic` signed?
|
||||
/// If no information are available about signed/unsigned, `None` should be returned.
|
||||
#[deprecated = "Use and implement `!is_bare()` instead"]
|
||||
fn is_signed(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns `true` if this `Extrinsic` is bare.
|
||||
fn is_bare(&self) -> bool {
|
||||
#[allow(deprecated)]
|
||||
!self
|
||||
.is_signed()
|
||||
.expect("`is_signed` must return `Some` on production extrinsics; qed")
|
||||
}
|
||||
|
||||
/// Create a new old-school extrinsic, either a bare extrinsic if `_signed_data` is `None` or
|
||||
/// a signed transaction is it is `Some`.
|
||||
#[deprecated = "Use `new_inherent` or the `CreateTransaction` trait instead"]
|
||||
/// Create new instance of the extrinsic.
|
||||
///
|
||||
/// Extrinsics can be split into:
|
||||
/// 1. Inherents (no signature; created by validators during block production)
|
||||
/// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of
|
||||
/// calls) 3. Signed Transactions (with signature; a regular transactions with known origin)
|
||||
fn new(_call: Self::Call, _signed_data: Option<Self::SignaturePayload>) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a new inherent extrinsic.
|
||||
fn new_inherent(function: Self::Call) -> Self {
|
||||
#[allow(deprecated)]
|
||||
Self::new(function, None).expect("Extrinsic must provide inherents; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that acts like a [`SignaturePayload`](Extrinsic::SignaturePayload) of an
|
||||
@@ -1389,8 +1371,7 @@ pub trait ExtrinsicMetadata {
|
||||
const VERSION: u8;
|
||||
|
||||
/// Signed extensions attached to this `Extrinsic`.
|
||||
// TODO: metadata-v16: rename to `Extension`.
|
||||
type Extra;
|
||||
type SignedExtensions: SignedExtension;
|
||||
}
|
||||
|
||||
/// Extract the hashing type for a block.
|
||||
@@ -1475,8 +1456,6 @@ pub trait Dispatchable {
|
||||
-> crate::DispatchResultWithInfo<Self::PostInfo>;
|
||||
}
|
||||
|
||||
/// Shortcut to reference the `Origin` type of a `Dispatchable`.
|
||||
pub type OriginOf<T> = <T as Dispatchable>::RuntimeOrigin;
|
||||
/// Shortcut to reference the `Info` type of a `Dispatchable`.
|
||||
pub type DispatchInfoOf<T> = <T as Dispatchable>::Info;
|
||||
/// Shortcut to reference the `PostInfo` type of a `Dispatchable`.
|
||||
@@ -1495,49 +1474,8 @@ impl Dispatchable for () {
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatchable impl containing an arbitrary value which panics if it actually is dispatched.
|
||||
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
|
||||
pub struct FakeDispatchable<Inner>(pub Inner);
|
||||
impl<Inner> From<Inner> for FakeDispatchable<Inner> {
|
||||
fn from(inner: Inner) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
}
|
||||
impl<Inner> FakeDispatchable<Inner> {
|
||||
/// Take `self` and return the underlying inner value.
|
||||
pub fn deconstruct(self) -> Inner {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
impl<Inner> AsRef<Inner> for FakeDispatchable<Inner> {
|
||||
fn as_ref(&self) -> &Inner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner> Dispatchable for FakeDispatchable<Inner> {
|
||||
type RuntimeOrigin = ();
|
||||
type Config = ();
|
||||
type Info = ();
|
||||
type PostInfo = ();
|
||||
fn dispatch(
|
||||
self,
|
||||
_origin: Self::RuntimeOrigin,
|
||||
) -> crate::DispatchResultWithInfo<Self::PostInfo> {
|
||||
panic!("This implementation should not be used for actual dispatch.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Runtime Origin which includes a System Origin variant whose `AccountId` is the parameter.
|
||||
pub trait AsSystemOriginSigner<AccountId> {
|
||||
/// Extract a reference of the inner value of the System `Origin::Signed` variant, if self has
|
||||
/// that variant.
|
||||
fn as_system_origin_signer(&self) -> Option<&AccountId>;
|
||||
}
|
||||
|
||||
/// Means by which a transaction may be extended. This type embodies both the data and the logic
|
||||
/// that should be additionally associated with the transaction. It should be plain old data.
|
||||
#[deprecated = "Use `TransactionExtension` instead."]
|
||||
pub trait SignedExtension:
|
||||
Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
|
||||
{
|
||||
@@ -1555,7 +1493,7 @@ pub trait SignedExtension:
|
||||
|
||||
/// Any additional data that will go into the signed payload. This may be created dynamically
|
||||
/// from the transaction using the `additional_signed` function.
|
||||
type AdditionalSigned: Codec + TypeInfo;
|
||||
type AdditionalSigned: Encode + TypeInfo;
|
||||
|
||||
/// The type that encodes information that can be passed from pre_dispatch to post-dispatch.
|
||||
type Pre;
|
||||
@@ -1594,6 +1532,38 @@ pub trait SignedExtension:
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError>;
|
||||
|
||||
/// Validate an unsigned transaction for the transaction queue.
|
||||
///
|
||||
/// This function can be called frequently by the transaction queue
|
||||
/// to obtain transaction validity against current state.
|
||||
/// It should perform all checks that determine a valid unsigned transaction,
|
||||
/// and quickly eliminate ones that are stale or incorrect.
|
||||
///
|
||||
/// Make sure to perform the same checks in `pre_dispatch_unsigned` function.
|
||||
fn validate_unsigned(
|
||||
_call: &Self::Call,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(ValidTransaction::default())
|
||||
}
|
||||
|
||||
/// Do any pre-flight stuff for a unsigned transaction.
|
||||
///
|
||||
/// Note this function by default delegates to `validate_unsigned`, so that
|
||||
/// all checks performed for the transaction queue are also performed during
|
||||
/// the dispatch phase (applying the extrinsic).
|
||||
///
|
||||
/// If you ever override this function, you need to make sure to always
|
||||
/// perform the same validation as in `validate_unsigned`.
|
||||
fn pre_dispatch_unsigned(
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Self::validate_unsigned(call, info, len).map(|_| ()).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Do any post-flight stuff for an extrinsic.
|
||||
///
|
||||
/// If the transaction is signed, then `_pre` will contain the output of `pre_dispatch`,
|
||||
@@ -1624,47 +1594,126 @@ pub trait SignedExtension:
|
||||
///
|
||||
/// As a [`SignedExtension`] can be a tuple of [`SignedExtension`]s we need to return a `Vec`
|
||||
/// that holds the metadata of each one. Each individual `SignedExtension` must return
|
||||
/// *exactly* one [`TransactionExtensionMetadata`].
|
||||
/// *exactly* one [`SignedExtensionMetadata`].
|
||||
///
|
||||
/// This method provides a default implementation that returns a vec containing a single
|
||||
/// [`TransactionExtensionMetadata`].
|
||||
fn metadata() -> Vec<TransactionExtensionMetadata> {
|
||||
sp_std::vec![TransactionExtensionMetadata {
|
||||
/// [`SignedExtensionMetadata`].
|
||||
fn metadata() -> Vec<SignedExtensionMetadata> {
|
||||
sp_std::vec![SignedExtensionMetadata {
|
||||
identifier: Self::IDENTIFIER,
|
||||
ty: scale_info::meta_type::<Self>(),
|
||||
additional_signed: scale_info::meta_type::<Self::AdditionalSigned>()
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// Validate an unsigned transaction for the transaction queue.
|
||||
///
|
||||
/// This function can be called frequently by the transaction queue
|
||||
/// to obtain transaction validity against current state.
|
||||
/// It should perform all checks that determine a valid unsigned transaction,
|
||||
/// and quickly eliminate ones that are stale or incorrect.
|
||||
fn validate_unsigned(
|
||||
_call: &Self::Call,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(ValidTransaction::default())
|
||||
/// Information about a [`SignedExtension`] for the runtime metadata.
|
||||
pub struct SignedExtensionMetadata {
|
||||
/// The unique identifier of the [`SignedExtension`].
|
||||
pub identifier: &'static str,
|
||||
/// The type of the [`SignedExtension`].
|
||||
pub ty: MetaType,
|
||||
/// The type of the [`SignedExtension`] additional signed data for the payload.
|
||||
pub additional_signed: MetaType,
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl<AccountId, Call: Dispatchable> SignedExtension for Tuple {
|
||||
for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call,> )* );
|
||||
type AccountId = AccountId;
|
||||
type Call = Call;
|
||||
const IDENTIFIER: &'static str = "You should call `identifier()`!";
|
||||
for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); );
|
||||
for_tuples!( type Pre = ( #( Tuple::Pre ),* ); );
|
||||
|
||||
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
|
||||
Ok(for_tuples!( ( #( Tuple.additional_signed()? ),* ) ))
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
let valid = ValidTransaction::default();
|
||||
for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info, len)?); )* );
|
||||
Ok(valid)
|
||||
}
|
||||
|
||||
fn pre_dispatch(
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) ))
|
||||
}
|
||||
|
||||
fn validate_unsigned(
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
let valid = ValidTransaction::default();
|
||||
for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* );
|
||||
Ok(valid)
|
||||
}
|
||||
|
||||
/// Do any pre-flight stuff for an unsigned transaction.
|
||||
///
|
||||
/// Note this function by default delegates to `validate_unsigned`, so that
|
||||
/// all checks performed for the transaction queue are also performed during
|
||||
/// the dispatch phase (applying the extrinsic).
|
||||
///
|
||||
/// If you ever override this function, you need not perform the same validation as in
|
||||
/// `validate_unsigned`.
|
||||
fn pre_dispatch_unsigned(
|
||||
_call: &Self::Call,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
for_tuples!( #( Tuple::pre_dispatch_unsigned(call, info, len)?; )* );
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn post_dispatch(
|
||||
pre: Option<Self::Pre>,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
post_info: &PostDispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
match pre {
|
||||
Some(x) => {
|
||||
for_tuples!( #( Tuple::post_dispatch(Some(x.Tuple), info, post_info, len, result)?; )* );
|
||||
},
|
||||
None => {
|
||||
for_tuples!( #( Tuple::post_dispatch(None, info, post_info, len, result)?; )* );
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn metadata() -> Vec<SignedExtensionMetadata> {
|
||||
let mut ids = Vec::new();
|
||||
for_tuples!( #( ids.extend(Tuple::metadata()); )* );
|
||||
ids
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedExtension for () {
|
||||
type AccountId = u64;
|
||||
type AdditionalSigned = ();
|
||||
type Call = ();
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "UnitSignedExtension";
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
fn pre_dispatch(
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
self.validate(who, call, info, len).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// An "executable" piece of information, used by the standard Substrate Executive in order to
|
||||
@@ -1713,7 +1762,6 @@ pub trait GetNodeBlockType {
|
||||
/// function is called right before dispatching the call wrapped by an unsigned extrinsic. The
|
||||
/// [`validate_unsigned`](Self::validate_unsigned) function is mainly being used in the context of
|
||||
/// the transaction pool to check the validity of the call wrapped by an unsigned extrinsic.
|
||||
// TODO: Rename to ValidateBareTransaction (or just remove).
|
||||
pub trait ValidateUnsigned {
|
||||
/// The call to validate
|
||||
type Call;
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! The [AsTransactionExtension] adapter struct for adapting [SignedExtension]s to
|
||||
//! [TransactionExtension]s.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use scale_info::TypeInfo;
|
||||
use sp_core::RuntimeDebug;
|
||||
|
||||
use crate::{
|
||||
traits::{AsSystemOriginSigner, SignedExtension, ValidateResult},
|
||||
InvalidTransaction,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Adapter to use a `SignedExtension` in the place of a `TransactionExtension`.
|
||||
#[derive(TypeInfo, Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
|
||||
#[deprecated = "Convert your SignedExtension to a TransactionExtension."]
|
||||
pub struct AsTransactionExtension<SE: SignedExtension>(pub SE);
|
||||
|
||||
impl<SE: SignedExtension + Default> Default for AsTransactionExtension<SE> {
|
||||
fn default() -> Self {
|
||||
Self(SE::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<SE: SignedExtension> From<SE> for AsTransactionExtension<SE> {
|
||||
fn from(value: SE) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<SE: SignedExtension> TransactionExtensionBase for AsTransactionExtension<SE> {
|
||||
const IDENTIFIER: &'static str = SE::IDENTIFIER;
|
||||
type Implicit = SE::AdditionalSigned;
|
||||
|
||||
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
|
||||
self.0.additional_signed()
|
||||
}
|
||||
fn metadata() -> Vec<TransactionExtensionMetadata> {
|
||||
SE::metadata()
|
||||
}
|
||||
}
|
||||
|
||||
impl<SE: SignedExtension, Context> TransactionExtension<SE::Call, Context>
|
||||
for AsTransactionExtension<SE>
|
||||
where
|
||||
<SE::Call as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<SE::AccountId> + Clone,
|
||||
{
|
||||
type Val = ();
|
||||
type Pre = SE::Pre;
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
origin: <SE::Call as Dispatchable>::RuntimeOrigin,
|
||||
call: &SE::Call,
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
_context: &mut Context,
|
||||
_self_implicit: Self::Implicit,
|
||||
_inherited_implication: &impl Encode,
|
||||
) -> ValidateResult<Self::Val, SE::Call> {
|
||||
let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
|
||||
let r = self.0.validate(who, call, info, len)?;
|
||||
Ok((r, (), origin))
|
||||
}
|
||||
|
||||
fn prepare(
|
||||
self,
|
||||
_: (),
|
||||
origin: &<SE::Call as Dispatchable>::RuntimeOrigin,
|
||||
call: &SE::Call,
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
_context: &Context,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?;
|
||||
self.0.pre_dispatch(who, call, info, len)
|
||||
}
|
||||
|
||||
fn post_dispatch(
|
||||
pre: Self::Pre,
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
post_info: &PostDispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
result: &DispatchResult,
|
||||
_context: &Context,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
SE::post_dispatch(Some(pre), info, post_info, len, result)
|
||||
}
|
||||
|
||||
fn validate_bare_compat(
|
||||
call: &SE::Call,
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
SE::validate_unsigned(call, info, len)
|
||||
}
|
||||
|
||||
fn pre_dispatch_bare_compat(
|
||||
call: &SE::Call,
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
SE::pre_dispatch_unsigned(call, info, len)
|
||||
}
|
||||
|
||||
fn post_dispatch_bare_compat(
|
||||
info: &DispatchInfoOf<SE::Call>,
|
||||
post_info: &PostDispatchInfoOf<SE::Call>,
|
||||
len: usize,
|
||||
result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
SE::post_dispatch(None, info, post_info, len, result)
|
||||
}
|
||||
}
|
||||
-141
@@ -1,141 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! The [DispatchTransaction] trait.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Single-function utility trait with a blanket impl over [TransactionExtension] in order to
|
||||
/// provide transaction dispatching functionality. We avoid implementing this directly on the trait
|
||||
/// since we never want it to be overriden by the trait implementation.
|
||||
pub trait DispatchTransaction<Call: Dispatchable> {
|
||||
/// The origin type of the transaction.
|
||||
type Origin;
|
||||
/// The info type.
|
||||
type Info;
|
||||
/// The resultant type.
|
||||
type Result;
|
||||
/// The `Val` of the extension.
|
||||
type Val;
|
||||
/// The `Pre` of the extension.
|
||||
type Pre;
|
||||
/// Just validate a transaction.
|
||||
///
|
||||
/// The is basically the same as [validate](TransactionExtension::validate), except that there
|
||||
/// is no need to supply the bond data.
|
||||
fn validate_only(
|
||||
&self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &Self::Info,
|
||||
len: usize,
|
||||
) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>;
|
||||
/// Prepare and validate a transaction, ready for dispatch.
|
||||
fn validate_and_prepare(
|
||||
self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &Self::Info,
|
||||
len: usize,
|
||||
) -> Result<(Self::Pre, Self::Origin), TransactionValidityError>;
|
||||
/// Dispatch a transaction with the given base origin and call.
|
||||
fn dispatch_transaction(
|
||||
self,
|
||||
origin: Self::Origin,
|
||||
call: Call,
|
||||
info: &Self::Info,
|
||||
len: usize,
|
||||
) -> Self::Result;
|
||||
/// Do everything which would be done in a [dispatch_transaction](Self::dispatch_transaction),
|
||||
/// but instead of executing the call, execute `substitute` instead. Since this doesn't actually
|
||||
/// dispatch the call, it doesn't need to consume it and so `call` can be passed as a reference.
|
||||
fn test_run(
|
||||
self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &Self::Info,
|
||||
len: usize,
|
||||
substitute: impl FnOnce(
|
||||
Self::Origin,
|
||||
) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
|
||||
) -> Self::Result;
|
||||
}
|
||||
|
||||
impl<T: TransactionExtension<Call, ()>, Call: Dispatchable + Encode> DispatchTransaction<Call>
|
||||
for T
|
||||
{
|
||||
type Origin = <Call as Dispatchable>::RuntimeOrigin;
|
||||
type Info = DispatchInfoOf<Call>;
|
||||
type Result = crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Call>>;
|
||||
type Val = T::Val;
|
||||
type Pre = T::Pre;
|
||||
|
||||
fn validate_only(
|
||||
&self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> {
|
||||
self.validate(origin, call, info, len, &mut (), self.implicit()?, call)
|
||||
}
|
||||
fn validate_and_prepare(
|
||||
self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
) -> Result<(T::Pre, Self::Origin), TransactionValidityError> {
|
||||
let (_, val, origin) = self.validate_only(origin, call, info, len)?;
|
||||
let pre = self.prepare(val, &origin, &call, info, len, &())?;
|
||||
Ok((pre, origin))
|
||||
}
|
||||
fn dispatch_transaction(
|
||||
self,
|
||||
origin: <Call as Dispatchable>::RuntimeOrigin,
|
||||
call: Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
) -> Self::Result {
|
||||
let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?;
|
||||
let res = call.dispatch(origin);
|
||||
let post_info = res.unwrap_or_else(|err| err.post_info);
|
||||
let pd_res = res.map(|_| ()).map_err(|e| e.error);
|
||||
T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?;
|
||||
Ok(res)
|
||||
}
|
||||
fn test_run(
|
||||
self,
|
||||
origin: Self::Origin,
|
||||
call: &Call,
|
||||
info: &Self::Info,
|
||||
len: usize,
|
||||
substitute: impl FnOnce(
|
||||
Self::Origin,
|
||||
) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
|
||||
) -> Self::Result {
|
||||
let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?;
|
||||
let res = substitute(origin);
|
||||
let post_info = match res {
|
||||
Ok(info) => info,
|
||||
Err(err) => err.post_info,
|
||||
};
|
||||
let pd_res = res.map(|_| ()).map_err(|e| e.error);
|
||||
T::post_dispatch(pre, info, &post_info, len, &pd_res, &())?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
@@ -1,526 +0,0 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! The transaction extension trait.
|
||||
|
||||
use crate::{
|
||||
scale_info::{MetaType, StaticTypeInfo},
|
||||
transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction},
|
||||
DispatchResult,
|
||||
};
|
||||
use codec::{Codec, Decode, Encode};
|
||||
use impl_trait_for_tuples::impl_for_tuples;
|
||||
#[doc(hidden)]
|
||||
pub use sp_std::marker::PhantomData;
|
||||
use sp_std::{self, fmt::Debug, prelude::*};
|
||||
use sp_weights::Weight;
|
||||
use tuplex::{PopFront, PushBack};
|
||||
|
||||
use super::{DispatchInfoOf, Dispatchable, OriginOf, PostDispatchInfoOf};
|
||||
|
||||
mod as_transaction_extension;
|
||||
mod dispatch_transaction;
|
||||
#[allow(deprecated)]
|
||||
pub use as_transaction_extension::AsTransactionExtension;
|
||||
pub use dispatch_transaction::DispatchTransaction;
|
||||
|
||||
/// Shortcut for the result value of the `validate` function.
|
||||
pub type ValidateResult<Val, Call> =
|
||||
Result<(ValidTransaction, Val, OriginOf<Call>), TransactionValidityError>;
|
||||
|
||||
/// Simple blanket implementation trait to denote the bounds of a type which can be contained within
|
||||
/// a [`TransactionExtension`].
|
||||
pub trait TransactionExtensionInterior:
|
||||
Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo
|
||||
{
|
||||
}
|
||||
impl<T: Codec + Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo>
|
||||
TransactionExtensionInterior for T
|
||||
{
|
||||
}
|
||||
|
||||
/// Base for [TransactionExtension]s; this contains the associated types and does not require any
|
||||
/// generic parameterization.
|
||||
pub trait TransactionExtensionBase: TransactionExtensionInterior {
|
||||
/// Unique identifier of this signed extension.
|
||||
///
|
||||
/// This will be exposed in the metadata to identify the signed extension used in an extrinsic.
|
||||
const IDENTIFIER: &'static str;
|
||||
|
||||
/// Any additional data which was known at the time of transaction construction and can be
|
||||
/// useful in authenticating the transaction. This is determined dynamically in part from the
|
||||
/// on-chain environment using the `implicit` function and not directly contained in the
|
||||
/// transaction itself and therefore is considered "implicit".
|
||||
type Implicit: Codec + StaticTypeInfo;
|
||||
|
||||
/// Determine any additional data which was known at the time of transaction construction and
|
||||
/// can be useful in authenticating the transaction. The expected usage of this is to include in
|
||||
/// any data which is signed and verified as part of transactiob validation. Also perform any
|
||||
/// pre-signature-verification checks and return an error if needed.
|
||||
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
|
||||
use crate::InvalidTransaction::IndeterminateImplicit;
|
||||
Ok(Self::Implicit::decode(&mut &[][..]).map_err(|_| IndeterminateImplicit)?)
|
||||
}
|
||||
|
||||
/// The weight consumed by executing this extension instance fully during transaction dispatch.
|
||||
fn weight(&self) -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
|
||||
/// Returns the metadata for this extension.
|
||||
///
|
||||
/// As a [`TransactionExtension`] can be a tuple of [`TransactionExtension`]s we need to return
|
||||
/// a `Vec` that holds the metadata of each one. Each individual `TransactionExtension` must
|
||||
/// return *exactly* one [`TransactionExtensionMetadata`].
|
||||
///
|
||||
/// This method provides a default implementation that returns a vec containing a single
|
||||
/// [`TransactionExtensionMetadata`].
|
||||
fn metadata() -> Vec<TransactionExtensionMetadata> {
|
||||
sp_std::vec![TransactionExtensionMetadata {
|
||||
identifier: Self::IDENTIFIER,
|
||||
ty: scale_info::meta_type::<Self>(),
|
||||
// TODO: Metadata-v16: Rename to "implicit"
|
||||
additional_signed: scale_info::meta_type::<Self::Implicit>()
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
/// Means by which a transaction may be extended. This type embodies both the data and the logic
|
||||
/// that should be additionally associated with the transaction. It should be plain old data.
|
||||
///
|
||||
/// The simplest transaction extension would be the Unit type (and empty pipeline) `()`. This
|
||||
/// executes no additional logic and implies a dispatch of the transaction's call using the
|
||||
/// inherited origin (either `None` or `Signed`, depending on whether this is a signed or general
|
||||
/// transaction).
|
||||
///
|
||||
/// Transaction extensions are capable of altering certain associated semantics:
|
||||
///
|
||||
/// - They may define the origin with which the transaction's call should be dispatched.
|
||||
/// - They may define various parameters used by the transction queue to determine under what
|
||||
/// conditions the transaction should be retained and introduced on-chain.
|
||||
/// - They may define whether this transaction is acceptable for introduction on-chain at all.
|
||||
///
|
||||
/// Each of these semantics are defined by the `validate` function.
|
||||
///
|
||||
/// **NOTE: Transaction extensions cannot under any circumctances alter the call itself.**
|
||||
///
|
||||
/// Transaction extensions are capable of defining logic which is executed additionally to the
|
||||
/// dispatch of the call:
|
||||
///
|
||||
/// - They may define logic which must be executed prior to the dispatch of the call.
|
||||
/// - They may also define logic which must be executed after the dispatch of the call.
|
||||
///
|
||||
/// Each of these semantics are defined by the `prepare` and `post_dispatch` functions respectively.
|
||||
///
|
||||
/// Finally, transaction extensions may define additional data to help define the implications of
|
||||
/// the logic they introduce. This additional data may be explicitly defined by the transaction
|
||||
/// author (in which case it is included as part of the transaction body), or it may be implicitly
|
||||
/// defined by the transaction extension based around the on-chain state (which the transaction
|
||||
/// author is assumed to know). This data may be utilized by the above logic to alter how a node's
|
||||
/// transaction queue treats this transaction.
|
||||
///
|
||||
/// ## Default implementations
|
||||
///
|
||||
/// Of the 5 functions in this trait, 3 of them must return a value of an associated type on
|
||||
/// success, and none of these types implement [Default] or anything like it. This means that
|
||||
/// default implementations cannot be provided for these functions. However, a macro is provided
|
||||
/// [impl_tx_ext_default](crate::impl_tx_ext_default) which is capable of generating default
|
||||
/// implementations for each of these 3 functions. If you do not wish to introduce additional logic
|
||||
/// into the transaction pipeline, then it is recommended that you use this macro to implement these
|
||||
/// functions.
|
||||
///
|
||||
/// ## Pipelines, Inherited Implications, and Authorized Origins
|
||||
///
|
||||
/// Requiring a single transaction extension to define all of the above semantics would be
|
||||
/// cumbersome and would lead to a lot of boilerplate. Instead, transaction extensions are
|
||||
/// aggregated into pipelines, which are tuples of transaction extensions. Each extension in the
|
||||
/// pipeline is executed in order, and the output of each extension is aggregated and/or relayed as
|
||||
/// the input to the next extension in the pipeline.
|
||||
///
|
||||
/// This ordered composition happens with all datatypes ([Val](TransactionExtension::Val),
|
||||
/// [Pre](TransactionExtension::Pre) and [Implicit](TransactionExtensionBase::Implicit)) as well as
|
||||
/// all functions. There are important consequences stemming from how the composition affects the
|
||||
/// meaning of the `origin` and `implication` parameters as well as the results. Whereas the
|
||||
/// [prepare](TransactionExtension::prepare) and
|
||||
/// [post_dispatch](TransactionExtension::post_dispatch) functions are clear in their meaning, the
|
||||
/// [validate](TransactionExtension::validate) function is fairly sophisticated and warrants
|
||||
/// further explanation.
|
||||
///
|
||||
/// Firstly, the `origin` parameter. The `origin` passed into the first item in a pipeline is simply
|
||||
/// that passed into the tuple itself. It represents an authority who has authorized the implication
|
||||
/// of the transaction, as of the extension it has been passed into *and any further extensions it
|
||||
/// may pass though, all the way to, and including, the transaction's dispatch call itself. Each
|
||||
/// following item in the pipeline is passed the origin which the previous item returned. The origin
|
||||
/// returned from the final item in the pipeline is the origin which is returned by the tuple
|
||||
/// itself.
|
||||
///
|
||||
/// This means that if a constituent extension returns a different origin to the one it was called
|
||||
/// with, then (assuming no other extension changes it further) *this new origin will be used for
|
||||
/// all extensions following it in the pipeline, and will be returned from the pipeline to be used
|
||||
/// as the origin for the call's dispatch*. The call itself as well as all these extensions
|
||||
/// following may each imply consequence for this origin. We call this the *inherited implication*.
|
||||
///
|
||||
/// The *inherited implication* is the cumulated on-chain effects born by whatever origin is
|
||||
/// returned. It is expressed to the [validate](TransactionExtension::validate) function only as the
|
||||
/// `implication` argument which implements the [Encode] trait. A transaction extension may define
|
||||
/// its own implications through its own fields and the
|
||||
/// [implicit](TransactionExtensionBase::implicit) function. This is only utilized by extensions
|
||||
/// which preceed it in a pipeline or, if the transaction is an old-school signed trasnaction, the
|
||||
/// underlying transaction verification logic.
|
||||
///
|
||||
/// **The inherited implication passed as the `implication` parameter to
|
||||
/// [validate](TransactionExtension::validate) does not include the extension's inner data itself
|
||||
/// nor does it include the result of the extension's `implicit` function.** If you both provide an
|
||||
/// implication and rely on the implication, then you need to manually aggregate your extensions
|
||||
/// implication with the aggregated implication passed in.
|
||||
pub trait TransactionExtension<Call: Dispatchable, Context>: TransactionExtensionBase {
|
||||
/// The type that encodes information that can be passed from validate to prepare.
|
||||
type Val;
|
||||
|
||||
/// The type that encodes information that can be passed from prepare to post-dispatch.
|
||||
type Pre;
|
||||
|
||||
/// Validate a transaction for the transaction queue.
|
||||
///
|
||||
/// This function can be called frequently by the transaction queue to obtain transaction
|
||||
/// validity against current state. It should perform all checks that determine a valid
|
||||
/// transaction, that can pay for its execution and quickly eliminate ones that are stale or
|
||||
/// incorrect.
|
||||
///
|
||||
/// Parameters:
|
||||
/// - `origin`: The origin of the transaction which this extension inherited; coming from an
|
||||
/// "old-school" *signed transaction*, this will be a system `RawOrigin::Signed` value. If the
|
||||
/// transaction is a "new-school" *General Transaction*, then this will be a system
|
||||
/// `RawOrigin::None` value. If this extension is an item in a composite, then it could be
|
||||
/// anything which was previously returned as an `origin` value in the result of a `validate`
|
||||
/// call.
|
||||
/// - `call`: The `Call` wrapped by this extension.
|
||||
/// - `info`: Information concerning, and inherent to, the transaction's call.
|
||||
/// - `len`: The total length of the encoded transaction.
|
||||
/// - `inherited_implication`: The *implication* which this extension inherits. This is a tuple
|
||||
/// of the transaction's call and some additional opaque-but-encodable data. Coming directly
|
||||
/// from a transaction, the latter is [()]. However, if this extension is expressed as part of
|
||||
/// a composite type, then the latter component is equal to any further implications to which
|
||||
/// the returned `origin` could potentially apply. See Pipelines, Inherited Implications, and
|
||||
/// Authorized Origins for more information.
|
||||
/// - `context`: Some opaque mutable context, as yet unused.
|
||||
///
|
||||
/// Returns a [ValidateResult], which is a [Result] whose success type is a tuple of
|
||||
/// [ValidTransaction] (defining useful metadata for the transaction queue), the [Self::Val]
|
||||
/// token of this transaction, which gets passed into [prepare](TransactionExtension::prepare),
|
||||
/// and the origin of the transaction, which gets passed into
|
||||
/// [prepare](TransactionExtension::prepare) and is ultimately used for dispatch.
|
||||
fn validate(
|
||||
&self,
|
||||
origin: OriginOf<Call>,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
context: &mut Context,
|
||||
self_implicit: Self::Implicit,
|
||||
inherited_implication: &impl Encode,
|
||||
) -> ValidateResult<Self::Val, Call>;
|
||||
|
||||
/// Do any pre-flight stuff for a transaction after validation.
|
||||
///
|
||||
/// This is for actions which do not happen in the transaction queue but only immediately prior
|
||||
/// to the point of dispatch on-chain. This should not return an error, since errors should
|
||||
/// already have been identified during the [validate](TransactionExtension::validate) call. If
|
||||
/// an error is returned, the transaction will be considered invalid but no state changes will
|
||||
/// happen and therefore work done in [validate](TransactionExtension::validate) will not be
|
||||
/// paid for.
|
||||
///
|
||||
/// Unlike `validate`, this function may consume `self`.
|
||||
///
|
||||
/// Parameters:
|
||||
/// - `val`: `Self::Val` returned by the result of the `validate` call.
|
||||
/// - `origin`: The origin returned by the result of the `validate` call.
|
||||
/// - `call`: The `Call` wrapped by this extension.
|
||||
/// - `info`: Information concerning, and inherent to, the transaction's call.
|
||||
/// - `len`: The total length of the encoded transaction.
|
||||
/// - `context`: Some opaque mutable context, as yet unused.
|
||||
///
|
||||
/// Returns a [Self::Pre] value on success, which gets passed into
|
||||
/// [post_dispatch](TransactionExtension::post_dispatch) and after the call is dispatched.
|
||||
///
|
||||
/// IMPORTANT: **Checks made in validation need not be repeated here.**
|
||||
fn prepare(
|
||||
self,
|
||||
val: Self::Val,
|
||||
origin: &OriginOf<Call>,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
context: &Context,
|
||||
) -> Result<Self::Pre, TransactionValidityError>;
|
||||
|
||||
/// Do any post-flight stuff for an extrinsic.
|
||||
///
|
||||
/// `_pre` contains the output of `prepare`.
|
||||
///
|
||||
/// This gets given the `DispatchResult` `_result` from the extrinsic and can, if desired,
|
||||
/// introduce a `TransactionValidityError`, causing the block to become invalid for including
|
||||
/// it.
|
||||
///
|
||||
/// Parameters:
|
||||
/// - `pre`: `Self::Pre` returned by the result of the `prepare` call prior to dispatch.
|
||||
/// - `info`: Information concerning, and inherent to, the transaction's call.
|
||||
/// - `post_info`: Information concerning the dispatch of the transaction's call.
|
||||
/// - `len`: The total length of the encoded transaction.
|
||||
/// - `result`: The result of the dispatch.
|
||||
/// - `context`: Some opaque mutable context, as yet unused.
|
||||
///
|
||||
/// WARNING: It is dangerous to return an error here. To do so will fundamentally invalidate the
|
||||
/// transaction and any block that it is included in, causing the block author to not be
|
||||
/// compensated for their work in validating the transaction or producing the block so far. It
|
||||
/// can only be used safely when you *know* that the transaction is one that would only be
|
||||
/// introduced by the current block author.
|
||||
fn post_dispatch(
|
||||
_pre: Self::Pre,
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_post_info: &PostDispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
_result: &DispatchResult,
|
||||
_context: &Context,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compatibility function for supporting the `SignedExtension::validate_unsigned` function.
|
||||
///
|
||||
/// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME!
|
||||
#[deprecated = "Only for compatibility. DO NOT USE."]
|
||||
fn validate_bare_compat(
|
||||
_call: &Call,
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(ValidTransaction::default())
|
||||
}
|
||||
|
||||
/// Compatibility function for supporting the `SignedExtension::pre_dispatch_unsigned` function.
|
||||
///
|
||||
/// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME!
|
||||
#[deprecated = "Only for compatibility. DO NOT USE."]
|
||||
fn pre_dispatch_bare_compat(
|
||||
_call: &Call,
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compatibility function for supporting the `SignedExtension::post_dispatch` function where
|
||||
/// `pre` is `None`.
|
||||
///
|
||||
/// DO NOT USE! THIS MAY BE REMOVED AT ANY TIME!
|
||||
#[deprecated = "Only for compatibility. DO NOT USE."]
|
||||
fn post_dispatch_bare_compat(
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_post_info: &PostDispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
_result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Implict
|
||||
#[macro_export]
|
||||
macro_rules! impl_tx_ext_default {
|
||||
($call:ty ; $context:ty ; , $( $rest:tt )*) => {
|
||||
impl_tx_ext_default!{$call ; $context ; $( $rest )*}
|
||||
};
|
||||
($call:ty ; $context:ty ; validate $( $rest:tt )*) => {
|
||||
fn validate(
|
||||
&self,
|
||||
origin: $crate::traits::OriginOf<$call>,
|
||||
_call: &$call,
|
||||
_info: &$crate::traits::DispatchInfoOf<$call>,
|
||||
_len: usize,
|
||||
_context: &mut $context,
|
||||
_self_implicit: Self::Implicit,
|
||||
_inherited_implication: &impl $crate::codec::Encode,
|
||||
) -> $crate::traits::ValidateResult<Self::Val, $call> {
|
||||
Ok((Default::default(), Default::default(), origin))
|
||||
}
|
||||
impl_tx_ext_default!{$call ; $context ; $( $rest )*}
|
||||
};
|
||||
($call:ty ; $context:ty ; prepare $( $rest:tt )*) => {
|
||||
fn prepare(
|
||||
self,
|
||||
_val: Self::Val,
|
||||
_origin: &$crate::traits::OriginOf<$call>,
|
||||
_call: &$call,
|
||||
_info: &$crate::traits::DispatchInfoOf<$call>,
|
||||
_len: usize,
|
||||
_context: & $context,
|
||||
) -> Result<Self::Pre, $crate::TransactionValidityError> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
impl_tx_ext_default!{$call ; $context ; $( $rest )*}
|
||||
};
|
||||
($call:ty ; $context:ty ;) => {};
|
||||
}
|
||||
|
||||
/// Information about a [`TransactionExtension`] for the runtime metadata.
|
||||
pub struct TransactionExtensionMetadata {
|
||||
/// The unique identifier of the [`TransactionExtension`].
|
||||
pub identifier: &'static str,
|
||||
/// The type of the [`TransactionExtension`].
|
||||
pub ty: MetaType,
|
||||
/// The type of the [`TransactionExtension`] additional signed data for the payload.
|
||||
// TODO: Rename "implicit"
|
||||
pub additional_signed: MetaType,
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl TransactionExtensionBase for Tuple {
|
||||
for_tuples!( where #( Tuple: TransactionExtensionBase )* );
|
||||
const IDENTIFIER: &'static str = "Use `metadata()`!";
|
||||
for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); );
|
||||
fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
|
||||
Ok(for_tuples!( ( #( Tuple.implicit()? ),* ) ))
|
||||
}
|
||||
fn weight(&self) -> Weight {
|
||||
let mut weight = Weight::zero();
|
||||
for_tuples!( #( weight += Tuple.weight(); )* );
|
||||
weight
|
||||
}
|
||||
fn metadata() -> Vec<TransactionExtensionMetadata> {
|
||||
let mut ids = Vec::new();
|
||||
for_tuples!( #( ids.extend(Tuple::metadata()); )* );
|
||||
ids
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl<Call: Dispatchable, Context> TransactionExtension<Call, Context> for Tuple {
|
||||
for_tuples!( where #( Tuple: TransactionExtension<Call, Context> )* );
|
||||
for_tuples!( type Val = ( #( Tuple::Val ),* ); );
|
||||
for_tuples!( type Pre = ( #( Tuple::Pre ),* ); );
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
origin: <Call as Dispatchable>::RuntimeOrigin,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
context: &mut Context,
|
||||
self_implicit: Self::Implicit,
|
||||
inherited_implication: &impl Encode,
|
||||
) -> Result<
|
||||
(ValidTransaction, Self::Val, <Call as Dispatchable>::RuntimeOrigin),
|
||||
TransactionValidityError,
|
||||
> {
|
||||
let valid = ValidTransaction::default();
|
||||
let val = ();
|
||||
let following_explicit_implications = for_tuples!( ( #( &self.Tuple ),* ) );
|
||||
let following_implicit_implications = self_implicit;
|
||||
|
||||
for_tuples!(#(
|
||||
// Implication of this pipeline element not relevant for later items, so we pop it.
|
||||
let (_item, following_explicit_implications) = following_explicit_implications.pop_front();
|
||||
let (item_implicit, following_implicit_implications) = following_implicit_implications.pop_front();
|
||||
let (item_valid, item_val, origin) = {
|
||||
let implications = (
|
||||
// The first is the implications born of the fact we return the mutated
|
||||
// origin.
|
||||
inherited_implication,
|
||||
// This is the explicitly made implication born of the fact the new origin is
|
||||
// passed into the next items in this pipeline-tuple.
|
||||
&following_explicit_implications,
|
||||
// This is the implicitly made implication born of the fact the new origin is
|
||||
// passed into the next items in this pipeline-tuple.
|
||||
&following_implicit_implications,
|
||||
);
|
||||
Tuple.validate(origin, call, info, len, context, item_implicit, &implications)?
|
||||
};
|
||||
let valid = valid.combine_with(item_valid);
|
||||
let val = val.push_back(item_val);
|
||||
)* );
|
||||
Ok((valid, val, origin))
|
||||
}
|
||||
|
||||
fn prepare(
|
||||
self,
|
||||
val: Self::Val,
|
||||
origin: &<Call as Dispatchable>::RuntimeOrigin,
|
||||
call: &Call,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
context: &Context,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
Ok(for_tuples!( ( #(
|
||||
Tuple::prepare(self.Tuple, val.Tuple, origin, call, info, len, context)?
|
||||
),* ) ))
|
||||
}
|
||||
|
||||
fn post_dispatch(
|
||||
pre: Self::Pre,
|
||||
info: &DispatchInfoOf<Call>,
|
||||
post_info: &PostDispatchInfoOf<Call>,
|
||||
len: usize,
|
||||
result: &DispatchResult,
|
||||
context: &Context,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result, context)?; )* );
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TransactionExtensionBase for () {
|
||||
const IDENTIFIER: &'static str = "UnitTransactionExtension";
|
||||
type Implicit = ();
|
||||
fn implicit(&self) -> sp_std::result::Result<Self::Implicit, TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
fn weight(&self) -> Weight {
|
||||
Weight::zero()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Call: Dispatchable, Context> TransactionExtension<Call, Context> for () {
|
||||
type Val = ();
|
||||
type Pre = ();
|
||||
fn validate(
|
||||
&self,
|
||||
origin: <Call as Dispatchable>::RuntimeOrigin,
|
||||
_call: &Call,
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
_context: &mut Context,
|
||||
_self_implicit: Self::Implicit,
|
||||
_inherited_implication: &impl Encode,
|
||||
) -> Result<
|
||||
(ValidTransaction, (), <Call as Dispatchable>::RuntimeOrigin),
|
||||
TransactionValidityError,
|
||||
> {
|
||||
Ok((ValidTransaction::default(), (), origin))
|
||||
}
|
||||
fn prepare(
|
||||
self,
|
||||
_val: (),
|
||||
_origin: &<Call as Dispatchable>::RuntimeOrigin,
|
||||
_call: &Call,
|
||||
_info: &DispatchInfoOf<Call>,
|
||||
_len: usize,
|
||||
_context: &Context,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -82,8 +82,6 @@ pub enum InvalidTransaction {
|
||||
MandatoryValidation,
|
||||
/// The sending address is disabled or known to be invalid.
|
||||
BadSigner,
|
||||
/// The implicit data was unable to be calculated.
|
||||
IndeterminateImplicit,
|
||||
}
|
||||
|
||||
impl InvalidTransaction {
|
||||
@@ -115,8 +113,6 @@ impl From<InvalidTransaction> for &'static str {
|
||||
"Transaction dispatch is mandatory; transactions must not be validated.",
|
||||
InvalidTransaction::Custom(_) => "InvalidTransaction custom error",
|
||||
InvalidTransaction::BadSigner => "Invalid signing address",
|
||||
InvalidTransaction::IndeterminateImplicit =>
|
||||
"The implicit data was unable to be calculated",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +338,7 @@ pub struct ValidTransactionBuilder {
|
||||
impl ValidTransactionBuilder {
|
||||
/// Set the priority of a transaction.
|
||||
///
|
||||
/// Note that the final priority for `FRAME` is combined from all `TransactionExtension`s.
|
||||
/// Note that the final priority for `FRAME` is combined from all `SignedExtension`s.
|
||||
/// Most likely for unsigned transactions you want the priority to be higher
|
||||
/// than for regular transactions. We recommend exposing a base priority for unsigned
|
||||
/// transactions as a runtime module parameter, so that the runtime can tune inter-module
|
||||
|
||||
Reference in New Issue
Block a user