feat: Rebrand Polkadot/Substrate references to PezkuwiChain

This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
This commit is contained in:
2025-12-14 00:04:10 +03:00
parent 286de54384
commit 1c0e57d984
9084 changed files with 997839 additions and 997557 deletions
+50
View File
@@ -0,0 +1,50 @@
[package]
name = "pezsp-weights"
version = "27.0.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "Types and traits for interfacing between the host and the wasm runtime."
documentation = "https://docs.rs/pezsp-wasm-interface"
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
bounded-collections = { workspace = true }
codec = { features = ["derive"], workspace = true }
scale-info = { features = ["derive"], workspace = true }
schemars = { optional = true, workspace = true }
serde = { optional = true, features = ["alloc", "derive"], workspace = true }
smallvec = { workspace = true, default-features = true }
pezsp-arithmetic = { workspace = true }
pezsp-debug-derive = { workspace = true }
[features]
default = ["std"]
std = [
"bounded-collections/std",
"codec/std",
"scale-info/std",
"serde/std",
"pezsp-arithmetic/std",
"pezsp-debug-derive/std",
]
# By default some types have documentation, `full-metadata-docs` allows to add documentation to
# more types in the metadata.
full-metadata-docs = ["scale-info/docs"]
# Serde support without relying on std features.
serde = [
"bounded-collections/serde",
"dep:serde",
"scale-info/serde",
"pezsp-arithmetic/serde",
]
json-schema = ["dep:schemars"]
+362
View File
@@ -0,0 +1,362 @@
// This file is part of Bizinikiwi.
// 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)]
extern crate self as pezsp_weights;
mod weight_meter;
mod weight_v2;
use bounded_collections::Get;
use codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use pezsp_arithmetic::{
traits::{BaseArithmetic, SaturatedConversion, Unsigned},
Perbill,
};
use pezsp_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 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>(core::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>(core::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 bounded_collections::ConstU128;
/// # use pezsp_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>(core::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 bounded_collections::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
);
}
}
@@ -0,0 +1,306 @@
// This file is part of Bizinikiwi.
// 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.
//! Contains the `WeightMeter` primitive to meter weight usage.
use super::Weight;
use pezsp_arithmetic::Perbill;
/// Meters consumed weight and a hard limit for the maximal consumable weight.
///
/// Can be used to check if enough weight for an operation is available before committing to it.
///
/// # Example
///
/// ```rust
/// use pezsp_weights::{Weight, WeightMeter};
///
/// // The weight is limited to (10, 0).
/// let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 0));
/// // There is enough weight remaining for an operation with (6, 0) weight.
/// assert!(meter.try_consume(Weight::from_parts(6, 0)).is_ok());
/// assert_eq!(meter.remaining(), Weight::from_parts(4, 0));
/// // There is not enough weight remaining for an operation with (5, 0) weight.
/// assert!(!meter.try_consume(Weight::from_parts(5, 0)).is_ok());
/// // The total limit is obviously unchanged:
/// assert_eq!(meter.limit(), Weight::from_parts(10, 0));
/// ```
#[derive(Debug, Clone)]
pub struct WeightMeter {
/// The already consumed weight.
consumed: Weight,
/// The maximal consumable weight.
limit: Weight,
}
impl WeightMeter {
/// Creates [`Self`] from `consumed` and `limit`.
pub fn with_consumed_and_limit(consumed: Weight, limit: Weight) -> Self {
Self { consumed, limit }
}
/// Creates [`Self`] from a limit for the maximal consumable weight.
pub fn with_limit(limit: Weight) -> Self {
Self { consumed: Weight::zero(), limit }
}
/// Creates [`Self`] with the maximal possible limit for the consumable weight.
pub fn new() -> Self {
Self::with_limit(Weight::MAX)
}
/// Change the limit to the given `weight`.
///
/// The actual weight will be determined by `min(weight, self.remaining())`.
pub fn limit_to(self, weight: Weight) -> Self {
Self::with_limit(self.remaining().min(weight))
}
/// The already consumed weight.
pub fn consumed(&self) -> Weight {
self.consumed
}
/// The limit can ever be accrued.
pub fn limit(&self) -> Weight {
self.limit
}
/// The remaining weight that can still be consumed.
pub fn remaining(&self) -> Weight {
self.limit.saturating_sub(self.consumed)
}
/// The ratio of consumed weight to the limit.
///
/// Calculates one ratio per component and returns the largest.
///
/// # Example
/// ```rust
/// use pezsp_weights::{Weight, WeightMeter};
/// use pezsp_arithmetic::Perbill;
///
/// let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 20));
/// // Nothing consumed so far:
/// assert_eq!(meter.consumed_ratio(), Perbill::from_percent(0));
/// meter.consume(Weight::from_parts(5, 5));
/// // The ref-time is the larger ratio:
/// assert_eq!(meter.consumed_ratio(), Perbill::from_percent(50));
/// meter.consume(Weight::from_parts(1, 10));
/// // Now the larger ratio is proof-size:
/// assert_eq!(meter.consumed_ratio(), Perbill::from_percent(75));
/// // Eventually it reaches 100%:
/// meter.consume(Weight::from_parts(4, 0));
/// assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
/// // Saturating the second component won't change anything anymore:
/// meter.consume(Weight::from_parts(0, 5));
/// assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
/// ```
pub fn consumed_ratio(&self) -> Perbill {
let time = Perbill::from_rational(self.consumed.ref_time(), self.limit.ref_time());
let pov = Perbill::from_rational(self.consumed.proof_size(), self.limit.proof_size());
time.max(pov)
}
/// Consume some weight and defensively fail if it is over the limit. Saturate in any case.
#[deprecated(note = "Use `consume` instead. Will be removed after December 2023.")]
pub fn defensive_saturating_accrue(&mut self, w: Weight) {
self.consume(w);
}
/// Consume some weight and defensively fail if it is over the limit. Saturate in any case.
pub fn consume(&mut self, w: Weight) {
self.consumed.saturating_accrue(w);
debug_assert!(self.consumed.all_lte(self.limit), "Weight counter overflow");
}
/// Consume the given weight after checking that it can be consumed.
///
/// Returns `Ok` if the weight can be consumed or otherwise an `Err`.
pub fn try_consume(&mut self, w: Weight) -> Result<(), ()> {
self.consumed.checked_add(&w).map_or(Err(()), |test| {
if test.any_gt(self.limit) {
Err(())
} else {
self.consumed = test;
Ok(())
}
})
}
/// Check if the given weight can be consumed.
pub fn can_consume(&self, w: Weight) -> bool {
self.consumed.checked_add(&w).map_or(false, |t| t.all_lte(self.limit))
}
/// Reclaim the given weight.
pub fn reclaim_proof_size(&mut self, s: u64) {
self.consumed.saturating_reduce(Weight::from_parts(0, s));
}
}
#[cfg(test)]
mod tests {
use crate::*;
use pezsp_arithmetic::traits::Zero;
#[test]
fn weight_meter_remaining_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 20));
assert_eq!(meter.try_consume(Weight::from_parts(5, 0)), Ok(()));
assert_eq!(meter.consumed, Weight::from_parts(5, 0));
assert_eq!(meter.remaining(), Weight::from_parts(5, 20));
assert_eq!(meter.try_consume(Weight::from_parts(2, 10)), Ok(()));
assert_eq!(meter.consumed, Weight::from_parts(7, 10));
assert_eq!(meter.remaining(), Weight::from_parts(3, 10));
assert_eq!(meter.try_consume(Weight::from_parts(3, 10)), Ok(()));
assert_eq!(meter.consumed, Weight::from_parts(10, 20));
assert_eq!(meter.remaining(), Weight::from_parts(0, 0));
}
#[test]
fn weight_meter_can_consume_works() {
let meter = WeightMeter::with_limit(Weight::from_parts(1, 1));
assert!(meter.can_consume(Weight::from_parts(0, 0)));
assert!(meter.can_consume(Weight::from_parts(1, 1)));
assert!(!meter.can_consume(Weight::from_parts(0, 2)));
assert!(!meter.can_consume(Weight::from_parts(2, 0)));
assert!(!meter.can_consume(Weight::from_parts(2, 2)));
}
#[test]
fn weight_meter_try_consume_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(2, 2));
assert_eq!(meter.try_consume(Weight::from_parts(0, 0)), Ok(()));
assert_eq!(meter.try_consume(Weight::from_parts(1, 1)), Ok(()));
assert_eq!(meter.try_consume(Weight::from_parts(0, 2)), Err(()));
assert_eq!(meter.try_consume(Weight::from_parts(2, 0)), Err(()));
assert_eq!(meter.try_consume(Weight::from_parts(2, 2)), Err(()));
assert_eq!(meter.try_consume(Weight::from_parts(0, 1)), Ok(()));
assert_eq!(meter.try_consume(Weight::from_parts(1, 0)), Ok(()));
}
#[test]
fn weight_meter_check_and_can_consume_works() {
let mut meter = WeightMeter::new();
assert!(meter.can_consume(Weight::from_parts(u64::MAX, 0)));
assert_eq!(meter.try_consume(Weight::from_parts(u64::MAX, 0)), Ok(()));
assert!(meter.can_consume(Weight::from_parts(0, u64::MAX)));
assert_eq!(meter.try_consume(Weight::from_parts(0, u64::MAX)), Ok(()));
assert!(!meter.can_consume(Weight::from_parts(0, 1)));
assert_eq!(meter.try_consume(Weight::from_parts(0, 1)), Err(()));
assert!(!meter.can_consume(Weight::from_parts(1, 0)));
assert_eq!(meter.try_consume(Weight::from_parts(1, 0)), Err(()));
assert!(meter.can_consume(Weight::zero()));
assert_eq!(meter.try_consume(Weight::zero()), Ok(()));
}
#[test]
fn consumed_ratio_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 20));
assert_eq!(meter.try_consume(Weight::from_parts(5, 0)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(50));
assert_eq!(meter.try_consume(Weight::from_parts(0, 12)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(60));
assert_eq!(meter.try_consume(Weight::from_parts(2, 0)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(70));
assert_eq!(meter.try_consume(Weight::from_parts(0, 4)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(80));
assert_eq!(meter.try_consume(Weight::from_parts(3, 0)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
assert_eq!(meter.try_consume(Weight::from_parts(0, 4)), Ok(()));
assert_eq!(meter.consumed_ratio(), Perbill::from_percent(100));
}
#[test]
fn try_consume_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 0));
assert!(meter.try_consume(Weight::from_parts(11, 0)).is_err());
assert!(meter.consumed().is_zero(), "No modification");
assert!(meter.try_consume(Weight::from_parts(9, 0)).is_ok());
assert!(meter.try_consume(Weight::from_parts(2, 0)).is_err());
assert!(meter.try_consume(Weight::from_parts(1, 0)).is_ok());
assert!(meter.remaining().is_zero());
assert_eq!(meter.consumed(), Weight::from_parts(10, 0));
}
#[test]
fn can_consume_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 0));
assert!(!meter.can_consume(Weight::from_parts(11, 0)));
assert!(meter.consumed().is_zero(), "No modification");
assert!(meter.can_consume(Weight::from_parts(9, 0)));
meter.consume(Weight::from_parts(9, 0));
assert!(!meter.can_consume(Weight::from_parts(2, 0)));
assert!(meter.can_consume(Weight::from_parts(1, 0)));
}
#[test]
#[cfg(debug_assertions)]
fn consume_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(5, 10));
meter.consume(Weight::from_parts(4, 0));
assert_eq!(meter.remaining(), Weight::from_parts(1, 10));
meter.consume(Weight::from_parts(1, 0));
assert_eq!(meter.remaining(), Weight::from_parts(0, 10));
meter.consume(Weight::from_parts(0, 10));
assert_eq!(meter.consumed(), Weight::from_parts(5, 10));
}
#[test]
#[cfg(debug_assertions)]
fn reclaim_works() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(5, 10));
meter.consume(Weight::from_parts(5, 10));
assert_eq!(meter.consumed(), Weight::from_parts(5, 10));
meter.reclaim_proof_size(3);
assert_eq!(meter.consumed(), Weight::from_parts(5, 7));
meter.reclaim_proof_size(10);
assert_eq!(meter.consumed(), Weight::from_parts(5, 0));
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "Weight counter overflow")]
fn consume_defensive_fail() {
let mut meter = WeightMeter::with_limit(Weight::from_parts(10, 0));
let _ = meter.consume(Weight::from_parts(11, 0));
}
}
@@ -0,0 +1,776 @@
// This file is part of Bizinikiwi.
// 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.
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
use core::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};
use pezsp_arithmetic::traits::{Bounded, CheckedAdd, CheckedSub, Zero};
use super::*;
#[derive(
Encode,
Decode,
DecodeWithMemTracking,
MaxEncodedLen,
TypeInfo,
Eq,
PartialEq,
Copy,
Clone,
Debug,
Default,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
pub struct Weight {
#[codec(compact)]
/// The weight of computational time used based on some reference hardware.
ref_time: u64,
#[codec(compact)]
/// The weight of storage space used by proof of validity.
proof_size: u64,
}
impl Weight {
/// Set the reference time part of the weight.
pub const fn set_ref_time(mut self, c: u64) -> Self {
self.ref_time = c;
self
}
/// Set the storage size part of the weight.
pub const fn set_proof_size(mut self, c: u64) -> Self {
self.proof_size = c;
self
}
/// Return the reference time part of the weight.
pub const fn ref_time(&self) -> u64 {
self.ref_time
}
/// Return the storage size part of the weight.
pub const fn proof_size(&self) -> u64 {
self.proof_size
}
/// Return a mutable reference to the reference time part of the weight.
pub fn ref_time_mut(&mut self) -> &mut u64 {
&mut self.ref_time
}
/// Return a mutable reference to the storage size part of the weight.
pub fn proof_size_mut(&mut self) -> &mut u64 {
&mut self.proof_size
}
/// The maximal weight in all dimensions.
pub const MAX: Self = Self { ref_time: u64::MAX, proof_size: u64::MAX };
/// Get the conservative min of `self` and `other` weight.
pub fn min(&self, other: Self) -> Self {
Self {
ref_time: self.ref_time.min(other.ref_time),
proof_size: self.proof_size.min(other.proof_size),
}
}
/// Get the aggressive max of `self` and `other` weight.
pub fn max(&self, other: Self) -> Self {
Self {
ref_time: self.ref_time.max(other.ref_time),
proof_size: self.proof_size.max(other.proof_size),
}
}
/// Try to add some `other` weight while upholding the `limit`.
pub fn try_add(&self, other: &Self, limit: &Self) -> Option<Self> {
let total = self.checked_add(other)?;
if total.any_gt(*limit) {
None
} else {
Some(total)
}
}
/// Construct [`Weight`] from weight parts, namely reference time and proof size weights.
pub const fn from_parts(ref_time: u64, proof_size: u64) -> Self {
Self { ref_time, proof_size }
}
/// Construct [`Weight`] from the same weight for all parts.
pub const fn from_all(value: u64) -> Self {
Self { ref_time: value, proof_size: value }
}
/// Saturating [`Weight`] addition. Computes `self + rhs`, saturating at the numeric bounds of
/// all fields instead of overflowing.
pub const fn saturating_add(self, rhs: Self) -> Self {
Self {
ref_time: self.ref_time.saturating_add(rhs.ref_time),
proof_size: self.proof_size.saturating_add(rhs.proof_size),
}
}
/// Saturating [`Weight`] subtraction. Computes `self - rhs`, saturating at the numeric bounds
/// of all fields instead of overflowing.
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self {
ref_time: self.ref_time.saturating_sub(rhs.ref_time),
proof_size: self.proof_size.saturating_sub(rhs.proof_size),
}
}
/// Saturating [`Weight`] scalar multiplication. Computes `self.field * scalar` for all fields,
/// saturating at the numeric bounds of all fields instead of overflowing.
pub const fn saturating_mul(self, scalar: u64) -> Self {
Self {
ref_time: self.ref_time.saturating_mul(scalar),
proof_size: self.proof_size.saturating_mul(scalar),
}
}
/// Saturating [`Weight`] scalar division. Computes `self.field / scalar` for all fields,
/// saturating at the numeric bounds of all fields instead of overflowing.
pub const fn saturating_div(self, scalar: u64) -> Self {
Self {
ref_time: self.ref_time.saturating_div(scalar),
proof_size: self.proof_size.saturating_div(scalar),
}
}
/// Saturating [`Weight`] scalar exponentiation. Computes `self.field.pow(exp)` for all fields,
/// saturating at the numeric bounds of all fields instead of overflowing.
pub const fn saturating_pow(self, exp: u32) -> Self {
Self {
ref_time: self.ref_time.saturating_pow(exp),
proof_size: self.proof_size.saturating_pow(exp),
}
}
/// Increment [`Weight`] by `amount` via saturating addition.
pub fn saturating_accrue(&mut self, amount: Self) {
*self = self.saturating_add(amount);
}
/// Reduce [`Weight`] by `amount` via saturating subtraction.
pub fn saturating_reduce(&mut self, amount: Self) {
*self = self.saturating_sub(amount);
}
/// Checked [`Weight`] addition. Computes `self + rhs`, returning `None` if overflow occurred.
pub const fn checked_add(&self, rhs: &Self) -> Option<Self> {
let ref_time = match self.ref_time.checked_add(rhs.ref_time) {
Some(t) => t,
None => return None,
};
let proof_size = match self.proof_size.checked_add(rhs.proof_size) {
Some(s) => s,
None => return None,
};
Some(Self { ref_time, proof_size })
}
/// Checked [`Weight`] subtraction. Computes `self - rhs`, returning `None` if overflow
/// occurred.
pub const fn checked_sub(&self, rhs: &Self) -> Option<Self> {
let ref_time = match self.ref_time.checked_sub(rhs.ref_time) {
Some(t) => t,
None => return None,
};
let proof_size = match self.proof_size.checked_sub(rhs.proof_size) {
Some(s) => s,
None => return None,
};
Some(Self { ref_time, proof_size })
}
/// Checked [`Weight`] scalar multiplication. Computes `self.field * scalar` for each field,
/// returning `None` if overflow occurred.
pub const fn checked_mul(self, scalar: u64) -> Option<Self> {
let ref_time = match self.ref_time.checked_mul(scalar) {
Some(t) => t,
None => return None,
};
let proof_size = match self.proof_size.checked_mul(scalar) {
Some(s) => s,
None => return None,
};
Some(Self { ref_time, proof_size })
}
/// Checked [`Weight`] scalar division. Computes `self.field / scalar` for each field, returning
/// `None` if overflow occurred.
pub const fn checked_div(self, scalar: u64) -> Option<Self> {
let ref_time = match self.ref_time.checked_div(scalar) {
Some(t) => t,
None => return None,
};
let proof_size = match self.proof_size.checked_div(scalar) {
Some(s) => s,
None => return None,
};
Some(Self { ref_time, proof_size })
}
/// Calculates how many `other` fit into `self`.
///
/// Divides each component of `self` against the same component of `other`. Returns the minimum
/// of all those divisions. Returns `None` in case **all** components of `other` are zero.
///
/// This returns `Some` even if some components of `other` are zero as long as there is at least
/// one non-zero component in `other`. The division for this particular component will then
/// yield the maximum value (e.g u64::MAX). This is because we assume not every operation and
/// hence each `Weight` will necessarily use each resource.
pub const fn checked_div_per_component(self, other: &Self) -> Option<u64> {
let mut all_zero = true;
let ref_time = match self.ref_time.checked_div(other.ref_time) {
Some(ref_time) => {
all_zero = false;
ref_time
},
None => u64::MAX,
};
let proof_size = match self.proof_size.checked_div(other.proof_size) {
Some(proof_size) => {
all_zero = false;
proof_size
},
None => u64::MAX,
};
if all_zero {
None
} else {
Some(if ref_time < proof_size { ref_time } else { proof_size })
}
}
/// Try to increase `self` by `amount` via checked addition.
pub fn checked_accrue(&mut self, amount: Self) -> Option<()> {
self.checked_add(&amount).map(|new_self| *self = new_self)
}
/// Try to reduce `self` by `amount` via checked subtraction.
pub fn checked_reduce(&mut self, amount: Self) -> Option<()> {
self.checked_sub(&amount).map(|new_self| *self = new_self)
}
/// Return a [`Weight`] where all fields are zero.
pub const fn zero() -> Self {
Self { ref_time: 0, proof_size: 0 }
}
/// Constant version of Add for `ref_time` component with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn add_ref_time(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time + scalar, proof_size: self.proof_size }
}
/// Constant version of Add for `proof_size` component with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn add_proof_size(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time, proof_size: self.proof_size + scalar }
}
/// Constant version of Sub for `ref_time` component with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn sub_ref_time(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time - scalar, proof_size: self.proof_size }
}
/// Constant version of Sub for `proof_size` component with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn sub_proof_size(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time, proof_size: self.proof_size - scalar }
}
/// Saturating version of Add for `ref_time` component with u64.
pub const fn saturating_add_ref_time(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time.saturating_add(scalar), proof_size: self.proof_size }
}
/// Saturating version of Add for `proof_size` component with u64.
pub const fn saturating_add_proof_size(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time, proof_size: self.proof_size.saturating_add(scalar) }
}
/// Saturating version of Sub for `ref_time` component with u64.
pub const fn saturating_sub_ref_time(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time.saturating_sub(scalar), proof_size: self.proof_size }
}
/// Saturating version of Sub for `proof_size` component with u64.
pub const fn saturating_sub_proof_size(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time, proof_size: self.proof_size.saturating_sub(scalar) }
}
/// Constant version of Div with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn div(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time / scalar, proof_size: self.proof_size / scalar }
}
/// Constant version of Mul with u64.
///
/// Is only overflow safe when evaluated at compile-time.
pub const fn mul(self, scalar: u64) -> Self {
Self { ref_time: self.ref_time * scalar, proof_size: self.proof_size * scalar }
}
/// Returns true if any of `self`'s constituent weights is strictly greater than that of the
/// `other`'s, otherwise returns false.
pub const fn any_gt(self, other: Self) -> bool {
self.ref_time > other.ref_time || self.proof_size > other.proof_size
}
/// Returns true if all of `self`'s constituent weights is strictly greater than that of the
/// `other`'s, otherwise returns false.
pub const fn all_gt(self, other: Self) -> bool {
self.ref_time > other.ref_time && self.proof_size > other.proof_size
}
/// Returns true if any of `self`'s constituent weights is strictly less than that of the
/// `other`'s, otherwise returns false.
pub const fn any_lt(self, other: Self) -> bool {
self.ref_time < other.ref_time || self.proof_size < other.proof_size
}
/// Returns true if all of `self`'s constituent weights is strictly less than that of the
/// `other`'s, otherwise returns false.
pub const fn all_lt(self, other: Self) -> bool {
self.ref_time < other.ref_time && self.proof_size < other.proof_size
}
/// Returns true if any of `self`'s constituent weights is greater than or equal to that of the
/// `other`'s, otherwise returns false.
pub const fn any_gte(self, other: Self) -> bool {
self.ref_time >= other.ref_time || self.proof_size >= other.proof_size
}
/// Returns true if all of `self`'s constituent weights is greater than or equal to that of the
/// `other`'s, otherwise returns false.
pub const fn all_gte(self, other: Self) -> bool {
self.ref_time >= other.ref_time && self.proof_size >= other.proof_size
}
/// Returns true if any of `self`'s constituent weights is less than or equal to that of the
/// `other`'s, otherwise returns false.
pub const fn any_lte(self, other: Self) -> bool {
self.ref_time <= other.ref_time || self.proof_size <= other.proof_size
}
/// Returns true if all of `self`'s constituent weights is less than or equal to that of the
/// `other`'s, otherwise returns false.
pub const fn all_lte(self, other: Self) -> bool {
self.ref_time <= other.ref_time && self.proof_size <= other.proof_size
}
/// Returns true if any of `self`'s constituent weights is equal to that of the `other`'s,
/// otherwise returns false.
pub const fn any_eq(self, other: Self) -> bool {
self.ref_time == other.ref_time || self.proof_size == other.proof_size
}
// NOTE: `all_eq` does not exist, as it's simply the `eq` method from the `PartialEq` trait.
}
impl Zero for Weight {
fn zero() -> Self {
Self::zero()
}
fn is_zero(&self) -> bool {
self == &Self::zero()
}
}
impl Add for Weight {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
ref_time: self.ref_time + rhs.ref_time,
proof_size: self.proof_size + rhs.proof_size,
}
}
}
impl Sub for Weight {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self {
ref_time: self.ref_time - rhs.ref_time,
proof_size: self.proof_size - rhs.proof_size,
}
}
}
impl<T> Mul<T> for Weight
where
T: Mul<u64, Output = u64> + Copy,
{
type Output = Self;
fn mul(self, b: T) -> Self {
Self { ref_time: b * self.ref_time, proof_size: b * self.proof_size }
}
}
#[cfg(any(test, feature = "std"))]
impl From<u64> for Weight {
fn from(value: u64) -> Self {
Self::from_parts(value, value)
}
}
#[cfg(any(test, feature = "std"))]
impl From<(u64, u64)> for Weight {
fn from(value: (u64, u64)) -> Self {
Self::from_parts(value.0, value.1)
}
}
macro_rules! weight_mul_per_impl {
($($t:ty),* $(,)?) => {
$(
impl Mul<Weight> for $t {
type Output = Weight;
fn mul(self, b: Weight) -> Weight {
Weight {
ref_time: self * b.ref_time,
proof_size: self * b.proof_size,
}
}
}
)*
}
}
weight_mul_per_impl!(
pezsp_arithmetic::Percent,
pezsp_arithmetic::PerU16,
pezsp_arithmetic::Permill,
pezsp_arithmetic::Perbill,
pezsp_arithmetic::Perquintill,
);
macro_rules! weight_mul_primitive_impl {
($($t:ty),* $(,)?) => {
$(
impl Mul<Weight> for $t {
type Output = Weight;
fn mul(self, b: Weight) -> Weight {
Weight {
ref_time: u64::from(self) * b.ref_time,
proof_size: u64::from(self) * b.proof_size,
}
}
}
)*
}
}
weight_mul_primitive_impl!(u8, u16, u32, u64);
impl<T> Div<T> for Weight
where
u64: Div<T, Output = u64>,
T: Copy,
{
type Output = Self;
fn div(self, b: T) -> Self {
Self { ref_time: self.ref_time / b, proof_size: self.proof_size / b }
}
}
impl CheckedAdd for Weight {
fn checked_add(&self, rhs: &Self) -> Option<Self> {
self.checked_add(rhs)
}
}
impl CheckedSub for Weight {
fn checked_sub(&self, rhs: &Self) -> Option<Self> {
self.checked_sub(rhs)
}
}
impl core::fmt::Display for Weight {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Weight(ref_time: {}, proof_size: {})", self.ref_time, self.proof_size)
}
}
impl Bounded for Weight {
fn min_value() -> Self {
Zero::zero()
}
fn max_value() -> Self {
Self::MAX
}
}
impl AddAssign for Weight {
fn add_assign(&mut self, other: Self) {
*self = Self {
ref_time: self.ref_time + other.ref_time,
proof_size: self.proof_size + other.proof_size,
};
}
}
impl SubAssign for Weight {
fn sub_assign(&mut self, other: Self) {
*self = Self {
ref_time: self.ref_time - other.ref_time,
proof_size: self.proof_size - other.proof_size,
};
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_zero_works() {
assert!(Weight::zero().is_zero());
assert!(!Weight::from_parts(1, 0).is_zero());
assert!(!Weight::from_parts(0, 1).is_zero());
assert!(!Weight::MAX.is_zero());
}
#[test]
fn from_parts_works() {
assert_eq!(Weight::from_parts(0, 0), Weight { ref_time: 0, proof_size: 0 });
assert_eq!(Weight::from_parts(5, 5), Weight { ref_time: 5, proof_size: 5 });
assert_eq!(
Weight::from_parts(u64::MAX, u64::MAX),
Weight { ref_time: u64::MAX, proof_size: u64::MAX }
);
}
#[test]
fn from_all_works() {
assert_eq!(Weight::from_all(0), Weight::from_parts(0, 0));
assert_eq!(Weight::from_all(5), Weight::from_parts(5, 5));
assert_eq!(Weight::from_all(u64::MAX), Weight::from_parts(u64::MAX, u64::MAX));
}
#[test]
fn from_u64_works() {
assert_eq!(Weight::from_all(0), 0_u64.into());
assert_eq!(Weight::from_all(123), 123_u64.into());
assert_eq!(Weight::from_all(u64::MAX), u64::MAX.into());
}
#[test]
fn from_u64_pair_works() {
assert_eq!(Weight::from_parts(0, 1), (0, 1).into());
assert_eq!(Weight::from_parts(123, 321), (123u64, 321u64).into());
assert_eq!(Weight::from_parts(u64::MAX, 0), (u64::MAX, 0).into());
}
#[test]
fn saturating_reduce_works() {
let mut weight = Weight::from_parts(10, 20);
weight.saturating_reduce(Weight::from_all(5));
assert_eq!(weight, Weight::from_parts(5, 15));
weight.saturating_reduce(Weight::from_all(5));
assert_eq!(weight, Weight::from_parts(0, 10));
weight.saturating_reduce(Weight::from_all(11));
assert!(weight.is_zero());
weight.saturating_reduce(Weight::from_all(u64::MAX));
assert!(weight.is_zero());
}
#[test]
fn checked_accrue_works() {
let mut weight = Weight::from_parts(10, 20);
assert!(weight.checked_accrue(Weight::from_all(2)).is_some());
assert_eq!(weight, Weight::from_parts(12, 22));
assert!(weight.checked_accrue(Weight::from_parts(u64::MAX, 0)).is_none());
assert!(weight.checked_accrue(Weight::from_parts(0, u64::MAX)).is_none());
assert_eq!(weight, Weight::from_parts(12, 22));
assert!(weight
.checked_accrue(Weight::from_parts(u64::MAX - 12, u64::MAX - 22))
.is_some());
assert_eq!(weight, Weight::MAX);
assert!(weight.checked_accrue(Weight::from_parts(1, 0)).is_none());
assert!(weight.checked_accrue(Weight::from_parts(0, 1)).is_none());
assert_eq!(weight, Weight::MAX);
}
#[test]
fn checked_reduce_works() {
let mut weight = Weight::from_parts(10, 20);
assert!(weight.checked_reduce(Weight::from_all(2)).is_some());
assert_eq!(weight, Weight::from_parts(8, 18));
assert!(weight.checked_reduce(Weight::from_parts(9, 0)).is_none());
assert!(weight.checked_reduce(Weight::from_parts(0, 19)).is_none());
assert_eq!(weight, Weight::from_parts(8, 18));
assert!(weight.checked_reduce(Weight::from_parts(8, 0)).is_some());
assert_eq!(weight, Weight::from_parts(0, 18));
assert!(weight.checked_reduce(Weight::from_parts(0, 18)).is_some());
assert!(weight.is_zero());
}
#[test]
fn checked_div_per_component_works() {
assert_eq!(
Weight::from_parts(10, 20).checked_div_per_component(&Weight::from_parts(2, 10)),
Some(2)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(2, 10)),
Some(5)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(1, 10)),
Some(10)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(2, 1)),
Some(5)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(0, 10)),
Some(20)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(1, 0)),
Some(10)
);
assert_eq!(
Weight::from_parts(0, 200).checked_div_per_component(&Weight::from_parts(2, 3)),
Some(0)
);
assert_eq!(
Weight::from_parts(10, 0).checked_div_per_component(&Weight::from_parts(2, 3)),
Some(0)
);
assert_eq!(
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(0, 0)),
None,
);
assert_eq!(
Weight::from_parts(0, 0).checked_div_per_component(&Weight::from_parts(0, 0)),
None,
);
}
#[test]
fn saturating_add_ref_time_works() {
// Normal addition
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_add_ref_time(5), Weight::from_parts(15, 20));
// Saturation at MAX
let weight = Weight::from_parts(u64::MAX - 5, 20);
assert_eq!(weight.saturating_add_ref_time(10), Weight::from_parts(u64::MAX, 20));
// Already at MAX
let weight = Weight::from_parts(u64::MAX, 20);
assert_eq!(weight.saturating_add_ref_time(1), Weight::from_parts(u64::MAX, 20));
// Adding zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_add_ref_time(0), Weight::from_parts(10, 20));
// Proof size remains unchanged
let weight = Weight::from_parts(10, 42);
assert_eq!(weight.saturating_add_ref_time(5).proof_size(), 42);
}
#[test]
fn saturating_add_proof_size_works() {
// Normal addition
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_add_proof_size(5), Weight::from_parts(10, 25));
// Saturation at MAX
let weight = Weight::from_parts(10, u64::MAX - 5);
assert_eq!(weight.saturating_add_proof_size(10), Weight::from_parts(10, u64::MAX));
// Already at MAX
let weight = Weight::from_parts(10, u64::MAX);
assert_eq!(weight.saturating_add_proof_size(1), Weight::from_parts(10, u64::MAX));
// Adding zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_add_proof_size(0), Weight::from_parts(10, 20));
// Ref time remains unchanged
let weight = Weight::from_parts(42, 20);
assert_eq!(weight.saturating_add_proof_size(5).ref_time(), 42);
}
#[test]
fn saturating_sub_ref_time_works() {
// Normal subtraction
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_ref_time(5), Weight::from_parts(5, 20));
// Saturation at zero (underflow)
let weight = Weight::from_parts(5, 20);
assert_eq!(weight.saturating_sub_ref_time(10), Weight::from_parts(0, 20));
// Already at zero
let weight = Weight::from_parts(0, 20);
assert_eq!(weight.saturating_sub_ref_time(1), Weight::from_parts(0, 20));
// Subtracting zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_ref_time(0), Weight::from_parts(10, 20));
// Exact subtraction to zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_ref_time(10), Weight::from_parts(0, 20));
// Proof size remains unchanged
let weight = Weight::from_parts(10, 42);
assert_eq!(weight.saturating_sub_ref_time(5).proof_size(), 42);
}
#[test]
fn saturating_sub_proof_size_works() {
// Normal subtraction
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_proof_size(5), Weight::from_parts(10, 15));
// Saturation at zero (underflow)
let weight = Weight::from_parts(10, 5);
assert_eq!(weight.saturating_sub_proof_size(10), Weight::from_parts(10, 0));
// Already at zero
let weight = Weight::from_parts(10, 0);
assert_eq!(weight.saturating_sub_proof_size(1), Weight::from_parts(10, 0));
// Subtracting zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_proof_size(0), Weight::from_parts(10, 20));
// Exact subtraction to zero
let weight = Weight::from_parts(10, 20);
assert_eq!(weight.saturating_sub_proof_size(20), Weight::from_parts(10, 0));
// Ref time remains unchanged
let weight = Weight::from_parts(42, 20);
assert_eq!(weight.saturating_sub_proof_size(5).ref_time(), 42);
}
}