Files
pezkuwi-subxt/substrate/primitives/weights/src/lib.rs
T
Juan Girini 43415ef58c feat: FRAME umbrella crate. (#1337)
### Original PR https://github.com/paritytech/substrate/pull/14137

This PR brings in the first version of the "_`frame` umbrella crate_".
This crate is intended to serve two purposes:

1. documentation
2. easier development with frame. Ideally, we want most users to be able
to build a frame-based pallet and runtime using just `frame` (plus
`scale-codec` and `scale-info`).

The crate is not finalized and is not yet intended for external use.
Therefore, the version is set to `0.0.1-dev`, this PR is `silent`, and
the entire crate is hidden behind the `experimental` flag. The main
intention in merging it early on is to be able to iterate on it in the
rest of
[`developer-hub`](https://github.com/paritytech/polkadot-sdk-docs/)
efforts.

The public API of the `frame` crate is at the moment as follows: 

```
pub mod frame
pub use frame::log
pub use frame::pallet
pub mod frame::arithmetic
pub use frame::arithmetic::<<sp_arithmetic::*>>
pub use frame::arithmetic::<<sp_arithmetic::traits::*>>
pub mod frame::deps
pub use frame::deps::codec
pub use frame::deps::frame_executive
pub use frame::deps::frame_support
pub use frame::deps::frame_system
pub use frame::deps::scale_info
pub use frame::deps::sp_api
pub use frame::deps::sp_arithmetic
pub use frame::deps::sp_block_builder
pub use frame::deps::sp_consensus_aura
pub use frame::deps::sp_consensus_grandpa
pub use frame::deps::sp_core
pub use frame::deps::sp_inherents
pub use frame::deps::sp_io
pub use frame::deps::sp_offchain
pub use frame::deps::sp_runtime
pub use frame::deps::sp_std
pub use frame::deps::sp_version
pub mod frame::derive
pub use frame::derive::CloneNoBound
pub use frame::derive::Debug
pub use frame::derive::Debug
pub use frame::derive::DebugNoBound
pub use frame::derive::Decode
pub use frame::derive::Decode
pub use frame::derive::DefaultNoBound
pub use frame::derive::Encode
pub use frame::derive::Encode
pub use frame::derive::EqNoBound
pub use frame::derive::PartialEqNoBound
pub use frame::derive::RuntimeDebug
pub use frame::derive::RuntimeDebugNoBound
pub use frame::derive::TypeInfo
pub use frame::derive::TypeInfo
pub mod frame::prelude
pub use frame::prelude::<<frame_support::pallet_prelude::*>>
pub use frame::prelude::<<frame_system::pallet_prelude::*>>
pub use frame::prelude::<<sp_std::prelude::*>>
pub use frame::prelude::CloneNoBound
pub use frame::prelude::Debug
pub use frame::prelude::Debug
pub use frame::prelude::DebugNoBound
pub use frame::prelude::Decode
pub use frame::prelude::Decode
pub use frame::prelude::DefaultNoBound
pub use frame::prelude::Encode
pub use frame::prelude::Encode
pub use frame::prelude::EqNoBound
pub use frame::prelude::PartialEqNoBound
pub use frame::prelude::RuntimeDebug
pub use frame::prelude::RuntimeDebugNoBound
pub use frame::prelude::TypeInfo
pub use frame::prelude::TypeInfo
pub use frame::prelude::frame_system
pub mod frame::primitives
pub use frame::primitives::BlakeTwo256
pub use frame::primitives::H160
pub use frame::primitives::H256
pub use frame::primitives::H512
pub use frame::primitives::Hash
pub use frame::primitives::Keccak256
pub use frame::primitives::U256
pub use frame::primitives::U512
pub mod frame::runtime
pub mod frame::runtime::apis
pub use frame::runtime::apis::<<frame_system_rpc_runtime_api::*>>
pub use frame::runtime::apis::<<sp_api::*>>
pub use frame::runtime::apis::<<sp_block_builder::*>>
pub use frame::runtime::apis::<<sp_consensus_aura::*>>
pub use frame::runtime::apis::<<sp_consensus_grandpa::*>>
pub use frame::runtime::apis::<<sp_offchain::*>>
pub use frame::runtime::apis::<<sp_session::runtime_api::*>>
pub use frame::runtime::apis::<<sp_transaction_pool::runtime_api::*>>
pub use frame::runtime::apis::ApplyExtrinsicResult
pub use frame::runtime::apis::CheckInherentsResult
pub use frame::runtime::apis::InherentData
pub use frame::runtime::apis::OpaqueMetadata
pub use frame::runtime::apis::impl_runtime_apis
pub use frame::runtime::apis::sp_api
pub mod frame::runtime::prelude
pub use frame::runtime::prelude::<<frame_executive::*>>
pub use frame::runtime::prelude::ConstBool
pub use frame::runtime::prelude::ConstI128
pub use frame::runtime::prelude::ConstI16
pub use frame::runtime::prelude::ConstI32
pub use frame::runtime::prelude::ConstI64
pub use frame::runtime::prelude::ConstI8
pub use frame::runtime::prelude::ConstU128
pub use frame::runtime::prelude::ConstU16
pub use frame::runtime::prelude::ConstU32
pub use frame::runtime::prelude::ConstU64
pub use frame::runtime::prelude::ConstU8
pub use frame::runtime::prelude::NativeVersion
pub use frame::runtime::prelude::RuntimeVersion
pub use frame::runtime::prelude::construct_runtime
pub use frame::runtime::prelude::create_runtime_str
pub use frame::runtime::prelude::derive_impl
pub use frame::runtime::prelude::frame_support
pub use frame::runtime::prelude::ord_parameter_types
pub use frame::runtime::prelude::parameter_types
pub use frame::runtime::prelude::runtime_version
pub mod frame::runtime::testing_prelude
pub use frame::runtime::testing_prelude::BuildStorage
pub use frame::runtime::testing_prelude::Storage
pub mod frame::runtime::types_common
pub type frame::runtime::types_common::AccountId = <<frame::runtime::types_common::Signature as sp_runtime::traits::Verify>::Signer as sp_runtime::traits::IdentifyAccount>::AccountId
pub type frame::runtime::types_common::BlockNumber = u32
pub type frame::runtime::types_common::BlockOf<T, Extra> = sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<frame::runtime::types_common::BlockNumber, sp_runtime::traits::BlakeTwo256>, sp_runtime::generic::unchecked_extrinsic::UncheckedExtrinsic<sp_runtime::multiaddress::MultiAddress<frame::runtime::types_common::AccountId, ()>, <T as frame_system::pallet::Config>::RuntimeCall, frame::runtime::types_common::Signature, Extra>>
pub type frame::runtime::types_common::OpaqueBlock = sp_runtime::generic::block::Block<sp_runtime::generic::header::Header<frame::runtime::types_common::BlockNumber, sp_runtime::traits::BlakeTwo256>, sp_runtime::OpaqueExtrinsic>
pub type frame::runtime::types_common::Signature = sp_runtime::MultiSignature
pub type frame::runtime::types_common::SystemSignedExtensionsOf<T> = (frame_system::extensions::check_non_zero_sender::CheckNonZeroSender<T>, frame_system::extensions::check_spec_version::CheckSpecVersion<T>, frame_system::extensions::check_tx_version::CheckTxVersion<T>, frame_system::extensions::check_genesis::CheckGenesis<T>, frame_system::extensions::check_mortality::CheckMortality<T>, frame_system::extensions::check_nonce::CheckNonce<T>, frame_system::extensions::check_weight::CheckWeight<T>)
pub mod frame::testing_prelude
pub use frame::testing_prelude::<<frame_executive::*>>
pub use frame::testing_prelude::<<frame_system::mocking::*>>
pub use frame::testing_prelude::BuildStorage
pub use frame::testing_prelude::ConstBool
pub use frame::testing_prelude::ConstI128
pub use frame::testing_prelude::ConstI16
pub use frame::testing_prelude::ConstI32
pub use frame::testing_prelude::ConstI64
pub use frame::testing_prelude::ConstI8
pub use frame::testing_prelude::ConstU128
pub use frame::testing_prelude::ConstU16
pub use frame::testing_prelude::ConstU32
pub use frame::testing_prelude::ConstU64
pub use frame::testing_prelude::ConstU8
pub use frame::testing_prelude::NativeVersion
pub use frame::testing_prelude::RuntimeVersion
pub use frame::testing_prelude::Storage
pub use frame::testing_prelude::TestState
pub use frame::testing_prelude::assert_err
pub use frame::testing_prelude::assert_err_ignore_postinfo
pub use frame::testing_prelude::assert_error_encoded_size
pub use frame::testing_prelude::assert_noop
pub use frame::testing_prelude::assert_ok
pub use frame::testing_prelude::assert_storage_noop
pub use frame::testing_prelude::construct_runtime
pub use frame::testing_prelude::create_runtime_str
pub use frame::testing_prelude::derive_impl
pub use frame::testing_prelude::frame_support
pub use frame::testing_prelude::frame_system
pub use frame::testing_prelude::if_std
pub use frame::testing_prelude::ord_parameter_types
pub use frame::testing_prelude::parameter_types
pub use frame::testing_prelude::runtime_version
pub use frame::testing_prelude::storage_alias
pub mod frame::traits
pub use frame::traits::<<frame_support::traits::*>>
pub use frame::traits::<<sp_runtime::traits::*>>
```

---

The road to full stabilization is

- [ ] https://github.com/paritytech/polkadot-sdk/issues/127
- [ ] have a more intentional version bump, as opposed to the current bi
weekly force-major-bump
- [ ] revise the internal API of `frame`, especially what goes into the
`prelude`s.
- [ ] migrate all internal pallets and runtime to use `frame`

---------

Co-authored-by: kianenigma <kian@parity.io>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Francisco Aguirre <franciscoaguirreperez@gmail.com>
2023-10-27 11:38:16 +02:00

388 lines
11 KiB
Rust

// 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.
//! # Primitives for transaction weighting.
#![cfg_attr(not(feature = "std"), no_std)]
// TODO remove once `OldWeight` is gone. I dont know why this is needed, maybe by one of the macros
// of `OldWeight`.
#![allow(deprecated)]
extern crate self as sp_weights;
mod weight_meter;
mod weight_v2;
use codec::{CompactAs, Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use sp_arithmetic::{
traits::{BaseArithmetic, SaturatedConversion, Unsigned},
Perbill,
};
use sp_core::Get;
use sp_debug_derive::RuntimeDebug;
pub use weight_meter::*;
pub use weight_v2::*;
pub mod constants {
pub const WEIGHT_REF_TIME_PER_SECOND: u64 = 1_000_000_000_000;
pub const WEIGHT_REF_TIME_PER_MILLIS: u64 = 1_000_000_000;
pub const WEIGHT_REF_TIME_PER_MICROS: u64 = 1_000_000;
pub const WEIGHT_REF_TIME_PER_NANOS: u64 = 1_000;
pub const WEIGHT_PROOF_SIZE_PER_MB: u64 = 1024 * 1024;
pub const WEIGHT_PROOF_SIZE_PER_KB: u64 = 1024;
}
/// The old weight type.
///
/// NOTE: This type exists purely for compatibility purposes! Use [`weight_v2::Weight`] in all other
/// cases.
#[derive(
Decode,
Encode,
CompactAs,
PartialEq,
Eq,
Clone,
Copy,
RuntimeDebug,
Default,
MaxEncodedLen,
TypeInfo,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
#[deprecated(note = "Will be removed soon; use `Weight` instead.")]
pub struct OldWeight(pub u64);
/// The weight of database operations that the runtime can invoke.
///
/// NOTE: This is currently only measured in computational time, and will probably
/// be updated all together once proof size is accounted for.
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo)]
pub struct RuntimeDbWeight {
pub read: u64,
pub write: u64,
}
impl RuntimeDbWeight {
pub fn reads(self, r: u64) -> Weight {
Weight::from_parts(self.read.saturating_mul(r), 0)
}
pub fn writes(self, w: u64) -> Weight {
Weight::from_parts(self.write.saturating_mul(w), 0)
}
pub fn reads_writes(self, r: u64, w: u64) -> Weight {
let read_weight = self.read.saturating_mul(r);
let write_weight = self.write.saturating_mul(w);
Weight::from_parts(read_weight.saturating_add(write_weight), 0)
}
}
/// One coefficient and its position in the `WeightToFee`.
///
/// One term of polynomial is calculated as:
///
/// ```ignore
/// coeff_integer * x^(degree) + coeff_frac * x^(degree)
/// ```
///
/// The `negative` value encodes whether the term is added or subtracted from the
/// overall polynomial result.
#[derive(Clone, Encode, Decode, TypeInfo)]
pub struct WeightToFeeCoefficient<Balance> {
/// The integral part of the coefficient.
pub coeff_integer: Balance,
/// The fractional part of the coefficient.
pub coeff_frac: Perbill,
/// True iff the coefficient should be interpreted as negative.
pub negative: bool,
/// Degree/exponent of the term.
pub degree: u8,
}
impl<Balance> WeightToFeeCoefficient<Balance>
where
Balance: BaseArithmetic + From<u32> + Copy + Unsigned,
{
/// Evaluate the term at `x` and saturatingly amalgamate into `result`.
///
/// The unsigned value for the term is calculated as:
/// ```ignore
/// (frac * x^(degree) + integer * x^(degree))
/// ```
/// Depending on the value of `negative`, it is added or subtracted from the `result`.
pub 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.
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
}
}
/// A list of coefficients that represent a polynomial.
pub type WeightToFeeCoefficients<T> = SmallVec<[WeightToFeeCoefficient<T>; 4]>;
/// A list of coefficients that represent a polynomial.
///
/// Can be [eval](Self::eval)uated at a specific `u64` to get the fee. The evaluations happens by
/// summing up all term [results](`WeightToFeeCoefficient::saturating_eval`). The order of the
/// coefficients matters since it uses saturating arithmetic. This struct does therefore not model a
/// polynomial in the mathematical sense (polynomial ring).
///
/// For visualization purposes, the formulas of the unsigned terms look like:
///
/// ```ignore
/// (c[0].frac * x^(c[0].degree) + c[0].integer * x^(c[0].degree))
/// (c[1].frac * x^(c[1].degree) + c[1].integer * x^(c[1].degree))
/// ...
/// ```
/// Depending on the value of `c[i].negative`, each term is added or subtracted from the result.
/// The result is initialized as zero.
pub struct FeePolynomial<Balance> {
coefficients: SmallVec<[WeightToFeeCoefficient<Balance>; 4]>,
}
impl<Balance> From<WeightToFeeCoefficients<Balance>> for FeePolynomial<Balance> {
fn from(coefficients: WeightToFeeCoefficients<Balance>) -> Self {
Self { coefficients }
}
}
impl<Balance> FeePolynomial<Balance>
where
Balance: BaseArithmetic + From<u32> + Copy + Unsigned,
{
/// Evaluate the polynomial at a specific `x`.
pub fn eval(&self, x: u64) -> Balance {
self.coefficients.iter().fold(Balance::zero(), |acc, term| {
term.saturating_eval(acc, Balance::saturated_from(x))
})
}
}
/// A trait that describes the weight to fee calculation.
pub trait WeightToFee {
/// The type that is returned as result from calculation.
type Balance: BaseArithmetic + From<u32> + Copy + Unsigned;
/// Calculates the fee from the passed `weight`.
fn weight_to_fee(weight: &Weight) -> Self::Balance;
}
/// A trait that describes the weight to fee calculation as polynomial.
///
/// An implementor should only implement the `polynomial` function.
pub trait WeightToFeePolynomial {
/// The type that is returned as result from polynomial evaluation.
type Balance: BaseArithmetic + From<u32> + Copy + Unsigned;
/// Returns a polynomial that describes the weight to fee conversion.
///
/// This is the only function that should be manually implemented. Please note
/// that all calculation is done in the probably unsigned `Balance` type. This means
/// that the order of coefficients is important as putting the negative coefficients
/// first will most likely saturate the result to zero mid evaluation.
fn polynomial() -> WeightToFeeCoefficients<Self::Balance>;
}
impl<T> WeightToFee for T
where
T: WeightToFeePolynomial,
{
type Balance = <Self as WeightToFeePolynomial>::Balance;
/// Calculates the fee from the passed `weight` according to the `polynomial`.
///
/// This should not be overridden in most circumstances. Calculation is done in the
/// `Balance` type and never overflows. All evaluation is saturating.
fn weight_to_fee(weight: &Weight) -> Self::Balance {
let poly: FeePolynomial<Self::Balance> = Self::polynomial().into();
poly.eval(weight.ref_time())
}
}
/// Implementor of `WeightToFee` that maps one unit of weight to one unit of fee.
pub struct IdentityFee<T>(sp_std::marker::PhantomData<T>);
impl<T> WeightToFee for IdentityFee<T>
where
T: BaseArithmetic + From<u32> + Copy + Unsigned,
{
type Balance = T;
fn weight_to_fee(weight: &Weight) -> Self::Balance {
Self::Balance::saturated_from(weight.ref_time())
}
}
/// Implementor of [`WeightToFee`] such that it maps any unit of weight to a fixed fee.
pub struct FixedFee<const F: u32, T>(sp_std::marker::PhantomData<T>);
impl<const F: u32, T> WeightToFee for FixedFee<F, T>
where
T: BaseArithmetic + From<u32> + Copy + Unsigned,
{
type Balance = T;
fn weight_to_fee(_: &Weight) -> Self::Balance {
F.into()
}
}
/// An implementation of [`WeightToFee`] that collects no fee.
pub type NoFee<T> = FixedFee<0, T>;
/// Implementor of [`WeightToFee`] that uses a constant multiplier.
///
/// # Example
///
/// ```
/// # use sp_core::ConstU128;
/// # use sp_weights::ConstantMultiplier;
/// // Results in a multiplier of 10 for each unit of weight (or length)
/// type LengthToFee = ConstantMultiplier::<u128, ConstU128<10u128>>;
/// ```
pub struct ConstantMultiplier<T, M>(sp_std::marker::PhantomData<(T, M)>);
impl<T, M> WeightToFee for ConstantMultiplier<T, M>
where
T: BaseArithmetic + From<u32> + Copy + Unsigned,
M: Get<T>,
{
type Balance = T;
fn weight_to_fee(weight: &Weight) -> Self::Balance {
Self::Balance::saturated_from(weight.ref_time()).saturating_mul(M::get())
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use super::*;
use smallvec::smallvec;
type Balance = u64;
// 0.5x^3 + 2.333x^2 + 7x - 10_000
struct Poly;
impl WeightToFeePolynomial for Poly {
type Balance = Balance;
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
smallvec![
WeightToFeeCoefficient {
coeff_integer: 0,
coeff_frac: Perbill::from_float(0.5),
negative: false,
degree: 3
},
WeightToFeeCoefficient {
coeff_integer: 2,
coeff_frac: Perbill::from_rational(1u32, 3u32),
negative: false,
degree: 2
},
WeightToFeeCoefficient {
coeff_integer: 7,
coeff_frac: Perbill::zero(),
negative: false,
degree: 1
},
WeightToFeeCoefficient {
coeff_integer: 10_000,
coeff_frac: Perbill::zero(),
negative: true,
degree: 0
},
]
}
}
#[test]
fn polynomial_works() {
// 100^3/2=500000 100^2*(2+1/3)=23333 700 -10000
assert_eq!(Poly::weight_to_fee(&Weight::from_parts(100, 0)), 514033);
// 10123^3/2=518677865433 10123^2*(2+1/3)=239108634 70861 -10000
assert_eq!(Poly::weight_to_fee(&Weight::from_parts(10_123, 0)), 518917034928);
}
#[test]
fn polynomial_does_not_underflow() {
assert_eq!(Poly::weight_to_fee(&Weight::zero()), 0);
assert_eq!(Poly::weight_to_fee(&Weight::from_parts(10, 0)), 0);
}
#[test]
fn polynomial_does_not_overflow() {
assert_eq!(Poly::weight_to_fee(&Weight::MAX), Balance::max_value() - 10_000);
}
#[test]
fn identity_fee_works() {
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::zero()), 0);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::from_parts(50, 0)), 50);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::MAX), Balance::max_value());
}
#[test]
fn constant_fee_works() {
use sp_core::ConstU128;
assert_eq!(
ConstantMultiplier::<u128, ConstU128<100u128>>::weight_to_fee(&Weight::zero()),
0
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<10u128>>::weight_to_fee(&Weight::from_parts(
50, 0
)),
500
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<1024u128>>::weight_to_fee(&Weight::from_parts(
16, 0
)),
16384
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<{ u128::MAX }>>::weight_to_fee(
&Weight::from_parts(2, 0)
),
u128::MAX
);
}
}