// This file is part of Substrate.
// Copyright (C) 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 jsonrpsee::types::error::ErrorObject;
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 transaction 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(),
}),
}
}
}
/// TransactionBroadcast error.
#[derive(Debug, thiserror::Error)]
pub enum ErrorBroadcast {
/// The provided operation ID is invalid.
#[error("Invalid operation id")]
InvalidOperationID,
}
/// General purpose errors, as defined in
/// <https://www.jsonrpc.org/specification#error_object>.
pub mod json_rpc_spec {
/// Invalid parameter error.
pub const INVALID_PARAM_ERROR: i32 = -32602;
}
impl From<ErrorBroadcast> for ErrorObject<'static> {
fn from(e: ErrorBroadcast) -> Self {
let msg = e.to_string();
match e {
ErrorBroadcast::InvalidOperationID =>
ErrorObject::owned(json_rpc_spec::INVALID_PARAM_ERROR, msg, None::<()>),
}
}
}