From cfe8667f16d1d193aaf07f98837872996f375334 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 17:19:35 +0900 Subject: [PATCH 01/32] add source to transaction extension --- bridges/bin/runtime-common/src/extensions.rs | 10 ++++--- bridges/modules/relayers/src/extension/mod.rs | 6 +++++ .../src/extensions.rs | 3 ++- substrate/frame/examples/basic/src/lib.rs | 2 ++ substrate/frame/examples/basic/src/tests.rs | 5 ++-- .../examples/kitchensink/src/benchmarking.rs | 1 + substrate/frame/sudo/src/extension.rs | 3 ++- .../frame/system/benchmarking/src/inner.rs | 2 ++ .../system/src/extensions/check_mortality.rs | 5 +++- .../src/extensions/check_non_zero_sender.rs | 11 +++++--- .../system/src/extensions/check_nonce.rs | 26 ++++++++++++------- .../system/src/extensions/check_weight.rs | 2 ++ .../asset-conversion-tx-payment/src/lib.rs | 2 ++ .../asset-tx-payment/src/lib.rs | 3 ++- .../skip-feeless-payment/src/lib.rs | 13 ++++++++-- .../skip-feeless-payment/src/mock.rs | 1 + .../skip-feeless-payment/src/tests.rs | 5 ++-- .../frame/transaction-payment/src/lib.rs | 2 ++ .../frame/transaction-payment/src/tests.rs | 21 ++++++++------- .../verify-signature/src/benchmarking.rs | 17 ++++++++++-- .../frame/verify-signature/src/extension.rs | 3 ++- substrate/frame/verify-signature/src/tests.rs | 10 +++---- .../runtime/src/generic/checked_extrinsic.rs | 23 +++++++++++----- .../as_transaction_extension.rs | 3 ++- .../dispatch_transaction.rs | 14 +++++++--- .../src/traits/transaction_extension/mod.rs | 10 +++++-- substrate/test-utils/runtime/src/lib.rs | 4 +++ 27 files changed, 149 insertions(+), 58 deletions(-) diff --git a/bridges/bin/runtime-common/src/extensions.rs b/bridges/bin/runtime-common/src/extensions.rs index 19d1554c668b..7266f1997084 100644 --- a/bridges/bin/runtime-common/src/extensions.rs +++ b/bridges/bin/runtime-common/src/extensions.rs @@ -299,6 +299,7 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl codec::Encode, + _source: sp_runtime::transaction_validity::TransactionSource, ) -> Result< ( sp_runtime::transaction_validity::ValidTransaction, @@ -393,6 +394,7 @@ mod tests { transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, DispatchError, }; + use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new( @@ -610,7 +612,8 @@ mod tests { 42u64.into(), &MockCall { data: 1 }, &(), - 0 + 0, + External, ), InvalidTransaction::Custom(1) ); @@ -629,7 +632,8 @@ mod tests { 42u64.into(), &MockCall { data: 2 }, &(), - 0 + 0, + External, ), InvalidTransaction::Custom(2) ); @@ -645,7 +649,7 @@ mod tests { assert_eq!( BridgeRejectObsoleteHeadersAndMessages - .validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0) + .validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0, External) .unwrap() .0, ValidTransaction { priority: 3, ..Default::default() }, diff --git a/bridges/modules/relayers/src/extension/mod.rs b/bridges/modules/relayers/src/extension/mod.rs index 710533c223a0..af408545c462 100644 --- a/bridges/modules/relayers/src/extension/mod.rs +++ b/bridges/modules/relayers/src/extension/mod.rs @@ -33,6 +33,7 @@ use bp_runtime::{Chain, RangeInclusiveExt, StaticStrProvider}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, PostDispatchInfo}, + pallet_prelude::TransactionSource, weights::Weight, CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; @@ -304,6 +305,7 @@ where _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { // Prepare relevant data for `prepare` let parsed_call = match C::parse_and_check_for_obsolete_call(call)? { @@ -466,6 +468,7 @@ mod tests { transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, DispatchError, }; + use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { TestParachain: u32 = BridgedUnderlyingParachain::PARACHAIN_ID; @@ -1076,6 +1079,7 @@ mod tests { &call, &DispatchInfo::default(), 0, + External, ) .map(|t| t.0) } @@ -1088,6 +1092,7 @@ mod tests { &call, &DispatchInfo::default(), 0, + External, ) .map(|t| t.0) } @@ -1100,6 +1105,7 @@ mod tests { &call, &DispatchInfo::default(), 0, + External, ) .map(|t| t.0) } diff --git a/substrate/frame/examples/authorization-tx-extension/src/extensions.rs b/substrate/frame/examples/authorization-tx-extension/src/extensions.rs index d1e56916d3a2..dcbe171c183a 100644 --- a/substrate/frame/examples/authorization-tx-extension/src/extensions.rs +++ b/substrate/frame/examples/authorization-tx-extension/src/extensions.rs @@ -18,7 +18,7 @@ use core::{fmt, marker::PhantomData}; use codec::{Decode, Encode}; -use frame_support::{traits::OriginTrait, Parameter}; +use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, Parameter}; use scale_info::TypeInfo; use sp_runtime::{ impl_tx_ext_default, @@ -94,6 +94,7 @@ where _len: usize, _self_implicit: Self::Implicit, inherited_implication: &impl codec::Encode, + _source: TransactionSource, ) -> ValidateResult { // If the extension is inactive, just move on in the pipeline. let Some(auth) = &self.inner else { diff --git a/substrate/frame/examples/basic/src/lib.rs b/substrate/frame/examples/basic/src/lib.rs index 2f1b32d964e4..efdf4332e329 100644 --- a/substrate/frame/examples/basic/src/lib.rs +++ b/substrate/frame/examples/basic/src/lib.rs @@ -61,6 +61,7 @@ use codec::{Decode, Encode}; use core::marker::PhantomData; use frame_support::{ dispatch::{ClassifyDispatch, DispatchClass, DispatchResult, Pays, PaysFee, WeighData}, + pallet_prelude::TransactionSource, traits::IsSubType, weights::Weight, }; @@ -508,6 +509,7 @@ where len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult::RuntimeCall> { // if the transaction is too big, just drop it. if len > 200 { diff --git a/substrate/frame/examples/basic/src/tests.rs b/substrate/frame/examples/basic/src/tests.rs index 8e33d3d0a348..8008f9264c7b 100644 --- a/substrate/frame/examples/basic/src/tests.rs +++ b/substrate/frame/examples/basic/src/tests.rs @@ -28,6 +28,7 @@ use sp_core::H256; // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. use sp_runtime::{ traits::{BlakeTwo256, DispatchTransaction, IdentityLookup}, + transaction_validity::TransactionSource::External, BuildStorage, }; // Reexport crate as its pallet name for construct_runtime. @@ -146,7 +147,7 @@ fn signed_ext_watch_dummy_works() { assert_eq!( WatchDummy::(PhantomData) - .validate_only(Some(1).into(), &call, &info, 150) + .validate_only(Some(1).into(), &call, &info, 150, External) .unwrap() .0 .priority, @@ -154,7 +155,7 @@ fn signed_ext_watch_dummy_works() { ); assert_eq!( WatchDummy::(PhantomData) - .validate_only(Some(1).into(), &call, &info, 250) + .validate_only(Some(1).into(), &call, &info, 250, External) .unwrap_err(), InvalidTransaction::ExhaustsResources.into(), ); diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 5f1d378e06fe..1d7022c55b61 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -26,6 +26,7 @@ use crate::Pallet as Kitchensink; use frame_benchmarking::v2::*; use frame_system::RawOrigin; +use frame_support::pallet_prelude::TransactionSource; // To actually run this benchmark on pallet-example-kitchensink, we need to put this pallet into the // runtime and compile it with `runtime-benchmarks` feature. The detail procedures are diff --git a/substrate/frame/sudo/src/extension.rs b/substrate/frame/sudo/src/extension.rs index 573de45ba32d..d2669de79e54 100644 --- a/substrate/frame/sudo/src/extension.rs +++ b/substrate/frame/sudo/src/extension.rs @@ -18,7 +18,7 @@ use crate::{Config, Key}; use codec::{Decode, Encode}; use core::{fmt, marker::PhantomData}; -use frame_support::{dispatch::DispatchInfo, ensure}; +use frame_support::{dispatch::DispatchInfo, ensure, pallet_prelude::TransactionSource}; use scale_info::TypeInfo; use sp_runtime::{ impl_tx_ext_default, @@ -94,6 +94,7 @@ where _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< ( ValidTransaction, diff --git a/substrate/frame/system/benchmarking/src/inner.rs b/substrate/frame/system/benchmarking/src/inner.rs index 0fb592f3dbba..08a14ea6f401 100644 --- a/substrate/frame/system/benchmarking/src/inner.rs +++ b/substrate/frame/system/benchmarking/src/inner.rs @@ -49,6 +49,8 @@ pub trait Config: frame_system::Config { #[benchmarks] mod benchmarks { + use frame_support::pallet_prelude::TransactionSource; + use super::*; #[benchmark] diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs index 7da5521f353d..59edafa792e3 100644 --- a/substrate/frame/system/src/extensions/check_mortality.rs +++ b/substrate/frame/system/src/extensions/check_mortality.rs @@ -17,6 +17,7 @@ use crate::{pallet_prelude::BlockNumberFor, BlockHash, Config, Pallet}; use codec::{Decode, Encode}; +use frame_support::pallet_prelude::TransactionSource; use scale_info::TypeInfo; use sp_runtime::{ generic::Era, @@ -91,6 +92,7 @@ impl TransactionExtension for CheckMort _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { let current_u64 = >::block_number().saturated_into::(); let valid_till = self.0.death(current_u64); @@ -116,6 +118,7 @@ mod tests { }; use sp_core::H256; use sp_runtime::traits::DispatchTransaction; + use sp_runtime::transaction_validity::TransactionSource::External; #[test] fn signed_ext_check_era_should_work() { @@ -151,7 +154,7 @@ mod tests { >::insert(16, H256::repeat_byte(1)); assert_eq!( - ext.validate_only(Some(1).into(), CALL, &normal, len).unwrap().0.longevity, + ext.validate_only(Some(1).into(), CALL, &normal, len, External).unwrap().0.longevity, 15 ); }) diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs index ec8c12b790d2..189bc35a3bf7 100644 --- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs +++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs @@ -18,7 +18,7 @@ use crate::Config; use codec::{Decode, Encode}; use core::marker::PhantomData; -use frame_support::{traits::OriginTrait, DefaultNoBound}; +use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, DefaultNoBound}; use scale_info::TypeInfo; use sp_runtime::{ impl_tx_ext_default, @@ -68,6 +68,7 @@ impl TransactionExtension for CheckNonZ _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> sp_runtime::traits::ValidateResult { if let Some(who) = origin.as_signer() { if who.using_encoded(|d| d.iter().all(|x| *x == 0)) { @@ -88,6 +89,7 @@ mod tests { traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}, transaction_validity::TransactionValidityError, }; + use sp_runtime::transaction_validity::TransactionSource::External; #[test] fn zero_account_ban_works() { @@ -96,7 +98,7 @@ mod tests { let len = 0_usize; assert_eq!( CheckNonZeroSender::::new() - .validate_only(Some(0).into(), CALL, &info, len) + .validate_only(Some(0).into(), CALL, &info, len, External) .unwrap_err(), TransactionValidityError::from(InvalidTransaction::BadSigner) ); @@ -104,7 +106,8 @@ mod tests { Some(1).into(), CALL, &info, - len + len, + External, )); }) } @@ -115,7 +118,7 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; let (_, _, origin) = CheckNonZeroSender::::new() - .validate(None.into(), CALL, &info, len, (), CALL) + .validate(None.into(), CALL, &info, len, (), CALL, External) .unwrap(); assert!(!origin.is_transaction_authorized()); }) diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index d96d2c2c0662..73ab8aec799f 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -18,7 +18,9 @@ use crate::Config; use alloc::vec; use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchInfo, RuntimeDebugNoBound}; +use frame_support::{ + dispatch::DispatchInfo, pallet_prelude::TransactionSource, RuntimeDebugNoBound, +}; use scale_info::TypeInfo; use sp_runtime::{ traits::{ @@ -108,6 +110,7 @@ where _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { let Some(who) = origin.as_system_origin_signer() else { return Ok((Default::default(), Val::Refund(self.weight(call)), origin)) @@ -183,6 +186,7 @@ mod tests { assert_ok, assert_storage_noop, dispatch::GetDispatchInfo, traits::OriginTrait, }; use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}; + use sp_runtime::transaction_validity::TransactionSource::External; #[test] fn signed_ext_check_nonce_works() { @@ -203,7 +207,7 @@ mod tests { assert_storage_noop!({ assert_eq!( CheckNonce::(0u64.into()) - .validate_only(Some(1).into(), CALL, &info, len) + .validate_only(Some(1).into(), CALL, &info, len, External) .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Stale) ); @@ -219,7 +223,8 @@ mod tests { Some(1).into(), CALL, &info, - len + len, + External, )); assert_ok!(CheckNonce::(1u64.into()).validate_and_prepare( Some(1).into(), @@ -232,7 +237,8 @@ mod tests { Some(1).into(), CALL, &info, - len + len, + External, )); assert_eq!( CheckNonce::(5u64.into()) @@ -272,7 +278,7 @@ mod tests { assert_storage_noop!({ assert_eq!( CheckNonce::(1u64.into()) - .validate_only(Some(1).into(), CALL, &info, len) + .validate_only(Some(1).into(), CALL, &info, len, External) .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Payment) ); @@ -288,7 +294,8 @@ mod tests { Some(2).into(), CALL, &info, - len + len, + External, )); assert_ok!(CheckNonce::(1u64.into()).validate_and_prepare( Some(2).into(), @@ -301,7 +308,8 @@ mod tests { Some(3).into(), CALL, &info, - len + len, + External, )); assert_ok!(CheckNonce::(1u64.into()).validate_and_prepare( Some(3).into(), @@ -318,7 +326,7 @@ mod tests { let info = DispatchInfo::default(); let len = 0_usize; let (_, val, origin) = CheckNonce::(1u64.into()) - .validate(None.into(), CALL, &info, len, (), CALL) + .validate(None.into(), CALL, &info, len, (), CALL, External) .unwrap(); assert!(!origin.is_transaction_authorized()); assert_ok!(CheckNonce::(1u64.into()).prepare(val, &origin, CALL, &info, len)); @@ -342,7 +350,7 @@ mod tests { let len = 0_usize; // run the validation step let (_, val, origin) = CheckNonce::(1u64.into()) - .validate(Some(1).into(), CALL, &info, len, (), CALL) + .validate(Some(1).into(), CALL, &info, len, (), CALL, External) .unwrap(); // mutate `AccountData` for the caller crate::Account::::mutate(1, |info| { diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs index 131057f54a78..435c96c8741f 100644 --- a/substrate/frame/system/src/extensions/check_weight.rs +++ b/substrate/frame/system/src/extensions/check_weight.rs @@ -19,6 +19,7 @@ use crate::{limits::BlockWeights, Config, Pallet, LOG_TARGET}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, PostDispatchInfo}, + pallet_prelude::TransactionSource, traits::Get, }; use scale_info::TypeInfo; @@ -254,6 +255,7 @@ where len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { let (validity, next_len) = Self::do_validate(info, len)?; Ok((validity, next_len, origin)) diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs index 787f6b122e86..d6721c46422b 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/lib.rs @@ -47,6 +47,7 @@ extern crate alloc; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo}, + pallet_prelude::TransactionSource, traits::IsType, DefaultNoBound, }; @@ -308,6 +309,7 @@ where len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { let Some(who) = origin.as_system_origin_signer() else { return Ok((ValidTransaction::default(), Val::NoCharge, origin)) diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs index 25aa272ba01b..dd752989c366 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/lib.rs @@ -38,7 +38,7 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, DispatchResult, PostDispatchInfo}, - pallet_prelude::Weight, + pallet_prelude::{TransactionSource, Weight}, traits::{ tokens::{ fungibles::{Balanced, Credit, Inspect}, @@ -324,6 +324,7 @@ where len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs index d6ac648cefd4..dd907f6fcbb7 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/lib.rs @@ -39,6 +39,7 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::{CheckIfFeeless, DispatchResult}, + pallet_prelude::TransactionSource, traits::{IsType, OriginTrait}, weights::Weight, }; @@ -147,12 +148,20 @@ where len: usize, self_implicit: S::Implicit, inherited_implication: &impl Encode, + source: TransactionSource, ) -> ValidateResult { if call.is_feeless(&origin) { Ok((Default::default(), Skip(origin.caller().clone()), origin)) } else { - let (x, y, z) = - self.0.validate(origin, call, info, len, self_implicit, inherited_implication)?; + let (x, y, z) = self.0.validate( + origin, + call, + info, + len, + self_implicit, + inherited_implication, + source, + )?; Ok((x, Apply(y), z)) } } diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs index 83f7b7dfe2b5..cff232a0cae3 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/mock.rs @@ -60,6 +60,7 @@ impl TransactionExtension for DummyExtension { _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { ValidateCount::mutate(|c| *c += 1); Ok((ValidTransaction::default(), (), origin)) diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs index 666844c883bd..e6f8373e59e8 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs @@ -18,6 +18,7 @@ use crate::mock::{ pallet_dummy::Call, DummyExtension, PrepareCount, Runtime, RuntimeCall, ValidateCount, }; use frame_support::dispatch::DispatchInfo; +use sp_runtime::transaction_validity::TransactionSource; use sp_runtime::traits::DispatchTransaction; #[test] @@ -41,14 +42,14 @@ fn validate_works() { let call = RuntimeCall::DummyPallet(Call::::aux { data: 1 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0) + .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); let call = RuntimeCall::DummyPallet(Call::::aux { data: 0 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0) + .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index 711189be8d07..018c2f6b5919 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -54,6 +54,7 @@ use frame_support::{ dispatch::{ DispatchClass, DispatchInfo, DispatchResult, GetDispatchInfo, Pays, PostDispatchInfo, }, + pallet_prelude::TransactionSource, traits::{Defensive, EstimateCallFee, Get}, weights::{Weight, WeightToFee}, RuntimeDebugNoBound, @@ -916,6 +917,7 @@ where len: usize, _: (), _implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index e8f5ab99529f..85e0a4ae4727 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -24,6 +24,7 @@ use sp_runtime::{ generic::UncheckedExtrinsic, traits::{DispatchTransaction, One}, transaction_validity::InvalidTransaction, + transaction_validity::TransactionSource::External, BuildStorage, }; @@ -235,7 +236,7 @@ fn transaction_extension_allows_free_transactions() { class: DispatchClass::Operational, pays_fee: Pays::No, }; - assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len)); + assert_ok!(Ext::from(0).validate_only(Some(1).into(), CALL, &op_tx, len, External)); // like a InsecureFreeNormal let free_tx = DispatchInfo { @@ -245,7 +246,7 @@ fn transaction_extension_allows_free_transactions() { pays_fee: Pays::Yes, }; assert_eq!( - Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len).unwrap_err(), + Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len, External).unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Payment), ); }); @@ -659,11 +660,11 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; assert_eq!(priority, 60); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; assert_eq!(priority, 110); }); @@ -676,11 +677,11 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5810); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 6110); }); } @@ -698,7 +699,7 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; assert_eq!(priority, 10); }); @@ -710,7 +711,7 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5510); }); } @@ -729,7 +730,7 @@ fn higher_tip_have_higher_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len).unwrap().0.priority; + pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { @@ -740,7 +741,7 @@ fn higher_tip_have_higher_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - pri2 = ext.validate_only(Some(2).into(), CALL, &op, len).unwrap().0.priority; + pri2 = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; }); (pri1, pri2) diff --git a/substrate/frame/verify-signature/src/benchmarking.rs b/substrate/frame/verify-signature/src/benchmarking.rs index 2b592a4023ec..475cf4cec591 100644 --- a/substrate/frame/verify-signature/src/benchmarking.rs +++ b/substrate/frame/verify-signature/src/benchmarking.rs @@ -27,7 +27,10 @@ use super::*; use crate::{extension::VerifySignature, Config, Pallet as VerifySignaturePallet}; use alloc::vec; use frame_benchmarking::{v2::*, BenchmarkError}; -use frame_support::dispatch::{DispatchInfo, GetDispatchInfo}; +use frame_support::{ + dispatch::{DispatchInfo, GetDispatchInfo}, + pallet_prelude::TransactionSource, +}; use frame_system::{Call as SystemCall, RawOrigin}; use sp_io::hashing::blake2_256; use sp_runtime::traits::{AsTransactionAuthorizedOrigin, Dispatchable, TransactionExtension}; @@ -55,7 +58,17 @@ mod benchmarks { #[block] { - assert!(ext.validate(RawOrigin::None.into(), &call, &info, 0, (), &call).is_ok()); + assert!(ext + .validate( + RawOrigin::None.into(), + &call, + &info, + 0, + (), + &call, + TransactionSource::External + ) + .is_ok()); } Ok(()) diff --git a/substrate/frame/verify-signature/src/extension.rs b/substrate/frame/verify-signature/src/extension.rs index 4490a0a600bb..d48991e7a1da 100644 --- a/substrate/frame/verify-signature/src/extension.rs +++ b/substrate/frame/verify-signature/src/extension.rs @@ -20,7 +20,7 @@ use crate::{Config, WeightInfo}; use codec::{Decode, Encode}; -use frame_support::traits::OriginTrait; +use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait}; use scale_info::TypeInfo; use sp_io::hashing::blake2_256; use sp_runtime::{ @@ -113,6 +113,7 @@ where _len: usize, _: (), inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, diff --git a/substrate/frame/verify-signature/src/tests.rs b/substrate/frame/verify-signature/src/tests.rs index 3e4c8db12fe2..1d1de4449f3a 100644 --- a/substrate/frame/verify-signature/src/tests.rs +++ b/substrate/frame/verify-signature/src/tests.rs @@ -25,7 +25,7 @@ use extension::VerifySignature; use frame_support::{ derive_impl, dispatch::GetDispatchInfo, - pallet_prelude::{InvalidTransaction, TransactionValidityError}, + pallet_prelude::{InvalidTransaction, TransactionValidityError, TransactionSource}, traits::OriginTrait, }; use frame_system::Call as SystemCall; @@ -84,7 +84,7 @@ fn verification_works() { let info = call.get_dispatch_info(); let (_, _, origin) = VerifySignature::::new_with_signature(sig, who) - .validate_only(None.into(), &call, &info, 0) + .validate_only(None.into(), &call, &info, 0, TransactionSource::External) .unwrap(); assert_eq!(origin.as_signer().unwrap(), &who) } @@ -98,7 +98,7 @@ fn bad_signature() { assert_eq!( VerifySignature::::new_with_signature(sig, who) - .validate_only(None.into(), &call, &info, 0) + .validate_only(None.into(), &call, &info, 0, TransactionSource::External) .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::BadProof) ); @@ -113,7 +113,7 @@ fn bad_starting_origin() { assert_eq!( VerifySignature::::new_with_signature(sig, who) - .validate_only(Some(42).into(), &call, &info, 0) + .validate_only(Some(42).into(), &call, &info, 0, TransactionSource::External) .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::BadSigner) ); @@ -126,7 +126,7 @@ fn disabled_extension_works() { let info = call.get_dispatch_info(); let (_, _, origin) = VerifySignature::::new_disabled() - .validate_only(Some(who).into(), &call, &info, 0) + .validate_only(Some(who).into(), &call, &info, 0, TransactionSource::External) .unwrap(); assert_eq!(origin.as_signer().unwrap(), &who) } diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs index e2ecd5ed6da7..2fee8d85b136 100644 --- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs @@ -85,10 +85,11 @@ where }, ExtrinsicFormat::Signed(ref signer, ref extension) => { let origin = Some(signer.clone()).into(); - extension.validate_only(origin, &self.function, info, len).map(|x| x.0) + extension.validate_only(origin, &self.function, info, len, source).map(|x| x.0) }, - ExtrinsicFormat::General(ref extension) => - extension.validate_only(None.into(), &self.function, info, len).map(|x| x.0), + ExtrinsicFormat::General(ref extension) => extension + .validate_only(None.into(), &self.function, info, len, source) + .map(|x| x.0), } } @@ -111,10 +112,18 @@ where Extension::bare_post_dispatch(info, &mut 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), + 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, + ), } } } diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs index a5179748673f..282064078fe3 100644 --- a/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs +++ b/substrate/primitives/runtime/src/traits/transaction_extension/as_transaction_extension.rs @@ -25,7 +25,7 @@ use sp_core::RuntimeDebug; use crate::{ traits::{AsSystemOriginSigner, SignedExtension, ValidateResult}, - transaction_validity::InvalidTransaction, + transaction_validity::{InvalidTransaction, TransactionSource}, }; use super::*; @@ -74,6 +74,7 @@ where len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> ValidateResult { let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; let r = self.0.validate(who, call, info, len)?; diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs index e2fb556bf9d3..0dcb153413ff 100644 --- a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs +++ b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs @@ -17,7 +17,10 @@ //! The [DispatchTransaction] trait. -use crate::{traits::AsTransactionAuthorizedOrigin, transaction_validity::InvalidTransaction}; +use crate::{ + traits::AsTransactionAuthorizedOrigin, + transaction_validity::{InvalidTransaction, TransactionSource}, +}; use super::*; @@ -45,6 +48,7 @@ pub trait DispatchTransaction { call: &Call, info: &Self::Info, len: usize, + source: TransactionSource, ) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>; /// Validate and prepare a transaction, ready for dispatch. fn validate_and_prepare( @@ -93,8 +97,9 @@ where call: &Call, info: &DispatchInfoOf, len: usize, + source: TransactionSource, ) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> { - match self.validate(origin, call, info, len, self.implicit()?, call) { + match self.validate(origin, call, info, len, self.implicit()?, call, source) { // After validation, some origin must have been authorized. Ok((_, _, origin)) if !origin.is_transaction_authorized() => Err(InvalidTransaction::UnknownOrigin.into()), @@ -108,7 +113,7 @@ where info: &DispatchInfoOf, len: usize, ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> { - let (_, val, origin) = self.validate_only(origin, call, info, len)?; + let (_, val, origin) = self.validate_only(origin, call, info, len, TransactionSource::InBlock)?; let pre = self.prepare(val, &origin, &call, info, len)?; Ok((pre, origin)) } @@ -140,7 +145,8 @@ where Self::Origin, ) -> crate::DispatchResultWithInfo<::PostInfo>, ) -> Self::Result { - let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; + let (pre, origin) = + self.validate_and_prepare(origin, &call, info, len)?; let mut res = substitute(origin); let pd_res = res.map(|_| ()).map_err(|e| e.error); let post_info = match &mut res { diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs index 58cd0974661a..f8c5dc6a724e 100644 --- a/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs +++ b/substrate/primitives/runtime/src/traits/transaction_extension/mod.rs @@ -19,7 +19,9 @@ use crate::{ scale_info::{MetaType, StaticTypeInfo}, - transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, + transaction_validity::{ + TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, + }, DispatchResult, }; use codec::{Codec, Decode, Encode}; @@ -243,6 +245,7 @@ pub trait TransactionExtension: len: usize, self_implicit: Self::Implicit, inherited_implication: &impl Encode, + source: TransactionSource, ) -> ValidateResult; /// Do any pre-flight stuff for a transaction after validation. @@ -429,6 +432,7 @@ macro_rules! impl_tx_ext_default { _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl $crate::codec::Encode, + _source: $crate::transaction_validity::TransactionSource, ) -> $crate::traits::ValidateResult { Ok((Default::default(), Default::default(), origin)) } @@ -496,6 +500,7 @@ impl TransactionExtension for Tuple { len: usize, self_implicit: Self::Implicit, inherited_implication: &impl Encode, + source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, @@ -521,7 +526,7 @@ impl TransactionExtension for Tuple { // passed into the next items in this pipeline-tuple. &following_implicit_implications, ); - Tuple.validate(origin, call, info, len, item_implicit, &implications)? + Tuple.validate(origin, call, info, len, item_implicit, &implications, source)? }; let valid = valid.combine_with(item_valid); let val = val.push_back(item_val); @@ -616,6 +621,7 @@ impl TransactionExtension for () { _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, (), ::RuntimeOrigin), TransactionValidityError, diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index a4a0d348a390..67451267eb94 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -292,6 +292,7 @@ impl sp_runtime::traits::TransactionExtension for CheckSubstrateCal _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, @@ -1054,6 +1055,7 @@ mod tests { use sp_runtime::{ traits::{DispatchTransaction, Hash as _}, transaction_validity::{InvalidTransaction, ValidTransaction}, + transaction_validity::TransactionSource::External, }; use substrate_test_runtime_client::{ prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder, @@ -1211,6 +1213,7 @@ mod tests { &ExtrinsicBuilder::new_call_with_priority(16).build().function, &info, len, + External, ) .unwrap() .0 @@ -1225,6 +1228,7 @@ mod tests { &ExtrinsicBuilder::new_call_do_not_propagate().build().function, &info, len, + External, ) .unwrap() .0 From f84192bc2b71a8f4ed487f4287a9b11733cf1436 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 17:32:59 +0900 Subject: [PATCH 02/32] impl authorize --- Cargo.lock | 1 + polkadot/runtime/rococo/src/lib.rs | 19 + polkadot/runtime/test-runtime/src/lib.rs | 18 + polkadot/runtime/westend/src/lib.rs | 19 + substrate/bin/node/runtime/src/lib.rs | 21 + substrate/frame/benchmarking/src/utils.rs | 10 +- .../examples/kitchensink/src/benchmarking.rs | 40 +- .../frame/examples/kitchensink/src/lib.rs | 43 +- .../frame/examples/kitchensink/src/weights.rs | 18 + substrate/frame/support/procedural/Cargo.toml | 13 +- .../src/construct_runtime/expand/call.rs | 34 ++ substrate/frame/support/procedural/src/lib.rs | 150 ++++++ .../procedural/src/pallet/expand/call.rs | 168 +++++- .../procedural/src/pallet/expand/mod.rs | 4 +- .../procedural/src/pallet/expand/origin.rs | 3 +- .../procedural/src/pallet/parse/call.rs | 182 +++++-- .../procedural/src/pallet/parse/origin.rs | 4 +- substrate/frame/support/src/dispatch.rs | 2 + substrate/frame/support/src/lib.rs | 13 +- substrate/frame/support/src/traits.rs | 2 +- .../frame/support/src/traits/dispatch.rs | 22 + substrate/frame/support/src/traits/tasks.rs | 2 +- .../frame/support/test/tests/authorize.rs | 501 ++++++++++++++++++ .../authorize_weight_but_no_closure.rs | 47 ++ .../authorize_weight_but_no_closure.stderr | 5 + .../pallet_ui/authorize_wrong_closure.rs | 48 ++ .../pallet_ui/authorize_wrong_closure.stderr | 8 + .../pallet_ui/authorize_wrong_closure_2.rs | 48 ++ .../authorize_wrong_closure_2.stderr | 54 ++ .../pallet_ui/authorize_wrong_closure_3.rs | 48 ++ .../authorize_wrong_closure_3.stderr | 5 + .../pallet_ui/authorize_wrong_closure_4.rs | 48 ++ .../authorize_wrong_closure_4.stderr | 39 ++ .../pallet_ui/authorize_wrong_closure_5.rs | 50 ++ .../authorize_wrong_closure_5.stderr | 8 + .../pallet_ui/authorize_wrong_closure_6.rs | 54 ++ .../authorize_wrong_closure_6.stderr | 67 +++ .../tests/pallet_ui/authorize_wrong_weight.rs | 48 ++ .../pallet_ui/authorize_wrong_weight.stderr | 22 + .../pallet_ui/authorize_wrong_weight_info.rs | 47 ++ .../authorize_wrong_weight_info.stderr | 5 + .../authorize_wrong_weight_info_2.rs | 47 ++ .../authorize_wrong_weight_info_2.stderr | 5 + .../test/tests/split_ui/pass/call/mod.rs | 9 +- .../system/src/extensions/authorize_call.rs | 325 ++++++++++++ substrate/frame/system/src/extensions/mod.rs | 1 + substrate/frame/system/src/lib.rs | 25 +- substrate/frame/system/src/offchain.rs | 20 + .../runtime/src/transaction_validity.rs | 5 + 49 files changed, 2255 insertions(+), 122 deletions(-) create mode 100644 substrate/frame/support/test/tests/authorize.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.rs create mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.stderr create mode 100644 substrate/frame/system/src/extensions/authorize_call.rs diff --git a/Cargo.lock b/Cargo.lock index 602891892a2b..575b966f118c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6494,6 +6494,7 @@ dependencies = [ "derive-syn-parse", "docify", "expander", + "frame-benchmarking", "frame-support", "frame-support-procedural-tools", "frame-system", diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 44dd820f8c3c..3b90963b392a 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -696,6 +696,25 @@ where } } +impl frame_system::offchain::CreateAuthorizedTransaction for Runtime +where + RuntimeCall: From, +{ + fn create_extension() -> Self::Extension { + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckMortality::::from(generic::Era::Immortal), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + frame_metadata_hash_extension::CheckMetadataHash::new(false), + ) + } +} + parameter_types! { pub Prefix: &'static [u8] = b"Pay ROCs to the Rococo account:"; } diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 9e7ee488af72..3f4fa74a3768 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -198,6 +198,24 @@ where } } +impl frame_system::offchain::CreateAuthorizedTransaction for Runtime +where + RuntimeCall: From, +{ + fn create_extension() -> Self::Extension { + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckMortality::::from(generic::Era::Immortal), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ) + } +} + parameter_types! { pub storage EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS as u64; pub storage ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index a91ca399db41..6cdc2cb0a31a 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -944,6 +944,25 @@ where } } +impl frame_system::offchain::CreateAuthorizedTransaction for Runtime +where + RuntimeCall: From, +{ + fn create_extension() -> Self::Extension { + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckMortality::::from(generic::Era::Immortal), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + frame_metadata_hash_extension::CheckMetadataHash::::new(false), + ) + } +} + parameter_types! { // Minimum 100 bytes/KSM deposited (1 CENT/byte) pub const BasicDeposit: Balance = 1000 * CENTS; // 258 bytes on-chain diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index d6a17856e470..fa8aa7922c1c 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1528,6 +1528,27 @@ where type RuntimeCall = RuntimeCall; } +impl frame_system::offchain::CreateAuthorizedTransaction for Runtime +where + RuntimeCall: From, +{ + fn create_extension() -> Self::Extension { + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::Immortal), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_skip_feeless_payment::SkipCheckIfFeeless::from( + pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from(0, None), + ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), + ) + } +} + impl pallet_im_online::Config for Runtime { type AuthorityId = ImOnlineId; type RuntimeEvent = RuntimeEvent; diff --git a/substrate/frame/benchmarking/src/utils.rs b/substrate/frame/benchmarking/src/utils.rs index ca362f7aa7ef..8d6098704566 100644 --- a/substrate/frame/benchmarking/src/utils.rs +++ b/substrate/frame/benchmarking/src/utils.rs @@ -23,7 +23,9 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_io::hashing::blake2_256; -use sp_runtime::{traits::TrailingZeroInput, DispatchError}; +use sp_runtime::{ + traits::TrailingZeroInput, transaction_validity::TransactionValidityError, DispatchError, +}; use sp_storage::TrackedStorageKey; /// An alphabet of possible parameters to use for benchmarking. @@ -195,6 +197,12 @@ impl From for BenchmarkError { } } +impl From for BenchmarkError { + fn from(e: TransactionValidityError) -> Self { + Self::Stop(e.into()) + } +} + /// Configuration used to setup and run runtime benchmarks. #[derive(Encode, Decode, Default, Clone, PartialEq, Debug, TypeInfo)] pub struct BenchmarkConfig { diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 1d7022c55b61..4906094b54b1 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -55,11 +55,45 @@ mod benchmarks { assert_eq!(Foo::::get(), Some(value)) } + // This will measure the execution time of `set_foo_using_authorize`. + #[benchmark] + fn set_foo_using_authorize() { + // This is the benchmark setup phase. + + // `set_foo_using_authorize` is only authorized when value is 42 so we will use it. + let value = 42u32; + // We dispatch with authorized origin, it is the origin resulting from authorization. + let origin = RawOrigin::Authorized; + + #[extrinsic_call] + _(origin, value); // The execution phase is just running `set_foo_using_authorize` extrinsic call + + // This is the optional benchmark verification phase, asserting certain states. + assert_eq!(Foo::::get(), Some(42)) + } + + // This will measure the weight for the closure in `[pallet::authorize(...)]`. + #[benchmark] + fn authorize_set_foo_using_authorize() { + // This is the benchmark setup phase. + + let call = Call::::set_foo_using_authorize { new_foo: 42 }; + let source = TransactionSource::External; + + // We use a block with specific code to benchmark the closure. + #[block] + { + use frame_support::traits::Authorize; + call.authorize(source) + .expect("Call give some authorization") + .expect("Authorization is successful"); + } + } + // This line generates test cases for benchmarking, and could be run by: // `cargo test -p pallet-example-kitchensink --all-features`, you will see one line per case: - // `test benchmarking::bench_sort_vector ... ok` - // `test benchmarking::bench_accumulate_dummy ... ok` - // `test benchmarking::bench_set_dummy_benchmark ... ok` in the result. + // `test benchmarking::bench_set_foo_benchmark ... ok` + // `test benchmarking::bench_set_foo_using_authorize_benchmark ... ok` in the result. // // The line generates three steps per benchmark, with repeat=1 and the three steps are // [low, mid, high] of the range. diff --git a/substrate/frame/examples/kitchensink/src/lib.rs b/substrate/frame/examples/kitchensink/src/lib.rs index 442318565426..ac62f8cf4d24 100644 --- a/substrate/frame/examples/kitchensink/src/lib.rs +++ b/substrate/frame/examples/kitchensink/src/lib.rs @@ -220,6 +220,35 @@ pub mod pallet { Ok(()) } + + /// A call that is specially authorized. + /// Authorized call can be dispatched by anybody without requiring any signature or fee. + #[pallet::call_index(1)] + #[pallet::authorize(| + _source: TransactionSource, + new_foo: &u32, + | -> TransactionValidityWithRefund { + if *new_foo == 42 { + let refund = Weight::zero(); + let validity = ValidTransaction::default(); + Ok((validity, refund)) + } else { + Err(InvalidTransaction::Call.into()) + } + })] + #[pallet::weight(T::WeightInfo::set_foo_using_authorize())] + #[pallet::weight_of_authorize(T::WeightInfo::authorize_set_foo_using_authorize())] + pub fn set_foo_using_authorize( + origin: OriginFor, + new_foo: u32, + ) -> DispatchResult { + // We only dispatch if it comes from the authorized origin. Meaning that the closure + // passed in `pallet::authorize` has successfully authorized the call. + ensure_authorized(origin)?; + Foo::::set(Some(new_foo)); + + Ok(()) + } } /// The event type. This exactly like a normal Rust enum. @@ -300,20 +329,6 @@ pub mod pallet { Staking, } - /// Allows the pallet to validate some unsigned transaction. See - /// [`sp_runtime::traits::ValidateUnsigned`] for more info. - #[pallet::validate_unsigned] - impl ValidateUnsigned for Pallet { - type Call = Call; - fn validate_unsigned(_: TransactionSource, _: &Self::Call) -> TransactionValidity { - unimplemented!() - } - - fn pre_dispatch(_: &Self::Call) -> Result<(), TransactionValidityError> { - unimplemented!() - } - } - /// Allows the pallet to provide some inherent. See [`frame_support::inherent::ProvideInherent`] /// for more info. #[pallet::inherent] diff --git a/substrate/frame/examples/kitchensink/src/weights.rs b/substrate/frame/examples/kitchensink/src/weights.rs index 43f48332ae94..fd630f68d082 100644 --- a/substrate/frame/examples/kitchensink/src/weights.rs +++ b/substrate/frame/examples/kitchensink/src/weights.rs @@ -51,6 +51,8 @@ use core::marker::PhantomData; /// Weight functions needed for pallet_template. pub trait WeightInfo { fn set_foo_benchmark() -> Weight; + fn set_foo_using_authorize() -> Weight; + fn authorize_set_foo_using_authorize() -> Weight; } /// Weight functions for `pallet_example_kitchensink`. @@ -67,6 +69,14 @@ impl WeightInfo for SubstrateWeight { .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } + fn set_foo_using_authorize() -> Weight { + // TODO TODO: + Weight::zero() + } + fn authorize_set_foo_using_authorize() -> Weight { + // TODO TODO: + Weight::zero() + } } impl WeightInfo for () { @@ -81,4 +91,12 @@ impl WeightInfo for () { .saturating_add(Weight::from_parts(0, 0)) .saturating_add(RocksDbWeight::get().writes(1)) } + fn set_foo_using_authorize() -> Weight { + // TODO TODO: + Weight::zero() + } + fn authorize_set_foo_using_authorize() -> Weight { + // TODO TODO: + Weight::zero() + } } diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 51790062b2c2..05472d8966ac 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -38,15 +38,18 @@ codec = { features = [ "max-encoded-len", ], workspace = true } regex = { workspace = true } -sp-metadata-ir = { workspace = true } +sp-metadata-ir = { workspace = true, features = ["std"] } scale-info = { features = ["derive"], workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } +sp-core = { workspace = true, features = ["std"] } +sp-io = { workspace = true, features = ["std"] } sp-runtime = { features = [ "serde", + "runtime-benchmarks", + "std", ], workspace = true } -frame-system = { workspace = true } -frame-support = { workspace = true } +frame-system = { workspace = true, features = ["runtime-benchmarks", "std"] } +frame-support = { workspace = true, features = ["runtime-benchmarks", "std"] } +frame-benchmarking = { workspace = true, features = ["std"] } pretty_assertions = { workspace = true } static_assertions = { workspace = true } diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs index f055e8ce28e9..f8a774e38554 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs @@ -29,6 +29,7 @@ pub fn expand_outer_dispatch( ) -> TokenStream { let mut variant_defs = TokenStream::new(); let mut variant_patterns = Vec::new(); + let mut variant_usages = Vec::new(); let mut query_call_part_macros = Vec::new(); let mut pallet_names = Vec::new(); let mut pallet_attrs = Vec::new(); @@ -55,6 +56,7 @@ pub fn expand_outer_dispatch( #[codec(index = #index)] #name( #scrate::dispatch::CallableCallFor<#name, #runtime> ), }); + variant_usages.push(quote!( #scrate::dispatch::CallableCallFor<#name, #runtime> )); variant_patterns.push(quote!(RuntimeCall::#name(call))); pallet_names.push(name); pallet_attrs.push(attr); @@ -220,5 +222,37 @@ pub fn expand_outer_dispatch( } } )* + + impl #scrate::traits::Authorize for RuntimeCall { + fn authorize( + &self, + source: #scrate::pallet_prelude::TransactionSource, + ) -> ::core::option::Option< + ::core::result::Result< + ( + #scrate::pallet_prelude::ValidTransaction, + #scrate::pallet_prelude::Weight, + ), + #scrate::pallet_prelude::TransactionValidityError + > + > { + match self { + #( + #pallet_attrs + #variant_patterns => #scrate::traits::Authorize::authorize(call, source), + )* + } + } + + fn weight_of_authorize(&self) -> #scrate::pallet_prelude::Weight { + match self { + #( + #pallet_attrs + #variant_patterns => + #scrate::traits::Authorize::weight_of_authorize(call), + )* + } + } + } } } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index c2f546d92048..2ca7598746e8 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1338,3 +1338,153 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream .unwrap_or_else(|r| r.into_compile_error()) .into() } + +/// Allows to authorize some general transactions with specific call. +/// +/// This attribute allows to specify a special validation logic for a specific call. +/// A general transaction with this specific call can then be validated by the given function, +/// and if valid then dispatched with the origin [`frame_system::Origin::Authorized`]. +/// +/// To ensure the origin of the call is the authorization process, the call must check the origin +/// with [`frame_system::ensure_authorized`] function. +/// +/// To enable the authorization process on the extrinsic, the runtime must use +/// [`frame_system::AuthorizeCall`] transaction extension in the transaction extension pipeline. +/// +/// To enable the creation of authorized call from offchain worker. The runtime should implement +/// [`frame_system::CreateAuthorizedTransaction`]. This trait allows to specify which transaction +/// extension to use when creating a transaction for an authorized call. +/// +/// # Usage in the pallet +/// +/// ## Example/Overview: +/// +/// ``` +/// # #[allow(unused)] +/// #[frame_support::pallet] +/// pub mod pallet { +/// use frame_support::pallet_prelude::*; +/// use frame_system::pallet_prelude::*; +/// +/// #[pallet::pallet] +/// pub struct Pallet(_); +/// +/// #[pallet::config] +/// pub trait Config: frame_system::Config {} +/// +/// #[pallet::call] +/// impl Pallet { +/// #[pallet::weight(Weight::zero())] +/// #[pallet::authorize(|_source, foo| if *foo == 42 { +/// let refund = Weight::zero(); +/// let validity = ValidTransaction::default(); +/// Ok((validity, refund)) +/// } else { +/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) +/// })] +/// #[pallet::weight_of_authorize(Weight::zero())] +/// #[pallet::call_index(0)] +/// pub fn some_call(origin: OriginFor, arg: u32) -> DispatchResult { +/// ensure_authorized(origin)?; +/// +/// Ok(()) +/// } +/// +/// #[pallet::weight(Weight::zero())] +/// // We can also give the callback as a function +/// #[pallet::authorize(Pallet::::authorize_some_other_call)] +/// #[pallet::weight_of_authorize(Weight::zero())] +/// #[pallet::call_index(1)] +/// pub fn some_other_call(origin: OriginFor, arg: u32) -> DispatchResult { +/// ensure_authorized(origin)?; +/// +/// Ok(()) +/// } +/// } +/// +/// impl Pallet { +/// fn authorize_some_other_call( +/// source: TransactionSource, +/// foo: &u32 +/// ) -> TransactionValidityWithRefund { +/// if *foo == 42 { +/// let refund = Weight::zero(); +/// let validity = ValidTransaction::default(); +/// Ok((validity, refund)) +/// } else { +/// Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) +/// } +/// } +/// } +/// +/// #[frame_benchmarking::v2::benchmarks] +/// mod benchmarks { +/// use super::*; +/// use frame_benchmarking::v2::BenchmarkError; +/// +/// #[benchmark] +/// fn authorize_some_call() -> Result<(), BenchmarkError> { +/// let call = Call::::some_call { arg: 42 }; +/// +/// #[block] +/// { +/// use frame_support::pallet_prelude::Authorize; +/// call.authorize(TransactionSource::External) +/// .ok_or("Call must give some authorization")??; +/// } +/// +/// Ok(()) +/// } +/// } +/// } +/// ``` +/// +/// ## Specification: +/// +/// Authorize process comes with 2 attributes macro on top of the authorized call: +/// +/// * `#[pallet::authorize($authorized_function)]` - defines the function that authorizes the call. +/// First argument is the transaction source [`frame_support::pallet_prelude::TransactionSource`] +/// then followed by the same as call arguments but by reference `&`. Return type is +/// [`TransactionValidityWithRefund`](frame_support::pallet_prelude::TransactionValidityWithRefund). +/// * `#[pallet::weight_of_authorize($weight)]` - defines the value of the weight of the authorize +/// function. This attribute is similar to `#[pallet::weight]`: +/// * it can be ignore in `dev_mode` +/// * it can be automatically infered from weight info. For the call `foo` the function +/// `authorize_foo` in the weight info will be used. +/// * it can be a fixed value like `Weight::from_all(0)` (not recommended in production). +/// +/// The weight must be small enough so that nodes don't get DDOS by validating transactions. +/// +/// Then in the call it must be ensured that the origin is the authorization process. This can +/// be done using [`frame_system::ensure_authorized`] function. +/// +/// # The macro expansion +/// +/// From the given "authorize" function and weight, the macro will implement the trait +/// [`Authorize`](frame_support::pallet_prelude::Authorize) on the call. +/// +/// # How to benchmark +/// +/// The authorize function is used as the implementation of the trait +/// [`Authorize`](frame_support::pallet_prelude::Authorize) for the call. +/// To benchmark a call variant, use the function +/// [`Authorize::authorize`](frame_support::pallet_prelude::Authorize) on a call value. +/// See the example in the first section. +#[proc_macro_attribute] +pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { + pallet_macro_stub() +} + +/// Allows to define the weight of the authorize function. +/// +/// See [`frame_support_procedural::authorize`] for more information on how authorization works. +/// +/// # Example: +/// ``` +/// // TODO TODO: copy paste +/// ``` +#[proc_macro_attribute] +pub fn weight_of_authorize(_: TokenStream, _: TokenStream) -> TokenStream { + pallet_macro_stub() +} diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs index 87fb4b8967e6..f0f98986e9b2 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/call.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs @@ -18,7 +18,10 @@ use crate::{ pallet::{ expand::warnings::{weight_constant_warning, weight_witness_warning}, - parse::{call::CallWeightDef, helper::CallReturnType}, + parse::{ + call::{CallVariantDef, CallWeightDef}, + helper::CallReturnType, + }, Def, }, COUNTER, @@ -28,6 +31,33 @@ use proc_macro_warning::Warning; use quote::{quote, ToTokens}; use syn::spanned::Spanned; +/// Expand the weight to final token stream and accumulate warnings. +fn expand_weight( + prefix: &str, + frame_support: &syn::Path, + dev_mode: bool, + weight_warnings: &mut Vec, + method: &CallVariantDef, + weight: &CallWeightDef, +) -> TokenStream2 { + match weight { + CallWeightDef::DevModeDefault => quote::quote!( + #frame_support::pallet_prelude::Weight::zero() + ), + CallWeightDef::Immediate(e) => { + weight_constant_warning(e, dev_mode, weight_warnings); + weight_witness_warning(method, dev_mode, weight_warnings); + + e.into_token_stream() + }, + CallWeightDef::Inherited(t) => { + // Expand `<::WeightInfo>::$prefix$call_name()`. + let n = &syn::Ident::new(&format!("{}{}", prefix, method.name), t.span()); + quote!({ < #t > :: #n () }) + }, + } +} + /// /// * Generate enum call and implement various trait on it. /// * Implement Callable and call_function on `Pallet` @@ -86,29 +116,15 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { let mut fn_weight = Vec::::new(); let mut weight_warnings = Vec::new(); for method in &methods { - match &method.weight { - CallWeightDef::DevModeDefault => fn_weight.push(syn::parse_quote!(0)), - CallWeightDef::Immediate(e) => { - weight_constant_warning(e, def.dev_mode, &mut weight_warnings); - weight_witness_warning(method, def.dev_mode, &mut weight_warnings); - - fn_weight.push(e.into_token_stream()); - }, - CallWeightDef::Inherited => { - let pallet_weight = def - .call - .as_ref() - .expect("we have methods; we have calls; qed") - .inherited_call_weight - .as_ref() - .expect("the parser prevents this"); - - // Expand `<::WeightInfo>::call_name()`. - let t = &pallet_weight.typename; - let n = &method.name; - fn_weight.push(quote!({ < #t > :: #n () })); - }, - } + let w = expand_weight( + "", + frame_support, + def.dev_mode, + &mut weight_warnings, + method, + &method.weight, + ); + fn_weight.push(w); } debug_assert_eq!(fn_weight.len(), methods.len()); @@ -272,7 +288,70 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { Err(e) => return e.into_compile_error(), }; - quote::quote_spanned!(span => + let authorize_fn = methods.iter().zip(args_name.iter()).zip(args_type.iter()).map( + |((method, arg_name), arg_type)| { + if let Some(authorize_def) = &method.authorize { + let authorize_fn = &authorize_def.expr; + let attr_fn_getter = syn::Ident::new( + &format!("macro_inner_authorize_call_for_{}", method.name), + authorize_fn.span(), + ); + + let typed_authorize_fn = quote::quote_spanned!(authorize_fn.span() => { + // Closure don't have a writable type. So we fix the authorize token stream to + // be any implementation of this generic F. + // This also allows to have good type inference on the closure. + fn #attr_fn_getter< + #type_impl_gen, + F: Fn( + #frame_support::pallet_prelude::TransactionSource, + #( &#arg_type ),* + ) -> ::core::result::Result< + ( + #frame_support::pallet_prelude::ValidTransaction, + #frame_support::pallet_prelude::Weight, + ), + #frame_support::pallet_prelude::TransactionValidityError, + > + >(f: F) -> F { + f + } + + #attr_fn_getter::<#type_use_gen, _>(#authorize_fn) + }); + + // `source` is from outside this block, so we can't use the authorize_fn span. + quote::quote!( + let authorize_fn = #typed_authorize_fn; + let res = authorize_fn(source, #( #arg_name, )*); + + Some(res) + ) + } else { + quote::quote!(None) + } + }, + ); + + let mut authorize_fn_weight = Vec::::new(); + for method in &methods { + let w = match &method.authorize { + Some(authorize_def) => expand_weight( + "authorize_", + frame_support, + def.dev_mode, + &mut weight_warnings, + method, + &authorize_def.weight, + ), + // No authorize logic, weight is negligible + None => quote::quote!(#frame_support::pallet_prelude::Weight::zero()), + }; + authorize_fn_weight.push(w); + } + assert_eq!(authorize_fn_weight.len(), methods.len()); + + quote::quote_spanned!(proc_macro2::Span::call_site() => #[doc(hidden)] mod warnings { #( @@ -451,6 +530,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { #frame_support::__private::sp_tracing::trace_span!(stringify!(#fn_name)) ); #maybe_allow_attrs + #[allow(deprecated)] <#pallet_ident<#type_use_gen>>::#fn_name(origin, #( #args_name, )* ) .map(Into::into).map_err(Into::into) }, @@ -480,5 +560,43 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { } } } + + impl<#type_impl_gen> #frame_support::traits::Authorize for #call_ident<#type_use_gen> + #where_clause + { + fn authorize(&self, source: #frame_support::pallet_prelude::TransactionSource) -> ::core::option::Option<::core::result::Result< + ( + #frame_support::pallet_prelude::ValidTransaction, + #frame_support::pallet_prelude::Weight, + ), + #frame_support::pallet_prelude::TransactionValidityError + >> + { + match *self { + #( + #cfg_attrs + Self::#fn_name { #( #args_name_pattern_ref, )* } => { + #authorize_fn + }, + )* + Self::__Ignore(_, _) => { + let _ = source; + unreachable!("__Ignore cannot be used") + }, + } + } + + fn weight_of_authorize(&self) -> #frame_support::pallet_prelude::Weight { + match *self { + #( + #cfg_attrs + Self::#fn_name { #( #args_name_pattern_ref, )* } => { + #authorize_fn_weight + }, + )* + Self::__Ignore(_, _) => unreachable!("__Ignore cannot be used"), + } + } + } ) } diff --git a/substrate/frame/support/procedural/src/pallet/expand/mod.rs b/substrate/frame/support/procedural/src/pallet/expand/mod.rs index 3f9b50f79c0c..f59ce1f2dc59 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/mod.rs @@ -72,7 +72,7 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { let genesis_build = genesis_build::expand_genesis_build(&mut def); let genesis_config = genesis_config::expand_genesis_config(&mut def); let type_values = type_value::expand_type_values(&mut def); - let origins = origin::expand_origins(&mut def); + let origin = origin::expand_origin(&mut def); let validate_unsigned = validate_unsigned::expand_validate_unsigned(&mut def); let tt_default_parts = tt_default_parts::expand_tt_default_parts(&mut def); let doc_only = doc_only::expand_doc_only(&mut def); @@ -114,7 +114,7 @@ storage item. Otherwise, all storage items are listed among [*Type Definitions*] #genesis_build #genesis_config #type_values - #origins + #origin #validate_unsigned #tt_default_parts #doc_only diff --git a/substrate/frame/support/procedural/src/pallet/expand/origin.rs b/substrate/frame/support/procedural/src/pallet/expand/origin.rs index 55865b42491a..b7a560bc5b64 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/origin.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/origin.rs @@ -20,7 +20,8 @@ use proc_macro2::TokenStream; use quote::quote; use syn::{spanned::Spanned, Ident}; -pub fn expand_origins(def: &mut Def) -> TokenStream { +/// expand the `is_origin_part_defined` macro. +pub fn expand_origin(def: &mut Def) -> TokenStream { let count = COUNTER.with(|counter| counter.borrow_mut().inc()); let macro_ident = Ident::new(&format!("__is_origin_part_defined_{}", count), def.item.span()); diff --git a/substrate/frame/support/procedural/src/pallet/parse/call.rs b/substrate/frame/support/procedural/src/pallet/parse/call.rs index 68ced1bc0ed3..da340caa85e2 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/call.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/call.rs @@ -20,7 +20,7 @@ use frame_support_procedural_tools::get_doc_literals; use proc_macro2::Span; use quote::ToTokens; use std::collections::HashMap; -use syn::{spanned::Spanned, ExprClosure}; +use syn::spanned::Spanned; /// List of additional token to be used for parsing. mod keyword { @@ -33,6 +33,8 @@ mod keyword { syn::custom_keyword!(T); syn::custom_keyword!(pallet); syn::custom_keyword!(feeless_if); + syn::custom_keyword!(authorize); + syn::custom_keyword!(weight_of_authorize); } /// Definition of dispatchables typically `impl Pallet { ... }` @@ -49,16 +51,15 @@ pub struct CallDef { pub attr_span: proc_macro2::Span, /// Docs, specified on the impl Block. pub docs: Vec, - /// The optional `weight` attribute on the `pallet::call`. - pub inherited_call_weight: Option, /// attributes pub attrs: Vec, } -/// The weight of a call. +/// The weight of a call or the weight of authorize. #[derive(Clone)] pub enum CallWeightDef { - /// Explicitly set on the call itself with `#[pallet::weight(…)]`. This value is used. + /// Explicitly set on the call itself with `#[pallet::weight(…)]` or + /// `#[pallet::weight_of_authorize(…)]`. This value is used. Immediate(syn::Expr), /// The default value that should be set for dev-mode pallets. Usually zero. @@ -67,7 +68,22 @@ pub enum CallWeightDef { /// Inherits whatever value is configured on the pallet level. /// /// The concrete value is not known at this point. - Inherited, + Inherited(syn::Type), +} + +impl CallWeightDef { + fn try_from( + weight: Option, + inherited_call_weight: &Option, + dev_mode: bool, + ) -> Option { + match (weight, inherited_call_weight) { + (Some(weight), _) => Some(CallWeightDef::Immediate(weight)), + (None, Some(inherited)) => Some(CallWeightDef::Inherited(inherited.typename.clone())), + (None, _) if dev_mode => Some(CallWeightDef::DevModeDefault), + (None, _) => None, + } + } } /// Definition of dispatchable typically: `#[weight...] fn foo(origin .., param1: ...) -> ..` @@ -93,6 +109,19 @@ pub struct CallVariantDef { pub feeless_check: Option, /// The return type of the call: `DispatchInfo` or `DispatchResultWithPostInfo`. pub return_type: helper::CallReturnType, + /// The information related to `authorize` attribute. + /// `(authorize expression, weight of authorize)` + pub authorize: Option, +} + +/// Definition related to the `authorize` attribute and other related attributes. +#[derive(Clone)] +pub struct AuthorizeDef { + /// The expression of the authorize attribute. + pub expr: syn::Expr, + /// The weight of the authorize attribute as define by the attribute + /// `[pallet::weight_of_authorize]`. + pub weight: CallWeightDef, } /// Attributes for functions in call impl block. @@ -103,6 +132,10 @@ pub enum FunctionAttr { Weight(syn::Expr), /// Parse for `#[pallet::feeless_if(expr)]` FeelessIf(Span, syn::ExprClosure), + /// Parse for `#[pallet::authorize(expr)]` + Authorize(syn::Expr), + /// Parse for `#[pallet::weight_of_authorize(expr)]` + WeightOfAuthorize(syn::Expr), } impl syn::parse::Parse for FunctionAttr { @@ -142,6 +175,16 @@ impl syn::parse::Parse for FunctionAttr { err })?, )) + } else if lookahead.peek(keyword::authorize) { + content.parse::()?; + let closure_content; + syn::parenthesized!(closure_content in content); + Ok(FunctionAttr::Authorize(closure_content.parse::()?)) + } else if lookahead.peek(keyword::weight_of_authorize) { + content.parse::()?; + let closure_content; + syn::parenthesized!(closure_content in content); + Ok(FunctionAttr::WeightOfAuthorize(closure_content.parse::()?)) } else { Err(lookahead.error()) } @@ -266,57 +309,94 @@ impl CallDef { let return_type = helper::check_pallet_call_return_type(&method.sig)?; let cfg_attrs: Vec = helper::get_item_cfg_attrs(&method.attrs); - let mut call_idx_attrs = vec![]; - let mut weight_attrs = vec![]; - let mut feeless_attrs = vec![]; + let mut call_index = None; + let mut weight = None; + let mut feeless_check = None; + let mut authorize = None; + let mut weight_of_authorize = None; + for attr in helper::take_item_pallet_attrs(&mut method.attrs)?.into_iter() { match attr { - FunctionAttr::CallIndex(_) => { - call_idx_attrs.push(attr); + FunctionAttr::CallIndex(idx) => { + if call_index.is_some() { + let msg = + "Invalid pallet::call, too many call_index attributes given"; + return Err(syn::Error::new(method.sig.span(), msg)) + } + + call_index = Some(idx); }, - FunctionAttr::Weight(_) => { - weight_attrs.push(attr); + FunctionAttr::Weight(w) => { + if weight.is_some() { + let msg = "Invalid pallet::call, too many weight attributes given"; + return Err(syn::Error::new(method.sig.span(), msg)) + } + weight = Some(w); }, - FunctionAttr::FeelessIf(span, _) => { - feeless_attrs.push((span, attr)); + FunctionAttr::FeelessIf(span, closure) => { + if feeless_check.is_some() { + let msg = + "Invalid pallet::call, there can only be one feeless_if attribute"; + return Err(syn::Error::new(span, msg)) + } + + feeless_check = Some(closure); + }, + FunctionAttr::Authorize(expr) => { + if authorize.is_some() { + let msg = + "Invalid pallet::call, there can only be one authorize attribute"; + return Err(syn::Error::new(method.sig.span(), msg)) + } + + authorize = Some(expr); + }, + FunctionAttr::WeightOfAuthorize(expr) => { + if weight_of_authorize.is_some() { + let msg = "Invalid pallet::call, there can only be one weight_of_authorize attribute"; + return Err(syn::Error::new(method.sig.span(), msg)) + } + + weight_of_authorize = Some(expr); }, } } - if weight_attrs.is_empty() && dev_mode { - // inject a default O(1) weight when dev mode is enabled and no weight has - // been specified on the call - let empty_weight: syn::Expr = syn::parse_quote!(0); - weight_attrs.push(FunctionAttr::Weight(empty_weight)); + if weight_of_authorize.is_some() && authorize.is_none() { + let msg = "Invalid pallet::call, weight_of_authorize attribute must be used with authorize attribute"; + return Err(syn::Error::new(weight_of_authorize.unwrap().span(), msg)) } - let weight = match weight_attrs.len() { - 0 if inherited_call_weight.is_some() => CallWeightDef::Inherited, - 0 if dev_mode => CallWeightDef::DevModeDefault, - 0 => return Err(syn::Error::new( - method.sig.span(), - "A pallet::call requires either a concrete `#[pallet::weight($expr)]` or an - inherited weight from the `#[pallet:call(weight($type))]` attribute, but - none were given.", - )), - 1 => match weight_attrs.pop().unwrap() { - FunctionAttr::Weight(w) => CallWeightDef::Immediate(w), - _ => unreachable!("checked during creation of the let binding"), - }, - _ => { - let msg = "Invalid pallet::call, too many weight attributes given"; - return Err(syn::Error::new(method.sig.span(), msg)); - }, + let authorize = if let Some(expr) = authorize { + let weight_of_authorize = CallWeightDef::try_from( + weight_of_authorize, + &inherited_call_weight, + dev_mode, + ) + .ok_or_else(|| { + syn::Error::new( + method.sig.span(), + "A pallet::call using authorize requires either a concrete \ + `#[pallet::weight_of_authorize($expr)]` or an inherited weight from \ + the `#[pallet:call(weight($type))]` attribute, but \ + none were given.", + ) + })?; + Some(AuthorizeDef { expr, weight: weight_of_authorize }) + } else { + None }; - if call_idx_attrs.len() > 1 { - let msg = "Invalid pallet::call, too many call_index attributes given"; - return Err(syn::Error::new(method.sig.span(), msg)); - } - let call_index = call_idx_attrs.pop().map(|attr| match attr { - FunctionAttr::CallIndex(idx) => idx, - _ => unreachable!("checked during creation of the let binding"), - }); + let weight = CallWeightDef::try_from(weight, &inherited_call_weight, dev_mode) + .ok_or_else(|| { + syn::Error::new( + method.sig.span(), + "A pallet::call requires either a concrete `#[pallet::weight($expr)]` \ + or an inherited weight from the `#[pallet:call(weight($type))]` \ + attribute, but none were given.", + ) + })?; + let explicit_call_index = call_index.is_some(); let final_index = match call_index { @@ -367,16 +447,6 @@ impl CallDef { let docs = get_doc_literals(&method.attrs); - if feeless_attrs.len() > 1 { - let msg = "Invalid pallet::call, there can only be one feeless_if attribute"; - return Err(syn::Error::new(feeless_attrs[1].0, msg)); - } - let feeless_check: Option = - feeless_attrs.pop().map(|(_, attr)| match attr { - FunctionAttr::FeelessIf(_, closure) => closure, - _ => unreachable!("checked during creation of the let binding"), - }); - if let Some(ref feeless_check) = feeless_check { if feeless_check.inputs.len() != args.len() + 1 { let msg = "Invalid pallet::call, feeless_if closure must have same \ @@ -446,6 +516,7 @@ impl CallDef { cfg_attrs, feeless_check, return_type, + authorize, }); } else { let msg = "Invalid pallet::call, only method accepted"; @@ -460,7 +531,6 @@ impl CallDef { methods, where_clause: item_impl.generics.where_clause.clone(), docs: get_doc_literals(&item_impl.attrs), - inherited_call_weight, attrs: item_impl.attrs.clone(), }) } diff --git a/substrate/frame/support/procedural/src/pallet/parse/origin.rs b/substrate/frame/support/procedural/src/pallet/parse/origin.rs index 11311b3d5033..495dbea11392 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/origin.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/origin.rs @@ -33,7 +33,7 @@ pub struct OriginDef { impl OriginDef { pub fn try_from(item: &mut syn::Item) -> syn::Result { let item_span = item.span(); - let (vis, ident, generics) = match &item { + let (vis, ident, generics) = match item { syn::Item::Enum(item) => (&item.vis, &item.ident, &item.generics), syn::Item::Struct(item) => (&item.vis, &item.ident, &item.generics), syn::Item::Type(item) => (&item.vis, &item.ident, &item.generics), @@ -46,7 +46,7 @@ impl OriginDef { let is_generic = !generics.params.is_empty(); let mut instances = vec![]; - if let Some(u) = helper::check_type_def_optional_gen(generics, item.span())? { + if let Some(u) = helper::check_type_def_optional_gen(generics, item_span)? { instances.push(u); } else { // construct_runtime only allow generic event for instantiable pallet. diff --git a/substrate/frame/support/src/dispatch.rs b/substrate/frame/support/src/dispatch.rs index 3678f958980a..f57268aee0cf 100644 --- a/substrate/frame/support/src/dispatch.rs +++ b/substrate/frame/support/src/dispatch.rs @@ -82,6 +82,8 @@ pub enum RawOrigin { /// * included and agreed upon by the validators anyway, /// * or unsigned transaction validated by a pallet. None, + /// It is signed by nobody, call is authorized by the runtime. + Authorized, } impl From> for RawOrigin { diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index cc805d724857..311466e14637 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -903,8 +903,9 @@ pub mod pallet_prelude { StorageList, }, traits::{ - BuildGenesisConfig, ConstU32, EnsureOrigin, Get, GetDefault, GetStorageVersion, Hooks, - IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, Task, TypedGet, + Authorize, BuildGenesisConfig, ConstU32, EnsureOrigin, Get, GetDefault, + GetStorageVersion, Hooks, IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, + Task, TypedGet, }, Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity, PartialEqNoBound, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, @@ -918,11 +919,12 @@ pub mod pallet_prelude { pub use sp_runtime::{ traits::{ CheckedAdd, CheckedConversion, CheckedDiv, CheckedMul, CheckedShl, CheckedShr, - CheckedSub, MaybeSerializeDeserialize, Member, One, ValidateUnsigned, Zero, + CheckedSub, MaybeSerializeDeserialize, Member, One, ValidateResult, ValidateUnsigned, + Zero, }, transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, - TransactionTag, TransactionValidity, TransactionValidityError, UnknownTransaction, + TransactionTag, TransactionValidity, TransactionValidityWithRefund, TransactionValidityError, UnknownTransaction, ValidTransaction, }, DispatchError, RuntimeDebug, MAX_MODULE_ERROR_ENCODED_SIZE, @@ -2510,7 +2512,8 @@ pub mod pallet_macros { pub use frame_support_procedural::storage; pub use frame_support_procedural::{ - task_condition, task_index, task_list, task_weight, tasks_experimental, + authorize, task_condition, task_index, task_list, task_weight, tasks_experimental, + weight_of_authorize, }; /// Allows a pallet to declare a type as an origin. diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 635036d488df..ce50c0081a74 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -104,7 +104,7 @@ mod dispatch; #[allow(deprecated)] pub use dispatch::EnsureOneOf; pub use dispatch::{ - AsEnsureOriginWithArg, CallerTrait, EitherOf, EitherOfDiverse, EnsureOrigin, + AsEnsureOriginWithArg, Authorize, CallerTrait, EitherOf, EitherOfDiverse, EnsureOrigin, EnsureOriginEqualOrHigherPrivilege, EnsureOriginWithArg, MapSuccess, NeverEnsureOrigin, OriginTrait, TryMapSuccess, TryWithMorphedArg, UnfilteredDispatchable, }; diff --git a/substrate/frame/support/src/traits/dispatch.rs b/substrate/frame/support/src/traits/dispatch.rs index dbdf0885dd24..a8680c9bc42e 100644 --- a/substrate/frame/support/src/traits/dispatch.rs +++ b/substrate/frame/support/src/traits/dispatch.rs @@ -22,8 +22,10 @@ use codec::MaxEncodedLen; use core::{cmp::Ordering, marker::PhantomData}; use sp_runtime::{ traits::{BadOrigin, Get, Member, Morph, TryMorph}, + transaction_validity::{TransactionSource, TransactionValidityError, ValidTransaction}, Either, }; +use sp_weights::Weight; use super::misc; @@ -565,6 +567,26 @@ pub trait OriginTrait: Sized { } } +/// A trait to allow calls to authorize themselves from origin `None`. +/// +/// It is usually implemented by the [`crate::pallet`] macro and used by the +/// [`frame_system::AuthorizeCall`] transaction extension. +pub trait Authorize { + /// The authorize function. + /// + /// Returns + /// * `Some(Ok((valid_transaction, unspent weight)))` if the call is successfully authorized, + /// * `Some(Err(error))` if the call authorization is invalid, + /// * `None` if the call doesn't provide any authorization. + fn authorize( + &self, + source: TransactionSource, + ) -> Option>; + + /// The weight of the authorization function. + fn weight_of_authorize(&self) -> Weight; +} + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/frame/support/src/traits/tasks.rs b/substrate/frame/support/src/traits/tasks.rs index 0b5d0c082509..a665403f5a7f 100644 --- a/substrate/frame/support/src/traits/tasks.rs +++ b/substrate/frame/support/src/traits/tasks.rs @@ -57,7 +57,7 @@ pub trait Task: Sized + FullCodec + TypeInfo + Clone + Debug + PartialEq + Eq { /// Performs the work for this particular `Task` variant. fn run(&self) -> Result<(), DispatchError>; - /// Returns the weight of executing this `Task`. + /// Returns the weight of `run` function. fn weight(&self) -> Weight; /// A unique value representing this `Task` within the current pallet. Analogous to diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs new file mode 100644 index 000000000000..95316cb8936c --- /dev/null +++ b/substrate/frame/support/test/tests/authorize.rs @@ -0,0 +1,501 @@ +// 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. + +use codec::Encode; +use frame_support::{ + derive_impl, + dispatch::GetDispatchInfo, + pallet_prelude::{TransactionSource, Weight}, +}; +use sp_runtime::{ + testing::UintAuthorityId, traits::{Applyable, Checkable}, transaction_validity::{ + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + }, BuildStorage, DispatchError +}; + +// test for instance +#[frame_support::pallet] +pub mod pallet1 { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + pub const CALL_1_AUTH_WEIGHT: Weight = Weight::from_all(1); + pub const CALL_1_WEIGHT: Weight = Weight::from_all(2); + pub const CALL_2_AUTH_WEIGHT: Weight = Weight::from_all(3); + pub const CALL_2_WEIGHT: Weight = Weight::from_all(5); + pub const CALL_2_REFUND: Weight = Weight::from_all(4); + pub const CALL_3_AUTH_WEIGHT: Weight = Weight::from_all(6); + pub const CALL_3_WEIGHT: Weight = Weight::from_all(7); + pub const CALL_3_REFUND: Weight = Weight::from_all(6); + pub const CALL_4_AUTH_WEIGHT: Weight = Weight::from_all(10); + pub const CALL_4_WEIGHT: Weight = Weight::from_all(11); + + #[pallet::pallet] + pub struct Pallet(_); + + pub trait WeightInfo { + fn call1() -> Weight; + fn call2() -> Weight; + fn authorize_call2() -> Weight; + fn call3() -> Weight; + fn authorize_call3() -> Weight; + } + + impl WeightInfo for () { + fn call1() -> Weight { + CALL_1_WEIGHT + } + fn call2() -> Weight { + CALL_2_WEIGHT + } + fn authorize_call2() -> Weight { + CALL_2_AUTH_WEIGHT + } + fn call3() -> Weight { + CALL_3_WEIGHT + } + fn authorize_call3() -> Weight { + CALL_3_AUTH_WEIGHT + } + } + + #[pallet::config] + pub trait Config: frame_system::Config { + type SomeGeneric: Parameter; + type WeightInfo: WeightInfo; + } + + #[pallet::call(weight = T::WeightInfo)] + impl, I: 'static> Pallet { + #[pallet::authorize(|_source| Ok((ValidTransaction::default(), Weight::zero())))] + #[pallet::weight_of_authorize(CALL_1_AUTH_WEIGHT)] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor) -> DispatchResult { + ensure_authorized(origin)?; + + Ok(()) + } + + #[pallet::authorize(|_source, a, b, c, d, e, f, authorize_refund| + if *a { + let valid = ValidTransaction { + priority: *b, + requires: vec![c.encode()], + provides: vec![d.encode()], + longevity: *e, + propagate: *f, + }; + Ok((valid, authorize_refund.clone())) + } else { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + )] + #[pallet::call_index(1)] + pub fn call2( + origin: OriginFor, + a: bool, + b: u64, + c: u8, + d: u8, + e: u64, + f: bool, + authorize_refund: Weight, + ) -> DispatchResultWithPostInfo { + ensure_authorized(origin)?; + + let _ = (a, b, c, d, e, f, authorize_refund); + + Ok(Some(CALL_2_REFUND).into()) + } + + #[pallet::authorize(Pallet::::authorize_call3)] + #[pallet::call_index(2)] + pub fn call3(origin: OriginFor, valid: bool, _some_gen: T::SomeGeneric) -> DispatchResultWithPostInfo { + ensure_authorized(origin)?; + + let _ = valid; + + Err(sp_runtime::DispatchErrorWithPostInfo { + post_info: Some(CALL_3_REFUND).into(), + error: DispatchError::Other("Call3 failed"), + }) + } + + #[cfg(feature = "frame-feature-testing")] + #[pallet::call_index(3)] + #[pallet::authorize(|_source| Ok(ValidTransaction::default()))] + #[pallet::weight_of_authorize(CALL_4_AUTH_WEIGHT)] + #[pallet::weight(CALL_4_WEIGHT)] + pub fn call4(origin: OriginFor) -> DispatchResult { + ensure_authorized(origin)?; + + Ok(()) + } + } + + impl, I: 'static> Pallet { + fn authorize_call3(_source: TransactionSource, valid: &bool, _some_gen: &T::SomeGeneric) -> TransactionValidityWithRefund { + if *valid { + Ok(Default::default()) + } else { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } + } +} + +// test for dev mode. +#[frame_support::pallet(dev_mode)] +pub mod pallet2 { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + pub trait SomeTrait {} + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::authorize(|_source| Ok(Default::default()))] + pub fn call1(origin: OriginFor) -> DispatchResult { + ensure_authorized(origin)?; + Ok(()) + } + } +} + +// test for no pallet info. +#[frame_support::pallet] +pub mod pallet3 { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + pub const CALL_1_AUTH_WEIGHT: Weight = Weight::from_all(1); + pub const CALL_1_WEIGHT: Weight = Weight::from_all(1); + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: crate::pallet1::Config + frame_system::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::authorize(|_source| Ok(Default::default()))] + #[pallet::weight_of_authorize(CALL_1_AUTH_WEIGHT)] + #[pallet::weight(CALL_1_WEIGHT)] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor) -> DispatchResult { + ensure_authorized(origin)?; + Ok(()) + } + } +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; +} + +impl pallet2::SomeTrait for RuntimeOrigin {} + +impl pallet1::Config for Runtime { + type SomeGeneric = u32; + type WeightInfo = (); +} + +impl pallet1::Config for Runtime { + type SomeGeneric = u32; + type WeightInfo = (); +} + +#[cfg(feature = "frame-feature-testing")] +impl pallet1::Config for Runtime { + type SomeGeneric = u32; + type WeightInfo = (); +} + +impl pallet2::Config for Runtime {} + +impl pallet3::Config for Runtime {} + +pub type TransactionExtension = frame_system::AuthorizeCall; + +pub type Header = sp_runtime::generic::Header; +pub type Block = sp_runtime::generic::Block; +pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< + u64, + RuntimeCall, + UintAuthorityId, + TransactionExtension, +>; + +frame_support::construct_runtime!( + pub enum Runtime { + System: frame_system, + Pallet1: pallet1, + Pallet1Instance2: pallet1::, + Pallet2: pallet2, + Pallet3: pallet3, + #[cfg(feature = "frame-feature-testing")] + Pallet1Instance3: pallet1::, + } +); + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = RuntimeGenesisConfig { ..Default::default() }.build_storage().unwrap(); + t.into() +} + +#[test] +fn valid_call_weight_test() { + // Tests for valid successful calls and assert their weight + + struct Test { + call: RuntimeCall, + dispatch_success: bool, + call_weight: Weight, + ext_weight: Weight, + actual_weight: Weight, + } + + let call_2_auth_weight_refund = Weight::from_all(2); + + let tests = vec![ + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call1 {}), + dispatch_success: true, + call_weight: pallet1::CALL_1_WEIGHT, + ext_weight: pallet1::CALL_1_AUTH_WEIGHT, + actual_weight: pallet1::CALL_1_WEIGHT + pallet1::CALL_1_AUTH_WEIGHT, + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call2 { + a: true, + b: 1, + c: 2, + d: 3, + e: 4, + f: true, + authorize_refund: Weight::zero(), + }), + dispatch_success: true, + call_weight: pallet1::CALL_2_WEIGHT, + ext_weight: pallet1::CALL_2_AUTH_WEIGHT, + actual_weight: pallet1::CALL_2_REFUND + pallet1::CALL_2_AUTH_WEIGHT, + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call3 { valid: true, some_gen: 1 }), + dispatch_success: false, + call_weight: pallet1::CALL_3_WEIGHT, + ext_weight: pallet1::CALL_3_AUTH_WEIGHT, + actual_weight: pallet1::CALL_3_REFUND + pallet1::CALL_3_AUTH_WEIGHT, + }, + Test { + call: RuntimeCall::Pallet1Instance2(pallet1::Call::call1 {}), + dispatch_success: true, + call_weight: pallet1::CALL_1_WEIGHT, + ext_weight: pallet1::CALL_1_AUTH_WEIGHT, + actual_weight: pallet1::CALL_1_WEIGHT + pallet1::CALL_1_AUTH_WEIGHT, + }, + Test { + call: RuntimeCall::Pallet1Instance2(pallet1::Call::call2 { + a: true, + b: 1, + c: 2, + d: 3, + e: 4, + f: true, + authorize_refund: call_2_auth_weight_refund, + }), + dispatch_success: true, + call_weight: pallet1::CALL_2_WEIGHT, + ext_weight: pallet1::CALL_2_AUTH_WEIGHT, + actual_weight: + pallet1::CALL_2_REFUND + + pallet1::CALL_2_AUTH_WEIGHT + - call_2_auth_weight_refund, + }, + Test { + call: RuntimeCall::Pallet1Instance2(pallet1::Call::call3 { valid: true, some_gen: 1 }), + dispatch_success: false, + call_weight: pallet1::CALL_3_WEIGHT, + ext_weight: pallet1::CALL_3_AUTH_WEIGHT, + actual_weight: pallet1::CALL_3_REFUND + pallet1::CALL_3_AUTH_WEIGHT, + }, + Test { + call: RuntimeCall::Pallet2(pallet2::Call::call1 {}), + dispatch_success: true, + call_weight: Weight::zero(), + ext_weight: Weight::zero(), + actual_weight: Weight::zero(), + }, + Test { + call: RuntimeCall::Pallet3(pallet3::Call::call1 {}), + dispatch_success: true, + call_weight: pallet3::CALL_1_WEIGHT, + ext_weight: pallet3::CALL_1_AUTH_WEIGHT, + actual_weight: pallet3::CALL_1_WEIGHT + pallet3::CALL_1_AUTH_WEIGHT, + }, + #[cfg(feature = "frame-feature-testing")] + Test { + call: RuntimeCall::Pallet1Instance3(pallet1::Call::call4 {}), + dispatch_success: true, + call_weight: pallet1::CALL_4_WEIGHT, + ext_weight: pallet1::CALL_4_AUTH_WEIGHT, + actual_weight: pallet1::CALL_4_WEIGHT + pallet3::CALL_4_AUTH_WEIGHT, + }, + ]; + + for (index, test) in tests.into_iter().enumerate() { + let Test { call, dispatch_success, call_weight, ext_weight, actual_weight } = test; + + println!("Running test {}", index); + + new_test_ext().execute_with(|| { + let tx_ext = frame_system::AuthorizeCall::::new(); + + let tx = UncheckedExtrinsic::new_transaction(call, tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + checked + .validate::(TransactionSource::External, &info, len) + .expect("call1 is always valid"); + + let dispatch_result = + checked.apply::(&info, len).expect("Transaction is valid"); + + assert_eq!(dispatch_result.is_ok(), dispatch_success); + + let post_info = dispatch_result.unwrap_or_else(|e| e.post_info); + + assert_eq!(info.call_weight, call_weight); + assert_eq!(info.extension_weight, ext_weight); + assert_eq!(post_info.actual_weight, Some(actual_weight)); + }); + } +} + +#[test] +fn valid_invalid_call() { + struct Test { + call: RuntimeCall, + validate_res: TransactionValidity, + } + + let tests = vec![ + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call1 {}), + validate_res: Ok(Default::default()), + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call2 { + a: true, + b: 1, + c: 2, + d: 3, + e: 4, + f: true, + authorize_refund: Weight::zero(), + }), + validate_res: Ok(ValidTransaction { + priority: 1, + requires: vec![2u8.encode()], + provides: vec![3u8.encode()], + longevity: 4, + propagate: true, + }), + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call2 { + a: false, + b: 1, + c: 2, + d: 3, + e: 4, + f: true, + authorize_refund: Weight::zero(), + }), + validate_res: Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call3 { valid: true, some_gen: 1 }), + validate_res: Ok(Default::default()), + }, + Test { + call: RuntimeCall::Pallet1(pallet1::Call::call3 { valid: false, some_gen: 1 }), + validate_res: Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + }, + ]; + + for (index, test) in tests.into_iter().enumerate() { + let Test { call, validate_res } = test; + + println!("Running test {}", index); + + new_test_ext().execute_with(|| { + let tx_ext = frame_system::AuthorizeCall::::new(); + + let tx = UncheckedExtrinsic::new_transaction(call, tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + let res = checked.validate::(TransactionSource::External, &info, len); + assert_eq!(res, validate_res); + }); + } +} + +#[test] +fn signed_is_valid_but_dispatch_error() { + new_test_ext().execute_with(|| { + let call = RuntimeCall::Pallet1(pallet1::Call::call1 {}); + let tx_ext = frame_system::AuthorizeCall::::new(); + + let tx = UncheckedExtrinsic::new_signed(call, 1u64, 1.into(), tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + checked + .validate::(TransactionSource::External, &info, len) + .expect("origin is signed, transaction is valid"); + + let dispatch_err = checked + .apply::(&info, len) + .expect("origin is signed, transaction is valid") + .expect_err("origin is wrong for the dispatched call"); + + assert_eq!(dispatch_err.error, DispatchError::BadOrigin); + }); +} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.rs new file mode 100644 index 000000000000..a472133d3376 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.rs @@ -0,0 +1,47 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.stderr new file mode 100644 index 000000000000..bb61ef04922b --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_weight_but_no_closure.stderr @@ -0,0 +1,5 @@ +error: Invalid pallet::call, weight_of_authorize attribute must be used with authorize attribute + --> tests/pallet_ui/authorize_weight_but_no_closure.rs:36:33 + | +36 | #[pallet::weight_of_authorize(Weight::zero())] + | ^^^^^^ diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.rs new file mode 100644 index 000000000000..1d82c42b1d58 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.rs @@ -0,0 +1,48 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(|_| true)] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.stderr new file mode 100644 index 000000000000..8abc901520bf --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure.stderr @@ -0,0 +1,8 @@ +error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument + --> tests/pallet_ui/authorize_wrong_closure.rs:36:23 + | +36 | #[pallet::authorize(|_| true)] + | ^-- + | | + | expected closure that takes 2 arguments + | takes 1 argument diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.rs new file mode 100644 index 000000000000..c0710efd9813 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.rs @@ -0,0 +1,48 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(|_, _: u8| -> bool { true })] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr new file mode 100644 index 000000000000..f773042bf52d --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr @@ -0,0 +1,54 @@ +error[E0631]: type mismatch in closure arguments + --> tests/pallet_ui/authorize_wrong_closure_2.rs:36:23 + | +36 | #[pallet::authorize(|_, _: u8| -> bool { true })] + | ^----------------- + | | + | expected due to this + | found signature defined here + | + = note: expected closure signature `for<'a> fn(TransactionSource, &'a u32) -> _` + found closure signature `fn(TransactionSource, u8) -> _` +note: required by a bound in `macro_inner_authorize_call_for_call1` + --> tests/pallet_ui/authorize_wrong_closure_2.rs:36:23 + | +36 | #[pallet::authorize(|_, _: u8| -> bool { true })] + | ^ required by this bound in `macro_inner_authorize_call_for_call1` + +error[E0308]: mismatched types + --> tests/pallet_ui/authorize_wrong_closure_2.rs:40:38 + | +18 | #[frame_support::pallet] + | ------------------------ arguments to this function are incorrect +... +40 | pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + | ^ expected `u8`, found `&u32` + | +note: closure parameter defined here + --> tests/pallet_ui/authorize_wrong_closure_2.rs:36:27 + | +36 | #[pallet::authorize(|_, _: u8| -> bool { true })] + | ^^^^^ + +error[E0308]: mismatched types + --> tests/pallet_ui/authorize_wrong_closure_2.rs:18:1 + | +18 | #[frame_support::pallet] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected `Result<(..., ...), ...>`, found `bool` + | arguments to this enum variant are incorrect + | + = note: expected enum `Result<(ValidTransaction, frame_support::weights::Weight), TransactionValidityError>` + found type `bool` +help: the type constructed contains `bool` due to the type of the argument passed + --> tests/pallet_ui/authorize_wrong_closure_2.rs:18:1 + | +18 | #[frame_support::pallet] + | ^^^^^^^^^^^^^^^^^^^^^^^^ this argument influences the type of `Some` +note: tuple variant defined here + --> $RUST/core/src/option.rs + | + | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ^^^^ + = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.rs new file mode 100644 index 000000000000..03a1de2e9ca8 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.rs @@ -0,0 +1,48 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize()] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.stderr new file mode 100644 index 000000000000..895955b2c658 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_3.stderr @@ -0,0 +1,5 @@ +error: unexpected end of input, expected an expression + --> tests/pallet_ui/authorize_wrong_closure_3.rs:36:22 + | +36 | #[pallet::authorize()] + | ^^ diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.rs new file mode 100644 index 000000000000..f8d2826fb604 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.rs @@ -0,0 +1,48 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(Ok(Default::default()))] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr new file mode 100644 index 000000000000..6b4e5cab9a6e --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr @@ -0,0 +1,39 @@ +error[E0277]: expected a `Fn(TransactionSource, &u32)` closure, found `Result<_, _>` + --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 + | +36 | #[pallet::authorize(Ok(Default::default()))] + | ^^ expected an `Fn(TransactionSource, &u32)` closure, found `Result<_, _>` + | + = help: the trait `for<'a> Fn(TransactionSource, &'a u32)` is not implemented for `Result<_, _>` +note: required by a bound in `macro_inner_authorize_call_for_call1` + --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 + | +36 | #[pallet::authorize(Ok(Default::default()))] + | ^^ required by this bound in `macro_inner_authorize_call_for_call1` + +error[E0277]: expected a `FnOnce(TransactionSource, &u32)` closure, found `Result<_, _>` + --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 + | +36 | #[pallet::authorize(Ok(Default::default()))] + | --^^^^^^^^^^^^^^^^^^^^ + | | + | expected an `FnOnce(TransactionSource, &u32)` closure, found `Result<_, _>` + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce(TransactionSource, &'a u32)` is not implemented for `Result<_, _>` +note: required by a bound in `macro_inner_authorize_call_for_call1` + --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 + | +36 | #[pallet::authorize(Ok(Default::default()))] + | ^^ required by this bound in `macro_inner_authorize_call_for_call1` + +error[E0618]: expected function, found `Result<_, _>` + --> tests/pallet_ui/authorize_wrong_closure_4.rs:18:1 + | +18 | #[frame_support::pallet] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | call expression requires function + | `authorize_fn` has type `Result<_, _>` + | + = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.rs new file mode 100644 index 000000000000..1aca309e0530 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.rs @@ -0,0 +1,50 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(|_a: &u32| -> TransactionValidityWithRefund { + Ok(Default::default()) + })] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.stderr new file mode 100644 index 000000000000..4b72a44daa61 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_5.stderr @@ -0,0 +1,8 @@ +error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument + --> tests/pallet_ui/authorize_wrong_closure_5.rs:36:23 + | +36 | #[pallet::authorize(|_a: &u32| -> TransactionValidityWithRefund { + | ^------------------------------------------ + | | + | expected closure that takes 2 arguments + | takes 1 argument diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs new file mode 100644 index 000000000000..44b06ae06f73 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs @@ -0,0 +1,54 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(Pallet::::authorize_call1)] + #[pallet::weight_of_authorize(Weight::zero())] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } + + impl Pallet { + fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { + Ok(Default::default()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr new file mode 100644 index 000000000000..9302c7c5da73 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr @@ -0,0 +1,67 @@ +error[E0631]: type mismatch in function arguments + --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 + | +36 | #[pallet::authorize(Pallet::::authorize_call1)] + | ^^^^^^ expected due to this +... +48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { + | ---------------------------------------------------------------------------------------- found signature defined here + | + = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` + found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` +note: required by a bound in `macro_inner_authorize_call_for_call1` + --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 + | +36 | #[pallet::authorize(Pallet::::authorize_call1)] + | ^^^^^^ required by this bound in `macro_inner_authorize_call_for_call1` +help: consider adjusting the signature so it borrows its argument + | +48 | fn authorize_call1(_source: TransactionSource, _a: &u32) -> TransactionValidityWithRefund { + | + + +error[E0631]: type mismatch in function arguments + --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 + | +36 | #[pallet::authorize(Pallet::::authorize_call1)] + | ------^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected due to this + | required by a bound introduced by this call +... +48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { + | ---------------------------------------------------------------------------------------- found signature defined here + | + = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` + found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` +note: required by a bound in `macro_inner_authorize_call_for_call1` + --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 + | +36 | #[pallet::authorize(Pallet::::authorize_call1)] + | ^^^^^^ required by this bound in `macro_inner_authorize_call_for_call1` +help: consider wrapping the function in a closure + | +36 | #[pallet::authorize(|_source: frame_support::pallet_prelude::TransactionSource, _a: &u32| Pallet::::authorize_call1(_source, *_a))] + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ +help: consider adjusting the signature so it borrows its argument + | +48 | fn authorize_call1(_source: TransactionSource, _a: &u32) -> TransactionValidityWithRefund { + | + + +error[E0308]: mismatched types + --> tests/pallet_ui/authorize_wrong_closure_6.rs:40:38 + | +18 | #[frame_support::pallet] + | ------------------------ arguments to this function are incorrect +... +40 | pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + | ^ expected `u32`, found `&u32` + | +note: associated function defined here + --> tests/pallet_ui/authorize_wrong_closure_6.rs:48:6 + | +48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { + | ^^^^^^^^^^^^^^^ ------- +help: consider dereferencing the borrow + | +40 | pub fn call1(origin: OriginFor, *a: u32) -> DispatchResult { + | + diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.rs new file mode 100644 index 000000000000..1b86cd3770ce --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.rs @@ -0,0 +1,48 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(|_, _| Ok(Default::default()))] + #[pallet::weight_of_authorize("foo")] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.stderr new file mode 100644 index 000000000000..83dac4430990 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight.stderr @@ -0,0 +1,22 @@ +error: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: + It is deprecated to use hard-coded constant as call weight. + Please instead benchmark all calls or put the pallet into `dev` mode. + + For more info see: + + --> tests/pallet_ui/authorize_wrong_weight.rs:37:33 + | +37 | #[pallet::weight_of_authorize("foo")] + | ^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(deprecated)]` + +error[E0308]: mismatched types + --> tests/pallet_ui/authorize_wrong_weight.rs:37:33 + | +18 | #[frame_support::pallet] + | ------------------------ expected `frame_support::weights::Weight` because of return type +... +37 | #[pallet::weight_of_authorize("foo")] + | ^^^^^ expected `Weight`, found `&str` diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.rs new file mode 100644 index 000000000000..5ec08ec50530 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.rs @@ -0,0 +1,47 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightInfo)] + impl Pallet { + #[pallet::authorize(|_, _| Ok(Default::default()))] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr new file mode 100644 index 000000000000..43fd98da9482 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr @@ -0,0 +1,5 @@ +error[E0599]: no function or associated item named `authorize_call1` found for associated type `::WeightInfo` in the current scope + --> tests/pallet_ui/authorize_wrong_weight_info.rs:34:26 + | +34 | #[pallet::call(weight = T::WeightInfo)] + | ^ function or associated item not found in `::WeightInfo` diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.rs new file mode 100644 index 000000000000..c628605c8312 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.rs @@ -0,0 +1,47 @@ +// 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. + +#[frame_support::pallet] +mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config(with_default)] + pub trait Config: frame_system::Config { + type WeightInfo: WeightInfo; + } + + pub trait WeightInfo { + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::call(weight = T::WeightIn)] + impl Pallet { + #[pallet::authorize(|_, _| Ok(Default::default()))] + #[pallet::weight(Weight::zero())] + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + let _ = origin; + let _ = a; + Ok(()) + } + } +} + +fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.stderr new file mode 100644 index 000000000000..237b1fc05461 --- /dev/null +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info_2.stderr @@ -0,0 +1,5 @@ +error[E0220]: associated type `WeightIn` not found for `T` + --> tests/pallet_ui/authorize_wrong_weight_info_2.rs:34:29 + | +34 | #[pallet::call(weight = T::WeightIn)] + | ^^^^^^^^ help: there is an associated type with a similar name: `WeightInfo` diff --git a/substrate/frame/support/test/tests/split_ui/pass/call/mod.rs b/substrate/frame/support/test/tests/split_ui/pass/call/mod.rs index 27b3ec31b835..62f1326ef0aa 100644 --- a/substrate/frame/support/test/tests/split_ui/pass/call/mod.rs +++ b/substrate/frame/support/test/tests/split_ui/pass/call/mod.rs @@ -32,7 +32,7 @@ mod call { ensure_signed(origin)?; Ok(()) } - + #[pallet::call_index(2)] pub fn noop2(origin: OriginFor, _x: u64, _y: u64) -> DispatchResult { ensure_signed(origin)?; @@ -59,5 +59,12 @@ mod call { ensure_signed(origin)?; Ok(()) } + + #[pallet::call_index(6)] + #[pallet::authorize(|_source, _x, _y| Ok(Default::default()))] + pub fn noop_authorize(origin: OriginFor, _x: u64, _y: u64) -> DispatchResult { + ensure_authorized(origin)?; + Ok(()) + } } } diff --git a/substrate/frame/system/src/extensions/authorize_call.rs b/substrate/frame/system/src/extensions/authorize_call.rs new file mode 100644 index 000000000000..1ed74f551187 --- /dev/null +++ b/substrate/frame/system/src/extensions/authorize_call.rs @@ -0,0 +1,325 @@ +// 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. + +use crate::Config; +use frame_support::{ + dispatch::DispatchInfo, + pallet_prelude::{Decode, DispatchResult, Encode, TransactionSource, TypeInfo, Weight}, + traits::{Authorize, OriginTrait}, + CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, +}; +use sp_runtime::{ + traits::{Dispatchable, PostDispatchInfoOf, TransactionExtension, ValidateResult}, + transaction_validity::TransactionValidityError, +}; + +#[derive( + Encode, Decode, CloneNoBound, EqNoBound, PartialEqNoBound, TypeInfo, RuntimeDebugNoBound, +)] +#[scale_info(skip_type_params(T))] +pub struct AuthorizeCall(core::marker::PhantomData); + +impl AuthorizeCall { + pub fn new() -> Self { + Self(Default::default()) + } +} + +impl TransactionExtension for AuthorizeCall +where + T::RuntimeCall: Dispatchable, +{ + const IDENTIFIER: &'static str = "AuthorizeCall"; + type Implicit = (); + type Val = Weight; + type Pre = Weight; + + fn validate( + &self, + origin: T::RuntimeOrigin, + call: &T::RuntimeCall, + _info: &DispatchInfo, + _len: usize, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + source: TransactionSource, + ) -> ValidateResult { + if let Some(crate::RawOrigin::None) = origin.as_system_ref() { + if let Some(authorize) = call.authorize(source) { + return authorize.map(|(validity, unspent)| { + (validity, unspent, crate::Origin::::Authorized.into()) + }) + } + } + + Ok((Default::default(), Weight::zero(), origin)) + } + + fn prepare( + self, + val: Self::Val, + _origin: &T::RuntimeOrigin, + _call: &T::RuntimeCall, + _info: &DispatchInfo, + _len: usize, + ) -> Result { + Ok(val) + } + + fn post_dispatch_details( + pre: Self::Pre, + _info: &DispatchInfo, + _post_info: &PostDispatchInfoOf, + _len: usize, + _result: &DispatchResult, + ) -> Result { + Ok(pre) + } + + fn weight(&self, call: &T::RuntimeCall) -> Weight { + call.weight_of_authorize() + } +} + +#[cfg(test)] +mod tests { + use crate as frame_system; + use codec::Encode; + use frame_support::{ + derive_impl, dispatch::GetDispatchInfo, pallet_prelude::TransactionSource, + traits::OriginTrait, + }; + use sp_runtime::{ + testing::UintAuthorityId, + traits::{Applyable, Checkable, TransactionExtension as _}, + transaction_validity::{InvalidTransaction, TransactionValidityError}, + transaction_validity::TransactionSource::External, + BuildStorage, DispatchError, + }; + + #[frame_support::pallet] + pub mod pallet1 { + use crate as frame_system; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + pub const CALL_WEIGHT: Weight = Weight::from_all(4); + pub const AUTH_WEIGHT: Weight = Weight::from_all(5); + + pub fn valid_transaction() -> ValidTransaction { + ValidTransaction { + priority: 10, + provides: vec![1u8.encode()], + requires: vec![], + longevity: 1000, + propagate: true, + } + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::weight(CALL_WEIGHT)] + #[pallet::call_index(0)] + #[pallet::authorize(|_source, valid| if *valid { + Ok((valid_transaction(), Weight::zero())) + } else { + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + })] + #[pallet::weight_of_authorize(AUTH_WEIGHT)] + pub fn call1(origin: OriginFor, valid: bool) -> DispatchResult { + crate::ensure_authorized(origin)?; + let _ = valid; + Ok(()) + } + } + } + + #[frame_support::runtime] + mod runtime { + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + #[runtime::pallet_index(0)] + pub type System = frame_system::Pallet; + + #[runtime::pallet_index(1)] + pub type Pallet1 = pallet1::Pallet; + } + + pub type TransactionExtension = (frame_system::AuthorizeCall,); + + pub type Header = sp_runtime::generic::Header; + pub type Block = sp_runtime::generic::Block; + pub type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic< + u64, + RuntimeCall, + UintAuthorityId, + TransactionExtension, + >; + + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] + impl frame_system::Config for Runtime { + type Block = Block; + } + + impl pallet1::Config for Runtime {} + + pub fn new_test_ext() -> sp_io::TestExternalities { + let t = RuntimeGenesisConfig { ..Default::default() }.build_storage().unwrap(); + t.into() + } + + #[test] + fn valid_transaction() { + let call = RuntimeCall::Pallet1(pallet1::Call::call1 { valid: true }); + + new_test_ext().execute_with(|| { + let tx_ext = (frame_system::AuthorizeCall::::new(),); + + let tx = UncheckedExtrinsic::new_transaction(call, tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + let valid_tx = checked + .validate::(TransactionSource::External, &info, len) + .expect("call valid"); + + let dispatch_result = + checked.apply::(&info, len).expect("Transaction is valid"); + + assert!(dispatch_result.is_ok()); + + let post_info = dispatch_result.unwrap_or_else(|e| e.post_info); + + assert_eq!(valid_tx, pallet1::valid_transaction()); + assert_eq!(info.call_weight, pallet1::CALL_WEIGHT); + assert_eq!(info.extension_weight, pallet1::AUTH_WEIGHT); + assert_eq!(post_info.actual_weight, Some(pallet1::CALL_WEIGHT + pallet1::AUTH_WEIGHT)); + }); + } + + #[test] + fn invalid_transaction_fail_authorization() { + let call = RuntimeCall::Pallet1(pallet1::Call::call1 { valid: false }); + + new_test_ext().execute_with(|| { + let tx_ext = (frame_system::AuthorizeCall::::new(),); + + let tx = UncheckedExtrinsic::new_transaction(call, tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + let validate_err = checked + .validate::(TransactionSource::External, &info, len) + .expect_err("call is invalid"); + + let apply_err = + checked.apply::(&info, len).expect_err("Transaction is invalid"); + + assert_eq!(validate_err, TransactionValidityError::Invalid(InvalidTransaction::Call)); + assert_eq!(apply_err, TransactionValidityError::Invalid(InvalidTransaction::Call)); + assert_eq!(info.call_weight, pallet1::CALL_WEIGHT); + assert_eq!(info.extension_weight, pallet1::AUTH_WEIGHT); + }); + } + + #[test] + fn failing_transaction_invalid_origin() { + let call = RuntimeCall::Pallet1(pallet1::Call::call1 { valid: true }); + + new_test_ext().execute_with(|| { + let tx_ext = (frame_system::AuthorizeCall::::new(),); + + let tx = UncheckedExtrinsic::new_signed(call, 42, Default::default(), tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Signature is good"); + + checked + .validate::(TransactionSource::External, &info, len) + .expect("Transaction is valid, tx ext doesn't deny none"); + + let dispatch_res = checked + .apply::(&info, len) + .expect("Transaction is valid") + .expect_err("Transaction is failing, because origin is wrong"); + + assert_eq!(dispatch_res.error, DispatchError::BadOrigin); + assert_eq!(info.call_weight, pallet1::CALL_WEIGHT); + assert_eq!(info.extension_weight, pallet1::AUTH_WEIGHT); + }); + } + + #[test] + fn call_filter_not_messed_up() { + new_test_ext().execute_with(|| { + let ext = frame_system::AuthorizeCall::::new(); + let filtered_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + + let origin = { + let mut o: RuntimeOrigin = crate::Origin::::Signed(42).into(); + let filter_clone = filtered_call.clone(); + o.add_filter(move |call| filter_clone != *call); + o + }; + + assert!(!origin.filter_call(&filtered_call)); + + let (_, _, new_origin) = ext + .validate( + origin, + &RuntimeCall::Pallet1(pallet1::Call::call1 { valid: true }), + &crate::DispatchInfo::default(), + Default::default(), + (), + &(), + External, + ) + .expect("valid"); + + assert!(!new_origin.filter_call(&filtered_call)); + }); + } +} diff --git a/substrate/frame/system/src/extensions/mod.rs b/substrate/frame/system/src/extensions/mod.rs index d79104d22403..b05042aed7ed 100644 --- a/substrate/frame/system/src/extensions/mod.rs +++ b/substrate/frame/system/src/extensions/mod.rs @@ -15,6 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +pub mod authorize_call; pub mod check_genesis; pub mod check_mortality; pub mod check_non_zero_sender; diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 02d61921741c..4772acf1a995 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -166,7 +166,7 @@ pub mod weights; pub mod migrations; pub use extensions::{ - check_genesis::CheckGenesis, check_mortality::CheckMortality, + authorize_call::AuthorizeCall, check_genesis::CheckGenesis, check_mortality::CheckMortality, check_non_zero_sender::CheckNonZeroSender, check_nonce::CheckNonce, check_spec_version::CheckSpecVersion, check_tx_version::CheckTxVersion, check_weight::CheckWeight, WeightInfo as ExtensionsWeightInfo, @@ -174,7 +174,7 @@ pub use extensions::{ // Backward compatible re-export. pub use extensions::check_mortality::CheckMortality as CheckEra; pub use frame_support::dispatch::RawOrigin; -use frame_support::traits::{PostInherents, PostTransactions, PreInherents}; +use frame_support::traits::{Authorize, PostInherents, PostTransactions, PreInherents}; use sp_core::storage::StateVersion; pub use weights::WeightInfo; @@ -507,7 +507,8 @@ pub mod pallet { type RuntimeCall: Parameter + Dispatchable + Debug - + From>; + + From> + + Authorize; /// The aggregated `RuntimeTask` type. #[pallet::no_default_bounds] @@ -667,7 +668,7 @@ pub mod pallet { } } - #[pallet::call] + #[pallet::call(weight = ::SystemWeightInfo)] impl Pallet { /// Make some on-chain remark. /// @@ -1415,6 +1416,18 @@ where } } +/// Ensure that the origin `o` represents an extrinsic with authorized call. Returns `Ok` or an +/// `Err` otherwise. +pub fn ensure_authorized(o: OuterOrigin) -> Result<(), BadOrigin> +where + OuterOrigin: Into, OuterOrigin>>, +{ + match o.into() { + Ok(RawOrigin::Authorized) => Ok(()), + _ => Err(BadOrigin), + } +} + /// Reference status; can be either referenced or unreferenced. #[derive(RuntimeDebug)] pub enum RefStatus { @@ -2292,7 +2305,9 @@ impl Lookup for ChainContext { /// Prelude to be used alongside pallet macro, for ease of use. pub mod pallet_prelude { - pub use crate::{ensure_none, ensure_root, ensure_signed, ensure_signed_or_root}; + pub use crate::{ + ensure_authorized, ensure_none, ensure_root, ensure_signed, ensure_signed_or_root, + }; /// Type alias for the `Origin` associated type of system config. pub type OriginFor = ::RuntimeOrigin; diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs index bedfdded8183..73ba5d58d976 100644 --- a/substrate/frame/system/src/offchain.rs +++ b/substrate/frame/system/src/offchain.rs @@ -517,6 +517,26 @@ pub trait SignMessage { TPayload: SignedPayload; } +/// Interface for creating a transaction with for a call that will be authorized. +/// +/// This interface allows to define the transaction extension that will be used alongside this call +/// to create the transaction. +/// +/// For more information about authorized call see [`frame_support::pallet::authorized`]. +pub trait CreateAuthorizedTransaction: CreateTransaction { + /// Create the transaction extension to be used alongside an authorized call. + /// + /// For more information about authorized call see [`frame_support::pallet::authorized`]. + fn create_extension() -> Self::Extension; + + /// Create a new transaction for an authorized call. + /// + /// For more information about authorized call see [`frame_support::pallet::authorized`]. + fn create_authorized_transaction(call: Self::RuntimeCall) -> Self::Extrinsic { + Self::create_transaction(call, Self::create_extension()) + } +} + /// Submit a signed transaction to the transaction pool. pub trait SendSignedTransaction< T: CreateSignedTransaction, diff --git a/substrate/primitives/runtime/src/transaction_validity.rs b/substrate/primitives/runtime/src/transaction_validity.rs index a48c8ee7ba84..9dc8856c1214 100644 --- a/substrate/primitives/runtime/src/transaction_validity.rs +++ b/substrate/primitives/runtime/src/transaction_validity.rs @@ -23,6 +23,7 @@ use crate::{ }; use alloc::{vec, vec::Vec}; use scale_info::TypeInfo; +use sp_weights::Weight; /// Priority for a transaction. Additive. Higher is better. pub type TransactionPriority = u64; @@ -217,6 +218,10 @@ impl std::fmt::Display for TransactionValidityError { /// Information on a transaction's validity and, if valid, on how it relates to other transactions. pub type TransactionValidity = Result; +/// Information on a transaction's validity and, if valid, on how it relates to other transactions +/// and some refund for the operation. +pub type TransactionValidityWithRefund = Result<(ValidTransaction, Weight), TransactionValidityError>; + impl From for TransactionValidity { fn from(invalid_transaction: InvalidTransaction) -> Self { Err(TransactionValidityError::Invalid(invalid_transaction)) From f14e5ca581d11c7b4fbac881adabc48f559f992a Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 19:32:17 +0900 Subject: [PATCH 03/32] fix --- polkadot/runtime/common/src/claims.rs | 10 ++++++---- .../frame/examples/kitchensink/src/benchmarking.rs | 1 - substrate/frame/system/benchmarking/src/inner.rs | 2 -- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index 2b36c19efce7..aa2c5ad0444d 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -39,7 +39,7 @@ use sp_runtime::{ Dispatchable, TransactionExtension, Zero, }, transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, + InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, TransactionSource, }, RuntimeDebug, }; @@ -652,6 +652,7 @@ where _len: usize, _self_implicit: Self::Implicit, _inherited_implication: &impl Encode, + _source: TransactionSource, ) -> Result< (ValidTransaction, Self::Val, ::RuntimeOrigin), TransactionValidityError, @@ -705,6 +706,7 @@ mod tests { use super::*; use hex_literal::hex; use secp_utils::*; + use sp_runtime::transaction_validity::TransactionSource::External; use codec::Encode; // The testing primitives are very useful for avoiding having to work with signatures @@ -1064,7 +1066,7 @@ mod tests { }); let di = c.get_dispatch_info(); assert_eq!(di.pays_fee, Pays::No); - let r = p.validate_only(Some(42).into(), &c, &di, 20); + let r = p.validate_only(Some(42).into(), &c, &di, 20, External); assert_eq!(r.unwrap().0, ValidTransaction::default()); }); } @@ -1077,13 +1079,13 @@ mod tests { statement: StatementKind::Regular.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate_only(Some(42).into(), &c, &di, 20); + let r = p.validate_only(Some(42).into(), &c, &di, 20, External); assert!(r.is_err()); let c = RuntimeCall::Claims(ClaimsCall::attest { statement: StatementKind::Saft.to_text().to_vec(), }); let di = c.get_dispatch_info(); - let r = p.validate_only(Some(69).into(), &c, &di, 20); + let r = p.validate_only(Some(69).into(), &c, &di, 20, External); assert!(r.is_err()); }); } diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 1d7022c55b61..5f1d378e06fe 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -26,7 +26,6 @@ use crate::Pallet as Kitchensink; use frame_benchmarking::v2::*; use frame_system::RawOrigin; -use frame_support::pallet_prelude::TransactionSource; // To actually run this benchmark on pallet-example-kitchensink, we need to put this pallet into the // runtime and compile it with `runtime-benchmarks` feature. The detail procedures are diff --git a/substrate/frame/system/benchmarking/src/inner.rs b/substrate/frame/system/benchmarking/src/inner.rs index 08a14ea6f401..0fb592f3dbba 100644 --- a/substrate/frame/system/benchmarking/src/inner.rs +++ b/substrate/frame/system/benchmarking/src/inner.rs @@ -49,8 +49,6 @@ pub trait Config: frame_system::Config { #[benchmarks] mod benchmarks { - use frame_support::pallet_prelude::TransactionSource; - use super::*; #[benchmark] From 16d691b650b8cb6a0f599a563370a72eaf7c1496 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 19:41:17 +0900 Subject: [PATCH 04/32] prdoc --- prdoc/pr_6323.prdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 prdoc/pr_6323.prdoc diff --git a/prdoc/pr_6323.prdoc b/prdoc/pr_6323.prdoc new file mode 100644 index 000000000000..4df79b4dd898 --- /dev/null +++ b/prdoc/pr_6323.prdoc @@ -0,0 +1,12 @@ +title: add `TransactionSource` to `TransactionExtension::validate` +doc: +- audience: Runtime Dev + description: | + Add a the source of the extrinsic as an argument in `TransactionExtension::validate`. + The transaction source can be useful for transactions that should only be valid if it comes from the node. For example from offchain worker. + To update the current code. The transaction source can simply be ignored: `_source: TransactionSource` + + +crates: +- name: sp-runtime + bump: major From ab46f1b81ce778de126a87f30820315114edb056 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 19:44:27 +0900 Subject: [PATCH 05/32] fmt --- bridges/bin/runtime-common/src/extensions.rs | 5 ++- bridges/modules/relayers/src/extension/mod.rs | 5 ++- .../examples/kitchensink/src/benchmarking.rs | 2 +- .../frame/examples/kitchensink/src/lib.rs | 5 +-- substrate/frame/support/procedural/Cargo.toml | 2 +- substrate/frame/support/src/lib.rs | 4 +- .../frame/support/test/tests/authorize.rs | 25 ++++++++---- .../system/src/extensions/authorize_call.rs | 5 ++- .../system/src/extensions/check_mortality.rs | 10 +++-- .../src/extensions/check_non_zero_sender.rs | 3 +- .../system/src/extensions/check_nonce.rs | 6 ++- .../skip-feeless-payment/src/tests.rs | 19 +++++++-- .../frame/transaction-payment/src/tests.rs | 40 ++++++++++++++----- substrate/frame/verify-signature/src/tests.rs | 2 +- .../runtime/src/generic/checked_extrinsic.rs | 16 ++------ .../dispatch_transaction.rs | 6 +-- .../runtime/src/transaction_validity.rs | 3 +- substrate/test-utils/runtime/src/lib.rs | 3 +- 18 files changed, 99 insertions(+), 62 deletions(-) diff --git a/bridges/bin/runtime-common/src/extensions.rs b/bridges/bin/runtime-common/src/extensions.rs index 7266f1997084..256e975f44c3 100644 --- a/bridges/bin/runtime-common/src/extensions.rs +++ b/bridges/bin/runtime-common/src/extensions.rs @@ -391,10 +391,11 @@ mod tests { parameter_types, AsSystemOriginSigner, AsTransactionAuthorizedOrigin, ConstU64, DispatchTransaction, Header as _, TransactionExtension, }, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + transaction_validity::{ + InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction, + }, DispatchError, }; - use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new( diff --git a/bridges/modules/relayers/src/extension/mod.rs b/bridges/modules/relayers/src/extension/mod.rs index af408545c462..a400aeaee074 100644 --- a/bridges/modules/relayers/src/extension/mod.rs +++ b/bridges/modules/relayers/src/extension/mod.rs @@ -465,10 +465,11 @@ mod tests { use pallet_utility::Call as UtilityCall; use sp_runtime::{ traits::{ConstU64, DispatchTransaction, Header as HeaderT}, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + transaction_validity::{ + InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction, + }, DispatchError, }; - use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { TestParachain: u32 = BridgedUnderlyingParachain::PARACHAIN_ID; diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 4906094b54b1..e749b3bb2b76 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -25,8 +25,8 @@ use super::*; use crate::Pallet as Kitchensink; use frame_benchmarking::v2::*; -use frame_system::RawOrigin; use frame_support::pallet_prelude::TransactionSource; +use frame_system::RawOrigin; // To actually run this benchmark on pallet-example-kitchensink, we need to put this pallet into the // runtime and compile it with `runtime-benchmarks` feature. The detail procedures are diff --git a/substrate/frame/examples/kitchensink/src/lib.rs b/substrate/frame/examples/kitchensink/src/lib.rs index ac62f8cf4d24..90cc04acc716 100644 --- a/substrate/frame/examples/kitchensink/src/lib.rs +++ b/substrate/frame/examples/kitchensink/src/lib.rs @@ -238,10 +238,7 @@ pub mod pallet { })] #[pallet::weight(T::WeightInfo::set_foo_using_authorize())] #[pallet::weight_of_authorize(T::WeightInfo::authorize_set_foo_using_authorize())] - pub fn set_foo_using_authorize( - origin: OriginFor, - new_foo: u32, - ) -> DispatchResult { + pub fn set_foo_using_authorize(origin: OriginFor, new_foo: u32) -> DispatchResult { // We only dispatch if it comes from the authorized origin. Meaning that the closure // passed in `pallet::authorize` has successfully authorized the call. ensure_authorized(origin)?; diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 05472d8966ac..8362b0b9eb05 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -43,8 +43,8 @@ scale-info = { features = ["derive"], workspace = true } sp-core = { workspace = true, features = ["std"] } sp-io = { workspace = true, features = ["std"] } sp-runtime = { features = [ - "serde", "runtime-benchmarks", + "serde", "std", ], workspace = true } frame-system = { workspace = true, features = ["runtime-benchmarks", "std"] } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index 311466e14637..b9cb3ed5bde7 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -924,8 +924,8 @@ pub mod pallet_prelude { }, transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, - TransactionTag, TransactionValidity, TransactionValidityWithRefund, TransactionValidityError, UnknownTransaction, - ValidTransaction, + TransactionTag, TransactionValidity, TransactionValidityError, + TransactionValidityWithRefund, UnknownTransaction, ValidTransaction, }, DispatchError, RuntimeDebug, MAX_MODULE_ERROR_ENCODED_SIZE, }; diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index 95316cb8936c..bfe2337ced57 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -22,9 +22,12 @@ use frame_support::{ pallet_prelude::{TransactionSource, Weight}, }; use sp_runtime::{ - testing::UintAuthorityId, traits::{Applyable, Checkable}, transaction_validity::{ + testing::UintAuthorityId, + traits::{Applyable, Checkable}, + transaction_validity::{ InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, - }, BuildStorage, DispatchError + }, + BuildStorage, DispatchError, }; // test for instance @@ -124,7 +127,11 @@ pub mod pallet1 { #[pallet::authorize(Pallet::::authorize_call3)] #[pallet::call_index(2)] - pub fn call3(origin: OriginFor, valid: bool, _some_gen: T::SomeGeneric) -> DispatchResultWithPostInfo { + pub fn call3( + origin: OriginFor, + valid: bool, + _some_gen: T::SomeGeneric, + ) -> DispatchResultWithPostInfo { ensure_authorized(origin)?; let _ = valid; @@ -148,7 +155,11 @@ pub mod pallet1 { } impl, I: 'static> Pallet { - fn authorize_call3(_source: TransactionSource, valid: &bool, _some_gen: &T::SomeGeneric) -> TransactionValidityWithRefund { + fn authorize_call3( + _source: TransactionSource, + valid: &bool, + _some_gen: &T::SomeGeneric, + ) -> TransactionValidityWithRefund { if *valid { Ok(Default::default()) } else { @@ -329,10 +340,8 @@ fn valid_call_weight_test() { dispatch_success: true, call_weight: pallet1::CALL_2_WEIGHT, ext_weight: pallet1::CALL_2_AUTH_WEIGHT, - actual_weight: - pallet1::CALL_2_REFUND - + pallet1::CALL_2_AUTH_WEIGHT - - call_2_auth_weight_refund, + actual_weight: pallet1::CALL_2_REFUND + pallet1::CALL_2_AUTH_WEIGHT - + call_2_auth_weight_refund, }, Test { call: RuntimeCall::Pallet1Instance2(pallet1::Call::call3 { valid: true, some_gen: 1 }), diff --git a/substrate/frame/system/src/extensions/authorize_call.rs b/substrate/frame/system/src/extensions/authorize_call.rs index 1ed74f551187..6cace91bffff 100644 --- a/substrate/frame/system/src/extensions/authorize_call.rs +++ b/substrate/frame/system/src/extensions/authorize_call.rs @@ -106,8 +106,9 @@ mod tests { use sp_runtime::{ testing::UintAuthorityId, traits::{Applyable, Checkable, TransactionExtension as _}, - transaction_validity::{InvalidTransaction, TransactionValidityError}, - transaction_validity::TransactionSource::External, + transaction_validity::{ + InvalidTransaction, TransactionSource::External, TransactionValidityError, + }, BuildStorage, DispatchError, }; diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs index 59edafa792e3..75e1fc2fc11a 100644 --- a/substrate/frame/system/src/extensions/check_mortality.rs +++ b/substrate/frame/system/src/extensions/check_mortality.rs @@ -117,8 +117,9 @@ mod tests { weights::Weight, }; use sp_core::H256; - use sp_runtime::traits::DispatchTransaction; - use sp_runtime::transaction_validity::TransactionSource::External; + use sp_runtime::{ + traits::DispatchTransaction, transaction_validity::TransactionSource::External, + }; #[test] fn signed_ext_check_era_should_work() { @@ -154,7 +155,10 @@ mod tests { >::insert(16, H256::repeat_byte(1)); assert_eq!( - ext.validate_only(Some(1).into(), CALL, &normal, len, External).unwrap().0.longevity, + ext.validate_only(Some(1).into(), CALL, &normal, len, External) + .unwrap() + .0 + .longevity, 15 ); }) diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs index 189bc35a3bf7..a4e54954dc2c 100644 --- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs +++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs @@ -87,9 +87,8 @@ mod tests { use frame_support::{assert_ok, dispatch::DispatchInfo}; use sp_runtime::{ traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}, - transaction_validity::TransactionValidityError, + transaction_validity::{TransactionSource::External, TransactionValidityError}, }; - use sp_runtime::transaction_validity::TransactionSource::External; #[test] fn zero_account_ban_works() { diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index 73ab8aec799f..eed08050338b 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -185,8 +185,10 @@ mod tests { use frame_support::{ assert_ok, assert_storage_noop, dispatch::GetDispatchInfo, traits::OriginTrait, }; - use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}; - use sp_runtime::transaction_validity::TransactionSource::External; + use sp_runtime::{ + traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}, + transaction_validity::TransactionSource::External, + }; #[test] fn signed_ext_check_nonce_works() { diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs index e6f8373e59e8..1940110a1f1d 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs @@ -18,8 +18,7 @@ use crate::mock::{ pallet_dummy::Call, DummyExtension, PrepareCount, Runtime, RuntimeCall, ValidateCount, }; use frame_support::dispatch::DispatchInfo; -use sp_runtime::transaction_validity::TransactionSource; -use sp_runtime::traits::DispatchTransaction; +use sp_runtime::{traits::DispatchTransaction, transaction_validity::TransactionSource}; #[test] fn skip_feeless_payment_works() { @@ -42,14 +41,26 @@ fn validate_works() { let call = RuntimeCall::DummyPallet(Call::::aux { data: 1 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) + .validate_only( + Some(0).into(), + &call, + &DispatchInfo::default(), + 0, + TransactionSource::External, + ) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); let call = RuntimeCall::DummyPallet(Call::::aux { data: 0 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) + .validate_only( + Some(0).into(), + &call, + &DispatchInfo::default(), + 0, + TransactionSource::External, + ) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index 85e0a4ae4727..dde696f09c2a 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -23,8 +23,7 @@ use codec::Encode; use sp_runtime::{ generic::UncheckedExtrinsic, traits::{DispatchTransaction, One}, - transaction_validity::InvalidTransaction, - transaction_validity::TransactionSource::External, + transaction_validity::{InvalidTransaction, TransactionSource::External}, BuildStorage, }; @@ -246,7 +245,9 @@ fn transaction_extension_allows_free_transactions() { pays_fee: Pays::Yes, }; assert_eq!( - Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len, External).unwrap_err(), + Ext::from(0) + .validate_only(Some(1).into(), CALL, &free_tx, len, External) + .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Payment), ); }); @@ -660,11 +661,19 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 60); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 110); }); @@ -677,11 +686,13 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5810); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 6110); }); } @@ -699,7 +710,11 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 10); }); @@ -711,7 +726,8 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5510); }); } @@ -730,7 +746,11 @@ fn higher_tip_have_higher_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + pri1 = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { diff --git a/substrate/frame/verify-signature/src/tests.rs b/substrate/frame/verify-signature/src/tests.rs index 1d1de4449f3a..505a33a883c2 100644 --- a/substrate/frame/verify-signature/src/tests.rs +++ b/substrate/frame/verify-signature/src/tests.rs @@ -25,7 +25,7 @@ use extension::VerifySignature; use frame_support::{ derive_impl, dispatch::GetDispatchInfo, - pallet_prelude::{InvalidTransaction, TransactionValidityError, TransactionSource}, + pallet_prelude::{InvalidTransaction, TransactionSource, TransactionValidityError}, traits::OriginTrait, }; use frame_system::Call as SystemCall; diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs index 2fee8d85b136..521f54bf4afd 100644 --- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs @@ -112,18 +112,10 @@ where Extension::bare_post_dispatch(info, &mut 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, - ), + 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), } } } diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs index 0dcb153413ff..19c8a2b2d496 100644 --- a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs +++ b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs @@ -113,7 +113,8 @@ where info: &DispatchInfoOf, len: usize, ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> { - let (_, val, origin) = self.validate_only(origin, call, info, len, TransactionSource::InBlock)?; + let (_, val, origin) = + self.validate_only(origin, call, info, len, TransactionSource::InBlock)?; let pre = self.prepare(val, &origin, &call, info, len)?; Ok((pre, origin)) } @@ -145,8 +146,7 @@ where Self::Origin, ) -> crate::DispatchResultWithInfo<::PostInfo>, ) -> Self::Result { - let (pre, origin) = - self.validate_and_prepare(origin, &call, info, len)?; + let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; let mut res = substitute(origin); let pd_res = res.map(|_| ()).map_err(|e| e.error); let post_info = match &mut res { diff --git a/substrate/primitives/runtime/src/transaction_validity.rs b/substrate/primitives/runtime/src/transaction_validity.rs index 9dc8856c1214..4fe69d60ec6d 100644 --- a/substrate/primitives/runtime/src/transaction_validity.rs +++ b/substrate/primitives/runtime/src/transaction_validity.rs @@ -220,7 +220,8 @@ pub type TransactionValidity = Result; +pub type TransactionValidityWithRefund = + Result<(ValidTransaction, Weight), TransactionValidityError>; impl From for TransactionValidity { fn from(invalid_transaction: InvalidTransaction) -> Self { diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 67451267eb94..3b80c94173a4 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -1054,8 +1054,7 @@ mod tests { use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext}; use sp_runtime::{ traits::{DispatchTransaction, Hash as _}, - transaction_validity::{InvalidTransaction, ValidTransaction}, - transaction_validity::TransactionSource::External, + transaction_validity::{InvalidTransaction, TransactionSource::External, ValidTransaction}, }; use substrate_test_runtime_client::{ prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder, From 93d9ed3d843f68c082ed52d3b2f895e0ebe7af8c Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 19:52:41 +0900 Subject: [PATCH 06/32] fmt --- bridges/bin/runtime-common/src/extensions.rs | 5 ++- bridges/modules/relayers/src/extension/mod.rs | 5 ++- polkadot/runtime/common/src/claims.rs | 3 +- .../system/src/extensions/check_mortality.rs | 10 +++-- .../src/extensions/check_non_zero_sender.rs | 3 +- .../system/src/extensions/check_nonce.rs | 6 ++- .../skip-feeless-payment/src/tests.rs | 19 +++++++-- .../frame/transaction-payment/src/tests.rs | 40 ++++++++++++++----- substrate/frame/verify-signature/src/tests.rs | 2 +- .../runtime/src/generic/checked_extrinsic.rs | 16 ++------ .../dispatch_transaction.rs | 6 +-- substrate/test-utils/runtime/src/lib.rs | 3 +- 12 files changed, 74 insertions(+), 44 deletions(-) diff --git a/bridges/bin/runtime-common/src/extensions.rs b/bridges/bin/runtime-common/src/extensions.rs index 7266f1997084..256e975f44c3 100644 --- a/bridges/bin/runtime-common/src/extensions.rs +++ b/bridges/bin/runtime-common/src/extensions.rs @@ -391,10 +391,11 @@ mod tests { parameter_types, AsSystemOriginSigner, AsTransactionAuthorizedOrigin, ConstU64, DispatchTransaction, Header as _, TransactionExtension, }, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + transaction_validity::{ + InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction, + }, DispatchError, }; - use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new( diff --git a/bridges/modules/relayers/src/extension/mod.rs b/bridges/modules/relayers/src/extension/mod.rs index af408545c462..a400aeaee074 100644 --- a/bridges/modules/relayers/src/extension/mod.rs +++ b/bridges/modules/relayers/src/extension/mod.rs @@ -465,10 +465,11 @@ mod tests { use pallet_utility::Call as UtilityCall; use sp_runtime::{ traits::{ConstU64, DispatchTransaction, Header as HeaderT}, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + transaction_validity::{ + InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction, + }, DispatchError, }; - use sp_runtime::transaction_validity::TransactionSource::External; parameter_types! { TestParachain: u32 = BridgedUnderlyingParachain::PARACHAIN_ID; diff --git a/polkadot/runtime/common/src/claims.rs b/polkadot/runtime/common/src/claims.rs index aa2c5ad0444d..bb7683ffcc7b 100644 --- a/polkadot/runtime/common/src/claims.rs +++ b/polkadot/runtime/common/src/claims.rs @@ -39,7 +39,8 @@ use sp_runtime::{ Dispatchable, TransactionExtension, Zero, }, transaction_validity::{ - InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction, TransactionSource, + InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, + ValidTransaction, }, RuntimeDebug, }; diff --git a/substrate/frame/system/src/extensions/check_mortality.rs b/substrate/frame/system/src/extensions/check_mortality.rs index 59edafa792e3..75e1fc2fc11a 100644 --- a/substrate/frame/system/src/extensions/check_mortality.rs +++ b/substrate/frame/system/src/extensions/check_mortality.rs @@ -117,8 +117,9 @@ mod tests { weights::Weight, }; use sp_core::H256; - use sp_runtime::traits::DispatchTransaction; - use sp_runtime::transaction_validity::TransactionSource::External; + use sp_runtime::{ + traits::DispatchTransaction, transaction_validity::TransactionSource::External, + }; #[test] fn signed_ext_check_era_should_work() { @@ -154,7 +155,10 @@ mod tests { >::insert(16, H256::repeat_byte(1)); assert_eq!( - ext.validate_only(Some(1).into(), CALL, &normal, len, External).unwrap().0.longevity, + ext.validate_only(Some(1).into(), CALL, &normal, len, External) + .unwrap() + .0 + .longevity, 15 ); }) diff --git a/substrate/frame/system/src/extensions/check_non_zero_sender.rs b/substrate/frame/system/src/extensions/check_non_zero_sender.rs index 189bc35a3bf7..a4e54954dc2c 100644 --- a/substrate/frame/system/src/extensions/check_non_zero_sender.rs +++ b/substrate/frame/system/src/extensions/check_non_zero_sender.rs @@ -87,9 +87,8 @@ mod tests { use frame_support::{assert_ok, dispatch::DispatchInfo}; use sp_runtime::{ traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}, - transaction_validity::TransactionValidityError, + transaction_validity::{TransactionSource::External, TransactionValidityError}, }; - use sp_runtime::transaction_validity::TransactionSource::External; #[test] fn zero_account_ban_works() { diff --git a/substrate/frame/system/src/extensions/check_nonce.rs b/substrate/frame/system/src/extensions/check_nonce.rs index 73ab8aec799f..eed08050338b 100644 --- a/substrate/frame/system/src/extensions/check_nonce.rs +++ b/substrate/frame/system/src/extensions/check_nonce.rs @@ -185,8 +185,10 @@ mod tests { use frame_support::{ assert_ok, assert_storage_noop, dispatch::GetDispatchInfo, traits::OriginTrait, }; - use sp_runtime::traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}; - use sp_runtime::transaction_validity::TransactionSource::External; + use sp_runtime::{ + traits::{AsTransactionAuthorizedOrigin, DispatchTransaction}, + transaction_validity::TransactionSource::External, + }; #[test] fn signed_ext_check_nonce_works() { diff --git a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs index e6f8373e59e8..1940110a1f1d 100644 --- a/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/skip-feeless-payment/src/tests.rs @@ -18,8 +18,7 @@ use crate::mock::{ pallet_dummy::Call, DummyExtension, PrepareCount, Runtime, RuntimeCall, ValidateCount, }; use frame_support::dispatch::DispatchInfo; -use sp_runtime::transaction_validity::TransactionSource; -use sp_runtime::traits::DispatchTransaction; +use sp_runtime::{traits::DispatchTransaction, transaction_validity::TransactionSource}; #[test] fn skip_feeless_payment_works() { @@ -42,14 +41,26 @@ fn validate_works() { let call = RuntimeCall::DummyPallet(Call::::aux { data: 1 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) + .validate_only( + Some(0).into(), + &call, + &DispatchInfo::default(), + 0, + TransactionSource::External, + ) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); let call = RuntimeCall::DummyPallet(Call::::aux { data: 0 }); SkipCheckIfFeeless::::from(DummyExtension) - .validate_only(Some(0).into(), &call, &DispatchInfo::default(), 0, TransactionSource::External) + .validate_only( + Some(0).into(), + &call, + &DispatchInfo::default(), + 0, + TransactionSource::External, + ) .unwrap(); assert_eq!(ValidateCount::get(), 1); assert_eq!(PrepareCount::get(), 0); diff --git a/substrate/frame/transaction-payment/src/tests.rs b/substrate/frame/transaction-payment/src/tests.rs index 85e0a4ae4727..dde696f09c2a 100644 --- a/substrate/frame/transaction-payment/src/tests.rs +++ b/substrate/frame/transaction-payment/src/tests.rs @@ -23,8 +23,7 @@ use codec::Encode; use sp_runtime::{ generic::UncheckedExtrinsic, traits::{DispatchTransaction, One}, - transaction_validity::InvalidTransaction, - transaction_validity::TransactionSource::External, + transaction_validity::{InvalidTransaction, TransactionSource::External}, BuildStorage, }; @@ -246,7 +245,9 @@ fn transaction_extension_allows_free_transactions() { pays_fee: Pays::Yes, }; assert_eq!( - Ext::from(0).validate_only(Some(1).into(), CALL, &free_tx, len, External).unwrap_err(), + Ext::from(0) + .validate_only(Some(1).into(), CALL, &free_tx, len, External) + .unwrap_err(), TransactionValidityError::Invalid(InvalidTransaction::Payment), ); }); @@ -660,11 +661,19 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 60); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 110); }); @@ -677,11 +686,13 @@ fn should_alter_operational_priority() { }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5810); let ext = Ext::from(2 * tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 6110); }); } @@ -699,7 +710,11 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + let priority = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; assert_eq!(priority, 10); }); @@ -711,7 +726,8 @@ fn no_tip_has_some_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - let priority = ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; + let priority = + ext.validate_only(Some(2).into(), CALL, &op, len, External).unwrap().0.priority; assert_eq!(priority, 5510); }); } @@ -730,7 +746,11 @@ fn higher_tip_have_higher_priority() { pays_fee: Pays::Yes, }; let ext = Ext::from(tip); - pri1 = ext.validate_only(Some(2).into(), CALL, &normal, len, External).unwrap().0.priority; + pri1 = ext + .validate_only(Some(2).into(), CALL, &normal, len, External) + .unwrap() + .0 + .priority; }); ExtBuilder::default().balance_factor(100).build().execute_with(|| { diff --git a/substrate/frame/verify-signature/src/tests.rs b/substrate/frame/verify-signature/src/tests.rs index 1d1de4449f3a..505a33a883c2 100644 --- a/substrate/frame/verify-signature/src/tests.rs +++ b/substrate/frame/verify-signature/src/tests.rs @@ -25,7 +25,7 @@ use extension::VerifySignature; use frame_support::{ derive_impl, dispatch::GetDispatchInfo, - pallet_prelude::{InvalidTransaction, TransactionValidityError, TransactionSource}, + pallet_prelude::{InvalidTransaction, TransactionSource, TransactionValidityError}, traits::OriginTrait, }; use frame_system::Call as SystemCall; diff --git a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs index 2fee8d85b136..521f54bf4afd 100644 --- a/substrate/primitives/runtime/src/generic/checked_extrinsic.rs +++ b/substrate/primitives/runtime/src/generic/checked_extrinsic.rs @@ -112,18 +112,10 @@ where Extension::bare_post_dispatch(info, &mut 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, - ), + 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), } } } diff --git a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs index 0dcb153413ff..19c8a2b2d496 100644 --- a/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs +++ b/substrate/primitives/runtime/src/traits/transaction_extension/dispatch_transaction.rs @@ -113,7 +113,8 @@ where info: &DispatchInfoOf, len: usize, ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> { - let (_, val, origin) = self.validate_only(origin, call, info, len, TransactionSource::InBlock)?; + let (_, val, origin) = + self.validate_only(origin, call, info, len, TransactionSource::InBlock)?; let pre = self.prepare(val, &origin, &call, info, len)?; Ok((pre, origin)) } @@ -145,8 +146,7 @@ where Self::Origin, ) -> crate::DispatchResultWithInfo<::PostInfo>, ) -> Self::Result { - let (pre, origin) = - self.validate_and_prepare(origin, &call, info, len)?; + let (pre, origin) = self.validate_and_prepare(origin, &call, info, len)?; let mut res = substitute(origin); let pd_res = res.map(|_| ()).map_err(|e| e.error); let post_info = match &mut res { diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs index 67451267eb94..3b80c94173a4 100644 --- a/substrate/test-utils/runtime/src/lib.rs +++ b/substrate/test-utils/runtime/src/lib.rs @@ -1054,8 +1054,7 @@ mod tests { use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext}; use sp_runtime::{ traits::{DispatchTransaction, Hash as _}, - transaction_validity::{InvalidTransaction, ValidTransaction}, - transaction_validity::TransactionSource::External, + transaction_validity::{InvalidTransaction, TransactionSource::External, ValidTransaction}, }; use substrate_test_runtime_client::{ prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder, From de1d4f4c5d13e3226969a95865a9e76472a2ac6e Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 1 Nov 2024 21:29:37 +0900 Subject: [PATCH 07/32] improve code gen --- .../examples/kitchensink/src/benchmarking.rs | 1 + substrate/frame/support/procedural/src/lib.rs | 2 +- .../procedural/src/pallet/expand/call.rs | 31 +++++------ .../frame/support/test/tests/authorize.rs | 2 +- .../authorize_wrong_closure_2.stderr | 43 --------------- .../authorize_wrong_closure_4.stderr | 32 ----------- .../authorize_wrong_closure_6.stderr | 55 ++----------------- 7 files changed, 21 insertions(+), 145 deletions(-) diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index e749b3bb2b76..354ddcd37cb9 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -94,6 +94,7 @@ mod benchmarks { // `cargo test -p pallet-example-kitchensink --all-features`, you will see one line per case: // `test benchmarking::bench_set_foo_benchmark ... ok` // `test benchmarking::bench_set_foo_using_authorize_benchmark ... ok` in the result. + // `test benchmarking::bench_authorize_set_foo_using_authorize_benchmark ... ok` in the result. // // The line generates three steps per benchmark, with repeat=1 and the three steps are // [low, mid, high] of the range. diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 2ca7598746e8..2654c78b821f 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1392,7 +1392,7 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream /// /// #[pallet::weight(Weight::zero())] /// // We can also give the callback as a function -/// #[pallet::authorize(Pallet::::authorize_some_other_call)] +/// #[pallet::authorize(Self::authorize_some_other_call)] /// #[pallet::weight_of_authorize(Weight::zero())] /// #[pallet::call_index(1)] /// pub fn some_other_call(origin: OriginFor, arg: u32) -> DispatchResult { diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs index f0f98986e9b2..cab5b46819ac 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/call.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs @@ -293,31 +293,28 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { if let Some(authorize_def) = &method.authorize { let authorize_fn = &authorize_def.expr; let attr_fn_getter = syn::Ident::new( - &format!("macro_inner_authorize_call_for_{}", method.name), + &format!("__macro_inner_authorize_call_for_{}", method.name), authorize_fn.span(), ); let typed_authorize_fn = quote::quote_spanned!(authorize_fn.span() => { // Closure don't have a writable type. So we fix the authorize token stream to - // be any implementation of this generic F. - // This also allows to have good type inference on the closure. - fn #attr_fn_getter< - #type_impl_gen, - F: Fn( + // be any implementation of a specific function. + // This allows to have good type inference on the closure. + // + // Then we wrap this into an implementation for `Pallet` in order to get access + // to `Self` as `Pallet` instead of `Call`. + impl<#type_impl_gen> Pallet<#type_use_gen> #where_clause { + #[doc(hidden)] + fn #attr_fn_getter() -> impl Fn( #frame_support::pallet_prelude::TransactionSource, #( &#arg_type ),* - ) -> ::core::result::Result< - ( - #frame_support::pallet_prelude::ValidTransaction, - #frame_support::pallet_prelude::Weight, - ), - #frame_support::pallet_prelude::TransactionValidityError, - > - >(f: F) -> F { - f + ) -> #frame_support::pallet_prelude::TransactionValidityWithRefund { + #authorize_fn + } } - #attr_fn_getter::<#type_use_gen, _>(#authorize_fn) + Pallet::<#type_use_gen>::#attr_fn_getter() }); // `source` is from outside this block, so we can't use the authorize_fn span. @@ -351,7 +348,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { } assert_eq!(authorize_fn_weight.len(), methods.len()); - quote::quote_spanned!(proc_macro2::Span::call_site() => + quote::quote_spanned!(span => #[doc(hidden)] mod warnings { #( diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index bfe2337ced57..a156c86a58c8 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -125,7 +125,7 @@ pub mod pallet1 { Ok(Some(CALL_2_REFUND).into()) } - #[pallet::authorize(Pallet::::authorize_call3)] + #[pallet::authorize(Self::authorize_call3)] #[pallet::call_index(2)] pub fn call3( origin: OriginFor, diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr index f773042bf52d..3f38dec1cb4b 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_2.stderr @@ -9,46 +9,3 @@ error[E0631]: type mismatch in closure arguments | = note: expected closure signature `for<'a> fn(TransactionSource, &'a u32) -> _` found closure signature `fn(TransactionSource, u8) -> _` -note: required by a bound in `macro_inner_authorize_call_for_call1` - --> tests/pallet_ui/authorize_wrong_closure_2.rs:36:23 - | -36 | #[pallet::authorize(|_, _: u8| -> bool { true })] - | ^ required by this bound in `macro_inner_authorize_call_for_call1` - -error[E0308]: mismatched types - --> tests/pallet_ui/authorize_wrong_closure_2.rs:40:38 - | -18 | #[frame_support::pallet] - | ------------------------ arguments to this function are incorrect -... -40 | pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { - | ^ expected `u8`, found `&u32` - | -note: closure parameter defined here - --> tests/pallet_ui/authorize_wrong_closure_2.rs:36:27 - | -36 | #[pallet::authorize(|_, _: u8| -> bool { true })] - | ^^^^^ - -error[E0308]: mismatched types - --> tests/pallet_ui/authorize_wrong_closure_2.rs:18:1 - | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected `Result<(..., ...), ...>`, found `bool` - | arguments to this enum variant are incorrect - | - = note: expected enum `Result<(ValidTransaction, frame_support::weights::Weight), TransactionValidityError>` - found type `bool` -help: the type constructed contains `bool` due to the type of the argument passed - --> tests/pallet_ui/authorize_wrong_closure_2.rs:18:1 - | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ this argument influences the type of `Some` -note: tuple variant defined here - --> $RUST/core/src/option.rs - | - | Some(#[stable(feature = "rust1", since = "1.0.0")] T), - | ^^^^ - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr index 6b4e5cab9a6e..4033c7857d96 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_4.stderr @@ -5,35 +5,3 @@ error[E0277]: expected a `Fn(TransactionSource, &u32)` closure, found `Result<_, | ^^ expected an `Fn(TransactionSource, &u32)` closure, found `Result<_, _>` | = help: the trait `for<'a> Fn(TransactionSource, &'a u32)` is not implemented for `Result<_, _>` -note: required by a bound in `macro_inner_authorize_call_for_call1` - --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 - | -36 | #[pallet::authorize(Ok(Default::default()))] - | ^^ required by this bound in `macro_inner_authorize_call_for_call1` - -error[E0277]: expected a `FnOnce(TransactionSource, &u32)` closure, found `Result<_, _>` - --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 - | -36 | #[pallet::authorize(Ok(Default::default()))] - | --^^^^^^^^^^^^^^^^^^^^ - | | - | expected an `FnOnce(TransactionSource, &u32)` closure, found `Result<_, _>` - | required by a bound introduced by this call - | - = help: the trait `for<'a> FnOnce(TransactionSource, &'a u32)` is not implemented for `Result<_, _>` -note: required by a bound in `macro_inner_authorize_call_for_call1` - --> tests/pallet_ui/authorize_wrong_closure_4.rs:36:23 - | -36 | #[pallet::authorize(Ok(Default::default()))] - | ^^ required by this bound in `macro_inner_authorize_call_for_call1` - -error[E0618]: expected function, found `Result<_, _>` - --> tests/pallet_ui/authorize_wrong_closure_4.rs:18:1 - | -18 | #[frame_support::pallet] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | call expression requires function - | `authorize_fn` has type `Result<_, _>` - | - = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr index 9302c7c5da73..0e102d889eb3 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr @@ -2,66 +2,19 @@ error[E0631]: type mismatch in function arguments --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 | 36 | #[pallet::authorize(Pallet::::authorize_call1)] - | ^^^^^^ expected due to this -... -48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { - | ---------------------------------------------------------------------------------------- found signature defined here - | - = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` - found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` -note: required by a bound in `macro_inner_authorize_call_for_call1` - --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 - | -36 | #[pallet::authorize(Pallet::::authorize_call1)] - | ^^^^^^ required by this bound in `macro_inner_authorize_call_for_call1` -help: consider adjusting the signature so it borrows its argument - | -48 | fn authorize_call1(_source: TransactionSource, _a: &u32) -> TransactionValidityWithRefund { - | + - -error[E0631]: type mismatch in function arguments - --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 - | -36 | #[pallet::authorize(Pallet::::authorize_call1)] - | ------^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^---------------------- | | | expected due to this - | required by a bound introduced by this call + | return type was inferred to be `fn(TransactionSource, u32) -> Result<(ValidTransaction, Weight), ...> {...::authorize_call1}` here ... 48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { | ---------------------------------------------------------------------------------------- found signature defined here | = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` -note: required by a bound in `macro_inner_authorize_call_for_call1` - --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 - | -36 | #[pallet::authorize(Pallet::::authorize_call1)] - | ^^^^^^ required by this bound in `macro_inner_authorize_call_for_call1` -help: consider wrapping the function in a closure - | -36 | #[pallet::authorize(|_source: frame_support::pallet_prelude::TransactionSource, _a: &u32| Pallet::::authorize_call1(_source, *_a))] - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++ + = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-a5d38637172660dc.long-type-4183595103124166336.txt' + = note: consider using `--verbose` to print the full type name to the console help: consider adjusting the signature so it borrows its argument | 48 | fn authorize_call1(_source: TransactionSource, _a: &u32) -> TransactionValidityWithRefund { | + - -error[E0308]: mismatched types - --> tests/pallet_ui/authorize_wrong_closure_6.rs:40:38 - | -18 | #[frame_support::pallet] - | ------------------------ arguments to this function are incorrect -... -40 | pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { - | ^ expected `u32`, found `&u32` - | -note: associated function defined here - --> tests/pallet_ui/authorize_wrong_closure_6.rs:48:6 - | -48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { - | ^^^^^^^^^^^^^^^ ------- -help: consider dereferencing the borrow - | -40 | pub fn call1(origin: OriginFor, *a: u32) -> DispatchResult { - | + From baa6fc5735fd28d91321631b92f0b1d0420b97c8 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 17:29:09 +0900 Subject: [PATCH 08/32] prdoc --- prdoc/pr_6323.prdoc | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/prdoc/pr_6323.prdoc b/prdoc/pr_6323.prdoc index 4df79b4dd898..6dcfb64e60ad 100644 --- a/prdoc/pr_6323.prdoc +++ b/prdoc/pr_6323.prdoc @@ -1,12 +1,27 @@ -title: add `TransactionSource` to `TransactionExtension::validate` +title: Introduce `#[pallet::authorize(...)]` macro attribute and `AuthorizeCall` system transaction extension doc: - audience: Runtime Dev description: | - Add a the source of the extrinsic as an argument in `TransactionExtension::validate`. - The transaction source can be useful for transactions that should only be valid if it comes from the node. For example from offchain worker. - To update the current code. The transaction source can simply be ignored: `_source: TransactionSource` + Some calls such as `claim` or `apply_authorized_upgrade` wants to be valid depending on the + parameters of the call or/and the state of the chain. + For instance `claim` is valid if the signature given as a parameter of the call is valid and if the state of the chain contains some pending claim. + Or the `apply_authorized_upgrade` is valid if the code given as a paramter of the call match the authorized hashed code on chain. + Those operation don't require a signed origin and are currently achieved using `ValidateUnsigned`. + This PR introduce a new pallet attribute `#[pallet::authorize(...)]` and a new system transaction extension `AuthorizeCall` to ease such operations. + This change is part of the broader plan for extrinsics: https://github.com/paritytech/polkadot-sdk/issues/2415. + The usage of `pallet::authorize` can be found in the rust documentation. It takes a function to define the validation logic. Another attribute `pallet::weight_of_authorize` is introduce, it takes a function to define the weight of the validation logic. + + The runtime must now use the new system transaction extension `AuthorizeCall` in their transaction extension pipeline. It is suggested to put it first. + ``` + pub type TxExtension = ( + frame_system::AuthorizeCall + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + ... + ); + ``` crates: -- name: sp-runtime +- name: frame-support bump: major From ffe33deeb0f477b0123a770e06f2c13d4c2ea221 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 17:36:49 +0900 Subject: [PATCH 09/32] apply suggestions --- substrate/frame/support/test/tests/authorize.rs | 2 +- substrate/frame/system/src/extensions/authorize_call.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index a156c86a58c8..c6832459db51 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -409,7 +409,7 @@ fn valid_call_weight_test() { } #[test] -fn valid_invalid_call() { +fn call_validity() { struct Test { call: RuntimeCall, validate_res: TransactionValidity, diff --git a/substrate/frame/system/src/extensions/authorize_call.rs b/substrate/frame/system/src/extensions/authorize_call.rs index 6cace91bffff..b513023e36cd 100644 --- a/substrate/frame/system/src/extensions/authorize_call.rs +++ b/substrate/frame/system/src/extensions/authorize_call.rs @@ -294,7 +294,7 @@ mod tests { } #[test] - fn call_filter_not_messed_up() { + fn call_filter_preserved() { new_test_ext().execute_with(|| { let ext = frame_system::AuthorizeCall::::new(); let filtered_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); From 78629703f1b2a028f4a69f89777549dd7789e7bd Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 17:59:50 +0900 Subject: [PATCH 10/32] use AsTransctionAuthorizedOrigin::is_transaction_authorized --- substrate/frame/system/src/extensions/authorize_call.rs | 9 ++++++--- substrate/frame/system/src/lib.rs | 9 +++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/substrate/frame/system/src/extensions/authorize_call.rs b/substrate/frame/system/src/extensions/authorize_call.rs index b513023e36cd..224b864d54dd 100644 --- a/substrate/frame/system/src/extensions/authorize_call.rs +++ b/substrate/frame/system/src/extensions/authorize_call.rs @@ -19,11 +19,14 @@ use crate::Config; use frame_support::{ dispatch::DispatchInfo, pallet_prelude::{Decode, DispatchResult, Encode, TransactionSource, TypeInfo, Weight}, - traits::{Authorize, OriginTrait}, + traits::Authorize, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; use sp_runtime::{ - traits::{Dispatchable, PostDispatchInfoOf, TransactionExtension, ValidateResult}, + traits::{ + AsTransactionAuthorizedOrigin, Dispatchable, PostDispatchInfoOf, TransactionExtension, + ValidateResult, + }, transaction_validity::TransactionValidityError, }; @@ -58,7 +61,7 @@ where _inherited_implication: &impl Encode, source: TransactionSource, ) -> ValidateResult { - if let Some(crate::RawOrigin::None) = origin.as_system_ref() { + if !origin.is_transaction_authorized() { if let Some(authorize) = call.authorize(source) { return authorize.map(|(validity, unspent)| { (validity, unspent, crate::Origin::::Authorized.into()) diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 744f578b7711..279ac26b08b2 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -110,9 +110,9 @@ use sp_runtime::traits::TrailingZeroInput; use sp_runtime::{ generic, traits::{ - self, AtLeast32Bit, BadOrigin, BlockNumberProvider, Bounded, CheckEqual, Dispatchable, - Hash, Header, Lookup, LookupError, MaybeDisplay, MaybeSerializeDeserialize, Member, One, - Saturating, SimpleBitOps, StaticLookup, Zero, + self, AsTransactionAuthorizedOrigin, AtLeast32Bit, BadOrigin, BlockNumberProvider, Bounded, + CheckEqual, Dispatchable, Hash, Header, Lookup, LookupError, MaybeDisplay, + MaybeSerializeDeserialize, Member, One, Saturating, SimpleBitOps, StaticLookup, Zero, }, transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity, @@ -500,7 +500,8 @@ pub mod pallet { type RuntimeOrigin: Into, Self::RuntimeOrigin>> + From> + Clone - + OriginTrait; + + OriginTrait + + AsTransactionAuthorizedOrigin; #[docify::export(system_runtime_call)] /// The aggregated `RuntimeCall` type. From 3dd50cab4a480d5c98d999b8d16f8594019817c8 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 18:14:00 +0900 Subject: [PATCH 11/32] test for call without authorization --- .../frame/support/test/tests/authorize.rs | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index c6832459db51..a7d7e9202f12 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -221,6 +221,28 @@ pub mod pallet3 { } } +// test for pallet with no authorized call +#[frame_support::pallet(dev_mode)] +pub mod pallet4 { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + pub fn call1(origin: OriginFor) -> DispatchResult { + ensure_authorized(origin)?; + Ok(()) + } + } +} + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for Runtime { type Block = Block; @@ -248,6 +270,8 @@ impl pallet2::Config for Runtime {} impl pallet3::Config for Runtime {} +impl pallet4::Config for Runtime {} + pub type TransactionExtension = frame_system::AuthorizeCall; pub type Header = sp_runtime::generic::Header; @@ -268,6 +292,7 @@ frame_support::construct_runtime!( Pallet3: pallet3, #[cfg(feature = "frame-feature-testing")] Pallet1Instance3: pallet1::, + Pallet4: pallet4, } ); @@ -494,7 +519,7 @@ fn signed_is_valid_but_dispatch_error() { let len = tx.using_encoded(|e| e.len()); let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) - .expect("Transaction is general so signature is good"); + .expect("Signature is good"); checked .validate::(TransactionSource::External, &info, len) @@ -508,3 +533,41 @@ fn signed_is_valid_but_dispatch_error() { assert_eq!(dispatch_err.error, DispatchError::BadOrigin); }); } + +#[test] +fn call_without_authorization() { + use frame_support::traits::Authorize; + + new_test_ext().execute_with(|| { + let call = RuntimeCall::Pallet4(pallet4::Call::call1 {}); + + // tests for trait implementation + assert_eq!(call.weight_of_authorize(), Weight::zero()); + assert_eq!(call.authorize(TransactionSource::External), None); + assert_eq!(call.authorize(TransactionSource::InBlock), None); + assert_eq!(call.authorize(TransactionSource::Local), None); + + // tests for transaction extension implementation + let tx_ext = frame_system::AuthorizeCall::::new(); + + let tx = UncheckedExtrinsic::new_transaction(call, tx_ext); + + let info = tx.get_dispatch_info(); + let len = tx.using_encoded(|e| e.len()); + + let checked = Checkable::check(tx, &frame_system::ChainContext::::default()) + .expect("Transaction is general so signature is good"); + + let err = checked + .validate::(TransactionSource::External, &info, len) + .expect_err("Call is not authorized, transaction is invalid"); + + assert_eq!(err, TransactionValidityError::Invalid(InvalidTransaction::UnknownOrigin)); + + let err = checked + .apply::(&info, len) + .expect_err("Call is not authorized, transaction is invalid"); + + assert_eq!(err, TransactionValidityError::Invalid(InvalidTransaction::UnknownOrigin)); + }); +} From ec1b263b01628b6d01bbff31b7cf3d8942a88bb3 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 18:26:58 +0900 Subject: [PATCH 12/32] do not force std in test --- substrate/frame/support/procedural/Cargo.toml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 8362b0b9eb05..030606fe28f8 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -38,18 +38,14 @@ codec = { features = [ "max-encoded-len", ], workspace = true } regex = { workspace = true } -sp-metadata-ir = { workspace = true, features = ["std"] } +sp-metadata-ir = { workspace = true } scale-info = { features = ["derive"], workspace = true } -sp-core = { workspace = true, features = ["std"] } -sp-io = { workspace = true, features = ["std"] } -sp-runtime = { features = [ - "runtime-benchmarks", - "serde", - "std", -], workspace = true } -frame-system = { workspace = true, features = ["runtime-benchmarks", "std"] } -frame-support = { workspace = true, features = ["runtime-benchmarks", "std"] } -frame-benchmarking = { workspace = true, features = ["std"] } +sp-core = { workspace = true } +sp-io = { workspace = true } +sp-runtime = { features = ["runtime-benchmarks", "serde"], workspace = true } +frame-system = { workspace = true, features = ["runtime-benchmarks"] } +frame-support = { workspace = true, features = ["runtime-benchmarks"] } +frame-benchmarking = { workspace = true } pretty_assertions = { workspace = true } static_assertions = { workspace = true } @@ -65,6 +61,7 @@ std = [ "sp-io/std", "sp-metadata-ir/std", "sp-runtime/std", + "frame-benchmarking/std", ] no-metadata-docs = [] experimental = [] From 25691b8e945a6453fa65fd5ae6eb54b6a523f280 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 20 Nov 2024 18:52:56 +0900 Subject: [PATCH 13/32] add authorize call tx ext everywhere --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 1 + .../runtimes/assets/asset-hub-westend/src/lib.rs | 2 ++ .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 11 +++++++++-- .../bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs | 5 ++++- .../bridge-hubs/bridge-hub-rococo/tests/tests.rs | 5 ++++- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 11 +++++++++-- .../bridge-hub-westend/tests/snowbridge.rs | 5 ++++- .../bridge-hubs/bridge-hub-westend/tests/tests.rs | 5 ++++- .../collectives/collectives-westend/src/lib.rs | 1 + .../runtimes/contracts/contracts-rococo/src/lib.rs | 1 + .../runtimes/coretime/coretime-rococo/src/lib.rs | 1 + .../runtimes/coretime/coretime-westend/src/lib.rs | 1 + .../runtimes/glutton/glutton-westend/src/lib.rs | 1 + .../runtimes/people/people-rococo/src/lib.rs | 1 + .../runtimes/people/people-westend/src/lib.rs | 1 + cumulus/parachains/runtimes/testing/penpal/src/lib.rs | 1 + .../runtimes/testing/rococo-parachain/src/lib.rs | 1 + cumulus/test/client/src/lib.rs | 3 ++- cumulus/test/runtime/src/lib.rs | 1 + cumulus/test/service/src/lib.rs | 3 ++- polkadot/node/service/src/benchmarking.rs | 4 ++++ polkadot/node/test/service/src/lib.rs | 2 ++ polkadot/runtime/rococo/src/lib.rs | 3 +++ polkadot/runtime/test-runtime/src/lib.rs | 3 +++ polkadot/runtime/westend/src/lib.rs | 3 +++ polkadot/xcm/xcm-builder/src/tests/pay/mock.rs | 1 + substrate/bin/node/cli/src/service.rs | 5 +++++ substrate/bin/node/cli/tests/submit_transaction.rs | 4 ++-- substrate/bin/node/runtime/src/lib.rs | 4 ++++ substrate/bin/node/testing/src/keyring.rs | 1 + substrate/frame/executive/src/tests.rs | 2 ++ substrate/frame/metadata-hash-extension/src/tests.rs | 1 + substrate/frame/src/lib.rs | 1 + templates/minimal/runtime/src/lib.rs | 2 ++ templates/parachain/runtime/src/lib.rs | 1 + templates/solochain/node/src/benchmarking.rs | 2 ++ templates/solochain/runtime/src/lib.rs | 1 + 37 files changed, 89 insertions(+), 12 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 2f9d83bd9d0b..e9019494aeab 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1005,6 +1005,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 2206aea78ec2..7c75d600e7fc 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1050,6 +1050,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -1072,6 +1073,7 @@ impl EthExtra for EthExtraImpl { fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index ff7af475f5e2..f97dd206f8c4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -125,7 +125,11 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( - frame_system::CheckNonZeroSender, + // `Debug` is implemented for tuple of at most 12 elements, so we group extensions. + ( + frame_system::AuthorizeCall, + frame_system::CheckNonZeroSender, + ), frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -1558,7 +1562,10 @@ mod tests { sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); let payload: TxExtension = ( - frame_system::CheckNonZeroSender::new(), + ( + frame_system::AuthorizeCall::::new(), + frame_system::CheckNonZeroSender::new(), + ), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), frame_system::CheckGenesis::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs index 8be2993c68f4..3fe5f6585320 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs @@ -171,7 +171,10 @@ fn construct_extrinsic( ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); let tx_ext: TxExtension = ( - frame_system::CheckNonZeroSender::::new(), + ( + frame_system::AuthorizeCall::::new(), + frame_system::CheckNonZeroSender::::new(), + ), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index 2e7dd98e9dce..afe84017b4d7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -50,7 +50,10 @@ fn construct_extrinsic( ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); let tx_ext: TxExtension = ( - frame_system::CheckNonZeroSender::::new(), + ( + frame_system::AuthorizeCall::::new(), + frame_system::CheckNonZeroSender::::new(), + ), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 065400016791..c8b5df778723 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -121,7 +121,11 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( - frame_system::CheckNonZeroSender, + // `Debug` is implemented for tuple of at most 12 elements, so we group extensions. + ( + frame_system::AuthorizeCall, + frame_system::CheckNonZeroSender, + ), frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -1379,7 +1383,10 @@ mod tests { sp_io::TestExternalities::default().execute_with(|| { frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); let payload: TxExtension = ( - frame_system::CheckNonZeroSender::new(), + ( + frame_system::AuthorizeCall::new(), + frame_system::CheckNonZeroSender::new(), + ), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), frame_system::CheckGenesis::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs index 1a1ce2a28ea3..9bb6c4fde7af 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/snowbridge.rs @@ -172,7 +172,10 @@ fn construct_extrinsic( ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); let extra: TxExtension = ( - frame_system::CheckNonZeroSender::::new(), + ( + frame_system::AuthorizeCall::::new(), + frame_system::CheckNonZeroSender::::new(), + ), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index 69301b34fe6b..5e768d5040a2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -82,7 +82,10 @@ fn construct_extrinsic( ) -> UncheckedExtrinsic { let account_id = AccountId32::from(sender.public()); let tx_ext: TxExtension = ( - frame_system::CheckNonZeroSender::::new(), + ( + frame_system::AuthorizeCall::::new(), + frame_system::CheckNonZeroSender::::new(), + ), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index c3e105a84fb6..20a1090dfad7 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -734,6 +734,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index f661a8bdccfe..004cc472ce0b 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -89,6 +89,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs index 31700c2e25ff..6ccc85cf5438 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/lib.rs @@ -101,6 +101,7 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( frame_system::CheckNonZeroSender, + frame_system::AuthorizeCall, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs index 1f0f54884fa8..1010700a80fb 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/lib.rs @@ -100,6 +100,7 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs index fdf467ab64b8..7f6c2ee87f62 100644 --- a/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/glutton/glutton-westend/src/lib.rs @@ -292,6 +292,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, pallet_sudo::CheckOnlySudoAccount, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs index 25356a84806d..a946df798fcf 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/lib.rs @@ -93,6 +93,7 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs index 1c5183636c49..84b9f222fcb2 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/lib.rs @@ -93,6 +93,7 @@ pub type BlockId = generic::BlockId; /// The transactionExtension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index b51670c792d6..93a4469af6b0 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -132,6 +132,7 @@ pub type AssetId = u32; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 42556e0b493c..2f07123e49c2 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -658,6 +658,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/cumulus/test/client/src/lib.rs b/cumulus/test/client/src/lib.rs index 863a8fa93f6f..337b71430ca8 100644 --- a/cumulus/test/client/src/lib.rs +++ b/cumulus/test/client/src/lib.rs @@ -136,6 +136,7 @@ pub fn generate_extrinsic_with_pair( BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -152,7 +153,7 @@ pub fn generate_extrinsic_with_pair( let raw_payload = SignedPayload::from_raw( function.clone(), tx_ext.clone(), - ((), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), + ((), (), VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| origin.sign(e)); diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index b1649c410581..9d1769abc94d 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -373,6 +373,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckGenesis, diff --git a/cumulus/test/service/src/lib.rs b/cumulus/test/service/src/lib.rs index 9234442d399c..18289911dfcf 100644 --- a/cumulus/test/service/src/lib.rs +++ b/cumulus/test/service/src/lib.rs @@ -968,6 +968,7 @@ pub fn construct_extrinsic( .unwrap_or(2) as u64; let tip = 0; let tx_ext: runtime::TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckGenesis::::new(), @@ -984,7 +985,7 @@ pub fn construct_extrinsic( let raw_payload = runtime::SignedPayload::from_raw( function.clone(), tx_ext.clone(), - ((), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), + ((), (), runtime::VERSION.spec_version, genesis_block, current_block_hash, (), (), (), ()), ); let signature = raw_payload.using_encoded(|e| caller.sign(e)); runtime::UncheckedExtrinsic::new_signed( diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs index 0cf16edc03cc..c34bf9799b0f 100644 --- a/polkadot/node/service/src/benchmarking.rs +++ b/polkadot/node/service/src/benchmarking.rs @@ -143,6 +143,7 @@ fn westend_sign_call( use westend_runtime as runtime; let tx_ext: runtime::TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -162,6 +163,7 @@ fn westend_sign_call( call.clone(), tx_ext.clone(), ( + (), (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, @@ -198,6 +200,7 @@ fn rococo_sign_call( use sp_core::Pair; let tx_ext: runtime::TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -217,6 +220,7 @@ fn rococo_sign_call( call.clone(), tx_ext.clone(), ( + (), (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs index 6e09bb9e4310..d3b54047ef0e 100644 --- a/polkadot/node/test/service/src/lib.rs +++ b/polkadot/node/test/service/src/lib.rs @@ -415,6 +415,7 @@ pub fn construct_extrinsic( BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let tip = 0; let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -429,6 +430,7 @@ pub fn construct_extrinsic( function.clone(), tx_ext.clone(), ( + (), (), VERSION.spec_version, VERSION.transaction_version, diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 514b9d69bc09..795bcb61c74a 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -651,6 +651,7 @@ where .saturating_sub(1); let tip = 0; let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -704,6 +705,7 @@ where { fn create_extension() -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -1611,6 +1613,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 873c3426c6f3..e21731f6176e 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -203,6 +203,7 @@ where { fn create_extension() -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -450,6 +451,7 @@ where let current_block = System::block_number().saturated_into::().saturating_sub(1); let tip = 0; let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -842,6 +844,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 22bb144565a8..bfbfb0a95ebb 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -911,6 +911,7 @@ where .saturating_sub(1); let tip = 0; let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -953,6 +954,7 @@ where { fn create_extension() -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -1819,6 +1821,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 26ea226313f0..0cc3682a0432 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -30,6 +30,7 @@ use sp_runtime::{generic, traits::MaybeEquivalence, AccountId32, BuildStorage}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/substrate/bin/node/cli/src/service.rs b/substrate/bin/node/cli/src/service.rs index 5cde85ae5790..82645d6d9fd6 100644 --- a/substrate/bin/node/cli/src/service.rs +++ b/substrate/bin/node/cli/src/service.rs @@ -122,6 +122,7 @@ pub fn create_extrinsic( let tip = 0; let tx_ext: kitchensink_runtime::TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -144,6 +145,7 @@ pub fn create_extrinsic( function.clone(), tx_ext.clone(), ( + (), (), kitchensink_runtime::VERSION.spec_version, kitchensink_runtime::VERSION.transaction_version, @@ -1050,6 +1052,7 @@ mod tests { value: amount, }); + let authorize_call = frame_system::AuthorizeCall::new(); let check_non_zero_sender = frame_system::CheckNonZeroSender::new(); let check_spec_version = frame_system::CheckSpecVersion::new(); let check_tx_version = frame_system::CheckTxVersion::new(); @@ -1062,6 +1065,7 @@ mod tests { ); let metadata_hash = frame_metadata_hash_extension::CheckMetadataHash::new(false); let tx_ext: TxExtension = ( + authorize_call, check_non_zero_sender, check_spec_version, check_tx_version, @@ -1076,6 +1080,7 @@ mod tests { function, tx_ext, ( + (), (), spec_version, transaction_version, diff --git a/substrate/bin/node/cli/tests/submit_transaction.rs b/substrate/bin/node/cli/tests/submit_transaction.rs index 3672432ae342..3d486030fea8 100644 --- a/substrate/bin/node/cli/tests/submit_transaction.rs +++ b/substrate/bin/node/cli/tests/submit_transaction.rs @@ -132,7 +132,7 @@ fn should_submit_signed_twice_from_the_same_account() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.0.preamble.to_signed().unwrap().2; - extra.5 + extra.6 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); @@ -181,7 +181,7 @@ fn should_submit_signed_twice_from_all_accounts() { let s = state.read(); fn nonce(tx: UncheckedExtrinsic) -> frame_system::CheckNonce { let extra = tx.0.preamble.to_signed().unwrap().2; - extra.5 + extra.6 } let nonce1 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[0]).unwrap()); let nonce2 = nonce(UncheckedExtrinsic::decode(&mut &*s.transactions[1]).unwrap()); diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index b537072630db..f3652fe7b6aa 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1517,6 +1517,7 @@ where .saturating_sub(1); let era = Era::mortal(period, current_block); let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -1574,6 +1575,7 @@ where { fn create_extension() -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -2679,6 +2681,7 @@ pub type BlockId = generic::BlockId; /// /// [`sign`]: <../../testing/src/keyring.rs.html> pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, @@ -2702,6 +2705,7 @@ impl EthExtra for EthExtraImpl { fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), diff --git a/substrate/bin/node/testing/src/keyring.rs b/substrate/bin/node/testing/src/keyring.rs index e5b0299f01a8..92d9c541ccf5 100644 --- a/substrate/bin/node/testing/src/keyring.rs +++ b/substrate/bin/node/testing/src/keyring.rs @@ -75,6 +75,7 @@ pub fn session_keys_from_seed(seed: &str) -> SessionKeys { /// Returns transaction extra. pub fn tx_ext(nonce: Nonce, extra_fee: Balance) -> TxExtension { ( + frame_system::AuthorizeCall::new(), frame_system::CheckNonZeroSender::new(), frame_system::CheckSpecVersion::new(), frame_system::CheckTxVersion::new(), diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs index 3841b010325b..aaafade65826 100644 --- a/substrate/frame/executive/src/tests.rs +++ b/substrate/frame/executive/src/tests.rs @@ -448,6 +448,7 @@ parameter_types! { } type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, @@ -556,6 +557,7 @@ impl MultiStepMigrator for MockedModeGetter { fn tx_ext(nonce: u64, fee: Balance) -> TxExtension { ( + frame_system::AuthorizeCall::::new(), frame_system::CheckEra::from(Era::Immortal), frame_system::CheckNonce::from(nonce), frame_system::CheckWeight::new(), diff --git a/substrate/frame/metadata-hash-extension/src/tests.rs b/substrate/frame/metadata-hash-extension/src/tests.rs index 11a3345ee15c..257d2d321008 100644 --- a/substrate/frame/metadata-hash-extension/src/tests.rs +++ b/substrate/frame/metadata-hash-extension/src/tests.rs @@ -134,6 +134,7 @@ mod docs { /// The `TransactionExtension` to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/substrate/frame/src/lib.rs b/substrate/frame/src/lib.rs index 0ca36ca8545a..3980189f4e90 100644 --- a/substrate/frame/src/lib.rs +++ b/substrate/frame/src/lib.rs @@ -477,6 +477,7 @@ pub mod runtime { /// /// crucially, this does NOT contain any tx-payment extension. pub type SystemTransactionExtensionsOf = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs index 7b8449f2abe4..f5360ae5c43b 100644 --- a/templates/minimal/runtime/src/lib.rs +++ b/templates/minimal/runtime/src/lib.rs @@ -101,6 +101,8 @@ pub fn native_version() -> NativeVersion { /// The transaction extensions that are added to the runtime. type TxExtension = ( + // Authorize calls that validate themselves. + frame_system::AuthorizeCall, // Checks that the sender is not the zero address. frame_system::CheckNonZeroSender, // Checks that the runtime version is correct. diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 43e76dba0591..3c81d60d85ac 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -75,6 +75,7 @@ pub type BlockId = generic::BlockId; /// The extension to the basic transaction logic. #[docify::export(template_signed_extra)] pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, diff --git a/templates/solochain/node/src/benchmarking.rs b/templates/solochain/node/src/benchmarking.rs index 0d60230cd19c..c588563d4824 100644 --- a/templates/solochain/node/src/benchmarking.rs +++ b/templates/solochain/node/src/benchmarking.rs @@ -110,6 +110,7 @@ pub fn create_benchmark_extrinsic( .map(|c| c / 2) .unwrap_or(2) as u64; let tx_ext: runtime::TxExtension = ( + frame_system::AuthorizeCall::::new(), frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), @@ -128,6 +129,7 @@ pub fn create_benchmark_extrinsic( call.clone(), tx_ext.clone(), ( + (), (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index ae0ea16ae42e..03529e503071 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -148,6 +148,7 @@ pub type BlockId = generic::BlockId; /// The `TransactionExtension` to the basic transaction logic. pub type TxExtension = ( + frame_system::AuthorizeCall, frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, From acd4282db2c98eb1114b1cfc90a4cbb4aa4a14c4 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 22 Nov 2024 11:34:08 +0900 Subject: [PATCH 14/32] update doc + example weight is zero --- substrate/frame/examples/kitchensink/src/weights.rs | 4 ---- substrate/frame/support/procedural/src/lib.rs | 10 ++++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/substrate/frame/examples/kitchensink/src/weights.rs b/substrate/frame/examples/kitchensink/src/weights.rs index fd630f68d082..f52a10e828f3 100644 --- a/substrate/frame/examples/kitchensink/src/weights.rs +++ b/substrate/frame/examples/kitchensink/src/weights.rs @@ -70,11 +70,9 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(1)) } fn set_foo_using_authorize() -> Weight { - // TODO TODO: Weight::zero() } fn authorize_set_foo_using_authorize() -> Weight { - // TODO TODO: Weight::zero() } } @@ -92,11 +90,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1)) } fn set_foo_using_authorize() -> Weight { - // TODO TODO: Weight::zero() } fn authorize_set_foo_using_authorize() -> Weight { - // TODO TODO: Weight::zero() } } diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 2654c78b821f..544417f46cca 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1480,10 +1480,12 @@ pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { /// /// See [`frame_support_procedural::authorize`] for more information on how authorization works. /// -/// # Example: -/// ``` -/// // TODO TODO: copy paste -/// ``` +/// Defines the value of the weight of the authorize function. This attribute is similar to +/// `#[pallet::weight]`: +/// * it can be ignore in `dev_mode` +/// * it can be automatically infered from weight info. For the call `foo` the function +/// `authorize_foo` in the weight info will be used. +/// * it can be a fixed value like `Weight::from_all(0)` (not recommended in production). #[proc_macro_attribute] pub fn weight_of_authorize(_: TokenStream, _: TokenStream) -> TokenStream { pallet_macro_stub() From 6b65245c9a00e4381a88b3f9e6d9598705eb7dfd Mon Sep 17 00:00:00 2001 From: gui Date: Mon, 2 Dec 2024 10:03:17 +0900 Subject: [PATCH 15/32] fmt --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 5 +---- .../runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs | 5 +---- substrate/frame/examples/kitchensink/src/benchmarking.rs | 3 ++- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index f97dd206f8c4..eb37cab38739 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -126,10 +126,7 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( // `Debug` is implemented for tuple of at most 12 elements, so we group extensions. - ( - frame_system::AuthorizeCall, - frame_system::CheckNonZeroSender, - ), + (frame_system::AuthorizeCall, frame_system::CheckNonZeroSender), frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index c8b5df778723..bba94b7f8e2e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -122,10 +122,7 @@ pub type BlockId = generic::BlockId; /// The TransactionExtension to the basic transaction logic. pub type TxExtension = ( // `Debug` is implemented for tuple of at most 12 elements, so we group extensions. - ( - frame_system::AuthorizeCall, - frame_system::CheckNonZeroSender, - ), + (frame_system::AuthorizeCall, frame_system::CheckNonZeroSender), frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, diff --git a/substrate/frame/examples/kitchensink/src/benchmarking.rs b/substrate/frame/examples/kitchensink/src/benchmarking.rs index 354ddcd37cb9..57594b5aa64b 100644 --- a/substrate/frame/examples/kitchensink/src/benchmarking.rs +++ b/substrate/frame/examples/kitchensink/src/benchmarking.rs @@ -94,7 +94,8 @@ mod benchmarks { // `cargo test -p pallet-example-kitchensink --all-features`, you will see one line per case: // `test benchmarking::bench_set_foo_benchmark ... ok` // `test benchmarking::bench_set_foo_using_authorize_benchmark ... ok` in the result. - // `test benchmarking::bench_authorize_set_foo_using_authorize_benchmark ... ok` in the result. + // `test benchmarking::bench_authorize_set_foo_using_authorize_benchmark ... ok` in the + // result. // // The line generates three steps per benchmark, with repeat=1 and the three steps are // [low, mid, high] of the range. From 743835c08f1a0a8715e57c872dd9c827a83b2da6 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 4 Dec 2024 11:20:01 +0900 Subject: [PATCH 16/32] do not leak runtime-benchmark feature in dev build --- substrate/frame/support/procedural/Cargo.toml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 030606fe28f8..708ef4dac7a9 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -42,12 +42,14 @@ sp-metadata-ir = { workspace = true } scale-info = { features = ["derive"], workspace = true } sp-core = { workspace = true } sp-io = { workspace = true } -sp-runtime = { features = ["runtime-benchmarks", "serde"], workspace = true } -frame-system = { workspace = true, features = ["runtime-benchmarks"] } -frame-support = { workspace = true, features = ["runtime-benchmarks"] } -frame-benchmarking = { workspace = true } +sp-runtime = { features = [ + "serde" +], workspace = true } +frame-system = { workspace = true } +frame-support = { workspace = true } pretty_assertions = { workspace = true } static_assertions = { workspace = true } +frame-benchmarking = { workspace = true } [features] default = ["std"] From 7d0898550d27b8010403270330d5856669f0df60 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 4 Dec 2024 11:21:51 +0900 Subject: [PATCH 17/32] minor --- substrate/frame/support/procedural/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 708ef4dac7a9..9727d4e713ac 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -43,7 +43,7 @@ scale-info = { features = ["derive"], workspace = true } sp-core = { workspace = true } sp-io = { workspace = true } sp-runtime = { features = [ - "serde" + "serde", ], workspace = true } frame-system = { workspace = true } frame-support = { workspace = true } From 83873c6ca4d78d5321cb74467bcd40b817eaa43d Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 4 Dec 2024 11:28:53 +0900 Subject: [PATCH 18/32] taplo --- substrate/frame/support/procedural/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/Cargo.toml b/substrate/frame/support/procedural/Cargo.toml index 9727d4e713ac..0a372a53fa38 100644 --- a/substrate/frame/support/procedural/Cargo.toml +++ b/substrate/frame/support/procedural/Cargo.toml @@ -55,6 +55,7 @@ frame-benchmarking = { workspace = true } default = ["std"] std = [ "codec/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", "scale-info/std", @@ -63,7 +64,6 @@ std = [ "sp-io/std", "sp-metadata-ir/std", "sp-runtime/std", - "frame-benchmarking/std", ] no-metadata-docs = [] experimental = [] From f62152a958fc3fe610454a48f7f9075a2739a7c6 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 4 Dec 2024 11:42:56 +0900 Subject: [PATCH 19/32] cannot link to dev dependencies --- substrate/frame/support/procedural/src/lib.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 544417f46cca..92928d983b1f 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1343,16 +1343,16 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream /// /// This attribute allows to specify a special validation logic for a specific call. /// A general transaction with this specific call can then be validated by the given function, -/// and if valid then dispatched with the origin [`frame_system::Origin::Authorized`]. +/// and if valid then dispatched with the origin `frame_system::Origin::Authorized`. /// /// To ensure the origin of the call is the authorization process, the call must check the origin -/// with [`frame_system::ensure_authorized`] function. +/// with `frame_system::ensure_authorized` function. /// /// To enable the authorization process on the extrinsic, the runtime must use -/// [`frame_system::AuthorizeCall`] transaction extension in the transaction extension pipeline. +/// `frame_system::AuthorizeCall` transaction extension in the transaction extension pipeline. /// /// To enable the creation of authorized call from offchain worker. The runtime should implement -/// [`frame_system::CreateAuthorizedTransaction`]. This trait allows to specify which transaction +/// `frame_system::CreateAuthorizedTransaction`. This trait allows to specify which transaction /// extension to use when creating a transaction for an authorized call. /// /// # Usage in the pallet @@ -1444,9 +1444,9 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream /// Authorize process comes with 2 attributes macro on top of the authorized call: /// /// * `#[pallet::authorize($authorized_function)]` - defines the function that authorizes the call. -/// First argument is the transaction source [`frame_support::pallet_prelude::TransactionSource`] +/// First argument is the transaction source `TransactionSource` /// then followed by the same as call arguments but by reference `&`. Return type is -/// [`TransactionValidityWithRefund`](frame_support::pallet_prelude::TransactionValidityWithRefund). +/// `TransactionValidityWithRefund`. /// * `#[pallet::weight_of_authorize($weight)]` - defines the value of the weight of the authorize /// function. This attribute is similar to `#[pallet::weight]`: /// * it can be ignore in `dev_mode` @@ -1457,19 +1457,19 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream /// The weight must be small enough so that nodes don't get DDOS by validating transactions. /// /// Then in the call it must be ensured that the origin is the authorization process. This can -/// be done using [`frame_system::ensure_authorized`] function. +/// be done using `frame_system::ensure_authorized` function. /// /// # The macro expansion /// /// From the given "authorize" function and weight, the macro will implement the trait -/// [`Authorize`](frame_support::pallet_prelude::Authorize) on the call. +/// `Authorize` on the call. /// /// # How to benchmark /// /// The authorize function is used as the implementation of the trait -/// [`Authorize`](frame_support::pallet_prelude::Authorize) for the call. +/// `Authorize` for the call. /// To benchmark a call variant, use the function -/// [`Authorize::authorize`](frame_support::pallet_prelude::Authorize) on a call value. +/// `Authorize::authorize` on a call value. /// See the example in the first section. #[proc_macro_attribute] pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { From 33646e72308bbb791cf719bb9f6f074ca9fdd016 Mon Sep 17 00:00:00 2001 From: gui Date: Wed, 4 Dec 2024 12:05:58 +0900 Subject: [PATCH 20/32] clippy --- substrate/frame/support/procedural/src/lib.rs | 5 ++--- substrate/frame/support/test/tests/authorize.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 92928d983b1f..2877075a8ddb 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1444,9 +1444,8 @@ pub fn dynamic_aggregated_params_internal(attrs: TokenStream, input: TokenStream /// Authorize process comes with 2 attributes macro on top of the authorized call: /// /// * `#[pallet::authorize($authorized_function)]` - defines the function that authorizes the call. -/// First argument is the transaction source `TransactionSource` -/// then followed by the same as call arguments but by reference `&`. Return type is -/// `TransactionValidityWithRefund`. +/// First argument is the transaction source `TransactionSource` then followed by the same as call +/// arguments but by reference `&`. Return type is `TransactionValidityWithRefund`. /// * `#[pallet::weight_of_authorize($weight)]` - defines the value of the weight of the authorize /// function. This attribute is similar to `#[pallet::weight]`: /// * it can be ignore in `dev_mode` diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index a7d7e9202f12..9f1089e3b05c 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -102,7 +102,7 @@ pub mod pallet1 { longevity: *e, propagate: *f, }; - Ok((valid, authorize_refund.clone())) + Ok((valid, *authorize_refund)) } else { Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) } From 2bc6d0ca3188318a6d5df6d6b789a6462dffe883 Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 09:28:18 +0900 Subject: [PATCH 21/32] fix tests and doc --- substrate/frame/support/procedural/src/lib.rs | 2 +- substrate/frame/support/test/tests/authorize.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 2877075a8ddb..090c166e8094 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1477,7 +1477,7 @@ pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { /// Allows to define the weight of the authorize function. /// -/// See [`frame_support_procedural::authorize`] for more information on how authorization works. +/// See `frame_support_procedural::authorize` for more information on how authorization works. /// /// Defines the value of the weight of the authorize function. This attribute is similar to /// `#[pallet::weight]`: diff --git a/substrate/frame/support/test/tests/authorize.rs b/substrate/frame/support/test/tests/authorize.rs index 9f1089e3b05c..345b1cc46ad9 100644 --- a/substrate/frame/support/test/tests/authorize.rs +++ b/substrate/frame/support/test/tests/authorize.rs @@ -144,7 +144,7 @@ pub mod pallet1 { #[cfg(feature = "frame-feature-testing")] #[pallet::call_index(3)] - #[pallet::authorize(|_source| Ok(ValidTransaction::default()))] + #[pallet::authorize(|_source| Ok((ValidTransaction::default(), Weight::zero())))] #[pallet::weight_of_authorize(CALL_4_AUTH_WEIGHT)] #[pallet::weight(CALL_4_WEIGHT)] pub fn call4(origin: OriginFor) -> DispatchResult { @@ -395,7 +395,7 @@ fn valid_call_weight_test() { dispatch_success: true, call_weight: pallet1::CALL_4_WEIGHT, ext_weight: pallet1::CALL_4_AUTH_WEIGHT, - actual_weight: pallet1::CALL_4_WEIGHT + pallet3::CALL_4_AUTH_WEIGHT, + actual_weight: pallet1::CALL_4_WEIGHT + pallet1::CALL_4_AUTH_WEIGHT, }, ]; From d040d4f3ab8dcc9287ff7eec320a7b8f7bf74fc5 Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 09:55:52 +0900 Subject: [PATCH 22/32] rustdoc --- substrate/frame/support/src/traits/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/src/traits/dispatch.rs b/substrate/frame/support/src/traits/dispatch.rs index a8680c9bc42e..9ac1635668d3 100644 --- a/substrate/frame/support/src/traits/dispatch.rs +++ b/substrate/frame/support/src/traits/dispatch.rs @@ -570,7 +570,7 @@ pub trait OriginTrait: Sized { /// A trait to allow calls to authorize themselves from origin `None`. /// /// It is usually implemented by the [`crate::pallet`] macro and used by the -/// [`frame_system::AuthorizeCall`] transaction extension. +/// `frame_system::AuthorizeCall` transaction extension. pub trait Authorize { /// The authorize function. /// From e538e29d1d96e26f698aa9429756f7010bcfe2bf Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 16:28:25 +0900 Subject: [PATCH 23/32] rustdoc --- substrate/frame/support/procedural/src/lib.rs | 2 +- substrate/frame/system/src/offchain.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index 090c166e8094..ee2648c43c9b 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -1477,7 +1477,7 @@ pub fn authorize(_: TokenStream, _: TokenStream) -> TokenStream { /// Allows to define the weight of the authorize function. /// -/// See `frame_support_procedural::authorize` for more information on how authorization works. +/// See [`authorize`](macro@authorize) for more information on how authorization works. /// /// Defines the value of the weight of the authorize function. This attribute is similar to /// `#[pallet::weight]`: diff --git a/substrate/frame/system/src/offchain.rs b/substrate/frame/system/src/offchain.rs index 73ba5d58d976..3a911cb7eda8 100644 --- a/substrate/frame/system/src/offchain.rs +++ b/substrate/frame/system/src/offchain.rs @@ -522,16 +522,16 @@ pub trait SignMessage { /// This interface allows to define the transaction extension that will be used alongside this call /// to create the transaction. /// -/// For more information about authorized call see [`frame_support::pallet::authorized`]. +/// For more information about authorized call see [`frame_support::pallet_prelude::authorize`]. pub trait CreateAuthorizedTransaction: CreateTransaction { /// Create the transaction extension to be used alongside an authorized call. /// - /// For more information about authorized call see [`frame_support::pallet::authorized`]. + /// For more information about authorized call see [`frame_support::pallet_prelude::authorize`]. fn create_extension() -> Self::Extension; /// Create a new transaction for an authorized call. /// - /// For more information about authorized call see [`frame_support::pallet::authorized`]. + /// For more information about authorized call see [`frame_support::pallet_prelude::authorize`]. fn create_authorized_transaction(call: Self::RuntimeCall) -> Self::Extrinsic { Self::create_transaction(call, Self::create_extension()) } From 3a757e8357e001ae291a4f2731015695cd23e1d1 Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 16:28:41 +0900 Subject: [PATCH 24/32] fix span for split feature --- substrate/frame/support/procedural/src/pallet/expand/call.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs index cab5b46819ac..cf7305052146 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/call.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs @@ -296,6 +296,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { &format!("__macro_inner_authorize_call_for_{}", method.name), authorize_fn.span(), ); + let source = syn::Ident::new("source", span); let typed_authorize_fn = quote::quote_spanned!(authorize_fn.span() => { // Closure don't have a writable type. So we fix the authorize token stream to @@ -320,7 +321,7 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream { // `source` is from outside this block, so we can't use the authorize_fn span. quote::quote!( let authorize_fn = #typed_authorize_fn; - let res = authorize_fn(source, #( #arg_name, )*); + let res = authorize_fn(#source, #( #arg_name, )*); Some(res) ) From 0946d798f2118496745c59d6e023c6c71c229e63 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 5 Dec 2024 08:12:22 +0000 Subject: [PATCH 25/32] Update from gui1117 running command 'update-ui' --- .../deprecated_where_block.stderr | 8 ++++---- .../tests/pallet_ui/authorize_wrong_closure_6.stderr | 2 +- .../test/tests/pallet_ui/call_invalid_attr.stderr | 2 +- .../test/tests/pallet_ui/call_missing_weight.stderr | 4 +--- .../pallet_ui/call_weight_inherited_invalid4.stderr | 12 ++++++------ .../test/tests/pallet_ui/dev_mode_without_arg.stderr | 4 +--- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 726b09cf54c9..c20e9129faa1 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -433,7 +433,7 @@ error[E0277]: the trait bound `Runtime: Config` is not satisfied note: required by a bound in `frame_system::Call` --> $WORKSPACE/substrate/frame/system/src/lib.rs | - | #[pallet::call] + | #[pallet::call(weight = ::SystemWeightInfo)] | ^^^^ required by this bound in `Call` = note: this error originates in the derive macro `self::sp_api_hidden_includes_construct_runtime::hidden_include::__private::codec::Encode` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -486,7 +486,7 @@ error[E0599]: the method `get_dispatch_info` exists for reference `&Call::SystemWeightInfo)] | ---- doesn't satisfy `frame_system::Call: GetDispatchInfo` | = note: the following trait bounds were not satisfied: @@ -517,7 +517,7 @@ error[E0599]: the method `is_feeless` exists for reference `&Call`, but | ::: $WORKSPACE/substrate/frame/system/src/lib.rs | - | #[pallet::call] + | #[pallet::call(weight = ::SystemWeightInfo)] | ---- doesn't satisfy `frame_system::Call: CheckIfFeeless` | = note: the following trait bounds were not satisfied: @@ -548,7 +548,7 @@ error[E0599]: the method `get_call_name` exists for reference `&Call`, | ::: $WORKSPACE/substrate/frame/system/src/lib.rs | - | #[pallet::call] + | #[pallet::call(weight = ::SystemWeightInfo)] | ---- doesn't satisfy `frame_system::Call: GetCallName` | = note: the following trait bounds were not satisfied: diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr index 0e102d889eb3..7ce24f68719f 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr @@ -12,7 +12,7 @@ error[E0631]: type mismatch in function arguments | = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` - = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-a5d38637172660dc.long-type-4183595103124166336.txt' + = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-ce4bafddabbb422c.long-type-7099819263235326850.txt' = note: consider using `--verbose` to print the full type name to the console help: consider adjusting the signature so it borrows its argument | diff --git a/substrate/frame/support/test/tests/pallet_ui/call_invalid_attr.stderr b/substrate/frame/support/test/tests/pallet_ui/call_invalid_attr.stderr index 1809fcb6ed99..b42697294ec9 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_invalid_attr.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_invalid_attr.stderr @@ -1,4 +1,4 @@ -error: expected one of: `weight`, `call_index`, `feeless_if` +error: expected one of: `weight`, `call_index`, `feeless_if`, `authorize`, `weight_of_authorize` --> tests/pallet_ui/call_invalid_attr.rs:31:13 | 31 | #[pallet::weird_attr] diff --git a/substrate/frame/support/test/tests/pallet_ui/call_missing_weight.stderr b/substrate/frame/support/test/tests/pallet_ui/call_missing_weight.stderr index 555dd426fe29..39b599ebe80e 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_missing_weight.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_missing_weight.stderr @@ -1,6 +1,4 @@ -error: A pallet::call requires either a concrete `#[pallet::weight($expr)]` or an - inherited weight from the `#[pallet:call(weight($type))]` attribute, but - none were given. +error: A pallet::call requires either a concrete `#[pallet::weight($expr)]` or an inherited weight from the `#[pallet:call(weight($type))]` attribute, but none were given. --> tests/pallet_ui/call_missing_weight.rs:34:7 | 34 | pub fn foo(origin: OriginFor) -> DispatchResultWithPostInfo {} diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr index b4c0885507cf..eb06b3674301 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr @@ -1,11 +1,11 @@ error[E0599]: no function or associated item named `foo` found for associated type `::WeightInfo` in the current scope - --> tests/pallet_ui/call_weight_inherited_invalid4.rs:41:10 + --> tests/pallet_ui/call_weight_inherited_invalid4.rs:38:24 | -41 | pub fn foo(_: OriginFor) -> DispatchResult { - | ^^^ function or associated item not found in `::WeightInfo` +38 | #[pallet::call(weight(::WeightInfo))] + | ^ function or associated item not found in `::WeightInfo` error[E0599]: no function or associated item named `foo` found for associated type `::WeightInfo` in the current scope - --> tests/pallet_ui/call_weight_inherited_invalid4.rs:62:10 + --> tests/pallet_ui/call_weight_inherited_invalid4.rs:59:26 | -62 | pub fn foo(_: OriginFor) -> DispatchResult { - | ^^^ function or associated item not found in `::WeightInfo` +59 | #[pallet::call(weight = ::WeightInfo)] + | ^ function or associated item not found in `::WeightInfo` diff --git a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg.stderr b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg.stderr index 5aea7d83a61c..828fd3aeeb91 100644 --- a/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/dev_mode_without_arg.stderr @@ -1,6 +1,4 @@ -error: A pallet::call requires either a concrete `#[pallet::weight($expr)]` or an - inherited weight from the `#[pallet:call(weight($type))]` attribute, but - none were given. +error: A pallet::call requires either a concrete `#[pallet::weight($expr)]` or an inherited weight from the `#[pallet:call(weight($type))]` attribute, but none were given. --> tests/pallet_ui/dev_mode_without_arg.rs:39:7 | 39 | pub fn my_call(_origin: OriginFor) -> DispatchResult { From d60e1709bc49f2248be5ee67f74946549a821540 Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 17:47:14 +0900 Subject: [PATCH 26/32] keep same error message as before --- .../support/procedural/src/pallet/expand/call.rs | 2 +- .../pallet_ui/call_weight_inherited_invalid4.stderr | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/substrate/frame/support/procedural/src/pallet/expand/call.rs b/substrate/frame/support/procedural/src/pallet/expand/call.rs index cf7305052146..13eff2a5f458 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/call.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/call.rs @@ -52,7 +52,7 @@ fn expand_weight( }, CallWeightDef::Inherited(t) => { // Expand `<::WeightInfo>::$prefix$call_name()`. - let n = &syn::Ident::new(&format!("{}{}", prefix, method.name), t.span()); + let n = &syn::Ident::new(&format!("{}{}", prefix, method.name), method.name.span()); quote!({ < #t > :: #n () }) }, } diff --git a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr index eb06b3674301..b4c0885507cf 100644 --- a/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/call_weight_inherited_invalid4.stderr @@ -1,11 +1,11 @@ error[E0599]: no function or associated item named `foo` found for associated type `::WeightInfo` in the current scope - --> tests/pallet_ui/call_weight_inherited_invalid4.rs:38:24 + --> tests/pallet_ui/call_weight_inherited_invalid4.rs:41:10 | -38 | #[pallet::call(weight(::WeightInfo))] - | ^ function or associated item not found in `::WeightInfo` +41 | pub fn foo(_: OriginFor) -> DispatchResult { + | ^^^ function or associated item not found in `::WeightInfo` error[E0599]: no function or associated item named `foo` found for associated type `::WeightInfo` in the current scope - --> tests/pallet_ui/call_weight_inherited_invalid4.rs:59:26 + --> tests/pallet_ui/call_weight_inherited_invalid4.rs:62:10 | -59 | #[pallet::call(weight = ::WeightInfo)] - | ^ function or associated item not found in `::WeightInfo` +62 | pub fn foo(_: OriginFor) -> DispatchResult { + | ^^^ function or associated item not found in `::WeightInfo` From f9cde01cccb97ae634abd4039bf0a869599f4d8a Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 17:52:48 +0900 Subject: [PATCH 27/32] fix test --- substrate/frame/system/src/extensions/authorize_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/system/src/extensions/authorize_call.rs b/substrate/frame/system/src/extensions/authorize_call.rs index 224b864d54dd..3dcab3bb0498 100644 --- a/substrate/frame/system/src/extensions/authorize_call.rs +++ b/substrate/frame/system/src/extensions/authorize_call.rs @@ -273,7 +273,7 @@ mod tests { new_test_ext().execute_with(|| { let tx_ext = (frame_system::AuthorizeCall::::new(),); - let tx = UncheckedExtrinsic::new_signed(call, 42, Default::default(), tx_ext); + let tx = UncheckedExtrinsic::new_signed(call, 42, 42.into(), tx_ext); let info = tx.get_dispatch_info(); let len = tx.using_encoded(|e| e.len()); From 2c905e338b65545eeac21ab4fa22da35692aa251 Mon Sep 17 00:00:00 2001 From: gui Date: Thu, 5 Dec 2024 18:06:36 +0900 Subject: [PATCH 28/32] prdoc bump versions --- prdoc/pr_6324.prdoc | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/prdoc/pr_6324.prdoc b/prdoc/pr_6324.prdoc index 6dcfb64e60ad..9b3987bc05b3 100644 --- a/prdoc/pr_6324.prdoc +++ b/prdoc/pr_6324.prdoc @@ -25,3 +25,51 @@ doc: crates: - name: frame-support bump: major +- name: sp-runtime + bump: minor +- name: frame-executive + bump: none +- name: frame-system + bump: major +- name: frame-benchmarking + bump: minor +- name: frame-support-procedural + bump: major +- name: staging-xcm-builder + bump: none +- name: polkadot-service + bump: major +- name: westend-runtime + bump: major +- name: frame-metadata-hash-extension + bump: none +- name: polkadot-sdk-frame + bump: major +- name: rococo-runtime + bump: major +- name: asset-hub-rococo-runtime + bump: major +- name: asset-hub-westend-runtime + bump: major +- name: bridge-hub-rococo-runtime + bump: major +- name: bridge-hub-westend-runtime + bump: major +- name: collectives-westend-runtime + bump: major +- name: coretime-rococo-runtime + bump: major +- name: coretime-westend-runtime + bump: major +- name: people-rococo-runtime + bump: major +- name: people-westend-runtime + bump: major +- name: penpal-runtime + bump: major +- name: contracts-rococo-runtime + bump: major +- name: glutton-westend-runtime + bump: major +- name: rococo-parachain-runtime + bump: major From 4bc94dd032164f836a5b18e7db0fde27a48fc59c Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 5 Dec 2024 10:21:14 +0000 Subject: [PATCH 29/32] Update from gui1117 running command 'update-ui' --- .../test/tests/pallet_ui/authorize_wrong_closure_6.stderr | 2 +- .../test/tests/pallet_ui/authorize_wrong_weight_info.stderr | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr index 7ce24f68719f..b945706e1851 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr @@ -12,7 +12,7 @@ error[E0631]: type mismatch in function arguments | = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` - = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-ce4bafddabbb422c.long-type-7099819263235326850.txt' + = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-ce4bafddabbb422c.long-type-10504070144385936145.txt' = note: consider using `--verbose` to print the full type name to the console help: consider adjusting the signature so it borrows its argument | diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr index 43fd98da9482..6997dfb2a6b2 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_weight_info.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `authorize_call1` found for associated type `::WeightInfo` in the current scope - --> tests/pallet_ui/authorize_wrong_weight_info.rs:34:26 + --> tests/pallet_ui/authorize_wrong_weight_info.rs:39:10 | -34 | #[pallet::call(weight = T::WeightInfo)] - | ^ function or associated item not found in `::WeightInfo` +39 | pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { + | ^^^^^ function or associated item not found in `::WeightInfo` From 2e756bc526cd81dac439a1ee75c9a4ba3eef6c7d Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 6 Dec 2024 08:54:55 +0900 Subject: [PATCH 30/32] ui test --- .../test/tests/pallet_ui/authorize_wrong_closure_6.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr index b945706e1851..b64321dabb7c 100644 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr +++ b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr @@ -12,7 +12,7 @@ error[E0631]: type mismatch in function arguments | = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` - = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-ce4bafddabbb422c.long-type-10504070144385936145.txt' + = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-f286e3c006f35842.long-type-458005035462757618.txt' = note: consider using `--verbose` to print the full type name to the console help: consider adjusting the signature so it borrows its argument | From c002f10083bbb50a2462abde858093ab282d80e6 Mon Sep 17 00:00:00 2001 From: gui Date: Fri, 6 Dec 2024 09:41:46 +0900 Subject: [PATCH 31/32] remove non deterministic UI test --- .../pallet_ui/authorize_wrong_closure_6.rs | 54 ------------------- .../authorize_wrong_closure_6.stderr | 20 ------- 2 files changed, 74 deletions(-) delete mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs delete mode 100644 substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs deleted file mode 100644 index 44b06ae06f73..000000000000 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.rs +++ /dev/null @@ -1,54 +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. - -#[frame_support::pallet] -mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config(with_default)] - pub trait Config: frame_system::Config { - type WeightInfo: WeightInfo; - } - - pub trait WeightInfo { - } - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::call(weight = T::WeightInfo)] - impl Pallet { - #[pallet::authorize(Pallet::::authorize_call1)] - #[pallet::weight_of_authorize(Weight::zero())] - #[pallet::weight(Weight::zero())] - #[pallet::call_index(0)] - pub fn call1(origin: OriginFor, a: u32) -> DispatchResult { - let _ = origin; - let _ = a; - Ok(()) - } - } - - impl Pallet { - fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { - Ok(Default::default()) - } - } -} - -fn main() {} diff --git a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr b/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr deleted file mode 100644 index b64321dabb7c..000000000000 --- a/substrate/frame/support/test/tests/pallet_ui/authorize_wrong_closure_6.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0631]: type mismatch in function arguments - --> tests/pallet_ui/authorize_wrong_closure_6.rs:36:23 - | -36 | #[pallet::authorize(Pallet::::authorize_call1)] - | ^^^^^^---------------------- - | | - | expected due to this - | return type was inferred to be `fn(TransactionSource, u32) -> Result<(ValidTransaction, Weight), ...> {...::authorize_call1}` here -... -48 | fn authorize_call1(_source: TransactionSource, _a: u32) -> TransactionValidityWithRefund { - | ---------------------------------------------------------------------------------------- found signature defined here - | - = note: expected function signature `for<'a> fn(frame_support::pallet_prelude::TransactionSource, &'a _) -> _` - found function signature `fn(frame_support::pallet_prelude::TransactionSource, _) -> _` - = note: the full name for the type has been written to '$WORKSPACE/target/tests/trybuild/x86_64-unknown-linux-gnu/debug/deps/$CRATE-f286e3c006f35842.long-type-458005035462757618.txt' - = note: consider using `--verbose` to print the full type name to the console -help: consider adjusting the signature so it borrows its argument - | -48 | fn authorize_call1(_source: TransactionSource, _a: &u32) -> TransactionValidityWithRefund { - | + From 36620e140f4292941f6c0e1a9a18e2de58e92964 Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Sun, 8 Dec 2024 12:27:52 +0900 Subject: [PATCH 32/32] Update substrate/frame/support/src/traits/tasks.rs --- substrate/frame/support/src/traits/tasks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/support/src/traits/tasks.rs b/substrate/frame/support/src/traits/tasks.rs index a665403f5a7f..0b5d0c082509 100644 --- a/substrate/frame/support/src/traits/tasks.rs +++ b/substrate/frame/support/src/traits/tasks.rs @@ -57,7 +57,7 @@ pub trait Task: Sized + FullCodec + TypeInfo + Clone + Debug + PartialEq + Eq { /// Performs the work for this particular `Task` variant. fn run(&self) -> Result<(), DispatchError>; - /// Returns the weight of `run` function. + /// Returns the weight of executing this `Task`. fn weight(&self) -> Weight; /// A unique value representing this `Task` within the current pallet. Analogous to