From 3a9606cc053f3ba037271f0660a850f6bcecf983 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Tue, 20 Jul 2021 11:46:05 +0200 Subject: [PATCH 1/6] Estimate call fee --- bin/node/runtime/src/lib.rs | 1 + .../election-provider-multi-phase/src/lib.rs | 19 ++++++++++++++--- .../src/signed.rs | 6 +++--- frame/support/src/traits.rs | 8 +++---- frame/support/src/traits/misc.rs | 21 ++++++++++++++++++- frame/transaction-payment/src/lib.rs | 18 +++++++++++++++- 6 files changed, 61 insertions(+), 12 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 4c8f1a8298704..a860c8319cba5 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -570,6 +570,7 @@ impl pallet_election_provider_multi_phase::BenchmarkingConfig for BenchmarkConfi impl pallet_election_provider_multi_phase::Config for Runtime { type Event = Event; type Currency = Balances; + type EstimateCallFee = TransactionPayment; type SignedPhase = SignedPhase; type UnsignedPhase = UnsignedPhase; type SolutionImprovementThreshold = SolutionImprovementThreshold; diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index e552335d02530..0adf950c1eec7 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -48,7 +48,7 @@ //! //! ### Signed Phase //! -//! In the signed phase, solutions (of type [`RawSolution`]) are submitted and queued on chain. A +//! In the signed phase, solutions (of type [`RawSolution`]) are submitted and queued on chain. A //! deposit is reserved, based on the size of the solution, for the cost of keeping this solution //! on-chain for a number of blocks, and the potential weight of the solution upon being checked. A //! maximum of `pallet::Config::MaxSignedSubmissions` solutions are stored. The queue is always @@ -558,15 +558,21 @@ pub use pallet::*; pub mod pallet { use super::*; use frame_support::pallet_prelude::*; + use frame_support::traits::EstimateCallFee; use frame_system::pallet_prelude::*; #[pallet::config] pub trait Config: frame_system::Config + SendTransactionTypes> { - type Event: From> + IsType<::Event> + TryInto>; + type Event: From> + + IsType<::Event> + + TryInto>; /// Currency type. type Currency: ReservableCurrency + Currency; + /// Something that can predict the fee of a call. + type EstimateCallFee: frame_support::traits::EstimateCallFee, BalanceOf>; + /// Duration of the unsigned phase. #[pallet::constant] type UnsignedPhase: Get; @@ -975,7 +981,14 @@ pub mod pallet { // create the submission let deposit = Self::deposit_for(&solution, size); - let submission = SignedSubmission { who: who.clone(), deposit, solution }; + let reward = { + use sp_runtime::traits::Saturating; + let call = Call::submit(solution.clone(), num_signed_submissions); + let call_fee = T::EstimateCallFee::estimate_call_fee(&call, None.into()); + T::SignedRewardBase::get().saturating_add(call_fee) + }; + + let submission = SignedSubmission { who: who.clone(), deposit, solution, reward }; // insert the submission if the queue has space or it's better than the weakest // eject the weakest if the queue was full diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 1aaf96b8add94..11013e422738f 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -51,6 +51,8 @@ pub struct SignedSubmission { pub deposit: Balance, /// The raw solution itself. pub solution: RawSolution, + /// The reward that should potentially be paid for this solution, if accepted. + pub reward: Balance, } impl Ord @@ -346,10 +348,8 @@ impl Pallet { let SolutionOrSnapshotSize { voters, targets } = Self::snapshot_metadata().unwrap_or_default(); - let reward = T::SignedRewardBase::get(); - while let Some(best) = all_submissions.pop_last() { - let SignedSubmission { solution, who, deposit} = best; + let SignedSubmission { solution, who, deposit, reward } = best; let active_voters = solution.compact.voter_count() as u32; let feasibility_weight = { // defensive only: at the end of signed phase, snapshot will exits. diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index ec47331285ef8..b0924180a6ab6 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -50,13 +50,13 @@ pub use filter::{ mod misc; pub use misc::{ - Len, Get, GetDefault, HandleLifetime, TryDrop, Time, UnixTime, IsType, IsSubType, ExecuteBlock, - SameOrOther, OnNewAccount, OnKilledAccount, OffchainWorker, GetBacking, Backing, ExtrinsicCall, - EnsureInherentsAreFirst, ConstU32, + Backing, ConstU32, EnsureInherentsAreFirst, EstimateCallFee, ExecuteBlock, ExtrinsicCall, Get, + GetBacking, GetDefault, HandleLifetime, IsSubType, IsType, Len, OffchainWorker, + OnKilledAccount, OnNewAccount, SameOrOther, Time, TryDrop, UnixTime, }; mod stored_map; -pub use stored_map::{StoredMap, StorageMapShim}; +pub use stored_map::{StorageMapShim, StoredMap}; mod randomness; pub use randomness::Randomness; diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 9cab2626cd6cb..6e73a53c0a023 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -328,7 +328,7 @@ impl ExtrinsicCall for sp_runtime::testing::TestXt whe } impl ExtrinsicCall -for sp_runtime::generic::UncheckedExtrinsic + for sp_runtime::generic::UncheckedExtrinsic where Extra: sp_runtime::traits::SignedExtension, { @@ -336,3 +336,22 @@ where &self.function } } + +use sp_runtime::traits::Zero; +/// Something that can estimate the fee of a call. +/// +/// Typically, the same pallet that will charge transaction fees will implement this. +pub trait EstimateCallFee { + /// Estimate the fee of this call. + /// + /// The dispatch info and the length is deduced from the call. The post info can optionally be + /// provided. + fn estimate_call_fee(call: &Call, post_info: crate::weights::PostDispatchInfo) -> Balance; +} + +#[cfg(feature = "std")] +impl EstimateCallFee for () { + fn estimate_call_fee(_: &Call, _: crate::weights::PostDispatchInfo) -> Balance { + Zero::zero() + } +} diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 25fce83e69930..d526549d871f5 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -580,7 +580,8 @@ impl sp_std::fmt::Debug for ChargeTransactionPayment { } } -impl SignedExtension for ChargeTransactionPayment where +impl SignedExtension for ChargeTransactionPayment +where BalanceOf: Send + Sync + From + FixedPointOperand, T::Call: Dispatchable, { @@ -642,6 +643,21 @@ impl SignedExtension for ChargeTransactionPayment where } } +use frame_support::traits::EstimateCallFee; +use sp_runtime::traits::Zero; +impl EstimateCallFee> + for Pallet +where + BalanceOf: FixedPointOperand, + T::Call: Dispatchable, +{ + fn estimate_call_fee(call: &AnyCall, post_info: PostDispatchInfo) -> BalanceOf { + let len = call.encoded_size() as u32; + let info = call.get_dispatch_info(); + Self::compute_actual_fee(len, &info, &post_info, Zero::zero()) + } +} + #[cfg(test)] mod tests { use super::*; From 7cbe1890dc0666988a79dfd52dfae3130c90bfb5 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Thu, 22 Jul 2021 09:44:42 +0200 Subject: [PATCH 2/6] More fix --- .../election-provider-multi-phase/src/lib.rs | 30 ++++++++----------- .../election-provider-multi-phase/src/mock.rs | 2 +- .../src/signed.rs | 6 ++-- frame/support/src/traits/misc.rs | 14 ++++----- 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 0adf950c1eec7..a6a9926345145 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -48,7 +48,7 @@ //! //! ### Signed Phase //! -//! In the signed phase, solutions (of type [`RawSolution`]) are submitted and queued on chain. A +//! In the signed phase, solutions (of type [`RawSolution`]) are submitted and queued on chain. A //! deposit is reserved, based on the size of the solution, for the cost of keeping this solution //! on-chain for a number of blocks, and the potential weight of the solution upon being checked. A //! maximum of `pallet::Config::MaxSignedSubmissions` solutions are stored. The queue is always @@ -228,34 +228,31 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; +use frame_election_provider_support::{onchain, ElectionDataProvider, ElectionProvider}; use frame_support::{ dispatch::DispatchResultWithPostInfo, ensure, - traits::{Currency, Get, ReservableCurrency, OnUnbalanced}, + traits::{Currency, Get, OnUnbalanced, ReservableCurrency}, weights::Weight, }; use frame_system::{ensure_none, offchain::SendTransactionTypes}; -use frame_election_provider_support::{ElectionDataProvider, ElectionProvider, onchain}; +use sp_arithmetic::{ + traits::{CheckedAdd, Saturating, Zero}, + UpperOf, +}; use sp_npos_elections::{ - assignment_ratio_to_staked_normalized, CompactSolution, ElectionScore, - EvaluateSupport, PerThing128, Supports, VoteWeight, + assignment_ratio_to_staked_normalized, CompactSolution, ElectionScore, EvaluateSupport, + PerThing128, Supports, VoteWeight, }; use sp_runtime::{ + traits::Bounded, transaction_validity::{ InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, TransactionValidityError, ValidTransaction, }, DispatchError, PerThing, Perbill, RuntimeDebug, SaturatedConversion, - traits::Bounded, -}; -use sp_std::{ - convert::TryInto, - prelude::*, -}; -use sp_arithmetic::{ - UpperOf, - traits::{Zero, CheckedAdd}, }; +use sp_std::{convert::TryInto, prelude::*}; #[cfg(any(feature = "runtime-benchmarks", test))] mod benchmarking; @@ -570,8 +567,8 @@ pub mod pallet { /// Currency type. type Currency: ReservableCurrency + Currency; - /// Something that can predict the fee of a call. - type EstimateCallFee: frame_support::traits::EstimateCallFee, BalanceOf>; + /// Something that can predict the fee of a call. Used to sensibly distribute rewards. + type EstimateCallFee: EstimateCallFee, BalanceOf>; /// Duration of the unsigned phase. #[pallet::constant] @@ -982,7 +979,6 @@ pub mod pallet { // create the submission let deposit = Self::deposit_for(&solution, size); let reward = { - use sp_runtime::traits::Saturating; let call = Call::submit(solution.clone(), num_signed_submissions); let call_fee = T::EstimateCallFee::estimate_call_fee(&call, None.into()); T::SignedRewardBase::get().saturating_add(call_fee) diff --git a/frame/election-provider-multi-phase/src/mock.rs b/frame/election-provider-multi-phase/src/mock.rs index 55fa58590ce71..929ad2a7943f5 100644 --- a/frame/election-provider-multi-phase/src/mock.rs +++ b/frame/election-provider-multi-phase/src/mock.rs @@ -265,7 +265,6 @@ parameter_types! { pub static SignedDepositByte: Balance = 0; pub static SignedDepositWeight: Balance = 0; pub static SignedRewardBase: Balance = 7; - pub static SignedRewardMax: Balance = 10; pub static SignedMaxWeight: Weight = BlockWeights::get().max_block; pub static MinerMaxIterations: u32 = 5; pub static MinerTxPriority: u64 = 100; @@ -360,6 +359,7 @@ impl multi_phase::weights::WeightInfo for DualMockWeightInfo { impl crate::Config for Runtime { type Event = Event; type Currency = Balances; + type EstimateCallFee = frame_support::traits::ConstU32<8>; type SignedPhase = SignedPhase; type UnsignedPhase = UnsignedPhase; type SolutionImprovementThreshold = SolutionImprovementThreshold; diff --git a/frame/election-provider-multi-phase/src/signed.rs b/frame/election-provider-multi-phase/src/signed.rs index 11013e422738f..6a8068e870571 100644 --- a/frame/election-provider-multi-phase/src/signed.rs +++ b/frame/election-provider-multi-phase/src/signed.rs @@ -559,7 +559,7 @@ mod tests { assert_eq!(balances(&99), (95, 5)); assert!(MultiPhase::finalize_signed_phase().0); - assert_eq!(balances(&99), (100 + 7, 0)); + assert_eq!(balances(&99), (100 + 7 + 8, 0)); }) } @@ -608,7 +608,7 @@ mod tests { assert!(MultiPhase::finalize_signed_phase().0); // 99 is rewarded. - assert_eq!(balances(&99), (100 + 7, 0)); + assert_eq!(balances(&99), (100 + 7 + 8, 0)); // 999 gets everything back. assert_eq!(balances(&999), (100, 0)); }) @@ -800,7 +800,7 @@ mod tests { assert!(MultiPhase::finalize_signed_phase().0); // 99 is rewarded. - assert_eq!(balances(&99), (100 + 7, 0)); + assert_eq!(balances(&99), (100 + 7 + 8, 0)); // 999 is slashed. assert_eq!(balances(&999), (95, 0)); // 9999 gets everything back. diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 6e73a53c0a023..349869a948e25 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -17,9 +17,8 @@ //! Smaller traits used in FRAME which don't need their own file. -use sp_runtime::{traits::Block as BlockT, DispatchError}; -use sp_arithmetic::traits::AtLeast32Bit; use crate::dispatch::Parameter; +use sp_runtime::{traits::Block as BlockT, DispatchError}; /// Anything that can have a `::len()` method. pub trait Len { @@ -166,7 +165,7 @@ pub trait HandleLifetime { impl HandleLifetime for () {} pub trait Time { - type Moment: AtLeast32Bit + Parameter + Default + Copy; + type Moment: sp_arithmetic::traits::AtLeast32Bit + Parameter + Default + Copy; fn now() -> Self::Moment; } @@ -284,7 +283,7 @@ pub trait OffchainWorker { fn offchain_worker(_n: BlockNumber) {} } -/// Some amount of backing from a group. The precise defintion of what it means to "back" something +/// Some amount of backing from a group. The precise definition of what it means to "back" something /// is left flexible. pub struct Backing { /// The number of members of the group that back some motion. @@ -337,8 +336,7 @@ where } } -use sp_runtime::traits::Zero; -/// Something that can estimate the fee of a call. +/// Something that can estimate the fee of a (frame-based) call. /// /// Typically, the same pallet that will charge transaction fees will implement this. pub trait EstimateCallFee { @@ -350,8 +348,8 @@ pub trait EstimateCallFee { } #[cfg(feature = "std")] -impl EstimateCallFee for () { +impl, const T: u32> EstimateCallFee for ConstU32 { fn estimate_call_fee(_: &Call, _: crate::weights::PostDispatchInfo) -> Balance { - Zero::zero() + T.into() } } From 40eb200da0bbbd1775114e2c738ff2708542a70d Mon Sep 17 00:00:00 2001 From: kianenigma Date: Thu, 22 Jul 2021 12:24:19 +0200 Subject: [PATCH 3/6] Fix --- frame/transaction-payment/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index f22dcfc278b72..61de183dac1b8 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -52,7 +52,7 @@ use codec::{Decode, Encode}; use sp_runtime::{ traits::{ Convert, DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating, - SignedExtension, + SignedExtension, Zero, }, transaction_validity::{ TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction, @@ -63,7 +63,7 @@ use sp_std::prelude::*; use frame_support::{ dispatch::DispatchResult, - traits::Get, + traits::{EstimateCallFee, Get}, weights::{ DispatchClass, DispatchInfo, GetDispatchInfo, Pays, PostDispatchInfo, Weight, WeightToFeeCoefficient, WeightToFeePolynomial, @@ -656,8 +656,6 @@ where } } -use frame_support::traits::EstimateCallFee; -use sp_runtime::traits::Zero; impl EstimateCallFee> for Pallet where From 6c292667a15d17d51a8d3c7271e09c792140121a Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Fri, 23 Jul 2021 09:08:50 +0200 Subject: [PATCH 4/6] Update frame/support/src/traits/misc.rs Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com> --- frame/support/src/traits/misc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index 2469554f13772..382c5ebf57134 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -369,6 +369,7 @@ pub trait EstimateCallFee { fn estimate_call_fee(call: &Call, post_info: crate::weights::PostDispatchInfo) -> Balance; } +// Useful for building mocks. #[cfg(feature = "std")] impl, const T: u32> EstimateCallFee for ConstU32 { fn estimate_call_fee(_: &Call, _: crate::weights::PostDispatchInfo) -> Balance { From efaf1ec224ee2ce6dc557b52a2ad844a50467c2d Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 23 Jul 2021 10:15:46 +0200 Subject: [PATCH 5/6] try and fix fmt stuff --- frame/election-provider-multi-phase/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 8fa9969cdcb83..4869733740242 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -1333,10 +1333,7 @@ impl Pallet { debug_assert!(buffer.len() == size && size == buffer.capacity()); sp_io::storage::set(&>::hashed_key(), &buffer); - Ok(w1 - .saturating_add(w2) - .saturating_add(w3) - .saturating_add(T::DbWeight::get().writes(3))) + Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3))) } /// Kill everything created by [`Pallet::create_snapshot`]. From 2f6bdf4a38bbacac8676d0d7afade512635c34c1 Mon Sep 17 00:00:00 2001 From: kianenigma Date: Fri, 23 Jul 2021 10:22:07 +0200 Subject: [PATCH 6/6] fmt aain --- client/network/src/request_responses.rs | 2 +- frame/election-provider-multi-phase/src/lib.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/network/src/request_responses.rs b/client/network/src/request_responses.rs index 226e1c546d6c9..f51055af55243 100644 --- a/client/network/src/request_responses.rs +++ b/client/network/src/request_responses.rs @@ -788,7 +788,7 @@ pub enum ResponseFailure { /// Implements the libp2p [`RequestResponseCodec`] trait. Defines how streams of bytes are turned /// into requests and responses and vice-versa. #[derive(Debug, Clone)] -#[doc(hidden)] // Needs to be public in order to satisfy the Rust compiler. +#[doc(hidden)]// Needs to be public in order to satisfy the Rust compiler. pub struct GenericCodec { max_request_size: u64, max_response_size: u64, diff --git a/frame/election-provider-multi-phase/src/lib.rs b/frame/election-provider-multi-phase/src/lib.rs index 4869733740242..48504b6073958 100644 --- a/frame/election-provider-multi-phase/src/lib.rs +++ b/frame/election-provider-multi-phase/src/lib.rs @@ -554,8 +554,7 @@ pub use pallet::*; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::pallet_prelude::*; - use frame_support::traits::EstimateCallFee; + use frame_support::{pallet_prelude::*, traits::EstimateCallFee}; use frame_system::pallet_prelude::*; #[pallet::config] @@ -1333,7 +1332,10 @@ impl Pallet { debug_assert!(buffer.len() == size && size == buffer.capacity()); sp_io::storage::set(&>::hashed_key(), &buffer); - Ok(w1.saturating_add(w2).saturating_add(w3).saturating_add(T::DbWeight::get().writes(3))) + Ok(w1 + .saturating_add(w2) + .saturating_add(w3) + .saturating_add(T::DbWeight::get().writes(3))) } /// Kill everything created by [`Pallet::create_snapshot`].