Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all 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
42 changes: 41 additions & 1 deletion core/client/src/block_builder/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ApplyOutcomeOld, ApplyErrorOld>;

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: <Block as BlockT>::Extrinsic) -> ApplyResultOld;
/// Apply the given extrinsics.
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult;
/// Finish the current block.
Expand Down
45 changes: 32 additions & 13 deletions core/client/src/block_builder/block_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<dyn BlockBuilderApi<Block>, _>(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.
Expand Down
56 changes: 55 additions & 1 deletion core/client/src/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -155,6 +159,52 @@ pub trait CallRuntimeAt<Block: BlockT> {
fn runtime_version_at(&self, at: &BlockId<Block>) -> error::Result<RuntimeVersion>;
}

/// 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<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
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<TransactionValidityOld> 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]
Expand All @@ -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: <Block as BlockT>::Extrinsic) -> TransactionValidityOld;
/// Validate the given transaction.
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity;
}
Expand Down
2 changes: 1 addition & 1 deletion core/rpc/src/state/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]]}";

Expand Down
17 changes: 14 additions & 3 deletions core/transaction-pool/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -63,8 +63,19 @@ impl<T, Block> txpool::ChainApi for ChainApi<T, Block> where
type Hash = H256;
type Error = error::Error;

fn validate_transaction(&self, at: &BlockId<Self::Block>, uxt: txpool::ExtrinsicFor<Self>) -> error::Result<TransactionValidity> {
Ok(self.client.runtime_api().validate_transaction(at, uxt)?)
fn validate_transaction(
&self,
at: &BlockId<Self::Block>,
uxt: txpool::ExtrinsicFor<Self>,
) -> error::Result<TransactionValidity> {
let api = self.client.runtime_api();

if api.has_api_with::<dyn TaggedTransactionQueue<Block>, _>(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<Self::Block>) -> error::Result<Option<txpool::NumberFor<Self>>> {
Expand Down