Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Refactor WeightToFee to include ProofSize #215

Merged
merged 14 commits into from
Jun 15, 2023
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", bra
# Substrate Runtime
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }

Expand Down
10 changes: 0 additions & 10 deletions runtime/stout/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,4 @@ pub mod fee {
}]
}
}

pub fn base_tx_fee() -> Balance {
valentinfernandez1 marked this conversation as resolved.
Show resolved Hide resolved
CENTS / 10
}

pub fn default_fee_per_second() -> u128 {
let base_weight = Balance::from(ExtrinsicBaseWeight::get().ref_time());
let base_tx_per_second = (WEIGHT_REF_TIME_PER_SECOND as u128) / base_weight;
base_tx_per_second * base_tx_fee()
}
}
13 changes: 3 additions & 10 deletions runtime/stout/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{constants::fee::default_fee_per_second, AllPalletsWithSystem};
valentinfernandez1 marked this conversation as resolved.
Show resolved Hide resolved
use crate::AllPalletsWithSystem;

use super::{
AccountId, Assets, Balance, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime,
Expand Down Expand Up @@ -192,11 +192,6 @@ parameter_types! {
// Statemine's Assets pallet index
pub StatemineAssetsPalletLocation: MultiLocation =
MultiLocation::new(1, X2(Parachain(1000), PalletInstance(50)));
pub XUsdPerSecond: (AssetId, u128, u128) = (
valentinfernandez1 marked this conversation as resolved.
Show resolved Hide resolved
MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1))).into(),
default_fee_per_second() * 10,
0
);
}

//- From PR https://github.com/paritytech/cumulus/pull/936
Expand Down Expand Up @@ -238,10 +233,8 @@ impl xcm_executor::Config for XcmConfig {
type IsTeleporter = (); // Teleporting is disabled.
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader = (
FixedRateOfFungible<XUsdPerSecond, ()>,
UsingComponents<WeightToFee, SelfReserve, AccountId, Balances, DealWithFees<Runtime>>,
);
type Trader =
UsingComponents<WeightToFee, SelfReserve, AccountId, Balances, DealWithFees<Runtime>>;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetClaims = PolkadotXcm;
Expand Down
1 change: 1 addition & 0 deletions runtime/trappist/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ smallvec = { workspace = true }
# Substrate Dependencies
## Substrate Primitive Dependencies
sp-api = { workspace = true }
sp-arithmetic = { workspace = true }
sp-block-builder = { workspace = true }
sp-consensus-aura = { workspace = true }
sp-core = { workspace = true }
Expand Down
62 changes: 56 additions & 6 deletions runtime/trappist/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,23 @@ pub mod currency {

/// Fee-related.
pub mod fee {
use super::currency::CENTS;
use frame_support::weights::{
constants::{ExtrinsicBaseWeight, WEIGHT_REF_TIME_PER_SECOND},
WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
use polkadot_core_primitives::Balance;
use smallvec::smallvec;

pub use sp_runtime::Perbill;
use sp_runtime::SaturatedConversion;

use crate::impls::WeightCoefficientCalc;

use super::currency::CENTS;

/// The block saturation level. Fees will be updates based on this value.
pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25);

//TODO: Update WeightToFee functionality to match cummulus implementation (Should be done in a
// separated issue)

/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
/// node's balance type.
///
Expand All @@ -58,8 +60,38 @@ pub mod fee {
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
/// - Setting it to `0` will essentially disable the weight fee.
/// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
///
/// TODO: Once the runtime is upgraded to polkadot v0.9.42 or above refactor this using
/// the FeePolynomial struct that already includes the methods to make this calculations
/// and remove the custom WeightCoefficientCalc inside ./trappist/src/impls.rs
pub struct WeightToFee;
impl WeightToFeePolynomial for WeightToFee {
impl frame_support::weights::WeightToFee for WeightToFee {
type Balance = Balance;

fn weight_to_fee(weight: &Weight) -> Self::Balance {
let ref_poly: smallvec::SmallVec<[WeightToFeeCoefficient<Balance>; 4]> =
valentinfernandez1 marked this conversation as resolved.
Show resolved Hide resolved
RefTimeToFee::polynomial();
let proof_poly: smallvec::SmallVec<[WeightToFeeCoefficient<Balance>; 4]> =
ProofSizeToFee::polynomial();

// Get fee amount from ref_time based on the RefTime polynomial
let ref_fee: Balance = ref_poly.iter().fold(0, |acc, term| {
term.saturating_eval(acc, Balance::saturated_from(weight.ref_time()))
valentinfernandez1 marked this conversation as resolved.
Show resolved Hide resolved
});

// Get fee amount from proof_size based on the ProofSize polynomial
let proof_fee: Balance = proof_poly.iter().fold(0, |acc, term| {
term.saturating_eval(acc, Balance::saturated_from(weight.proof_size()))
});

// Take the maximum instead of the sum to charge by the more scarce resource.
ref_fee.max(proof_fee)
}
}

/// Maps the Ref time component of `Weight` to a fee.
pub struct RefTimeToFee;
impl WeightToFeePolynomial for RefTimeToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
// in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT:
Expand All @@ -75,6 +107,24 @@ pub mod fee {
}
}

/// Maps the proof size component of `Weight` to a fee.
pub struct ProofSizeToFee;
impl WeightToFeePolynomial for ProofSizeToFee {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
// Map 10kb proof to 1 CENT.
let p = super::currency::CENTS;
let q = 10_000;

smallvec![WeightToFeeCoefficient {
degree: 1,
negative: false,
coeff_frac: Perbill::from_rational(p % q, q),
coeff_integer: p / q,
}]
}
}

pub fn base_tx_fee() -> Balance {
CENTS / 10
}
Expand Down
33 changes: 31 additions & 2 deletions runtime/trappist/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ use super::*;
use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler};
use frame_support::{
traits::{Contains, Currency, Imbalance, OnUnbalanced},
weights::Weight,
weights::{Weight, WeightToFeeCoefficient},
};
pub use log;
use sp_runtime::DispatchResult;
use sp_arithmetic::traits::{BaseArithmetic, Unsigned};
use sp_runtime::{DispatchResult, SaturatedConversion};

use sp_std::marker::PhantomData;

Expand Down Expand Up @@ -111,6 +112,34 @@ impl xcm_primitives::PauseXcmExecution for XcmExecutionManager {
XcmpQueue::resume_xcm_execution(RuntimeOrigin::root())
}
}

pub trait WeightCoefficientCalc<Balance> {
fn saturating_eval(&self, result: Balance, x: Balance) -> Balance;
}

impl<Balance> WeightCoefficientCalc<Balance> for WeightToFeeCoefficient<Balance>
where
Balance: BaseArithmetic + From<u32> + Copy + Unsigned + SaturatedConversion,
{
fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance {
let power = x.saturating_pow(self.degree.into());

let frac = self.coeff_frac * power; // Overflow safe.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can be more specific here and say that it's "Overflow safe" because coeff_frac is strictly less than 1.

let integer = self.coeff_integer.saturating_mul(power);
// Do not add them together here to avoid an underflow.

if self.negative {
result = result.saturating_sub(frac);
result = result.saturating_sub(integer);
} else {
result = result.saturating_add(frac);
result = result.saturating_add(integer);
}

result
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
42 changes: 24 additions & 18 deletions runtime/trappist/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
// limitations under the License.

use crate::{
constants::fee::default_fee_per_second, impls::ToAuthor, weights::TrappistDropAssetsWeigher,
constants::fee::{default_fee_per_second, WeightToFee},
impls::ToAuthor,
weights::TrappistDropAssetsWeigher,
AllPalletsWithSystem,
};

use super::{
AccountId, AssetRegistry, Assets, Balance, Balances, ParachainInfo, ParachainSystem,
PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue,
PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmpQueue,
};
use frame_support::{
match_types, parameter_types,
Expand All @@ -45,12 +47,11 @@ use xcm::latest::{prelude::*, Fungibility::Fungible, MultiAsset, MultiLocation};

use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex,
ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds,
FungiblesAdapter, IsConcrete, MintLocation, NativeAsset, NoChecking, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
UsingComponents, WeightInfoBounds,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin,
FixedRateOfFungible, FungiblesAdapter, IsConcrete, MintLocation, NativeAsset, NoChecking,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WeightInfoBounds,
};
use xcm_executor::XcmExecutor;

Expand Down Expand Up @@ -206,7 +207,6 @@ pub type Barrier = DenyThenTry<
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent and its exec plurality get free execution
AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
AllowUnpaidExecutionFrom<Rockmine>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
// Subscriptions for version tracking are OK.
Expand All @@ -220,11 +220,14 @@ parameter_types! {
// Rockmine's Assets pallet index
pub RockmineAssetsPalletLocation: MultiLocation =
MultiLocation::new(1, X2(Parachain(1000), PalletInstance(50)));
pub XUsdPerSecond: (xcm::v3::AssetId, u128, u128) = (
MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1))).into(),

pub RUsdPerSecond: (xcm::v3::AssetId, u128, u128) = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: changes to this files probably shouldn't be part of this PR.

MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984))).into(),
default_fee_per_second() * 10,
0
0u128
);
/// Roc = 7 RUSD
pub RocPerSecond: (xcm::v3::AssetId, u128,u128) = (MultiLocation::parent().into(), default_fee_per_second() * 70, 0u128);
}

//- From PR https://github.com/paritytech/cumulus/pull/936
Expand All @@ -251,7 +254,14 @@ impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for ReserveA
}
}

//--
pub type Traders = (
// RUSD
FixedRateOfFungible<RUsdPerSecond, ()>,
// Roc
FixedRateOfFungible<RocPerSecond, ()>,
// Everything else
UsingComponents<WeightToFee, SelfReserve, AccountId, Balances, ToAuthor<Runtime>>,
);

pub type Reserves = (NativeAsset, ReserveAssetsFrom<RockmineLocation>);

Expand All @@ -269,11 +279,7 @@ impl xcm_executor::Config for XcmConfig {
RuntimeCall,
MaxInstructions,
>;
//TODO: Modify current config of Trader removing XUsdPerSecond Implementation
type Trader = (
FixedRateOfFungible<XUsdPerSecond, ()>,
UsingComponents<WeightToFee, SelfReserve, AccountId, Balances, ToAuthor<Runtime>>,
);
type Trader = Traders;
type ResponseHandler = PolkadotXcm;
type AssetTrap = TrappistDropAssets<
AssetIdForTrustBackedAssets,
Expand Down