// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of substrate-subxt. // // subxt 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. // // subxt 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-subxt. If not, see . use codec::{ Decode, Encode, }; use core::{ fmt::Debug, marker::PhantomData, }; use sp_runtime::{ generic::Era, traits::SignedExtension, transaction_validity::TransactionValidityError, }; use crate::frame::{ balances::Balances, system::System, }; /// SignedExtra checks copied from substrate, in order to remove requirement to implement /// substrate's `frame_system::Trait` /// Ensure the runtime version registered in the transaction is the same as at present. /// /// # Note /// /// This is modified from the substrate version to allow passing in of the version, which is /// returned via `additional_signed()`. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckVersion( pub PhantomData, /// Local version to be used for `AdditionalSigned` #[codec(skip)] pub u32, ); impl SignedExtension for CheckVersion where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckVersion"; type AccountId = u64; type Call = (); type AdditionalSigned = u32; type Pre = (); fn additional_signed( &self, ) -> Result { Ok(self.1) } } /// Check genesis hash /// /// # Note /// /// This is modified from the substrate version to allow passing in of the genesis hash, which is /// returned via `additional_signed()`. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckGenesis( pub PhantomData, /// Local genesis hash to be used for `AdditionalSigned` #[codec(skip)] pub T::Hash, ); impl SignedExtension for CheckGenesis where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckGenesis"; type AccountId = u64; type Call = (); type AdditionalSigned = T::Hash; type Pre = (); fn additional_signed( &self, ) -> Result { Ok(self.1) } } /// Check for transaction mortality. /// /// # Note /// /// This is modified from the substrate version to allow passing in of the genesis hash, which is /// returned via `additional_signed()`. It assumes therefore `Era::Immortal` (The transaction is /// valid forever) #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckEra( /// The default structure for the Extra encoding pub (Era, PhantomData), /// Local genesis hash to be used for `AdditionalSigned` #[codec(skip)] pub T::Hash, ); impl SignedExtension for CheckEra where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckEra"; type AccountId = u64; type Call = (); type AdditionalSigned = T::Hash; type Pre = (); fn additional_signed( &self, ) -> Result { Ok(self.1) } } /// Nonce check and increment to give replay protection for transactions. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckNonce(#[codec(compact)] pub T::Index); impl SignedExtension for CheckNonce where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckNonce"; type AccountId = u64; type Call = (); type AdditionalSigned = (); type Pre = (); fn additional_signed( &self, ) -> Result { Ok(()) } } /// Resource limit check. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckWeight(pub PhantomData); impl SignedExtension for CheckWeight where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckWeight"; type AccountId = u64; type Call = (); type AdditionalSigned = (); type Pre = (); fn additional_signed( &self, ) -> Result { Ok(()) } } /// Require the transactor pay for themselves and maybe include a tip to gain additional priority /// in the queue. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct ChargeTransactionPayment(#[codec(compact)] pub T::Balance); impl SignedExtension for ChargeTransactionPayment where T: Balances + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "ChargeTransactionPayment"; type AccountId = u64; type Call = (); type AdditionalSigned = (); type Pre = (); fn additional_signed( &self, ) -> Result { Ok(()) } } /// Checks if a transaction would exhausts the block gas limit. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct CheckBlockGasLimit(pub PhantomData); impl SignedExtension for CheckBlockGasLimit where T: System + Clone + Debug + Eq + Send + Sync, { const IDENTIFIER: &'static str = "CheckBlockGasLimit"; type AccountId = u64; type Call = (); type AdditionalSigned = (); type Pre = (); fn additional_signed( &self, ) -> Result { Ok(()) } } /// Trait for implementing transaction extras for a runtime. pub trait SignedExtra { /// The type the extras. type Extra: SignedExtension; /// Creates a new `SignedExtra`. fn new(version: u32, nonce: T::Index, genesis_hash: T::Hash) -> Self; /// Returns the transaction extra. fn extra(&self) -> Self::Extra; } /// Default `SignedExtra` for substrate runtimes. #[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)] pub struct DefaultExtra { version: u32, nonce: T::Index, genesis_hash: T::Hash, } impl SignedExtra for DefaultExtra { type Extra = ( CheckVersion, CheckGenesis, CheckEra, CheckNonce, CheckWeight, ChargeTransactionPayment, CheckBlockGasLimit, ); fn new(version: u32, nonce: T::Index, genesis_hash: T::Hash) -> Self { DefaultExtra { version, nonce, genesis_hash, } } fn extra(&self) -> Self::Extra { ( CheckVersion(PhantomData, self.version), CheckGenesis(PhantomData, self.genesis_hash), CheckEra((Era::Immortal, PhantomData), self.genesis_hash), CheckNonce(self.nonce), CheckWeight(PhantomData), ChargeTransactionPayment(::Balance::default()), CheckBlockGasLimit(PhantomData), ) } } impl SignedExtension for DefaultExtra { const IDENTIFIER: &'static str = "DefaultExtra"; type AccountId = T::AccountId; type Call = (); type AdditionalSigned = <>::Extra as SignedExtension>::AdditionalSigned; type Pre = (); fn additional_signed( &self, ) -> Result { self.extra().additional_signed() } }