Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

rpc: Implement transaction RPC API #12328

Merged
merged 24 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fe72d1e
rpc/tx: Add transaction structures for serialization
lexnv Sep 22, 2022
bb9e92a
rpc/tx: Add public facing `TransactionEvent`
lexnv Sep 22, 2022
8ff7cc6
rpc/tx: Add trait for the `transaction` API
lexnv Sep 22, 2022
4b1431b
rpc/tx: Convert RPC errors to transaction events
lexnv Sep 22, 2022
e6680e4
rpc/tx: Implement `transaction` RPC methods
lexnv Sep 22, 2022
b0a1e4f
tx-pool: Propagate tx index to events
lexnv Sep 22, 2022
83880e8
tx-pool: Adjust testing to reflect tx index in events
lexnv Sep 20, 2022
a67aa03
rpc/tx: Convert tx-pool events for the new RPC spec
lexnv Sep 22, 2022
9aa5dcb
rpc/tx: Convert tx-pool `FinalityTimeout` event to `Dropped`
lexnv Sep 22, 2022
e5c3d29
service: Enable the `transaction` API
lexnv Sep 22, 2022
0ac07b2
rpc/tx: Add tests for tx event encoding and decoding
lexnv Sep 22, 2022
b8ea4cc
tx: Add indentation for subscriptions
lexnv Sep 22, 2022
67effb6
rpc/tx: Fix documentation
lexnv Sep 23, 2022
5952d97
rpc/tx: Serialize usize to hex
lexnv Sep 23, 2022
5e272e3
tx-pool: Rename closure parameters
lexnv Sep 26, 2022
6d6d23b
service: Separate RPC spec versions
lexnv Sep 26, 2022
f90e08a
rpc/tx: Use `H256` for testing block's hash
lexnv Sep 26, 2022
bf120a9
rpc/tx: Serialize numbers as string
lexnv Sep 26, 2022
0f03b1e
tx-pool: Backward compatibility with RPC v1
lexnv Sep 26, 2022
795d110
Update client/rpc-spec-v2/src/transaction/transaction.rs
lexnv Sep 28, 2022
b77cf97
rpc/tx: Remove comment about serde clone
lexnv Sep 28, 2022
aa1dde4
rpc/tx: Use RPC custom error code for invalid tx format
lexnv Sep 28, 2022
6459acd
Update client/rpc-spec-v2/src/transaction/event.rs
lexnv Sep 29, 2022
093c1a1
rpc/tx: Adjust internal structures for serialization/deserialization
lexnv Sep 29, 2022
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
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions client/rpc-spec-v2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ targets = ["x86_64-unknown-linux-gnu"]
jsonrpsee = { version = "0.15.1", features = ["server", "macros"] }
# Internal chain structures for "chain_spec".
sc-chain-spec = { version = "4.0.0-dev", path = "../chain-spec" }
# Pool for submitting extrinsics required by "transaction"
sc-transaction-pool-api = { version = "4.0.0-dev", path = "../transaction-pool/api" }
sp-core = { version = "6.0.0", path = "../../primitives/core" }
sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" }
sp-api = { version = "4.0.0-dev", path = "../../primitives/api" }
sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" }
codec = { package = "parity-scale-codec", version = "3.0.0" }
thiserror = "1.0"
serde = "1.0"
hex = "0.4"
futures = "0.3.21"

[dev-dependencies]
serde_json = "1.0"
Expand Down
4 changes: 4 additions & 0 deletions client/rpc-spec-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@
#![deny(unused_crate_dependencies)]

pub mod chain_spec;
pub mod transaction;

/// Task executor that is being used by RPC subscriptions.
pub type SubscriptionTaskExecutor = std::sync::Arc<dyn sp_core::traits::SpawnNamed>;
38 changes: 38 additions & 0 deletions client/rpc-spec-v2/src/transaction/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// This file is part of Substrate.

// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program 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.

// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

//! API trait for transactions.

use crate::transaction::event::TransactionEvent;
use jsonrpsee::proc_macros::rpc;
use sp_core::Bytes;

#[rpc(client, server)]
// This trait bound is required by serde, see `event`.
lexnv marked this conversation as resolved.
Show resolved Hide resolved
pub trait TransactionApi<Hash: Clone> {
/// Submit an extrinsic to watch.
///
/// See [`TransactionEvent`](crate::transaction::event::TransactionEvent) for details on
/// transaction life cycle.
#[subscription(
name = "transaction_unstable_submitAndWatch" => "transaction_unstable_submitExtrinsic",
unsubscribe = "transaction_unstable_unwatch",
item = TransactionEvent<Hash>,
)]
fn submit_and_watch(&self, bytes: Bytes);
}
100 changes: 100 additions & 0 deletions client/rpc-spec-v2/src/transaction/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// This file is part of Substrate.

// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program 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.

// This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

//! Transaction RPC errors.
//!
//! Errors are interpreted as transaction events for subscriptions.

use crate::transaction::event::{TransactionError, TransactionEvent};
use sc_transaction_pool_api::error::Error as PoolError;
use sp_runtime::transaction_validity::InvalidTransaction;

/// Transaction RPC errors.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Transaction pool error.
#[error("Transaction pool error: {}", .0)]
Pool(#[from] PoolError),
/// Verification error.
#[error("Extrinsic verification error: {}", .0)]
Verification(Box<dyn std::error::Error + Send + Sync>),
}

impl<Hash> From<Error> for TransactionEvent<Hash> {
fn from(e: Error) -> Self {
match e {
Error::Verification(e) => TransactionEvent::Invalid(TransactionError {
error: format!("Verification error: {}", e),
}),
Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) =>
TransactionEvent::Invalid(TransactionError {
error: format!("Invalid transaction with custom error: {}", e),
}),
Error::Pool(PoolError::InvalidTransaction(e)) => {
let msg: &str = e.into();
TransactionEvent::Invalid(TransactionError {
error: format!("Invalid transaction: {}", msg),
})
},
Error::Pool(PoolError::UnknownTransaction(e)) => {
let msg: &str = e.into();
TransactionEvent::Invalid(TransactionError {
error: format!("Unknown transaction validity: {}", msg),
})
},
Error::Pool(PoolError::TemporarilyBanned) =>
TransactionEvent::Invalid(TransactionError {
error: "Transaction is temporarily banned".into(),
}),
Error::Pool(PoolError::AlreadyImported(_)) =>
TransactionEvent::Invalid(TransactionError {
error: "Transaction is already imported".into(),
}),
Error::Pool(PoolError::TooLowPriority { old, new }) =>
TransactionEvent::Invalid(TransactionError {
error: format!(
"The priority of the transactin is too low (pool {} > current {})",
old, new
),
}),
Error::Pool(PoolError::CycleDetected) => TransactionEvent::Invalid(TransactionError {
error: "The transaction contains a cyclic dependency".into(),
}),
Error::Pool(PoolError::ImmediatelyDropped) =>
TransactionEvent::Invalid(TransactionError {
error: "The transaction could not enter the pool because of the limit".into(),
}),
Error::Pool(PoolError::Unactionable) => TransactionEvent::Invalid(TransactionError {
error: "Transaction cannot be propagated and the local node does not author blocks"
.into(),
}),
Error::Pool(PoolError::NoTagsProvided) => TransactionEvent::Invalid(TransactionError {
error: "Transaction does not provide any tags, so the pool cannot identify it"
.into(),
}),
Error::Pool(PoolError::InvalidBlockId(_)) =>
TransactionEvent::Invalid(TransactionError {
error: "The provided block ID is not valid".into(),
}),
Error::Pool(PoolError::RejectedFutureTransaction) =>
TransactionEvent::Invalid(TransactionError {
error: "The pool is not accepting future transactions".into(),
}),
}
}
}
Loading