Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(runtime): Fix inability to use vouchers with no balance #3967

Merged
merged 4 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions gsdk/src/metadata/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,6 @@ pub mod runtime_types {
)]
pub struct CheckNonZeroSender;
}
pub mod check_nonce {
use super::runtime_types;
#[derive(
Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode,
)]
pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32);
}
pub mod check_spec_version {
use super::runtime_types;
#[derive(
Expand Down Expand Up @@ -7459,6 +7452,8 @@ pub mod runtime_types {
}
}
#[derive(Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode)]
pub struct CustomCheckNonce(#[codec(compact)] pub ::core::primitive::u32);
#[derive(Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode)]
pub struct NposSolution16 {
pub votes1: ::std::vec::Vec<(
::subxt::ext::codec::Compact<::core::primitive::u32>,
Expand Down
2 changes: 1 addition & 1 deletion node/cli/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ macro_rules! with_signed_payload {
frame_system::CheckMortality::<runtime::Runtime>::from(
sp_runtime::generic::Era::mortal($period, $current_block),
),
frame_system::CheckNonce::<runtime::Runtime>::from($nonce),
runtime::CustomCheckNonce::<runtime::Runtime>::from($nonce),
frame_system::CheckWeight::<runtime::Runtime>::new(),
pallet_gear_payment::CustomChargeTransactionPayment::<runtime::Runtime>::from($tip),
);
Expand Down
6 changes: 3 additions & 3 deletions node/testing/src/keyring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use runtime_primitives::{AccountId, Nonce};
use sp_keyring::{AccountKeyring, Ed25519Keyring, Sr25519Keyring};
use sp_runtime::generic::Era;
use vara_runtime::{
CustomChargeTransactionPayment, RuntimeCall, SessionKeys, SignedExtra, StakingBlackList,
UncheckedExtrinsic,
CustomChargeTransactionPayment, CustomCheckNonce, RuntimeCall, SessionKeys, SignedExtra,
StakingBlackList, UncheckedExtrinsic,
};

pub type CheckedExtrinsic =
Expand Down Expand Up @@ -82,7 +82,7 @@ pub fn signed_extra(nonce: Nonce) -> SignedExtra {
frame_system::CheckTxVersion::new(),
frame_system::CheckGenesis::new(),
frame_system::CheckEra::from(Era::mortal(256, 0)),
frame_system::CheckNonce::from(nonce),
CustomCheckNonce::from(nonce),
frame_system::CheckWeight::new(),
CustomChargeTransactionPayment::from(0),
)
Expand Down
115 changes: 111 additions & 4 deletions runtime/vara/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use frame_election_provider_support::{
bounds::ElectionBoundsBuilder, onchain, ElectionDataProvider, NposSolution, SequentialPhragmen,
VoteWeight,
};
use frame_support::weights::ConstantMultiplier;
pub use frame_support::{
construct_runtime,
dispatch::{DispatchClass, WeighData},
Expand All @@ -52,6 +51,13 @@ pub use frame_support::{
},
PalletId, StorageValue,
};
use frame_support::{
dispatch::DispatchInfo,
pallet_prelude::{
InvalidTransaction, TransactionLongevity, TransactionValidityError, ValidTransaction,
},
weights::ConstantMultiplier,
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot,
Expand Down Expand Up @@ -81,6 +87,7 @@ pub use runtime_common::{
};
pub use runtime_primitives::{AccountId, Signature, VARA_SS58_PREFIX};
use runtime_primitives::{Balance, BlockNumber, Hash, Moment, Nonce};
use scale_info::TypeInfo;
use sp_api::impl_runtime_apis;
#[cfg(any(feature = "std", test))]
use sp_api::{CallApiAt, CallContext, Extensions, OverlayedChanges, ProofRecorder};
Expand All @@ -91,8 +98,8 @@ use sp_runtime::{
codec::{Decode, Encode, MaxEncodedLen},
create_runtime_str, generic, impl_opaque_keys,
traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentityLookup, NumberFor,
OpaqueKeys,
AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, DispatchInfoOf, Dispatchable,
IdentityLookup, NumberFor, One, OpaqueKeys, SignedExtension,
},
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedU128, Perbill, Percent, Permill, Perquintill, RuntimeDebug,
Expand Down Expand Up @@ -1303,7 +1310,7 @@ pub type SignedExtra = (
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
CustomCheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
CustomChargeTransactionPayment<Runtime>,
);
Expand Down Expand Up @@ -1554,3 +1561,103 @@ where
}
}
}

/// Nonce check and increment to give replay protection for transactions.
///
/// # Transaction Validity
///
/// This extension affects `requires` and `provides` tags of validity, but DOES NOT
/// set the `priority` field. Make sure that AT LEAST one of the signed extension sets
/// some kind of priority upon validating transactions.
///
/// NOTE: Copy-paste from substrate/frame/system/src/extensions/check_nonce.rs,
/// but without providers and sufficients checks, so contains revert of changes
/// from substrate v1.3.0 https://github.com/paritytech/polkadot-sdk/pull/1578.
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
#[scale_info(skip_type_params(T))]
pub struct CustomCheckNonce<T: frame_system::Config>(#[codec(compact)] pub T::Nonce);

impl<T: frame_system::Config> CustomCheckNonce<T> {
/// utility constructor. Used only in client/factory code.
pub fn from(nonce: T::Nonce) -> Self {
Self(nonce)
}
}

impl<T: frame_system::Config> sp_std::fmt::Debug for CustomCheckNonce<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CustomCheckNonce({})", self.0)
}

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

impl<T: frame_system::Config> SignedExtension for CustomCheckNonce<T>
where
T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
{
type AccountId = <frame_system::CheckNonce<T> as SignedExtension>::AccountId;
type Call = <frame_system::CheckNonce<T> as SignedExtension>::Call;
type AdditionalSigned = <frame_system::CheckNonce<T> as SignedExtension>::AdditionalSigned;
type Pre = <frame_system::CheckNonce<T> as SignedExtension>::Pre;
const IDENTIFIER: &'static str = <frame_system::CheckNonce<T> as SignedExtension>::IDENTIFIER;

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

fn pre_dispatch(
self,
who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> Result<(), TransactionValidityError> {
let mut account = frame_system::Account::<T>::get(who);

if self.0 != account.nonce {
return Err(if self.0 < account.nonce {
InvalidTransaction::Stale
} else {
InvalidTransaction::Future
}
.into());
}
account.nonce += T::Nonce::one();
frame_system::Account::<T>::insert(who, account);
Ok(())
}

fn validate(
&self,
who: &Self::AccountId,
_call: &Self::Call,
_info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
let account = frame_system::Account::<T>::get(who);

if self.0 < account.nonce {
return InvalidTransaction::Stale.into();
}

let provides = vec![Encode::encode(&(who, self.0))];
let requires = if account.nonce < self.0 {
vec![Encode::encode(&(who, self.0 - One::one()))]
} else {
vec![]
};

Ok(ValidTransaction {
priority: 0,
requires,
provides,
longevity: TransactionLongevity::max_value(),
propagate: true,
})
}
}
Loading