diff --git a/core/client/src/block_builder/api.rs b/core/client/src/block_builder/api.rs index 5bf742a4560d4..c05791e6f1fa7 100644 --- a/core/client/src/block_builder/api.rs +++ b/core/client/src/block_builder/api.rs @@ -19,12 +19,52 @@ use sr_primitives::{traits::Block as BlockT, ApplyResult}; use rstd::vec::Vec; use sr_api_macros::decl_runtime_apis; +use codec::Decode; pub use inherents::{InherentData, CheckInherentsResult}; +/// Outcome of a valid extrinsic application. Capable of being sliced. +/// +/// Deprecated and just present for compatibility reasons. +#[derive(Eq, PartialEq, Clone, Copy, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +#[repr(u8)] +pub enum ApplyOutcomeOld { + /// Successful application (extrinsic reported no issue). + Success = 0, + /// Failed application (extrinsic was probably a no-op other than fees). + Fail = 1, +} + +/// Reason why an extrinsic couldn't be applied (i.e. invalid extrinsic). +/// +/// Deprecated and just present for compatibility reasons. +#[derive(Eq, PartialEq, Clone, Copy, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +#[repr(u8)] +pub enum ApplyErrorOld { + /// Bad signature. + BadSignature = 0, + /// Nonce too low. + Stale = 1, + /// Nonce too high. + Future = 2, + /// Sending account had too low a balance. + CantPay = 3, + /// Block is full, no more extrinsics can be applied. + FullBlock = 255, +} + +/// Result from attempt to apply an extrinsic. +#[deprecated(note="Use `ApplyResult` from `sr-primitives`.")] +pub type ApplyResultOld = Result; + decl_runtime_apis! { /// The `BlockBuilder` api trait that provides required functions for building a block for a runtime. - #[api_version(3)] + #[api_version(4)] pub trait BlockBuilder { + /// Apply the given extrinsics. + #[changed_in(4)] + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResultOld; /// Apply the given extrinsics. fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyResult; /// Finish the current block. diff --git a/core/client/src/block_builder/block_builder.rs b/core/client/src/block_builder/block_builder.rs index b6fae5068a284..b0426ad566561 100644 --- a/core/client/src/block_builder/block_builder.rs +++ b/core/client/src/block_builder/block_builder.rs @@ -97,21 +97,40 @@ where let block_id = &self.block_id; let extrinsics = &mut self.extrinsics; - self.api.map_api_result(|api| { - match api.apply_extrinsic_with_context( - block_id, - ExecutionContext::BlockConstruction, - xt.clone() - )? { - Ok(_) => { - extrinsics.push(xt); - Ok(()) + if self.api.has_api_with::, _>(block_id, |version| version < 3)? { + self.api.map_api_result(|api| { + #[allow(deprecated)] + match api.apply_extrinsic_before_version_4_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + )? { + Ok(_) => { + extrinsics.push(xt); + Ok(()) + } + Err(e) => { + Err(error::Error::Msg(format!("Apply extrinsic failed: {:?}", e))) + } } - Err(e) => { - Err(error::Error::ApplyExtrinsicFailed(e)) + }) + } else { + self.api.map_api_result(|api| { + match api.apply_extrinsic_with_context( + block_id, + ExecutionContext::BlockConstruction, + xt.clone(), + )? { + Ok(_) => { + extrinsics.push(xt); + Ok(()) + } + Err(e) => { + Err(error::Error::ApplyExtrinsicFailed(e)) + } } - } - }) + }) + } } /// Consume the builder to return a valid `Block` containing all pushed extrinsics. diff --git a/core/client/src/runtime_api.rs b/core/client/src/runtime_api.rs index ed5c9fad48dc3..f73f0388b537b 100644 --- a/core/client/src/runtime_api.rs +++ b/core/client/src/runtime_api.rs @@ -28,7 +28,11 @@ pub use sr_primitives::{ Block as BlockT, GetNodeBlockType, GetRuntimeBlockType, Header as HeaderT, ApiRef, RuntimeApiInfo, Hash as HashT, }, - generic::BlockId, transaction_validity::TransactionValidity, + generic::BlockId, + transaction_validity::{ + TransactionValidity, ValidTransaction, TransactionLongevity, TransactionPriority, + InvalidTransaction, UnknownTransaction, + }, }; #[doc(hidden)] pub use primitives::{offchain, ExecutionContext}; @@ -155,6 +159,52 @@ pub trait CallRuntimeAt { fn runtime_version_at(&self, at: &BlockId) -> error::Result; } +/// Information on a transaction's validity and, if valid, on how it relates to other transactions. +/// +/// Deprecated and just present for compatibility reasons. +#[derive(Clone, PartialEq, Eq, Encode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum TransactionValidityOld { + /// Transaction is invalid. Details are described by the error code. + Invalid(i8), + /// Transaction is valid. + Valid(ValidTransaction), + /// Transaction validity can't be determined. + Unknown(i8), +} + +impl Decode for TransactionValidityOld { + fn decode(value: &mut I) -> Result { + match value.read_byte()? { + 0 => Ok(TransactionValidityOld::Invalid(i8::decode(value)?)), + 1 => { + let priority = TransactionPriority::decode(value)?; + let requires = rstd::vec::Vec::decode(value)?; + let provides = rstd::vec::Vec::decode(value)?; + let longevity = TransactionLongevity::decode(value)?; + let propagate = bool::decode(value).unwrap_or(true); + Ok(TransactionValidityOld::Valid(ValidTransaction { + priority, requires, provides, longevity, propagate, + })) + }, + 2 => Ok(TransactionValidityOld::Unknown(i8::decode(value)?)), + _ => Err("Invalid transaction validity variant".into()), + } + } +} + +impl From for TransactionValidity { + fn from(old: TransactionValidityOld) -> Self { + match old { + TransactionValidityOld::Invalid(invalid) => + InvalidTransaction::Custom(invalid as u8).into(), + TransactionValidityOld::Unknown(unknown) => + UnknownTransaction::Custom(unknown as u8).into(), + TransactionValidityOld::Valid(valid) => Ok(valid), + } + } +} + decl_runtime_apis! { /// The `Core` api trait that is mandatory for each runtime. #[core_trait] @@ -179,7 +229,11 @@ decl_runtime_apis! { } /// The `TaggedTransactionQueue` api trait for interfering with the new transaction queue. + #[api_version(2)] pub trait TaggedTransactionQueue { + /// Validate the given transaction. + #[changed_in(2)] + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidityOld; /// Validate the given transaction. fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity; } diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index ba1aac4cc3eb4..5652fe09d9e4e 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -280,7 +280,7 @@ fn should_return_runtime_version() { let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\ - [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\ + [\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",2],[\"0x40fe3ad401f8959a\",4],\ [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ [\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1]]}"; diff --git a/core/transaction-pool/src/api.rs b/core/transaction-pool/src/api.rs index c0c4c787a5012..24b86ab953efc 100644 --- a/core/transaction-pool/src/api.rs +++ b/core/transaction-pool/src/api.rs @@ -20,7 +20,7 @@ use std::{ sync::Arc, marker::PhantomData, }; -use client::{runtime_api::TaggedTransactionQueue, blockchain::HeaderBackend}; +use client::{runtime_api::{TaggedTransactionQueue, ApiExt}, blockchain::HeaderBackend}; use codec::Encode; use txpool; use primitives::{ @@ -63,8 +63,19 @@ impl txpool::ChainApi for ChainApi where type Hash = H256; type Error = error::Error; - fn validate_transaction(&self, at: &BlockId, uxt: txpool::ExtrinsicFor) -> error::Result { - Ok(self.client.runtime_api().validate_transaction(at, uxt)?) + fn validate_transaction( + &self, + at: &BlockId, + uxt: txpool::ExtrinsicFor, + ) -> error::Result { + let api = self.client.runtime_api(); + + if api.has_api_with::, _>(at, |v| v < 2)? { + #[allow(deprecated)] + api.validate_transaction_before_version_2(at, uxt).map(Into::into).map_err(Into::into) + } else { + api.validate_transaction(at, uxt).map_err(Into::into) + } } fn block_id_to_number(&self, at: &BlockId) -> error::Result>> {