Streamline frame_system weight parametrization (#6629)

* Basic weights builder.

* Fixing WiP

* Make the tests work.

* Fix weights in node/runtime.

* WiP.

* Update pallets with new weights parameters.

* Validate returns a Result now.

* Count mandatory weight separately.

* DRY

* BREAKING: Updating state root, because of the left-over weight-tracking stuff

* Update tests affected by Mandatory tracking.

* Fixing tests.

* Fix defaults for simple_max

* Update frame/system/src/weights.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Rework the API a bit.

* Fix compilation & tests.

* Apply suggestions from code review

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Add extra docs & rename few things.

* Fix whitespace in ASCII art.

* Update frame/system/src/limits.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Fix max_extrinsic calculations.

* Fix conflicts.

* Fix compilation.

* Fix new code.

* re-remove generic asset

* Fix usage.

* Update state root.

* Update proxy.

* Fix tests.

* Move weights validity to integrity_test

* Remove redundant BlockWeights.

* Add all/non_mandatory comment

* Add test.

* Remove fn block_weights

* Make the macro prettier.

* Fix some docs.

* Make max_total behave more predictabily.

* Add BlockWeights to metadata.

* fix balances test

* Fix utility test.

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
Co-authored-by: Benjamin Kampmann <ben@gnunicorn.org>
Co-authored-by: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
Tomasz Drwięga
2020-12-08 13:18:34 +01:00
committed by GitHub
parent f6198b4c1b
commit 39a776cd00
66 changed files with 1275 additions and 929 deletions
+117
View File
@@ -213,6 +213,9 @@ impl Default for Pays {
}
/// A generalized group of dispatch types.
///
/// NOTE whenever upgrading the enum make sure to also update
/// [DispatchClass::all] and [DispatchClass::non_mandatory] helper functions.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
@@ -242,6 +245,39 @@ impl Default for DispatchClass {
}
}
impl DispatchClass {
/// Returns an array containing all dispatch classes.
pub fn all() -> &'static [DispatchClass] {
&[DispatchClass::Normal, DispatchClass::Operational, DispatchClass::Mandatory]
}
/// Returns an array of all dispatch classes except `Mandatory`.
pub fn non_mandatory() -> &'static [DispatchClass] {
&[DispatchClass::Normal, DispatchClass::Operational]
}
}
/// A trait that represents one or many values of given type.
///
/// Useful to accept as parameter type to let the caller pass either a single value directly
/// or an iterator.
pub trait OneOrMany<T> {
/// The iterator type.
type Iter: Iterator<Item = T>;
/// Convert this item into an iterator.
fn into_iter(self) -> Self::Iter;
}
impl OneOrMany<DispatchClass> for DispatchClass {
type Iter = sp_std::iter::Once<DispatchClass>;
fn into_iter(self) -> Self::Iter { sp_std::iter::once(self) }
}
impl<'a> OneOrMany<DispatchClass> for &'a [DispatchClass] {
type Iter = sp_std::iter::Cloned<sp_std::slice::Iter<'a, DispatchClass>>;
fn into_iter(self) -> Self::Iter { self.iter().cloned() }
}
/// Primitives related to priority management of Frame.
pub mod priority {
/// The starting point of all Operational transactions. 3/4 of u64::max_value().
@@ -695,6 +731,87 @@ impl<T> WeightToFeePolynomial for IdentityFee<T> where
}
}
/// A struct holding value for each `DispatchClass`.
#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
pub struct PerDispatchClass<T> {
/// Value for `Normal` extrinsics.
normal: T,
/// Value for `Operational` extrinsics.
operational: T,
/// Value for `Mandatory` extrinsics.
mandatory: T,
}
impl<T> PerDispatchClass<T> {
/// Create new `PerDispatchClass` with the same value for every class.
pub fn new(val: impl Fn(DispatchClass) -> T) -> Self {
Self {
normal: val(DispatchClass::Normal),
operational: val(DispatchClass::Operational),
mandatory: val(DispatchClass::Mandatory),
}
}
/// Get a mutable reference to current value of given class.
pub fn get_mut(&mut self, class: DispatchClass) -> &mut T {
match class {
DispatchClass::Operational => &mut self.operational,
DispatchClass::Normal => &mut self.normal,
DispatchClass::Mandatory => &mut self.mandatory,
}
}
/// Get current value for given class.
pub fn get(&self, class: DispatchClass) -> &T {
match class {
DispatchClass::Normal => &self.normal,
DispatchClass::Operational => &self.operational,
DispatchClass::Mandatory => &self.mandatory,
}
}
}
impl<T: Clone> PerDispatchClass<T> {
/// Set the value of given class.
pub fn set(&mut self, new: T, class: impl OneOrMany<DispatchClass>) {
for class in class.into_iter() {
*self.get_mut(class) = new.clone();
}
}
}
impl PerDispatchClass<Weight> {
/// Returns the total weight consumed by all extrinsics in the block.
pub fn total(&self) -> Weight {
let mut sum = 0;
for class in DispatchClass::all() {
sum = sum.saturating_add(*self.get(*class));
}
sum
}
/// Add some weight of a specific dispatch class, saturating at the numeric bounds of `Weight`.
pub fn add(&mut self, weight: Weight, class: DispatchClass) {
let value = self.get_mut(class);
*value = value.saturating_add(weight);
}
/// Try to add some weight of a specific dispatch class, returning Err(()) if overflow would
/// 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(())?;
Ok(())
}
/// Subtract some weight of a specific dispatch class, saturating at the numeric bounds of
/// `Weight`.
pub fn sub(&mut self, weight: Weight, class: DispatchClass) {
let value = self.get_mut(class);
*value = value.saturating_sub(weight);
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {