// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see .
//! # Primitives for transaction weighting.
//!
//! All dispatchable functions defined in `decl_module!` must provide two trait implementations:
//! - [`WeightData`]: To determine the weight of the dispatch.
//! - [`ClassifyDispatch`]: To determine the class of the dispatch. See the enum definition for
//! more information on dispatch classes.
//!
//! Every dispatchable function is responsible for providing this data via an optional `#[weight =
//! $x]` attribute. In this snipped, `$x` can be any user provided struct that implements the
//! two aforementioned traits.
//!
//! Substrate then bundles then output information of the two traits into [`DispatchInfo`] struct
//! and provides it by implementing the [`GetDispatchInfo`] for all `Call` variants, and opaque
//! extrinsic types.
//!
//! If no `#[weight]` is defined, the macro automatically injects the `Default` implementation of
//! the [`SimpleDispatchInfo`].
//!
//! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct
//! (something that does not implement `Weighable`) is passed in.
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use codec::{Encode, Decode};
use sp_arithmetic::traits::Bounded;
use sp_runtime::{
RuntimeDebug,
traits::SignedExtension,
generic::{CheckedExtrinsic, UncheckedExtrinsic},
};
use crate::dispatch::{DispatchErrorWithPostInfo, DispatchError};
/// Re-export priority as type
pub use sp_runtime::transaction_validity::TransactionPriority;
/// Numeric range of a transaction weight.
pub type Weight = u32;
/// Means of weighing some particular kind of data (`T`).
pub trait WeighData {
/// Weigh the data `T` given by `target`. When implementing this for a dispatchable, `T` will be
/// a tuple of all arguments given to the function (except origin).
fn weigh_data(&self, target: T) -> Weight;
}
/// Means of classifying a dispatchable function.
pub trait ClassifyDispatch {
/// Classify the dispatch function based on input data `target` of type `T`. When implementing
/// this for a dispatchable, `T` will be a tuple of all arguments given to the function (except
/// origin).
fn classify_dispatch(&self, target: T) -> DispatchClass;
}
/// Indicates if dispatch function should pay fees or not.
/// If set to false, the block resource limits are applied, yet no fee is deducted.
pub trait PaysFee {
fn pays_fee(&self, _target: T) -> bool {
true
}
}
/// A generalized group of dispatch types. This is only distinguishing normal, user-triggered transactions
/// (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`).
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, RuntimeDebug)]
pub enum DispatchClass {
/// A normal dispatch.
Normal,
/// An operational dispatch.
Operational,
/// A mandatory dispatch. These kinds of dispatch are always included regardless of their
/// weight, therefore it is critical that they are separately validated to ensure that a
/// malicious validator cannot craft a valid but impossibly heavy block. Usually this just means
/// ensuring that the extrinsic can only be included once and that it is always very light.
///
/// Do *NOT* use it for extrinsics that can be heavy.
///
/// The only real use case for this is inherent extrinsics that are required to execute in a
/// block for the block to be valid, and it solves the issue in the case that the block
/// initialization is sufficiently heavy to mean that those inherents do not fit into the
/// block. Essentially, we assume that in these exceptional circumstances, it is better to
/// allow an overweight block to be created than to not allow any block at all to be created.
Mandatory,
}
impl Default for DispatchClass {
fn default() -> Self {
DispatchClass::Normal
}
}
impl From for DispatchClass {
fn from(tx: SimpleDispatchInfo) -> Self {
match tx {
SimpleDispatchInfo::FixedOperational(_) => DispatchClass::Operational,
SimpleDispatchInfo::MaxOperational => DispatchClass::Operational,
SimpleDispatchInfo::FixedNormal(_) => DispatchClass::Normal,
SimpleDispatchInfo::MaxNormal => DispatchClass::Normal,
SimpleDispatchInfo::InsecureFreeNormal => DispatchClass::Normal,
SimpleDispatchInfo::FixedMandatory(_) => DispatchClass::Mandatory,
}
}
}
/// A bundle of static information collected from the `#[weight = $x]` attributes.
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
pub struct DispatchInfo {
/// Weight of this transaction.
pub weight: Weight,
/// Class of this transaction.
pub class: DispatchClass,
/// Does this transaction pay fees.
pub pays_fee: bool,
}
/// Weight information that is only available post dispatch.
#[derive(Clone, Copy, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode)]
pub struct PostDispatchInfo {
/// Actual weight consumed by a call or `None` which stands for the worst case static weight.
pub actual_weight: Option,
}
impl PostDispatchInfo {
/// Calculate how much (if any) weight was not used by the `Dispatchable`.
pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
if let Some(actual_weight) = self.actual_weight {
if actual_weight >= info.weight {
0
} else {
info.weight - actual_weight
}
} else {
0
}
}
}
impl From