Weight v1.5: Opaque Struct (#12138)

* initial idea

* update frame_support

* update a bunch more

* add ord

* adjust RuntimeDbWeight

* frame_system builds

* re-export

* frame_support tests pass

* frame_executive compile

* frame_executive builds

* frame_system tests passing

* pallet-utility tests pass

* fix a bunch of pallets

* more

* phragmen

* state-trie-migration

* scheduler and referenda

* pallet-election-provider-multi-phase

* aura

* staking

* more

* babe

* balances

* bunch more

* sudo

* transaction-payment

* asset-tx-payment

* last pallets

* fix alliance merge

* fix node template runtime

* fix pallet-contracts cc @athei

* fix node runtime

* fix compile on runtime-benchmarks feature

* comment

* fix frame-support-test

* fix more tests

* weight regex

* frame system works

* fix a bunch

* more

* more

* more

* more

* more

* more fixes

* update templates

* fix contracts benchmarks

* Update lib.rs

* Update lib.rs

* fix ui

* make scalar saturating mul const

* more const functions

* scalar div

* refactor using constant functions

* move impl

* fix overhead template

* use compactas

* Update lib.rs
This commit is contained in:
Shawn Tabrizi
2022-08-31 12:26:13 +01:00
committed by GitHub
parent 299f4ba541
commit 30951822ba
187 changed files with 5932 additions and 4930 deletions
+106 -149
View File
@@ -123,6 +123,7 @@ mod block_weights;
mod extrinsic_weights;
mod paritydb_weights;
mod rocksdb_weights;
mod weight_v2;
use crate::{
dispatch::{DispatchError, DispatchErrorWithPostInfo, DispatchResultWithPostInfo},
@@ -146,18 +147,17 @@ use sp_runtime::{
/// Re-export priority as type
pub use sp_runtime::transaction_validity::TransactionPriority;
/// Numeric range of a transaction weight.
pub type Weight = u64;
pub use weight_v2::*;
/// These constants are specific to FRAME, and the current implementation of its various components.
/// For example: FRAME System, FRAME Executive, our FRAME support libraries, etc...
pub mod constants {
use super::Weight;
pub const WEIGHT_PER_SECOND: Weight = 1_000_000_000_000;
pub const WEIGHT_PER_MILLIS: Weight = WEIGHT_PER_SECOND / 1000; // 1_000_000_000
pub const WEIGHT_PER_MICROS: Weight = WEIGHT_PER_MILLIS / 1000; // 1_000_000
pub const WEIGHT_PER_NANOS: Weight = WEIGHT_PER_MICROS / 1000; // 1_000
pub const WEIGHT_PER_SECOND: Weight = Weight::from_ref_time(1_000_000_000_000);
pub const WEIGHT_PER_MILLIS: Weight = Weight::from_ref_time(1_000_000_000);
pub const WEIGHT_PER_MICROS: Weight = Weight::from_ref_time(1_000_000);
pub const WEIGHT_PER_NANOS: Weight = Weight::from_ref_time(1_000);
// Expose the Block and Extrinsic base weights.
pub use super::{block_weights::BlockExecutionWeight, extrinsic_weights::ExtrinsicBaseWeight};
@@ -204,6 +204,12 @@ impl Default for Pays {
}
}
impl From<Pays> for PostDispatchInfo {
fn from(pays_fee: Pays) -> Self {
Self { actual_weight: None, pays_fee }
}
}
/// A generalized group of dispatch types.
///
/// NOTE whenever upgrading the enum make sure to also update
@@ -359,25 +365,6 @@ pub fn extract_actual_pays_fee(result: &DispatchResultWithPostInfo, info: &Dispa
.pays_fee(info)
}
impl From<(Option<Weight>, Pays)> for PostDispatchInfo {
fn from(post_weight_info: (Option<Weight>, Pays)) -> Self {
let (actual_weight, pays_fee) = post_weight_info;
Self { actual_weight, pays_fee }
}
}
impl From<Pays> for PostDispatchInfo {
fn from(pays_fee: Pays) -> Self {
Self { actual_weight: None, pays_fee }
}
}
impl From<Option<Weight>> for PostDispatchInfo {
fn from(actual_weight: Option<Weight>) -> Self {
Self { actual_weight, pays_fee: Default::default() }
}
}
impl From<()> for PostDispatchInfo {
fn from(_: ()) -> Self {
Self { actual_weight: None, pays_fee: Default::default() }
@@ -407,7 +394,7 @@ pub trait WithPostDispatchInfo {
/// # Example
///
/// ```ignore
/// let who = ensure_signed(origin).map_err(|e| e.with_weight(100))?;
/// let who = ensure_signed(origin).map_err(|e| e.with_weight(Weight::from_ref_time(100)))?;
/// ensure!(who == me, Error::<T>::NotMe.with_weight(200_000));
/// ```
fn with_weight(self, actual_weight: Weight) -> DispatchErrorWithPostInfo;
@@ -428,78 +415,6 @@ where
}
}
impl<T> WeighData<T> for Weight {
fn weigh_data(&self, _: T) -> Weight {
*self
}
}
impl<T> ClassifyDispatch<T> for Weight {
fn classify_dispatch(&self, _: T) -> DispatchClass {
DispatchClass::Normal
}
}
impl<T> PaysFee<T> for Weight {
fn pays_fee(&self, _: T) -> Pays {
Pays::Yes
}
}
impl<T> WeighData<T> for (Weight, DispatchClass, Pays) {
fn weigh_data(&self, _: T) -> Weight {
self.0
}
}
impl<T> ClassifyDispatch<T> for (Weight, DispatchClass, Pays) {
fn classify_dispatch(&self, _: T) -> DispatchClass {
self.1
}
}
impl<T> PaysFee<T> for (Weight, DispatchClass, Pays) {
fn pays_fee(&self, _: T) -> Pays {
self.2
}
}
impl<T> WeighData<T> for (Weight, DispatchClass) {
fn weigh_data(&self, _: T) -> Weight {
self.0
}
}
impl<T> ClassifyDispatch<T> for (Weight, DispatchClass) {
fn classify_dispatch(&self, _: T) -> DispatchClass {
self.1
}
}
impl<T> PaysFee<T> for (Weight, DispatchClass) {
fn pays_fee(&self, _: T) -> Pays {
Pays::Yes
}
}
impl<T> WeighData<T> for (Weight, Pays) {
fn weigh_data(&self, _: T) -> Weight {
self.0
}
}
impl<T> ClassifyDispatch<T> for (Weight, Pays) {
fn classify_dispatch(&self, _: T) -> DispatchClass {
DispatchClass::Normal
}
}
impl<T> PaysFee<T> for (Weight, Pays) {
fn pays_fee(&self, _: T) -> Pays {
self.1
}
}
/// Implementation for unchecked extrinsic.
impl<Address, Call, Signature, Extra> GetDispatchInfo
for UncheckedExtrinsic<Address, Call, Signature, Extra>
@@ -527,30 +442,37 @@ where
impl<Call: Encode, Extra: Encode> GetDispatchInfo for sp_runtime::testing::TestXt<Call, Extra> {
fn get_dispatch_info(&self) -> DispatchInfo {
// for testing: weight == size.
DispatchInfo { weight: self.encode().len() as _, pays_fee: Pays::Yes, ..Default::default() }
DispatchInfo {
weight: Weight::from_ref_time(self.encode().len() as _),
pays_fee: Pays::Yes,
..Default::default()
}
}
}
/// 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: Weight,
pub write: Weight,
pub read: RefTimeWeight,
pub write: RefTimeWeight,
}
impl RuntimeDbWeight {
pub fn reads(self, r: Weight) -> Weight {
self.read.saturating_mul(r)
pub fn reads(self, r: u64) -> Weight {
Weight::from_ref_time(self.read.saturating_mul(r))
}
pub fn writes(self, w: Weight) -> Weight {
self.write.saturating_mul(w)
pub fn writes(self, w: u64) -> Weight {
Weight::from_ref_time(self.write.saturating_mul(w))
}
pub fn reads_writes(self, r: Weight, w: Weight) -> Weight {
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);
read_weight.saturating_add(write_weight)
Weight::from_ref_time(read_weight.saturating_add(write_weight))
}
}
@@ -618,7 +540,8 @@ where
Self::polynomial()
.iter()
.fold(Self::Balance::saturated_from(0u32), |mut acc, args| {
let w = Self::Balance::saturated_from(*weight).saturating_pow(args.degree.into());
let w = Self::Balance::saturated_from(weight.ref_time())
.saturating_pow(args.degree.into());
// The sum could get negative. Therefore we only sum with the accumulator.
// The Perbill Mul implementation is non overflowing.
@@ -648,7 +571,7 @@ where
type Balance = T;
fn weight_to_fee(weight: &Weight) -> Self::Balance {
Self::Balance::saturated_from(*weight)
Self::Balance::saturated_from(weight.ref_time())
}
}
@@ -671,7 +594,7 @@ where
type Balance = T;
fn weight_to_fee(weight: &Weight) -> Self::Balance {
Self::Balance::saturated_from(*weight).saturating_mul(M::get())
Self::Balance::saturated_from(weight.ref_time()).saturating_mul(M::get())
}
}
@@ -727,7 +650,7 @@ impl<T: Clone> PerDispatchClass<T> {
impl PerDispatchClass<Weight> {
/// Returns the total weight consumed by all extrinsics in the block.
pub fn total(&self) -> Weight {
let mut sum = 0;
let mut sum = Weight::new();
for class in DispatchClass::all() {
sum = sum.saturating_add(*self.get(*class));
}
@@ -744,7 +667,7 @@ impl PerDispatchClass<Weight> {
/// occur.
pub fn checked_add(&mut self, weight: Weight, class: DispatchClass) -> Result<(), ()> {
let value = self.get_mut(class);
*value = value.checked_add(weight).ok_or(())?;
*value = value.checked_add(&weight).ok_or(())?;
Ok(())
}
@@ -804,16 +727,16 @@ mod tests {
fn f03(_origin) { unimplemented!(); }
// weight = a x 10 + b
#[weight = ((_a * 10 + _eb * 1) as Weight, DispatchClass::Normal, Pays::Yes)]
#[weight = ((_a * 10 + _eb * 1) as RefTimeWeight, DispatchClass::Normal, Pays::Yes)]
fn f11(_origin, _a: u32, _eb: u32) { unimplemented!(); }
#[weight = (0, DispatchClass::Operational, Pays::Yes)]
fn f12(_origin, _a: u32, _eb: u32) { unimplemented!(); }
#[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + 10_000]
#[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + Weight::from_ref_time(10_000)]
fn f20(_origin) { unimplemented!(); }
#[weight = T::DbWeight::get().reads_writes(6, 5) + 40_000]
#[weight = T::DbWeight::get().reads_writes(6, 5) + Weight::from_ref_time(40_000)]
fn f21(_origin) { unimplemented!(); }
}
@@ -823,80 +746,98 @@ mod tests {
fn weights_are_correct() {
// #[weight = 1000]
let info = Call::<TraitImpl>::f00 {}.get_dispatch_info();
assert_eq!(info.weight, 1000);
assert_eq!(info.weight, Weight::from_ref_time(1000));
assert_eq!(info.class, DispatchClass::Normal);
assert_eq!(info.pays_fee, Pays::Yes);
// #[weight = (1000, DispatchClass::Mandatory)]
let info = Call::<TraitImpl>::f01 {}.get_dispatch_info();
assert_eq!(info.weight, 1000);
assert_eq!(info.weight, Weight::from_ref_time(1000));
assert_eq!(info.class, DispatchClass::Mandatory);
assert_eq!(info.pays_fee, Pays::Yes);
// #[weight = (1000, Pays::No)]
let info = Call::<TraitImpl>::f02 {}.get_dispatch_info();
assert_eq!(info.weight, 1000);
assert_eq!(info.weight, Weight::from_ref_time(1000));
assert_eq!(info.class, DispatchClass::Normal);
assert_eq!(info.pays_fee, Pays::No);
// #[weight = (1000, DispatchClass::Operational, Pays::No)]
let info = Call::<TraitImpl>::f03 {}.get_dispatch_info();
assert_eq!(info.weight, 1000);
assert_eq!(info.weight, Weight::from_ref_time(1000));
assert_eq!(info.class, DispatchClass::Operational);
assert_eq!(info.pays_fee, Pays::No);
// #[weight = ((_a * 10 + _eb * 1) as Weight, DispatchClass::Normal, Pays::Yes)]
let info = Call::<TraitImpl>::f11 { _a: 13, _eb: 20 }.get_dispatch_info();
assert_eq!(info.weight, 150); // 13*10 + 20
assert_eq!(info.weight, Weight::from_ref_time(150)); // 13*10 + 20
assert_eq!(info.class, DispatchClass::Normal);
assert_eq!(info.pays_fee, Pays::Yes);
// #[weight = (0, DispatchClass::Operational, Pays::Yes)]
let info = Call::<TraitImpl>::f12 { _a: 10, _eb: 20 }.get_dispatch_info();
assert_eq!(info.weight, 0);
assert_eq!(info.weight, Weight::from_ref_time(0));
assert_eq!(info.class, DispatchClass::Operational);
assert_eq!(info.pays_fee, Pays::Yes);
// #[weight = T::DbWeight::get().reads(3) + T::DbWeight::get().writes(2) + 10_000]
let info = Call::<TraitImpl>::f20 {}.get_dispatch_info();
assert_eq!(info.weight, 12300); // 100*3 + 1000*2 + 10_1000
assert_eq!(info.weight, Weight::from_ref_time(12300)); // 100*3 + 1000*2 + 10_1000
assert_eq!(info.class, DispatchClass::Normal);
assert_eq!(info.pays_fee, Pays::Yes);
// #[weight = T::DbWeight::get().reads_writes(6, 5) + 40_000]
let info = Call::<TraitImpl>::f21 {}.get_dispatch_info();
assert_eq!(info.weight, 45600); // 100*6 + 1000*5 + 40_1000
assert_eq!(info.weight, Weight::from_ref_time(45600)); // 100*6 + 1000*5 + 40_1000
assert_eq!(info.class, DispatchClass::Normal);
assert_eq!(info.pays_fee, Pays::Yes);
}
#[test]
fn extract_actual_weight_works() {
let pre = DispatchInfo { weight: 1000, ..Default::default() };
assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), 7);
assert_eq!(extract_actual_weight(&Ok(Some(1000).into()), &pre), 1000);
assert_eq!(extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(9)), &pre), 9);
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
assert_eq!(extract_actual_weight(&Ok(Some(7).into()), &pre), Weight::from_ref_time(7));
assert_eq!(
extract_actual_weight(&Ok(Some(1000).into()), &pre),
Weight::from_ref_time(1000)
);
assert_eq!(
extract_actual_weight(
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(9))),
&pre
),
Weight::from_ref_time(9)
);
}
#[test]
fn extract_actual_weight_caps_at_pre_weight() {
let pre = DispatchInfo { weight: 1000, ..Default::default() };
assert_eq!(extract_actual_weight(&Ok(Some(1250).into()), &pre), 1000);
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
assert_eq!(
extract_actual_weight(&Err(DispatchError::BadOrigin.with_weight(1300)), &pre),
1000
extract_actual_weight(&Ok(Some(1250).into()), &pre),
Weight::from_ref_time(1000)
);
assert_eq!(
extract_actual_weight(
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(1300))),
&pre
),
Weight::from_ref_time(1000),
);
}
#[test]
fn extract_actual_pays_fee_works() {
let pre = DispatchInfo { weight: 1000, ..Default::default() };
let pre = DispatchInfo { weight: Weight::from_ref_time(1000), ..Default::default() };
assert_eq!(extract_actual_pays_fee(&Ok(Some(7).into()), &pre), Pays::Yes);
assert_eq!(extract_actual_pays_fee(&Ok(Some(1000).into()), &pre), Pays::Yes);
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::Yes).into()), &pre), Pays::Yes);
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::No).into()), &pre), Pays::No);
assert_eq!(
extract_actual_pays_fee(&Err(DispatchError::BadOrigin.with_weight(9)), &pre),
extract_actual_pays_fee(
&Err(DispatchError::BadOrigin.with_weight(Weight::from_ref_time(9))),
&pre
),
Pays::Yes
);
assert_eq!(
@@ -910,7 +851,11 @@ mod tests {
Pays::No
);
let pre = DispatchInfo { weight: 1000, pays_fee: Pays::No, ..Default::default() };
let pre = DispatchInfo {
weight: Weight::from_ref_time(1000),
pays_fee: Pays::No,
..Default::default()
};
assert_eq!(extract_actual_pays_fee(&Ok(Some(7).into()), &pre), Pays::No);
assert_eq!(extract_actual_pays_fee(&Ok(Some(1000).into()), &pre), Pays::No);
assert_eq!(extract_actual_pays_fee(&Ok((Some(1000), Pays::Yes).into()), &pre), Pays::No);
@@ -956,40 +901,52 @@ mod tests {
#[test]
fn polynomial_works() {
// 100^3/2=500000 100^2*(2+1/3)=23333 700 -10000
assert_eq!(Poly::weight_to_fee(&100), 514033);
assert_eq!(Poly::weight_to_fee(&Weight::from_ref_time(100)), 514033);
// 10123^3/2=518677865433 10123^2*(2+1/3)=239108634 70861 -10000
assert_eq!(Poly::weight_to_fee(&10_123), 518917034928);
assert_eq!(Poly::weight_to_fee(&Weight::from_ref_time(10_123)), 518917034928);
}
#[test]
fn polynomial_does_not_underflow() {
assert_eq!(Poly::weight_to_fee(&0), 0);
assert_eq!(Poly::weight_to_fee(&10), 0);
assert_eq!(Poly::weight_to_fee(&Weight::zero()), 0);
assert_eq!(Poly::weight_to_fee(&Weight::from_ref_time(10)), 0);
}
#[test]
fn polynomial_does_not_overflow() {
assert_eq!(Poly::weight_to_fee(&Weight::max_value()), Balance::max_value() - 10_000);
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(&0), 0);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&50), 50);
assert_eq!(
IdentityFee::<Balance>::weight_to_fee(&Weight::max_value()),
Balance::max_value()
);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::zero()), 0);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::from_ref_time(50)), 50);
assert_eq!(IdentityFee::<Balance>::weight_to_fee(&Weight::MAX), Balance::max_value());
}
#[test]
fn constant_fee_works() {
use crate::traits::ConstU128;
assert_eq!(ConstantMultiplier::<u128, ConstU128<100u128>>::weight_to_fee(&0), 0);
assert_eq!(ConstantMultiplier::<u128, ConstU128<10u128>>::weight_to_fee(&50), 500);
assert_eq!(ConstantMultiplier::<u128, ConstU128<1024u128>>::weight_to_fee(&16), 16384);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<{ u128::MAX }>>::weight_to_fee(&2),
ConstantMultiplier::<u128, ConstU128<100u128>>::weight_to_fee(&Weight::zero()),
0
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<10u128>>::weight_to_fee(&Weight::from_ref_time(
50
)),
500
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<1024u128>>::weight_to_fee(&Weight::from_ref_time(
16
)),
16384
);
assert_eq!(
ConstantMultiplier::<u128, ConstU128<{ u128::MAX }>>::weight_to_fee(
&Weight::from_ref_time(2)
),
u128::MAX
);
}