Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Implement ValidateUnsigned as SignedExtension #5006

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
pub type Executive = frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, AllModules>;

impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
Expand Down
3 changes: 2 additions & 1 deletion bin/node/cli/src/factory_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl<Number> FactoryState<Number> {
frame_system::CheckEra::from(Era::mortal(256, phase)),
frame_system::CheckNonce::from(index),
frame_system::CheckWeight::new(),
frame_system::ValidateUnsigned::new(),
pallet_transaction_payment::ChargeTransactionPayment::from(0),
Default::default(),
)
Expand Down Expand Up @@ -122,7 +123,7 @@ impl RuntimeAdapter for FactoryState<Number> {
(*amount).into()
)
)
}, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), ()))
}, key, (version, genesis_hash.clone(), prior_block_hash.clone(), (), (), (), (), ()))
}

fn inherent_extrinsics(&self) -> InherentData {
Expand Down
4 changes: 3 additions & 1 deletion bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,20 +615,22 @@ mod tests {
let check_era = frame_system::CheckEra::from(Era::Immortal);
let check_nonce = frame_system::CheckNonce::from(index);
let check_weight = frame_system::CheckWeight::new();
let check_unsigned = frame_system::ValidateUnsigned::new();
let payment = pallet_transaction_payment::ChargeTransactionPayment::from(0);
let extra = (
check_version,
check_genesis,
check_era,
check_nonce,
check_weight,
check_unsigned,
payment,
Default::default(),
);
let raw_payload = SignedPayload::from_raw(
function,
extra,
(version, genesis_hash, genesis_hash, (), (), (), ())
(version, genesis_hash, genesis_hash, (), (), (), (), ())
);
let signature = raw_payload.using_encoded(|payload| {
signer.sign(payload)
Expand Down
9 changes: 5 additions & 4 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustm
/// Constant values used within the runtime.
pub mod constants;
use constants::{time::*, currency::*};
use frame_system::Trait;

// Make the WASM binary available.
#[cfg(feature = "std")]
Expand All @@ -83,8 +82,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 240,
impl_version: 1,
spec_version: 241,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
};

Expand Down Expand Up @@ -558,6 +557,7 @@ impl frame_system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for
frame_system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
frame_system::CheckNonce::<Runtime>::from(index),
frame_system::CheckWeight::<Runtime>::new(),
frame_system::ValidateUnsigned::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
Default::default(),
);
Expand Down Expand Up @@ -679,6 +679,7 @@ pub type SignedExtra = (
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
frame_system::ValidateUnsigned<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
pallet_contracts::CheckBlockGasLimit<Runtime>,
);
Expand All @@ -689,7 +690,7 @@ pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<Runtime, Block, frame_system::ChainContext<Runtime>, Runtime, AllModules>;
pub type Executive = frame_executive::Executive<Runtime, Block, frame_system::ChainContext<Runtime>, AllModules>;

impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
Expand Down
1 change: 1 addition & 0 deletions bin/node/testing/src/keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub fn signed_extra(nonce: Index, extra_fee: Balance) -> SignedExtra {
frame_system::CheckEra::from(Era::mortal(256, 0)),
frame_system::CheckNonce::from(nonce),
frame_system::CheckWeight::new(),
frame_system::ValidateUnsigned::new(),
pallet_transaction_payment::ChargeTransactionPayment::from(extra_fee),
Default::default(),
)
Expand Down
2 changes: 2 additions & 0 deletions bin/utils/subkey/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ fn create_extrinsic<C: Crypto>(
frame_system::CheckEra::<Runtime>::from(Era::Immortal),
frame_system::CheckNonce::<Runtime>::from(i),
frame_system::CheckWeight::<Runtime>::new(),
frame_system::ValidateUnsigned::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(f),
Default::default(),
)
Expand All @@ -696,6 +697,7 @@ fn create_extrinsic<C: Crypto>(
(),
(),
(),
(),
),
);
let signature = raw_payload.using_encoded(|payload| signer.sign(payload)).into_runtime();
Expand Down
36 changes: 12 additions & 24 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,8 @@
//! # pub type Balances = u64;
//! # pub type AllModules = u64;
//! # pub enum Runtime {};
//! # use sp_runtime::transaction_validity::{TransactionValidity, UnknownTransaction};
//! # use sp_runtime::traits::ValidateUnsigned;
//! # impl ValidateUnsigned for Runtime {
//! # type Call = ();
//! #
//! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity {
//! # UnknownTransaction::NoUnsignedValidator.into()
//! # }
//! # }
//! /// Executive: handles dispatch to the various modules.
//! pub type Executive = executive::Executive<Runtime, Block, Context, Runtime, AllModules>;
//! pub type Executive = executive::Executive<Runtime, Block, Context, AllModules>;
//! ```

#![cfg_attr(not(feature = "std"), no_std)]
Expand All @@ -84,7 +75,6 @@ use sp_runtime::{
},
transaction_validity::TransactionValidity,
};
use sp_runtime::traits::ValidateUnsigned;
use codec::{Codec, Encode};
use frame_system::{extrinsics_root, DigestOf};

Expand All @@ -98,56 +88,52 @@ pub type CheckedOf<E, C> = <E as Checkable<C>>::Checked;
pub type CallOf<E, C> = <CheckedOf<E, C> as Applyable>::Call;
pub type OriginOf<E, C> = <CallOf<E, C> as Dispatchable>::Origin;

pub struct Executive<System, Block, Context, UnsignedValidator, AllModules>(
PhantomData<(System, Block, Context, UnsignedValidator, AllModules)>
pub struct Executive<System, Block, Context, AllModules>(
PhantomData<(System, Block, Context, AllModules)>
);

impl<
System: frame_system::Trait,
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
Context: Default,
UnsignedValidator,
AllModules:
OnRuntimeUpgrade +
OnInitialize<System::BlockNumber> +
OnFinalize<System::BlockNumber> +
OffchainWorker<System::BlockNumber> +
WeighBlock<System::BlockNumber>,
> ExecuteBlock<Block> for Executive<System, Block, Context, UnsignedValidator, AllModules>
> ExecuteBlock<Block> for Executive<System, Block, Context, AllModules>
where
Block::Extrinsic: Checkable<Context> + Codec,
CheckedOf<Block::Extrinsic, Context>:
Applyable<DispatchInfo=DispatchInfo> +
GetDispatchInfo,
CallOf<Block::Extrinsic, Context>: Dispatchable,
OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
UnsignedValidator: ValidateUnsigned<Call=CallOf<Block::Extrinsic, Context>>,
{
fn execute_block(block: Block) {
Executive::<System, Block, Context, UnsignedValidator, AllModules>::execute_block(block);
Executive::<System, Block, Context, AllModules>::execute_block(block);
}
}

impl<
System: frame_system::Trait,
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
Context: Default,
UnsignedValidator,
AllModules:
OnRuntimeUpgrade +
OnInitialize<System::BlockNumber> +
OnFinalize<System::BlockNumber> +
OffchainWorker<System::BlockNumber> +
WeighBlock<System::BlockNumber>,
> Executive<System, Block, Context, UnsignedValidator, AllModules>
> Executive<System, Block, Context, AllModules>
where
Block::Extrinsic: Checkable<Context> + Codec,
CheckedOf<Block::Extrinsic, Context>:
Applyable<DispatchInfo=DispatchInfo> +
GetDispatchInfo,
CallOf<Block::Extrinsic, Context>: Dispatchable,
OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
UnsignedValidator: ValidateUnsigned<Call=CallOf<Block::Extrinsic, Context>>,
{
/// Start the execution of a particular block.
pub fn initialize_block(header: &System::Header) {
Expand Down Expand Up @@ -312,7 +298,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(xt, dispatch_info, encoded_len)?;

<frame_system::Module<System>>::note_applied_extrinsic(&r, encoded_len as u32, dispatch_info);

Expand Down Expand Up @@ -350,7 +336,7 @@ where
let xt = uxt.check(&Default::default())?;

let dispatch_info = xt.get_dispatch_info();
xt.validate::<UnsignedValidator>(dispatch_info, encoded_len)
xt.validate(dispatch_info, encoded_len)
}

/// Start an offchain worker and generate extrinsics.
Expand Down Expand Up @@ -511,7 +497,7 @@ mod tests {
}
impl custom::Trait for Runtime {}

impl ValidateUnsigned for Runtime {
impl traits::ValidateUnsigned for Runtime {
type Call = Call;

fn pre_dispatch(_call: &Self::Call) -> Result<(), TransactionValidityError> {
Expand Down Expand Up @@ -542,17 +528,19 @@ mod tests {
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
frame_system::ValidateUnsigned<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>
);
type AllModules = (System, Balances, Custom);
type TestXt = sp_runtime::testing::TestXt<Call, SignedExtra>;
type Executive = super::Executive<Runtime, Block<TestXt>, ChainContext<Runtime>, Runtime, AllModules>;
type Executive = super::Executive<Runtime, Block<TestXt>, ChainContext<Runtime>, AllModules>;

fn extra(nonce: u64, fee: u64) -> SignedExtra {
(
frame_system::CheckEra::from(Era::Immortal),
frame_system::CheckNonce::from(nonce),
frame_system::CheckWeight::new(),
frame_system::ValidateUnsigned::new(),
pallet_transaction_payment::ChargeTransactionPayment::from(fee)
)
}
Expand Down
53 changes: 53 additions & 0 deletions frame/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1282,6 +1282,59 @@ impl<T: Trait + Send + Sync> Debug for CheckWeight<T> {
}
}


/// Unsigned transactions validation.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct ValidateUnsigned<T: Trait + Send + Sync>(PhantomData<T>);
bkchr marked this conversation as resolved.
Show resolved Hide resolved

impl<T: Trait + Send + Sync> ValidateUnsigned<T> {
/// Creates new `SignedExtension` to validate unsigned transactions.
pub fn new() -> Self {
Self(PhantomData)
}
}

impl<T> SignedExtension for ValidateUnsigned<T> where
T: Trait + traits::ValidateUnsigned<Call = <T as Trait>::Call> + Send + Sync,
{
type AccountId = T::AccountId;
type Call = <T as Trait>::Call;
type AdditionalSigned = ();
type DispatchInfo = DispatchInfo;
type Pre = ();
const IDENTIFIER: &'static str = "ValidateUnsigned";

fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }

fn pre_dispatch_unsigned(
call: &Self::Call,
_info: Self::DispatchInfo,
_len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
<T as traits::ValidateUnsigned>::pre_dispatch(call)
}

fn validate_unsigned(
call: &Self::Call,
_info: Self::DispatchInfo,
_len: usize,
) -> TransactionValidity {
<T as traits::ValidateUnsigned>::validate_unsigned(call)
}
}

impl<T: Trait + Send + Sync> Debug for ValidateUnsigned<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "ValidateUnsigned")
}

#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}

/// Nonce check and increment to give replay protection for transactions.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct CheckNonce<T: Trait>(#[codec(compact)] T::Index);
Expand Down
10 changes: 3 additions & 7 deletions primitives/runtime/src/generic/checked_extrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use crate::traits::{
self, Member, MaybeDisplay, SignedExtension, Dispatchable,
};
use crate::traits::ValidateUnsigned;
use crate::transaction_validity::TransactionValidity;

/// Definition of something that the external world might want to say; its
Expand Down Expand Up @@ -48,21 +47,19 @@ where
type Call = Call;
type DispatchInfo = Info;

fn validate<U: ValidateUnsigned<Call = Self::Call>>(
fn validate(
&self,
info: Self::DispatchInfo,
len: usize,
) -> TransactionValidity {
if let Some((ref id, ref extra)) = self.signed {
Extra::validate(extra, id, &self.function, info.clone(), len)
} else {
let valid = Extra::validate_unsigned(&self.function, info, len)?;
let unsigned_validation = U::validate_unsigned(&self.function)?;
Ok(valid.combine_with(unsigned_validation))
Extra::validate_unsigned(&self.function, info, len)
}
}

fn apply<U: ValidateUnsigned<Call=Self::Call>>(
fn apply(
self,
info: Self::DispatchInfo,
len: usize,
Expand All @@ -72,7 +69,6 @@ where
(Some(id), pre)
} else {
let pre = Extra::pre_dispatch_unsigned(&self.function, info.clone(), len)?;
U::pre_dispatch(&self.function)?;
(None, pre)
};
let res = self.function.dispatch(Origin::from(maybe_who));
Expand Down
5 changes: 2 additions & 3 deletions primitives/runtime/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use crate::traits::{
self, Checkable, Applyable, BlakeTwo256, OpaqueKeys,
SignedExtension, Dispatchable,
};
use crate::traits::ValidateUnsigned;
use crate::{generic, KeyTypeId, ApplyExtrinsicResult};
pub use sp_core::{H256, sr25519};
use sp_core::{crypto::{CryptoType, Dummy, key_types, Public}, U256};
Expand Down Expand Up @@ -355,7 +354,7 @@ impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
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>>(
fn validate(
&self,
_info: Self::DispatchInfo,
_len: usize,
Expand All @@ -365,7 +364,7 @@ impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where

/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
/// index and sender.
fn apply<U: ValidateUnsigned<Call=Self::Call>>(
fn apply(
self,
info: Self::DispatchInfo,
len: usize,
Expand Down
4 changes: 2 additions & 2 deletions primitives/runtime/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,15 +894,15 @@ pub trait Applyable: Sized + Send + Sync {
type DispatchInfo: Clone;

/// Checks to see if this is a valid *transaction*. It returns information on it if so.
fn validate<V: ValidateUnsigned<Call=Self::Call>>(
fn validate(
&self,
info: Self::DispatchInfo,
len: usize,
) -> TransactionValidity;

/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
/// index and sender.
fn apply<V: ValidateUnsigned<Call=Self::Call>>(
fn apply(
self,
info: Self::DispatchInfo,
len: usize,
Expand Down