Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions core/sr-primitives/src/generic/checked_extrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::traits::{
self, Member, MaybeDisplay, SignedExtension, DispatchError, Dispatchable, DispatchResult,
ValidateUnsigned
};
use crate::weights::{Weigh, Weight};
use crate::weights::{DispatchInfo, TransactionInfo};
use crate::transaction_validity::TransactionValidity;

/// Definition of something that the external world might want to say; its
Expand Down Expand Up @@ -57,13 +57,13 @@ where
}

fn validate<U: ValidateUnsigned<Call=Self::Call>>(&self,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> TransactionValidity {
if let Some((ref id, ref extra)) = self.signed {
Extra::validate(extra, id, weight, len).into()
Extra::validate(extra, id, info, len).into()
} else {
match Extra::validate_unsigned(weight, len) {
match Extra::validate_unsigned(info, len) {
Ok(extra) => match U::validate_unsigned(&self.function) {
TransactionValidity::Valid(v) =>
TransactionValidity::Valid(v.combine_with(extra)),
Expand All @@ -75,25 +75,25 @@ where
}

fn dispatch(self,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<DispatchResult, DispatchError> {
let maybe_who = if let Some((id, extra)) = self.signed {
Extra::pre_dispatch(extra, &id, weight, len)?;
Extra::pre_dispatch(extra, &id, info, len)?;
Some(id)
} else {
Extra::pre_dispatch_unsigned(weight, len)?;
Extra::pre_dispatch_unsigned(info, len)?;
None
};
Ok(self.function.dispatch(Origin::from(maybe_who)))
}
}

impl<AccountId, Call, Extra> Weigh for CheckedExtrinsic<AccountId, Call, Extra>
impl<AccountId, Call, Extra> DispatchInfo for CheckedExtrinsic<AccountId, Call, Extra>
Comment thread
kianenigma marked this conversation as resolved.
Outdated
where
Call: Weigh,
Call: DispatchInfo,
{
fn weigh(&self) -> Weight {
self.function.weigh()
fn dispatch_info(&self) -> TransactionInfo {
self.function.dispatch_info()
}
}
19 changes: 11 additions & 8 deletions core/sr-primitives/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::traits::{
ValidateUnsigned, SignedExtension, Dispatchable,
};
use crate::{generic, KeyTypeId};
use crate::weights::{Weigh, Weight};
use crate::weights::{DispatchInfo, TransactionInfo};
pub use substrate_primitives::H256;
use substrate_primitives::U256;
use substrate_primitives::ed25519::{Public as AuthorityId};
Expand Down Expand Up @@ -240,7 +240,7 @@ impl<Origin, Call, Extra> Applyable for TestXt<Call, Extra> where

/// Checks to see if this is a valid *transaction*. It returns information on it if so.
fn validate<U: ValidateUnsigned<Call=Self::Call>>(&self,
_weight: Weight,
_info: TransactionInfo,
_len: usize,
) -> TransactionValidity {
TransactionValidity::Valid(Default::default())
Expand All @@ -249,23 +249,26 @@ impl<Origin, Call, Extra> Applyable for TestXt<Call, Extra> where
/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
/// index and sender.
fn dispatch(self,
weight: Weight,
info: TransactionInfo,
len: usize,
) -> Result<DispatchResult, DispatchError> {
let maybe_who = if let Some(who) = self.0 {
Extra::pre_dispatch(self.2, &who, weight, len)?;
Extra::pre_dispatch(self.2, &who, info, len)?;
Some(who)
} else {
Extra::pre_dispatch_unsigned(weight, len)?;
Extra::pre_dispatch_unsigned(info, len)?;
None
};
Ok(self.1.dispatch(maybe_who.into()))
}
}

impl<Call, Extra> Weigh for TestXt<Call, Extra> {
fn weigh(&self) -> Weight {
impl<Call: Encode, Extra: Encode> DispatchInfo for TestXt<Call, Extra> {
fn dispatch_info(&self) -> TransactionInfo {
// for testing: weight == size.
self.0.using_encoded(|d| d.len() as Weight)
TransactionInfo {
weight: self.encode().len() as u32,
..Default::default()
}
}
}
34 changes: 18 additions & 16 deletions core/sr-primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use substrate_primitives::{self, Hasher, Blake2Hasher};
use crate::codec::{Codec, Encode, Decode, HasCompact};
use crate::transaction_validity::{ValidTransaction, TransactionValidity};
use crate::generic::{Digest, DigestItem};
use crate::weights::TransactionInfo;
pub use substrate_primitives::crypto::TypedKey;
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{
Expand Down Expand Up @@ -752,6 +753,7 @@ impl<T: BlindCheckable, Context> Checkable<Context> for T {
/// An abstract error concerning an attempt to verify, check or dispatch the transaction. This
/// cannot be more concrete because it's designed to work reasonably well over a broad range of
/// possible transaction types.
#[cfg_attr(feature = "std", derive(Debug))]
pub enum DispatchError {
/// General error to do with the inability to pay some fees (e.g. account balance too low).
Payment,
Expand Down Expand Up @@ -825,31 +827,31 @@ pub trait SignedExtension:
fn validate(
&self,
_who: &Self::AccountId,
_weight: crate::weights::Weight,
_info: TransactionInfo,
_len: usize,
) -> Result<ValidTransaction, DispatchError> { Ok(Default::default()) }

/// Do any pre-flight stuff for a signed transaction.
fn pre_dispatch(
self,
who: &Self::AccountId,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<(), DispatchError> { self.validate(who, weight, len).map(|_| ()) }
) -> Result<(), DispatchError> { self.validate(who, info, len).map(|_| ()) }

/// Validate an unsigned transaction for the transaction queue. Normally the default
/// implementation is fine since `ValidateUnsigned` is a better way of recognising and
/// validating unsigned transactions.
fn validate_unsigned(
_weight: crate::weights::Weight,
_info: TransactionInfo,
_len: usize,
) -> Result<ValidTransaction, DispatchError> { Ok(Default::default()) }

/// Do any pre-flight stuff for a unsigned transaction.
fn pre_dispatch_unsigned(
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<(), DispatchError> { Self::validate_unsigned(weight, len).map(|_| ()) }
) -> Result<(), DispatchError> { Self::validate_unsigned(info, len).map(|_| ()) }
}

macro_rules! tuple_impl_indexed {
Expand All @@ -869,33 +871,33 @@ macro_rules! tuple_impl_indexed {
fn validate(
&self,
who: &Self::AccountId,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<ValidTransaction, DispatchError> {
let aggregator = vec![$(<$direct as SignedExtension>::validate(&self.$index, who, weight, len)?),+];
let aggregator = vec![$(<$direct as SignedExtension>::validate(&self.$index, who, info, len)?),+];
Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a)))
}
fn pre_dispatch(
self,
who: &Self::AccountId,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<(), DispatchError> {
$(self.$index.pre_dispatch(who, weight, len)?;)+
$(self.$index.pre_dispatch(who, info, len)?;)+
Ok(())
}
fn validate_unsigned(
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<ValidTransaction, DispatchError> {
let aggregator = vec![$($direct::validate_unsigned(weight, len)?),+];
let aggregator = vec![$($direct::validate_unsigned(info, len)?),+];
Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a)))
}
fn pre_dispatch_unsigned(
weight: crate::weights::Weight,
info: TransactionInfo,
Comment thread
kianenigma marked this conversation as resolved.
Outdated
len: usize,
) -> Result<(), DispatchError> {
$($direct::pre_dispatch_unsigned(weight, len)?;)+
$($direct::pre_dispatch_unsigned(info, len)?;)+
Ok(())
}
}
Expand Down Expand Up @@ -944,14 +946,14 @@ pub trait Applyable: Sized + Send + Sync {

/// Checks to see if this is a valid *transaction*. It returns information on it if so.
fn validate<V: ValidateUnsigned<Call=Self::Call>>(&self,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> TransactionValidity;

/// Executes all necessary logic needed prior to dispatch and deconstructs into function call,
/// index and sender.
fn dispatch(self,
weight: crate::weights::Weight,
info: TransactionInfo,
len: usize,
) -> Result<DispatchResult, DispatchError>;
}
Expand Down
107 changes: 74 additions & 33 deletions core/sr-primitives/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,61 @@

//! Primitives for transaction weighting.
//!
//! Each dispatch function within `decl_module!` can now have an optional
//! `#[weight = $x]` attribute. $x can be any object that implements the
//! `Weigh` trait. By default, All transactions are annotated by
//! `#[weight = TransactionWeight::default()]`.
//! Each dispatch function within `decl_module!` can have an optional `#[weight = $x]` attribute.
Comment thread
gavofyork marked this conversation as resolved.
//! `$x` can be any type that implements the `ClassifyDispatch<T>` and `WeighData<T>` traits. By
//! default, All transactions are annotated with `#[weight = WeightedTransaction::default()]`.
//!
//! Note that the decl_module macro _cannot_ enforce this and will simply fail
//! if an invalid struct is passed in.

/// The final type that each `#[weight = $x:expr]`'s
/// expression must evaluate to.
pub use crate::transaction_validity::TransactionPriority;

/// Numeric range of a transaction weight.
pub type Weight = u32;

/// A `Call` enum (aka transaction) that can be weighted using the custom weight attribute of
/// its dispatchable functions. Is implemented by default in the `decl_module!`.
///
/// Both the outer Call enum and the per-module individual ones will implement this.
/// The outer enum simply calls the inner ones based on call type.
pub trait Weigh {
/// Return the weight of this call. This is done independently of its encoded size.
fn weigh(&self) -> Weight;
/// A broad range of dispatch types. This is only distinguishing normal, user-triggered transactions
/// and anything beyond which serves a higher purpose to the system (`Operational`).
#[cfg_attr(feature = "std", derive(Debug))]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum DispatchClass {
/// A normal dispatch.
User,
/// An operational dispatch.
Operational,
}

impl Default for DispatchClass {
fn default() -> Self {
DispatchClass::User
}
}

impl From<WeightedTransaction> for DispatchClass {
fn from(tx: WeightedTransaction) -> Self {
match tx {
WeightedTransaction::Operational(_) => DispatchClass::Operational,
WeightedTransaction::Fixed(_) => DispatchClass::User,
}
}
}

/// A bundle of static information collected from the `#[weight = $x]` attributes.
#[cfg_attr(feature = "std", derive(PartialEq, Eq, Debug))]
#[derive(Clone, Copy, Default)]
pub struct TransactionInfo {
/// Weight of this transaction.
pub weight: Weight,
/// Class of this transaction.
pub class: DispatchClass,
}

/// A `Dispatchable` function (aka transaction) that can carry some static information along with it, using the
/// `#[weight]` attribute.
pub trait DispatchInfo {
/// Return a `TransactionInfo`, containing relevant information of this dispatch.
///
/// This is done independently of its encoded size.
fn dispatch_info(&self) -> TransactionInfo;
}

/// Means of weighing some particular kind of data (`T`).
Expand All @@ -44,38 +79,44 @@ pub trait WeighData<T> {
fn weigh_data(&self, target: T) -> Weight;
}

/// Default type used as the weight representative in a `#[weight = x]` attribute.
/// Means of classifying a dispatchable function.
pub trait ClassifyDispatch<T> {
/// Classify the dispatch function based on input data `target` of type `T`.
fn classify_dispatch(&self, target: T) -> DispatchClass;
}

/// Default type used with the `#[weight = x]` attribute in a substrate chain.
///
/// A user may pass in any other type that implements [`Weigh`]. If not, the `Default`
/// implementation of [`TransactionWeight`] is used.
pub enum TransactionWeight {
/// Basic weight (base, byte).
/// The values contained are the base weight and byte weight respectively.
/// A user may pass in any other type that implements the correct traits. If not, the `Default`
/// implementation of [`WeightedTransaction`] is used.
#[derive(Clone, Copy)]
pub enum WeightedTransaction {
Comment thread
kianenigma marked this conversation as resolved.
Outdated
/// A fixed-weight transaction. No dependency on state or input.
Fixed(Weight),
Comment thread
kianenigma marked this conversation as resolved.
Outdated
/// Maximum fee. This implies that this transaction _might_ get included but
/// no more transaction can be added. This can be done by setting the
/// implementation to _maximum block weight_.
Max,
Comment thread
kianenigma marked this conversation as resolved.
/// Free. The transaction does not increase the total weight
/// (i.e. is not included in weight calculation).
Free,
Comment thread
kianenigma marked this conversation as resolved.
/// An operational transaction. Still incurs a weight-fee but typically has a higher priority.
Operational(Weight),
Comment thread
kianenigma marked this conversation as resolved.
Outdated
}

impl<T> WeighData<T> for TransactionWeight {
impl<T> WeighData<T> for WeightedTransaction {
fn weigh_data(&self, _: T) -> Weight {
match self {
TransactionWeight::Fixed(w) => *w,
TransactionWeight::Max => 3 * 1024 * 1024,
TransactionWeight::Free => 0,
WeightedTransaction::Fixed(w) => *w,
WeightedTransaction::Operational(w) => *w,
}
}
}

impl Default for TransactionWeight {
impl<T> ClassifyDispatch<T> for WeightedTransaction {
fn classify_dispatch(&self, _: T) -> DispatchClass {
DispatchClass::from(*self)
}
}

impl Default for WeightedTransaction {
fn default() -> Self {
// This implies that the weight is currently equal to 100, nothing more
// for all substrate transactions that do NOT explicitly annotate weight.
// TODO #2431 needs to be updated with proper max values.
TransactionWeight::Fixed(1)
WeightedTransaction::Fixed(1)
}
}
3 changes: 3 additions & 0 deletions node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub fn native_version() -> NativeVersion {
parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024;
pub const MaximumBlockSize: u32 = 2 * 1024;
}

impl system::Trait for Runtime {
Expand All @@ -138,6 +139,8 @@ impl system::Trait for Runtime {
type BlockHashCount = BlockHashCount;
/// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
type MaximumBlockWeight = MaximumBlockWeight;
/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
type MaximumBlockSize = MaximumBlockSize;
}

impl aura::Trait for Runtime {
Expand Down
2 changes: 2 additions & 0 deletions node-template/runtime/src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ mod tests {
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockSize: u32 = 2 * 1024;
}
impl system::Trait for Test {
type Origin = Origin;
Expand All @@ -100,6 +101,7 @@ mod tests {
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockSize = MaximumBlockSize;
}
impl Trait for Test {
type Event = ();
Expand Down
Loading