mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
Refactor SignedExtension (#5540)
* Refactor SignedExtension * Move DispatchInfo Associated type to Dispatchable * Bound Call: Dispatchable * Pass PostDispatchInfo to post_dispatch * Pass DispatchInfo by reference to avoid clones * Whitespace fix Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * Style changes from code review Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Only decalre in test mod to remove warning * Deduplicate Call definition * Bound frame_system::trait::Call by Dispatchable * Introduce DispatchInfoOf type alias * Whitespace fix from review Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
f8c8355ac7
commit
30ae26074c
@@ -18,6 +18,19 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CallWithDispatchInfo;
|
||||
impl sp_runtime::traits::Dispatchable for CallWithDispatchInfo {
|
||||
type Origin = ();
|
||||
type Trait = ();
|
||||
type Info = frame_support::weights::DispatchInfo;
|
||||
type PostInfo = frame_support::weights::PostDispatchInfo;
|
||||
fn dispatch(self, _origin: Self::Origin)
|
||||
-> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
|
||||
panic!("Do not use dummy implementation for dispatch.");
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! decl_tests {
|
||||
($test:ty, $ext_builder:ty, $existential_deposit:expr) => {
|
||||
@@ -40,7 +53,7 @@ macro_rules! decl_tests {
|
||||
pub type System = frame_system::Module<$test>;
|
||||
pub type Balances = Module<$test>;
|
||||
|
||||
pub const CALL: &<$test as frame_system::Trait>::Call = &();
|
||||
pub const CALL: &<$test as frame_system::Trait>::Call = &$crate::tests::CallWithDispatchInfo;
|
||||
|
||||
/// create a transaction info struct from weight. Handy to avoid building the whole struct.
|
||||
pub fn info_from_weight(w: Weight) -> DispatchInfo {
|
||||
@@ -154,14 +167,14 @@ macro_rules! decl_tests {
|
||||
ChargeTransactionPayment::from(1),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
&info_from_weight(1),
|
||||
1,
|
||||
).is_err());
|
||||
assert!(<ChargeTransactionPayment<$test> as SignedExtension>::pre_dispatch(
|
||||
ChargeTransactionPayment::from(0),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
&info_from_weight(1),
|
||||
1,
|
||||
).is_ok());
|
||||
|
||||
@@ -172,14 +185,14 @@ macro_rules! decl_tests {
|
||||
ChargeTransactionPayment::from(1),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
&info_from_weight(1),
|
||||
1,
|
||||
).is_err());
|
||||
assert!(<ChargeTransactionPayment<$test> as SignedExtension>::pre_dispatch(
|
||||
ChargeTransactionPayment::from(0),
|
||||
&1,
|
||||
CALL,
|
||||
info_from_weight(1),
|
||||
&info_from_weight(1),
|
||||
1,
|
||||
).is_err());
|
||||
});
|
||||
|
||||
@@ -18,14 +18,18 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use sp_runtime::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header};
|
||||
use sp_runtime::{
|
||||
Perbill,
|
||||
traits::{ConvertInto, IdentityLookup},
|
||||
testing::Header,
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_io;
|
||||
use frame_support::{impl_outer_origin, parameter_types};
|
||||
use frame_support::traits::Get;
|
||||
use frame_support::weights::{Weight, DispatchInfo};
|
||||
use std::cell::RefCell;
|
||||
use crate::{GenesisConfig, Module, Trait, decl_tests};
|
||||
use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};
|
||||
|
||||
use frame_system as system;
|
||||
impl_outer_origin!{
|
||||
@@ -54,7 +58,7 @@ impl frame_system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Call = ();
|
||||
type Call = CallWithDispatchInfo;
|
||||
type Hash = H256;
|
||||
type Hashing = ::sp_runtime::traits::BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
|
||||
@@ -18,14 +18,18 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use sp_runtime::{Perbill, traits::{ConvertInto, IdentityLookup}, testing::Header};
|
||||
use sp_runtime::{
|
||||
Perbill,
|
||||
traits::{ConvertInto, IdentityLookup},
|
||||
testing::Header,
|
||||
};
|
||||
use sp_core::H256;
|
||||
use sp_io;
|
||||
use frame_support::{impl_outer_origin, parameter_types};
|
||||
use frame_support::traits::{Get, StorageMapShim};
|
||||
use frame_support::weights::{Weight, DispatchInfo};
|
||||
use std::cell::RefCell;
|
||||
use crate::{GenesisConfig, Module, Trait, decl_tests};
|
||||
use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};
|
||||
|
||||
use frame_system as system;
|
||||
impl_outer_origin!{
|
||||
@@ -54,7 +58,7 @@ impl frame_system::Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Call = ();
|
||||
type Call = CallWithDispatchInfo;
|
||||
type Hash = H256;
|
||||
type Hashing = ::sp_runtime::traits::BlakeTwo256;
|
||||
type AccountId = u64;
|
||||
|
||||
@@ -113,7 +113,10 @@ use sp_std::{prelude::*, marker::PhantomData, fmt::Debug};
|
||||
use codec::{Codec, Encode, Decode};
|
||||
use sp_io::hashing::blake2_256;
|
||||
use sp_runtime::{
|
||||
traits::{Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension},
|
||||
traits::{
|
||||
Hash, StaticLookup, Zero, MaybeSerializeDeserialize, Member, SignedExtension,
|
||||
DispatchInfoOf,
|
||||
},
|
||||
transaction_validity::{
|
||||
ValidTransaction, InvalidTransaction, TransactionValidity, TransactionValidityError,
|
||||
},
|
||||
@@ -123,7 +126,6 @@ use frame_support::dispatch::{DispatchResult, Dispatchable};
|
||||
use frame_support::{
|
||||
Parameter, decl_module, decl_event, decl_storage, decl_error, storage::child,
|
||||
parameter_types, IsSubType,
|
||||
weights::DispatchInfo,
|
||||
};
|
||||
use frame_support::traits::{OnUnbalanced, Currency, Get, Time, Randomness};
|
||||
use frame_system::{self as system, ensure_signed, RawOrigin, ensure_root};
|
||||
@@ -1091,7 +1093,6 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckBlockGasLimit<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Trait>::Call;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
@@ -1100,7 +1101,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckBlockGasLimit<T> {
|
||||
&self,
|
||||
_: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
_: Self::DispatchInfo,
|
||||
_: &DispatchInfoOf<Self::Call>,
|
||||
_: usize,
|
||||
) -> TransactionValidity {
|
||||
let call = match call.is_sub_type() {
|
||||
|
||||
@@ -2633,11 +2633,11 @@ fn check_block_gas_limit_works() {
|
||||
let call: Call = crate::Call::put_code(1000, vec![]).into();
|
||||
|
||||
assert_eq!(
|
||||
check.validate(&0, &call, info, 0), InvalidTransaction::ExhaustsResources.into(),
|
||||
check.validate(&0, &call, &info, 0), InvalidTransaction::ExhaustsResources.into(),
|
||||
);
|
||||
|
||||
let call: Call = crate::Call::update_schedule(Default::default()).into();
|
||||
assert_eq!(check.validate(&0, &call, info, 0), Ok(Default::default()));
|
||||
assert_eq!(check.validate(&0, &call, &info, 0), Ok(Default::default()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -257,15 +257,16 @@ use sp_std::marker::PhantomData;
|
||||
use frame_support::{
|
||||
dispatch::DispatchResult, decl_module, decl_storage, decl_event,
|
||||
weights::{
|
||||
SimpleDispatchInfo, DispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight,
|
||||
PaysFee,
|
||||
SimpleDispatchInfo, DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee,
|
||||
},
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
use frame_system::{self as system, ensure_signed, ensure_root};
|
||||
use codec::{Encode, Decode};
|
||||
use sp_runtime::{
|
||||
traits::{SignedExtension, Bounded, SaturatedConversion},
|
||||
traits::{
|
||||
SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf,
|
||||
},
|
||||
transaction_validity::{
|
||||
ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity,
|
||||
},
|
||||
@@ -619,7 +620,6 @@ impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T> {
|
||||
// other pallets.
|
||||
type Call = Call<T>;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
@@ -628,7 +628,7 @@ impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T> {
|
||||
&self,
|
||||
_who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
// if the transaction is too big, just drop it.
|
||||
@@ -713,7 +713,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
use frame_support::{
|
||||
assert_ok, impl_outer_origin, parameter_types, weights::GetDispatchInfo,
|
||||
assert_ok, impl_outer_origin, parameter_types, weights::{DispatchInfo, GetDispatchInfo},
|
||||
traits::{OnInitialize, OnFinalize}
|
||||
};
|
||||
use sp_core::H256;
|
||||
@@ -829,13 +829,13 @@ mod tests {
|
||||
let info = DispatchInfo::default();
|
||||
|
||||
assert_eq!(
|
||||
WatchDummy::<Test>(PhantomData).validate(&1, &call, info, 150)
|
||||
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 150)
|
||||
.unwrap()
|
||||
.priority,
|
||||
Bounded::max_value(),
|
||||
);
|
||||
assert_eq!(
|
||||
WatchDummy::<Test>(PhantomData).validate(&1, &call, info, 250),
|
||||
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 250),
|
||||
InvalidTransaction::ExhaustsResources.into(),
|
||||
);
|
||||
})
|
||||
|
||||
@@ -120,9 +120,9 @@ impl<
|
||||
where
|
||||
Block::Extrinsic: Checkable<Context> + Codec,
|
||||
CheckedOf<Block::Extrinsic, Context>:
|
||||
Applyable<DispatchInfo=DispatchInfo> +
|
||||
Applyable +
|
||||
GetDispatchInfo,
|
||||
CallOf<Block::Extrinsic, Context>: Dispatchable,
|
||||
CallOf<Block::Extrinsic, Context>: Dispatchable<Info=DispatchInfo>,
|
||||
OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
|
||||
UnsignedValidator: ValidateUnsigned<Call=CallOf<Block::Extrinsic, Context>>,
|
||||
{
|
||||
@@ -145,9 +145,9 @@ impl<
|
||||
where
|
||||
Block::Extrinsic: Checkable<Context> + Codec,
|
||||
CheckedOf<Block::Extrinsic, Context>:
|
||||
Applyable<DispatchInfo=DispatchInfo> +
|
||||
Applyable +
|
||||
GetDispatchInfo,
|
||||
CallOf<Block::Extrinsic, Context>: Dispatchable,
|
||||
CallOf<Block::Extrinsic, Context>: Dispatchable<Info=DispatchInfo>,
|
||||
OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
|
||||
UnsignedValidator: ValidateUnsigned<Call=CallOf<Block::Extrinsic, Context>>,
|
||||
{
|
||||
@@ -307,7 +307,7 @@ where
|
||||
|
||||
// Decode parameters and dispatch
|
||||
let dispatch_info = xt.get_dispatch_info();
|
||||
let r = Applyable::apply::<UnsignedValidator>(xt, dispatch_info, encoded_len)?;
|
||||
let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
|
||||
|
||||
<frame_system::Module<System>>::note_applied_extrinsic(&r, encoded_len as u32, dispatch_info);
|
||||
|
||||
@@ -348,7 +348,7 @@ where
|
||||
let xt = uxt.check(&Default::default())?;
|
||||
|
||||
let dispatch_info = xt.get_dispatch_info();
|
||||
xt.validate::<UnsignedValidator>(source, dispatch_info, encoded_len)
|
||||
xt.validate::<UnsignedValidator>(source, &dispatch_info, encoded_len)
|
||||
}
|
||||
|
||||
/// Start an offchain worker and generate extrinsics.
|
||||
|
||||
@@ -288,7 +288,7 @@ use sp_runtime::{
|
||||
curve::PiecewiseLinear,
|
||||
traits::{
|
||||
Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion, AtLeast32Bit,
|
||||
SignedExtension,
|
||||
SignedExtension, Dispatchable, DispatchInfoOf,
|
||||
},
|
||||
transaction_validity::{
|
||||
TransactionValidityError, TransactionValidity, ValidTransaction, InvalidTransaction,
|
||||
@@ -772,7 +772,7 @@ pub trait Trait: frame_system::Trait {
|
||||
type ElectionLookahead: Get<Self::BlockNumber>;
|
||||
|
||||
/// The overarching call type.
|
||||
type Call: From<Call<Self>> + IsSubType<Module<Self>, Self> + Clone;
|
||||
type Call: Dispatchable + From<Call<Self>> + IsSubType<Module<Self>, Self> + Clone;
|
||||
|
||||
/// A transaction submitter.
|
||||
type SubmitTransaction: SubmitUnsignedTransaction<Self, <Self as Trait>::Call>;
|
||||
@@ -3135,7 +3135,6 @@ impl<T: Trait + Send + Sync> SignedExtension for LockStakingStatus<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Trait>::Call;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = frame_support::weights::DispatchInfo;
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> Result<(), TransactionValidityError> { Ok(()) }
|
||||
@@ -3144,7 +3143,7 @@ impl<T: Trait + Send + Sync> SignedExtension for LockStakingStatus<T> {
|
||||
&self,
|
||||
_who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
if let Some(inner_call) = call.is_sub_type() {
|
||||
|
||||
@@ -2939,7 +2939,7 @@ mod offchain_phragmen {
|
||||
|
||||
let lock_staking: LockStakingStatus<Test> = Default::default();
|
||||
assert_eq!(
|
||||
lock_staking.validate(&10, &outer, Default::default(), Default::default(),),
|
||||
lock_staking.validate(&10, &outer, &Default::default(), Default::default(),),
|
||||
TransactionValidity::Err(InvalidTransaction::Stale.into()),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -53,7 +53,7 @@ pub enum Never {}
|
||||
/// Serializable version of Dispatchable.
|
||||
/// This value can be used as a "function" in an extrinsic.
|
||||
pub trait Callable<T> {
|
||||
type Call: Dispatchable<PostInfo=PostDispatchInfo> + Codec + Clone + PartialEq + Eq;
|
||||
type Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + Codec + Clone + PartialEq + Eq;
|
||||
}
|
||||
|
||||
// dirty hack to work around serde_derive issue
|
||||
@@ -1593,6 +1593,7 @@ macro_rules! decl_module {
|
||||
{
|
||||
type Trait = $trait_instance;
|
||||
type Origin = $origin_type;
|
||||
type Info = $crate::weights::DispatchInfo;
|
||||
type PostInfo = $crate::weights::PostDispatchInfo;
|
||||
fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo {
|
||||
match self {
|
||||
@@ -1720,6 +1721,7 @@ macro_rules! impl_outer_dispatch {
|
||||
impl $crate::dispatch::Dispatchable for $call_type {
|
||||
type Origin = $origin;
|
||||
type Trait = $call_type;
|
||||
type Info = $crate::weights::DispatchInfo;
|
||||
type PostInfo = $crate::weights::PostDispatchInfo;
|
||||
fn dispatch(
|
||||
self,
|
||||
|
||||
@@ -256,9 +256,8 @@ mod tests {
|
||||
struct TestExtension;
|
||||
impl sp_runtime::traits::SignedExtension for TestExtension {
|
||||
type AccountId = u32;
|
||||
type Call = u32;
|
||||
type Call = ();
|
||||
type AdditionalSigned = u32;
|
||||
type DispatchInfo = ();
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "testextension";
|
||||
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
|
||||
@@ -270,9 +269,8 @@ mod tests {
|
||||
struct TestExtension2;
|
||||
impl sp_runtime::traits::SignedExtension for TestExtension2 {
|
||||
type AccountId = u32;
|
||||
type Call = u32;
|
||||
type Call = ();
|
||||
type AdditionalSigned = u32;
|
||||
type DispatchInfo = ();
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "testextension2";
|
||||
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError> {
|
||||
|
||||
@@ -109,6 +109,7 @@ use sp_runtime::{
|
||||
self, CheckEqual, AtLeast32Bit, Zero, SignedExtension, Lookup, LookupError,
|
||||
SimpleBitOps, Hash, Member, MaybeDisplay, BadOrigin, SaturatedConversion,
|
||||
MaybeSerialize, MaybeSerializeDeserialize, MaybeMallocSizeOf, StaticLookup, One, Bounded,
|
||||
Dispatchable, DispatchInfoOf, PostDispatchInfoOf,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -146,7 +147,7 @@ pub trait Trait: 'static + Eq + Clone {
|
||||
+ Clone;
|
||||
|
||||
/// The aggregated `Call` type.
|
||||
type Call: Debug;
|
||||
type Call: Dispatchable + Debug;
|
||||
|
||||
/// Account index (aka nonce) type. This stores the number of previous transactions associated
|
||||
/// with a sender account.
|
||||
@@ -1167,7 +1168,9 @@ pub fn split_inner<T, R, S>(option: Option<T>, splitter: impl FnOnce(T) -> (R, S
|
||||
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
|
||||
pub struct CheckWeight<T: Trait + Send + Sync>(PhantomData<T>);
|
||||
|
||||
impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
impl<T: Trait + Send + Sync> CheckWeight<T> where
|
||||
T::Call: Dispatchable<Info=DispatchInfo>
|
||||
{
|
||||
/// Get the quota ratio of each dispatch class type. This indicates that all operational
|
||||
/// dispatches can use the full capacity of any resource, while user-triggered ones can consume
|
||||
/// a portion.
|
||||
@@ -1183,7 +1186,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
///
|
||||
/// Upon successes, it returns the new block weight as a `Result`.
|
||||
fn check_weight(
|
||||
info: <Self as SignedExtension>::DispatchInfo,
|
||||
info: &DispatchInfoOf<T::Call>,
|
||||
) -> Result<Weight, TransactionValidityError> {
|
||||
let current_weight = Module::<T>::all_extrinsics_weight();
|
||||
let maximum_weight = T::MaximumBlockWeight::get();
|
||||
@@ -1201,7 +1204,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
///
|
||||
/// Upon successes, it returns the new block length as a `Result`.
|
||||
fn check_block_length(
|
||||
info: <Self as SignedExtension>::DispatchInfo,
|
||||
info: &DispatchInfoOf<T::Call>,
|
||||
len: usize,
|
||||
) -> Result<u32, TransactionValidityError> {
|
||||
let current_len = Module::<T>::all_extrinsics_len();
|
||||
@@ -1217,7 +1220,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
}
|
||||
|
||||
/// get the priority of an extrinsic denoted by `info`.
|
||||
fn get_priority(info: <Self as SignedExtension>::DispatchInfo) -> TransactionPriority {
|
||||
fn get_priority(info: &DispatchInfoOf<T::Call>) -> TransactionPriority {
|
||||
match info.class {
|
||||
DispatchClass::Normal => info.weight.into(),
|
||||
DispatchClass::Operational => Bounded::max_value(),
|
||||
@@ -1235,7 +1238,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
///
|
||||
/// It checks and notes the new weight and length.
|
||||
fn do_pre_dispatch(
|
||||
info: <Self as SignedExtension>::DispatchInfo,
|
||||
info: &DispatchInfoOf<T::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
let next_len = Self::check_block_length(info, len)?;
|
||||
@@ -1249,7 +1252,7 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
///
|
||||
/// It only checks that the block weight and length limit will not exceed.
|
||||
fn do_validate(
|
||||
info: <Self as SignedExtension>::DispatchInfo,
|
||||
info: &DispatchInfoOf<T::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
// ignore the next weight and length. If they return `Ok`, then it is below the limit.
|
||||
@@ -1260,11 +1263,12 @@ impl<T: Trait + Send + Sync> CheckWeight<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> where
|
||||
T::Call: Dispatchable<Info=DispatchInfo>
|
||||
{
|
||||
type AccountId = T::AccountId;
|
||||
type Call = T::Call;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckWeight";
|
||||
|
||||
@@ -1274,7 +1278,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
self,
|
||||
_who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
if info.class == DispatchClass::Mandatory {
|
||||
@@ -1287,7 +1291,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
&self,
|
||||
_who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
if info.class == DispatchClass::Mandatory {
|
||||
@@ -1298,7 +1302,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
|
||||
fn pre_dispatch_unsigned(
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
Self::do_pre_dispatch(info, len)
|
||||
@@ -1306,7 +1310,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
|
||||
fn validate_unsigned(
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
Self::do_validate(info, len)
|
||||
@@ -1314,7 +1318,8 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckWeight<T> {
|
||||
|
||||
fn post_dispatch(
|
||||
_pre: Self::Pre,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
_post_info: &PostDispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
@@ -1363,11 +1368,12 @@ impl<T: Trait> Debug for CheckNonce<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> SignedExtension for CheckNonce<T> {
|
||||
impl<T: Trait> SignedExtension for CheckNonce<T> where
|
||||
T::Call: Dispatchable<Info=DispatchInfo>
|
||||
{
|
||||
type AccountId = T::AccountId;
|
||||
type Call = T::Call;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckNonce";
|
||||
|
||||
@@ -1377,7 +1383,7 @@ impl<T: Trait> SignedExtension for CheckNonce<T> {
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
let mut account = Account::<T>::get(who);
|
||||
@@ -1399,7 +1405,7 @@ impl<T: Trait> SignedExtension for CheckNonce<T> {
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
// check index
|
||||
@@ -1458,7 +1464,6 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckEra<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type Call = T::Call;
|
||||
type AdditionalSigned = T::Hash;
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckEra";
|
||||
|
||||
@@ -1466,7 +1471,7 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckEra<T> {
|
||||
&self,
|
||||
_who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
let current_u64 = <Module<T>>::block_number().saturated_into::<u64>();
|
||||
@@ -1515,7 +1520,6 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckGenesis<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Trait>::Call;
|
||||
type AdditionalSigned = T::Hash;
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckGenesis";
|
||||
|
||||
@@ -1551,7 +1555,6 @@ impl<T: Trait + Send + Sync> SignedExtension for CheckVersion<T> {
|
||||
type AccountId = T::AccountId;
|
||||
type Call = <T as Trait>::Call;
|
||||
type AdditionalSigned = u32;
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckVersion";
|
||||
|
||||
@@ -1615,9 +1618,22 @@ mod tests {
|
||||
fn on_killed_account(who: &u64) { KILLED.with(|r| r.borrow_mut().push(*who)) }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Call {}
|
||||
impl Dispatchable for Call {
|
||||
type Origin = ();
|
||||
type Trait = ();
|
||||
type Info = DispatchInfo;
|
||||
type PostInfo = ();
|
||||
fn dispatch(self, _origin: Self::Origin)
|
||||
-> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
|
||||
panic!("Do not use dummy implementation for dispatch.");
|
||||
}
|
||||
}
|
||||
|
||||
impl Trait for Test {
|
||||
type Origin = Origin;
|
||||
type Call = ();
|
||||
type Call = Call;
|
||||
type Index = u64;
|
||||
type BlockNumber = u64;
|
||||
type Hash = H256;
|
||||
@@ -1650,7 +1666,7 @@ mod tests {
|
||||
|
||||
type System = Module<Test>;
|
||||
|
||||
const CALL: &<Test as Trait>::Call = &();
|
||||
const CALL: &<Test as Trait>::Call = &Call {};
|
||||
|
||||
fn new_test_ext() -> sp_io::TestExternalities {
|
||||
GenesisConfig::default().build_storage::<Test>().unwrap().into()
|
||||
@@ -1851,14 +1867,14 @@ mod tests {
|
||||
let info = DispatchInfo::default();
|
||||
let len = 0_usize;
|
||||
// stale
|
||||
assert!(CheckNonce::<Test>(0).validate(&1, CALL, info, len).is_err());
|
||||
assert!(CheckNonce::<Test>(0).pre_dispatch(&1, CALL, info, len).is_err());
|
||||
assert!(CheckNonce::<Test>(0).validate(&1, CALL, &info, len).is_err());
|
||||
assert!(CheckNonce::<Test>(0).pre_dispatch(&1, CALL, &info, len).is_err());
|
||||
// correct
|
||||
assert!(CheckNonce::<Test>(1).validate(&1, CALL, info, len).is_ok());
|
||||
assert!(CheckNonce::<Test>(1).pre_dispatch(&1, CALL, info, len).is_ok());
|
||||
assert!(CheckNonce::<Test>(1).validate(&1, CALL, &info, len).is_ok());
|
||||
assert!(CheckNonce::<Test>(1).pre_dispatch(&1, CALL, &info, len).is_ok());
|
||||
// future
|
||||
assert!(CheckNonce::<Test>(5).validate(&1, CALL, info, len).is_ok());
|
||||
assert!(CheckNonce::<Test>(5).pre_dispatch(&1, CALL, info, len).is_err());
|
||||
assert!(CheckNonce::<Test>(5).validate(&1, CALL, &info, len).is_ok());
|
||||
assert!(CheckNonce::<Test>(5).pre_dispatch(&1, CALL, &info, len).is_err());
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1883,9 +1899,9 @@ mod tests {
|
||||
if f { assert!(r.is_err()) } else { assert!(r.is_ok()) }
|
||||
};
|
||||
|
||||
reset_check_weight(small, false, 0);
|
||||
reset_check_weight(medium, false, 0);
|
||||
reset_check_weight(big, true, 1);
|
||||
reset_check_weight(&small, false, 0);
|
||||
reset_check_weight(&medium, false, 0);
|
||||
reset_check_weight(&big, true, 1);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1896,7 +1912,7 @@ mod tests {
|
||||
let len = 0_usize;
|
||||
|
||||
assert_eq!(System::all_extrinsics_weight(), 0);
|
||||
let r = CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, free, len);
|
||||
let r = CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &free, len);
|
||||
assert!(r.is_ok());
|
||||
assert_eq!(System::all_extrinsics_weight(), 0);
|
||||
})
|
||||
@@ -1910,7 +1926,7 @@ mod tests {
|
||||
let normal_limit = normal_weight_limit();
|
||||
|
||||
assert_eq!(System::all_extrinsics_weight(), 0);
|
||||
let r = CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, max, len);
|
||||
let r = CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &max, len);
|
||||
assert!(r.is_ok());
|
||||
assert_eq!(System::all_extrinsics_weight(), normal_limit);
|
||||
})
|
||||
@@ -1927,15 +1943,15 @@ mod tests {
|
||||
// given almost full block
|
||||
AllExtrinsicsWeight::put(normal_limit);
|
||||
// will not fit.
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &normal, len).is_err());
|
||||
// will fit.
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &op, len).is_ok());
|
||||
|
||||
// likewise for length limit.
|
||||
let len = 100_usize;
|
||||
AllExtrinsicsLen::put(normal_length_limit());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, normal, len).is_err());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, op, len).is_ok());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &normal, len).is_err());
|
||||
assert!(CheckWeight::<Test>(PhantomData).pre_dispatch(&1, CALL, &op, len).is_ok());
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1947,13 +1963,13 @@ mod tests {
|
||||
let len = 0_usize;
|
||||
|
||||
let priority = CheckWeight::<Test>(PhantomData)
|
||||
.validate(&1, CALL, normal, len)
|
||||
.validate(&1, CALL, &normal, len)
|
||||
.unwrap()
|
||||
.priority;
|
||||
assert_eq!(priority, 100);
|
||||
|
||||
let priority = CheckWeight::<Test>(PhantomData)
|
||||
.validate(&1, CALL, op, len)
|
||||
.validate(&1, CALL, &op, len)
|
||||
.unwrap()
|
||||
.priority;
|
||||
assert_eq!(priority, u64::max_value());
|
||||
@@ -1971,16 +1987,16 @@ mod tests {
|
||||
if f { assert!(r.is_err()) } else { assert!(r.is_ok()) }
|
||||
};
|
||||
|
||||
reset_check_weight(normal, normal_limit - 1, false);
|
||||
reset_check_weight(normal, normal_limit, false);
|
||||
reset_check_weight(normal, normal_limit + 1, true);
|
||||
reset_check_weight(&normal, normal_limit - 1, false);
|
||||
reset_check_weight(&normal, normal_limit, false);
|
||||
reset_check_weight(&normal, normal_limit + 1, true);
|
||||
|
||||
// Operational ones don't have this limit.
|
||||
let op = DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: true };
|
||||
reset_check_weight(op, normal_limit, false);
|
||||
reset_check_weight(op, normal_limit + 100, false);
|
||||
reset_check_weight(op, 1024, false);
|
||||
reset_check_weight(op, 1025, true);
|
||||
reset_check_weight(&op, normal_limit, false);
|
||||
reset_check_weight(&op, normal_limit + 100, false);
|
||||
reset_check_weight(&op, 1024, false);
|
||||
reset_check_weight(&op, 1025, true);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2012,7 +2028,7 @@ mod tests {
|
||||
System::set_block_number(17);
|
||||
<BlockHash<Test>>::insert(16, H256::repeat_byte(1));
|
||||
|
||||
assert_eq!(ext.validate(&1, CALL, normal, len).unwrap().longevity, 15);
|
||||
assert_eq!(ext.validate(&1, CALL, &normal, len).unwrap().longevity, 15);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,10 @@ use sp_runtime::{
|
||||
TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError,
|
||||
TransactionValidity,
|
||||
},
|
||||
traits::{Zero, Saturating, SignedExtension, SaturatedConversion, Convert},
|
||||
traits::{
|
||||
Zero, Saturating, SignedExtension, SaturatedConversion, Convert, Dispatchable,
|
||||
DispatchInfoOf,
|
||||
},
|
||||
};
|
||||
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
|
||||
|
||||
@@ -98,7 +101,9 @@ decl_module! {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
impl<T: Trait> Module<T> where
|
||||
T::Call: Dispatchable<Info=DispatchInfo>,
|
||||
{
|
||||
/// Query the data that we know about the fee of a given `call`.
|
||||
///
|
||||
/// As this module is not and cannot be aware of the internals of a signed extension, it only
|
||||
@@ -122,7 +127,7 @@ impl<T: Trait> Module<T> {
|
||||
let dispatch_info = <Extrinsic as GetDispatchInfo>::get_dispatch_info(&unchecked_extrinsic);
|
||||
|
||||
let partial_fee =
|
||||
<ChargeTransactionPayment<T>>::compute_fee(len, dispatch_info, 0u32.into());
|
||||
<ChargeTransactionPayment<T>>::compute_fee(len, &dispatch_info, 0u32.into());
|
||||
let DispatchInfo { weight, class, .. } = dispatch_info;
|
||||
|
||||
RuntimeDispatchInfo { weight, class, partial_fee }
|
||||
@@ -134,7 +139,9 @@ impl<T: Trait> Module<T> {
|
||||
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
|
||||
pub struct ChargeTransactionPayment<T: Trait + Send + Sync>(#[codec(compact)] BalanceOf<T>);
|
||||
|
||||
impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> {
|
||||
impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> where
|
||||
T::Call: Dispatchable<Info=DispatchInfo>,
|
||||
{
|
||||
/// utility constructor. Used only in client/factory code.
|
||||
pub fn from(fee: BalanceOf<T>) -> Self {
|
||||
Self(fee)
|
||||
@@ -156,7 +163,7 @@ impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> {
|
||||
/// final_fee = base_fee + targeted_fee_adjustment(len_fee + weight_fee) + tip;
|
||||
pub fn compute_fee(
|
||||
len: u32,
|
||||
info: <Self as SignedExtension>::DispatchInfo,
|
||||
info: &DispatchInfoOf<T::Call>,
|
||||
tip: BalanceOf<T>,
|
||||
) -> BalanceOf<T>
|
||||
where
|
||||
@@ -200,14 +207,14 @@ impl<T: Trait + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T>
|
||||
where BalanceOf<T>: Send + Sync
|
||||
impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> where
|
||||
BalanceOf<T>: Send + Sync,
|
||||
T::Call: Dispatchable<Info=DispatchInfo>,
|
||||
{
|
||||
const IDENTIFIER: &'static str = "ChargeTransactionPayment";
|
||||
type AccountId = T::AccountId;
|
||||
type Call = T::Call;
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = DispatchInfo;
|
||||
type Pre = ();
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
|
||||
@@ -215,7 +222,7 @@ impl<T: Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T>
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
// pay any fees.
|
||||
@@ -438,14 +445,14 @@ mod tests {
|
||||
let len = 10;
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(0)
|
||||
.pre_dispatch(&1, CALL, info_from_weight(5), len)
|
||||
.pre_dispatch(&1, CALL, &info_from_weight(5), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(1), 100 - 5 - 5 - 10);
|
||||
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(5 /* tipped */)
|
||||
.pre_dispatch(&2, CALL, info_from_weight(3), len)
|
||||
.pre_dispatch(&2, CALL, &info_from_weight(3), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 3 - 5);
|
||||
@@ -463,7 +470,7 @@ mod tests {
|
||||
// maximum weight possible
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(0)
|
||||
.pre_dispatch(&1, CALL, info_from_weight(Weight::max_value()), 10)
|
||||
.pre_dispatch(&1, CALL, &info_from_weight(Weight::max_value()), 10)
|
||||
.is_ok()
|
||||
);
|
||||
// fee will be proportional to what is the actual maximum weight in the runtime.
|
||||
@@ -495,7 +502,7 @@ mod tests {
|
||||
};
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(0)
|
||||
.validate(&1, CALL, operational_transaction , len)
|
||||
.validate(&1, CALL, &operational_transaction , len)
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
@@ -507,7 +514,7 @@ mod tests {
|
||||
};
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(0)
|
||||
.validate(&1, CALL, free_transaction , len)
|
||||
.validate(&1, CALL, &free_transaction , len)
|
||||
.is_err()
|
||||
);
|
||||
});
|
||||
@@ -527,7 +534,7 @@ mod tests {
|
||||
|
||||
assert!(
|
||||
ChargeTransactionPayment::<Runtime>::from(10) // tipped
|
||||
.pre_dispatch(&1, CALL, info_from_weight(3), len)
|
||||
.pre_dispatch(&1, CALL, &info_from_weight(3), len)
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(Balances::free_balance(1), 100 - 10 - 5 - (10 + 3) * 3 / 2);
|
||||
@@ -587,25 +594,25 @@ mod tests {
|
||||
class: DispatchClass::Operational,
|
||||
pays_fee: false,
|
||||
};
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, dispatch_info, 10), 10);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, &dispatch_info, 10), 10);
|
||||
// No tip, only base fee works
|
||||
let dispatch_info = DispatchInfo {
|
||||
weight: 0,
|
||||
class: DispatchClass::Operational,
|
||||
pays_fee: true,
|
||||
};
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, dispatch_info, 0), 100);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, &dispatch_info, 0), 100);
|
||||
// Tip + base fee works
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, dispatch_info, 69), 169);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, &dispatch_info, 69), 169);
|
||||
// Len (byte fee) + base fee works
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(42, dispatch_info, 0), 520);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(42, &dispatch_info, 0), 520);
|
||||
// Weight fee + base fee works
|
||||
let dispatch_info = DispatchInfo {
|
||||
weight: 1000,
|
||||
class: DispatchClass::Operational,
|
||||
pays_fee: true,
|
||||
};
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, dispatch_info, 0), 1100);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, &dispatch_info, 0), 1100);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -626,7 +633,7 @@ mod tests {
|
||||
class: DispatchClass::Operational,
|
||||
pays_fee: true,
|
||||
};
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, dispatch_info, 0), 100);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(0, &dispatch_info, 0), 100);
|
||||
|
||||
// Everything works together :)
|
||||
let dispatch_info = DispatchInfo {
|
||||
@@ -638,7 +645,7 @@ mod tests {
|
||||
// adjustable fee = (123 * 1) + (456 * 10) = 4683
|
||||
// adjusted fee = (4683 * .5) + 4683 = 7024.5 -> 7024
|
||||
// final fee = 100 + 7024 + 789 tip = 7913
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(456, dispatch_info, 789), 7913);
|
||||
assert_eq!(ChargeTransactionPayment::<Runtime>::compute_fee(456, &dispatch_info, 789), 7913);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -660,7 +667,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
ChargeTransactionPayment::<Runtime>::compute_fee(
|
||||
<u32>::max_value(),
|
||||
dispatch_info,
|
||||
&dispatch_info,
|
||||
<u64>::max_value()
|
||||
),
|
||||
<u64>::max_value()
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
//! stage.
|
||||
|
||||
use crate::traits::{
|
||||
self, Member, MaybeDisplay, SignedExtension, Dispatchable,
|
||||
self, Member, MaybeDisplay, SignedExtension, Dispatchable, DispatchInfoOf, ValidateUnsigned,
|
||||
};
|
||||
use crate::traits::ValidateUnsigned;
|
||||
use crate::transaction_validity::{TransactionValidity, TransactionSource};
|
||||
|
||||
/// Definition of something that the external world might want to say; its
|
||||
@@ -36,28 +35,26 @@ pub struct CheckedExtrinsic<AccountId, Call, Extra> {
|
||||
pub function: Call,
|
||||
}
|
||||
|
||||
impl<AccountId, Call, Extra, Origin, Info> traits::Applyable for
|
||||
impl<AccountId, Call, Extra, Origin> traits::Applyable for
|
||||
CheckedExtrinsic<AccountId, Call, Extra>
|
||||
where
|
||||
AccountId: Member + MaybeDisplay,
|
||||
Call: Member + Dispatchable<Origin=Origin>,
|
||||
Extra: SignedExtension<AccountId=AccountId, Call=Call, DispatchInfo=Info>,
|
||||
Extra: SignedExtension<AccountId=AccountId, Call=Call>,
|
||||
Origin: From<Option<AccountId>>,
|
||||
Info: Clone,
|
||||
{
|
||||
type Call = Call;
|
||||
type DispatchInfo = Info;
|
||||
|
||||
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: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
if let Some((ref id, ref extra)) = self.signed {
|
||||
Extra::validate(extra, id, &self.function, info.clone(), len)
|
||||
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)?;
|
||||
@@ -67,21 +64,24 @@ where
|
||||
|
||||
fn apply<U: ValidateUnsigned<Call=Self::Call>>(
|
||||
self,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> crate::ApplyExtrinsicResult {
|
||||
let (maybe_who, pre) = if let Some((id, extra)) = self.signed {
|
||||
let pre = Extra::pre_dispatch(extra, &id, &self.function, info.clone(), len)?;
|
||||
let pre = Extra::pre_dispatch(extra, &id, &self.function, info, len)?;
|
||||
(Some(id), pre)
|
||||
} else {
|
||||
let pre = Extra::pre_dispatch_unsigned(&self.function, info.clone(), len)?;
|
||||
let pre = Extra::pre_dispatch_unsigned(&self.function, info, len)?;
|
||||
U::pre_dispatch(&self.function)?;
|
||||
(None, pre)
|
||||
};
|
||||
let res = self.function.dispatch(Origin::from(maybe_who))
|
||||
.map(|_| ())
|
||||
.map_err(|e| e.error);
|
||||
Extra::post_dispatch(pre, info.clone(), len, &res)?;
|
||||
let res = self.function.dispatch(Origin::from(maybe_who));
|
||||
let post_info = match res {
|
||||
Ok(info) => info,
|
||||
Err(err) => err.post_info,
|
||||
};
|
||||
let res = res.map(|_| ()).map_err(|e| e.error);
|
||||
Extra::post_dispatch(pre, info, &post_info, len, &res)?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +357,6 @@ mod tests {
|
||||
type AccountId = u64;
|
||||
type Call = ();
|
||||
type AdditionalSigned = ();
|
||||
type DispatchInfo = ();
|
||||
type Pre = ();
|
||||
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::{fmt::Debug, ops::Deref, fmt, cell::RefCell};
|
||||
use crate::codec::{Codec, Encode, Decode};
|
||||
use crate::traits::{
|
||||
self, Checkable, Applyable, BlakeTwo256, OpaqueKeys,
|
||||
SignedExtension, Dispatchable,
|
||||
SignedExtension, Dispatchable, DispatchInfoOf,
|
||||
};
|
||||
use crate::traits::ValidateUnsigned;
|
||||
use crate::{generic, KeyTypeId, ApplyExtrinsicResult};
|
||||
@@ -345,20 +345,18 @@ impl<Call: Codec + Sync + Send, Extra> traits::Extrinsic for TestXt<Call, Extra>
|
||||
}
|
||||
}
|
||||
|
||||
impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
|
||||
impl<Origin, Call, Extra> Applyable for TestXt<Call, Extra> where
|
||||
Call: 'static + Sized + Send + Sync + Clone + Eq + Codec + Debug + Dispatchable<Origin=Origin>,
|
||||
Extra: SignedExtension<AccountId=u64, Call=Call, DispatchInfo=Info>,
|
||||
Extra: SignedExtension<AccountId=u64, Call=Call>,
|
||||
Origin: From<Option<u64>>,
|
||||
Info: Clone,
|
||||
{
|
||||
type Call = Call;
|
||||
type DispatchInfo = Info;
|
||||
|
||||
/// 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: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(Default::default())
|
||||
@@ -368,7 +366,7 @@ impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
|
||||
/// index and sender.
|
||||
fn apply<U: ValidateUnsigned<Call=Self::Call>>(
|
||||
self,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> ApplyExtrinsicResult {
|
||||
let maybe_who = if let Some((who, extra)) = self.signature {
|
||||
|
||||
@@ -625,6 +625,10 @@ pub trait Dispatchable {
|
||||
type Origin;
|
||||
/// ...
|
||||
type Trait;
|
||||
/// An opaque set of information attached to the transaction. This could be constructed anywhere
|
||||
/// down the line in a runtime. The current Substrate runtime uses a struct with the same name
|
||||
/// to represent the dispatch class and weight.
|
||||
type Info;
|
||||
/// Additional information that is returned by `dispatch`. Can be used to supply the caller
|
||||
/// with information about a `Dispatchable` that is ownly known post dispatch.
|
||||
type PostInfo: Eq + PartialEq + Clone + Copy + Encode + Decode + Printable;
|
||||
@@ -632,6 +636,21 @@ pub trait Dispatchable {
|
||||
fn dispatch(self, origin: Self::Origin) -> crate::DispatchResultWithInfo<Self::PostInfo>;
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
pub type PostDispatchInfoOf<T> = <T as Dispatchable>::PostInfo;
|
||||
|
||||
impl Dispatchable for () {
|
||||
type Origin = ();
|
||||
type Trait = ();
|
||||
type Info = ();
|
||||
type PostInfo = ();
|
||||
fn dispatch(self, _origin: Self::Origin) -> crate::DispatchResultWithInfo<Self::PostInfo> {
|
||||
panic!("This implemention should not be used for actual dispatch.");
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq {
|
||||
@@ -645,7 +664,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
type AccountId;
|
||||
|
||||
/// The type which encodes the call to be dispatched.
|
||||
type Call;
|
||||
type Call: Dispatchable;
|
||||
|
||||
/// Any additional data that will go into the signed payload. This may be created dynamically
|
||||
/// from the transaction using the `additional_signed` function.
|
||||
@@ -654,11 +673,6 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
/// The type that encodes information that can be passed from pre_dispatch to post-dispatch.
|
||||
type Pre: Default;
|
||||
|
||||
/// An opaque set of information attached to the transaction. This could be constructed anywhere
|
||||
/// down the line in a runtime. The current Substrate runtime uses a struct with the same name
|
||||
/// to represent the dispatch class and weight.
|
||||
type DispatchInfo: Clone;
|
||||
|
||||
/// Construct any additional data that should be in the signed payload of the transaction. Can
|
||||
/// also perform any pre-signature-verification checks and return an error if needed.
|
||||
fn additional_signed(&self) -> Result<Self::AdditionalSigned, TransactionValidityError>;
|
||||
@@ -676,7 +690,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
&self,
|
||||
_who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(ValidTransaction::default())
|
||||
@@ -694,7 +708,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
self.validate(who, call, info.clone(), len)
|
||||
@@ -712,7 +726,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
/// Make sure to perform the same checks in `pre_dispatch_unsigned` function.
|
||||
fn validate_unsigned(
|
||||
_call: &Self::Call,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
Ok(ValidTransaction::default())
|
||||
@@ -728,7 +742,7 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
/// perform the same validation as in `validate_unsigned`.
|
||||
fn pre_dispatch_unsigned(
|
||||
call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
Self::validate_unsigned(call, info.clone(), len)
|
||||
@@ -751,7 +765,8 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
/// will come from either an offchain-worker or via `InherentData`.
|
||||
fn post_dispatch(
|
||||
_pre: Self::Pre,
|
||||
_info: Self::DispatchInfo,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_post_info: &PostDispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
_result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
@@ -771,11 +786,10 @@ pub trait SignedExtension: Codec + Debug + Sync + Send + Clone + Eq + PartialEq
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl<AccountId, Call, Info: Clone> SignedExtension for Tuple {
|
||||
for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call, DispatchInfo=Info> )* );
|
||||
impl<AccountId, Call: Dispatchable> SignedExtension for Tuple {
|
||||
for_tuples!( where #( Tuple: SignedExtension<AccountId=AccountId, Call=Call,> )* );
|
||||
type AccountId = AccountId;
|
||||
type Call = Call;
|
||||
type DispatchInfo = Info;
|
||||
const IDENTIFIER: &'static str = "You should call `identifier()`!";
|
||||
for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); );
|
||||
for_tuples!( type Pre = ( #( Tuple::Pre ),* ); );
|
||||
@@ -788,45 +802,46 @@ impl<AccountId, Call, Info: Clone> SignedExtension for Tuple {
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
let valid = ValidTransaction::default();
|
||||
for_tuples!( #( let valid = valid.combine_with(Tuple.validate(who, call, info.clone(), len)?); )* );
|
||||
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: Self::DispatchInfo, len: usize)
|
||||
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.clone(), len)? ),* ) ))
|
||||
Ok(for_tuples!( ( #( Tuple.pre_dispatch(who, call, info, len)? ),* ) ))
|
||||
}
|
||||
|
||||
fn validate_unsigned(
|
||||
call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity {
|
||||
let valid = ValidTransaction::default();
|
||||
for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info.clone(), len)?); )* );
|
||||
for_tuples!( #( let valid = valid.combine_with(Tuple::validate_unsigned(call, info, len)?); )* );
|
||||
Ok(valid)
|
||||
}
|
||||
|
||||
fn pre_dispatch_unsigned(
|
||||
call: &Self::Call,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info.clone(), len)? ),* ) ))
|
||||
Ok(for_tuples!( ( #( Tuple::pre_dispatch_unsigned(call, info, len)? ),* ) ))
|
||||
}
|
||||
|
||||
fn post_dispatch(
|
||||
pre: Self::Pre,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
post_info: &PostDispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
result: &DispatchResult,
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info.clone(), len, result)?; )* );
|
||||
for_tuples!( #( Tuple::post_dispatch(pre.Tuple, info, post_info, len, result)?; )* );
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -844,7 +859,6 @@ impl SignedExtension for () {
|
||||
type AdditionalSigned = ();
|
||||
type Call = ();
|
||||
type Pre = ();
|
||||
type DispatchInfo = ();
|
||||
const IDENTIFIER: &'static str = "UnitSignedExtension";
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
|
||||
}
|
||||
@@ -857,16 +871,13 @@ impl SignedExtension for () {
|
||||
/// each piece of attributable information to be disambiguated.
|
||||
pub trait Applyable: Sized + Send + Sync {
|
||||
/// Type by which we can dispatch. Restricts the `UnsignedValidator` type.
|
||||
type Call;
|
||||
|
||||
/// An opaque set of information attached to the transaction.
|
||||
type DispatchInfo: Clone;
|
||||
type Call: Dispatchable;
|
||||
|
||||
/// Checks to see if this is a valid *transaction*. It returns information on it if so.
|
||||
fn validate<V: ValidateUnsigned<Call=Self::Call>>(
|
||||
&self,
|
||||
source: TransactionSource,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> TransactionValidity;
|
||||
|
||||
@@ -874,7 +885,7 @@ pub trait Applyable: Sized + Send + Sync {
|
||||
/// index and sender.
|
||||
fn apply<V: ValidateUnsigned<Call=Self::Call>>(
|
||||
self,
|
||||
info: Self::DispatchInfo,
|
||||
info: &DispatchInfoOf<Self::Call>,
|
||||
len: usize,
|
||||
) -> crate::ApplyExtrinsicResult;
|
||||
}
|
||||
@@ -1273,6 +1284,12 @@ impl Printable for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl Printable for () {
|
||||
fn print(&self) {
|
||||
"()".print()
|
||||
}
|
||||
}
|
||||
|
||||
#[impl_for_tuples(1, 12)]
|
||||
impl Printable for Tuple {
|
||||
fn print(&self) {
|
||||
|
||||
@@ -181,6 +181,16 @@ impl ExtrinsicT for Extrinsic {
|
||||
}
|
||||
}
|
||||
|
||||
impl sp_runtime::traits::Dispatchable for Extrinsic {
|
||||
type Origin = ();
|
||||
type Trait = ();
|
||||
type Info = ();
|
||||
type PostInfo = ();
|
||||
fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
|
||||
panic!("This implemention should not be used for actual dispatch.");
|
||||
}
|
||||
}
|
||||
|
||||
impl Extrinsic {
|
||||
pub fn transfer(&self) -> &Transfer {
|
||||
match self {
|
||||
|
||||
Reference in New Issue
Block a user