mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-22 16:05:41 +00:00
This PR reverts #2280 which introduced `TransactionExtension` to replace `SignedExtension`. As a result of the discussion [here](https://github.com/paritytech/polkadot-sdk/pull/3623#issuecomment-1986789700), the changes will be reverted for now with plans to reintroduce the concept in the future. --------- Signed-off-by: georgepisaltu <george.pisaltu@parity.io>
This commit is contained in:
@@ -15,19 +15,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{AccountInfo, Config};
|
||||
use crate::Config;
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::dispatch::DispatchInfo;
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::{
|
||||
AsSystemOriginSigner, DispatchInfoOf, Dispatchable, One, TransactionExtension,
|
||||
TransactionExtensionBase, ValidateResult, Zero,
|
||||
},
|
||||
traits::{DispatchInfoOf, Dispatchable, One, SignedExtension, Zero},
|
||||
transaction_validity::{
|
||||
InvalidTransaction, TransactionLongevity, TransactionValidityError, ValidTransaction,
|
||||
InvalidTransaction, TransactionLongevity, TransactionValidity, TransactionValidityError,
|
||||
ValidTransaction,
|
||||
},
|
||||
Saturating,
|
||||
};
|
||||
use sp_std::vec;
|
||||
|
||||
@@ -61,78 +58,75 @@ impl<T: Config> sp_std::fmt::Debug for CheckNonce<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> TransactionExtensionBase for CheckNonce<T> {
|
||||
const IDENTIFIER: &'static str = "CheckNonce";
|
||||
type Implicit = ();
|
||||
fn weight(&self) -> sp_weights::Weight {
|
||||
<T::ExtensionsWeightInfo as super::WeightInfo>::check_nonce()
|
||||
}
|
||||
}
|
||||
impl<T: Config, Context> TransactionExtension<T::RuntimeCall, Context> for CheckNonce<T>
|
||||
impl<T: Config> SignedExtension for CheckNonce<T>
|
||||
where
|
||||
T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
|
||||
<T::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<T::AccountId> + Clone,
|
||||
{
|
||||
type Val = Option<(T::AccountId, AccountInfo<T::Nonce, T::AccountData>)>;
|
||||
type AccountId = T::AccountId;
|
||||
type Call = T::RuntimeCall;
|
||||
type AdditionalSigned = ();
|
||||
type Pre = ();
|
||||
const IDENTIFIER: &'static str = "CheckNonce";
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
origin: <T as Config>::RuntimeOrigin,
|
||||
_call: &T::RuntimeCall,
|
||||
_info: &DispatchInfoOf<T::RuntimeCall>,
|
||||
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pre_dispatch(
|
||||
self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
_context: &mut Context,
|
||||
_self_implicit: Self::Implicit,
|
||||
_inherited_implication: &impl Encode,
|
||||
) -> ValidateResult<Self::Val, T::RuntimeCall> {
|
||||
let Some(who) = origin.as_system_origin_signer() else {
|
||||
return Ok((Default::default(), None, origin))
|
||||
};
|
||||
let account = crate::Account::<T>::get(who);
|
||||
) -> Result<(), TransactionValidityError> {
|
||||
let mut account = crate::Account::<T>::get(who);
|
||||
if account.providers.is_zero() && account.sufficients.is_zero() {
|
||||
// Nonce storage not paid for
|
||||
return Err(InvalidTransaction::Payment.into())
|
||||
}
|
||||
if self.0 != account.nonce {
|
||||
return Err(if self.0 < account.nonce {
|
||||
InvalidTransaction::Stale
|
||||
} else {
|
||||
InvalidTransaction::Future
|
||||
}
|
||||
.into())
|
||||
}
|
||||
account.nonce += T::Nonce::one();
|
||||
crate::Account::<T>::insert(who, account);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate(
|
||||
&self,
|
||||
who: &Self::AccountId,
|
||||
_call: &Self::Call,
|
||||
_info: &DispatchInfoOf<Self::Call>,
|
||||
_len: usize,
|
||||
) -> TransactionValidity {
|
||||
let account = crate::Account::<T>::get(who);
|
||||
if account.providers.is_zero() && account.sufficients.is_zero() {
|
||||
// Nonce storage not paid for
|
||||
return InvalidTransaction::Payment.into()
|
||||
}
|
||||
if self.0 < account.nonce {
|
||||
return Err(InvalidTransaction::Stale.into())
|
||||
return InvalidTransaction::Stale.into()
|
||||
}
|
||||
|
||||
let provides = vec![Encode::encode(&(who.clone(), self.0))];
|
||||
let provides = vec![Encode::encode(&(who, self.0))];
|
||||
let requires = if account.nonce < self.0 {
|
||||
vec![Encode::encode(&(who.clone(), self.0.saturating_sub(One::one())))]
|
||||
vec![Encode::encode(&(who, self.0 - One::one()))]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let validity = ValidTransaction {
|
||||
Ok(ValidTransaction {
|
||||
priority: 0,
|
||||
requires,
|
||||
provides,
|
||||
longevity: TransactionLongevity::max_value(),
|
||||
propagate: true,
|
||||
};
|
||||
|
||||
Ok((validity, Some((who.clone(), account)), origin))
|
||||
}
|
||||
|
||||
fn prepare(
|
||||
self,
|
||||
val: Self::Val,
|
||||
_origin: &T::RuntimeOrigin,
|
||||
_call: &T::RuntimeCall,
|
||||
_info: &DispatchInfoOf<T::RuntimeCall>,
|
||||
_len: usize,
|
||||
_context: &Context,
|
||||
) -> Result<Self::Pre, TransactionValidityError> {
|
||||
let Some((who, mut account)) = val else { return Ok(()) };
|
||||
// `self.0 < account.nonce` already checked in `validate`.
|
||||
if self.0 > account.nonce {
|
||||
return Err(InvalidTransaction::Future.into())
|
||||
}
|
||||
account.nonce.saturating_inc();
|
||||
crate::Account::<T>::insert(who, account);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,8 +134,7 @@ where
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{new_test_ext, Test, CALL};
|
||||
use frame_support::assert_ok;
|
||||
use sp_runtime::traits::DispatchTransaction;
|
||||
use frame_support::{assert_noop, assert_ok};
|
||||
|
||||
#[test]
|
||||
fn signed_ext_check_nonce_works() {
|
||||
@@ -159,33 +152,22 @@ mod tests {
|
||||
let info = DispatchInfo::default();
|
||||
let len = 0_usize;
|
||||
// stale
|
||||
assert_eq!(
|
||||
CheckNonce::<Test>(0)
|
||||
.validate_only(Some(1).into(), CALL, &info, len,)
|
||||
.unwrap_err(),
|
||||
TransactionValidityError::Invalid(InvalidTransaction::Stale)
|
||||
assert_noop!(
|
||||
CheckNonce::<Test>(0).validate(&1, CALL, &info, len),
|
||||
InvalidTransaction::Stale
|
||||
);
|
||||
assert_eq!(
|
||||
CheckNonce::<Test>(0)
|
||||
.validate_and_prepare(Some(1).into(), CALL, &info, len)
|
||||
.unwrap_err(),
|
||||
InvalidTransaction::Stale.into()
|
||||
assert_noop!(
|
||||
CheckNonce::<Test>(0).pre_dispatch(&1, CALL, &info, len),
|
||||
InvalidTransaction::Stale
|
||||
);
|
||||
// correct
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_only(Some(1).into(), CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_and_prepare(
|
||||
Some(1).into(),
|
||||
CALL,
|
||||
&info,
|
||||
len
|
||||
));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate(&1, CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).pre_dispatch(&1, CALL, &info, len));
|
||||
// future
|
||||
assert_ok!(CheckNonce::<Test>(5).validate_only(Some(1).into(), CALL, &info, len));
|
||||
assert_eq!(
|
||||
CheckNonce::<Test>(5)
|
||||
.validate_and_prepare(Some(1).into(), CALL, &info, len)
|
||||
.unwrap_err(),
|
||||
InvalidTransaction::Future.into()
|
||||
assert_ok!(CheckNonce::<Test>(5).validate(&1, CALL, &info, len));
|
||||
assert_noop!(
|
||||
CheckNonce::<Test>(5).pre_dispatch(&1, CALL, &info, len),
|
||||
InvalidTransaction::Future
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -216,44 +198,20 @@ mod tests {
|
||||
let info = DispatchInfo::default();
|
||||
let len = 0_usize;
|
||||
// Both providers and sufficients zero
|
||||
assert_eq!(
|
||||
CheckNonce::<Test>(1)
|
||||
.validate_only(Some(1).into(), CALL, &info, len)
|
||||
.unwrap_err(),
|
||||
TransactionValidityError::Invalid(InvalidTransaction::Payment)
|
||||
assert_noop!(
|
||||
CheckNonce::<Test>(1).validate(&1, CALL, &info, len),
|
||||
InvalidTransaction::Payment
|
||||
);
|
||||
assert_eq!(
|
||||
CheckNonce::<Test>(1)
|
||||
.validate_and_prepare(Some(1).into(), CALL, &info, len)
|
||||
.unwrap_err(),
|
||||
TransactionValidityError::Invalid(InvalidTransaction::Payment)
|
||||
assert_noop!(
|
||||
CheckNonce::<Test>(1).pre_dispatch(&1, CALL, &info, len),
|
||||
InvalidTransaction::Payment
|
||||
);
|
||||
// Non-zero providers
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_only(Some(2).into(), CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_and_prepare(
|
||||
Some(2).into(),
|
||||
CALL,
|
||||
&info,
|
||||
len
|
||||
));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate(&2, CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).pre_dispatch(&2, CALL, &info, len));
|
||||
// Non-zero sufficients
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_only(Some(3).into(), CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_and_prepare(
|
||||
Some(3).into(),
|
||||
CALL,
|
||||
&info,
|
||||
len
|
||||
));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_check_nonce_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let info = DispatchInfo::default();
|
||||
let len = 0_usize;
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_only(None.into(), CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate_and_prepare(None.into(), CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).validate(&3, CALL, &info, len));
|
||||
assert_ok!(CheckNonce::<Test>(1).pre_dispatch(&3, CALL, &info, len));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user