Skip to main content

soil_client/transaction_pool/
error.rs

1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Transaction pool errors.
8
9use subsoil::runtime::transaction_validity::{
10	InvalidTransaction, TransactionPriority as Priority, UnknownTransaction,
11};
12
13/// Transaction pool result.
14pub type Result<T> = std::result::Result<T, Error>;
15
16/// Transaction pool error type.
17#[derive(Debug, thiserror::Error, strum::AsRefStr)]
18#[allow(missing_docs)]
19pub enum Error {
20	#[error("Unknown transaction validity: {0:?}")]
21	UnknownTransaction(UnknownTransaction),
22
23	#[error("Invalid transaction validity: {0:?}")]
24	InvalidTransaction(InvalidTransaction),
25
26	/// The transaction validity returned no "provides" tag.
27	///
28	/// Such transactions are not accepted to the pool, since we use those tags
29	/// to define identity of transactions (occupancy of the same "slot").
30	#[error("Transaction does not provide any tags, so the pool can't identify it")]
31	NoTagsProvided,
32
33	#[error("Transaction temporarily Banned")]
34	TemporarilyBanned,
35
36	#[error("[{0:?}] Already imported")]
37	AlreadyImported(Box<dyn std::any::Any + Send + Sync>),
38
39	#[error("Too low priority ({} > {})", old, new)]
40	TooLowPriority {
41		/// Transaction already in the pool.
42		old: Priority,
43		/// Transaction entering the pool.
44		new: Priority,
45	},
46	#[error("Transaction with cyclic dependency")]
47	CycleDetected,
48
49	#[error("Transaction couldn't enter the pool because of the limit")]
50	ImmediatelyDropped,
51
52	#[error("Transaction cannot be propagated and the local node does not author blocks")]
53	Unactionable,
54
55	#[error("{0}")]
56	InvalidBlockId(String),
57
58	#[error("The pool is not accepting future transactions")]
59	RejectedFutureTransaction,
60}
61
62impl Error {
63	/// Returns true if the transaction could be re-submitted to the pool in the future.
64	///
65	/// For example, `Error::ImmediatelyDropped` is retriable, because the transaction
66	/// may enter the pool if there is space for it in the future.
67	pub fn is_retriable(&self) -> bool {
68		match self {
69			// An invalid transaction is temporarily banned, however it can
70			// become valid at a later time.
71			Error::TemporarilyBanned |
72			// The pool is full at the moment.
73			Error::ImmediatelyDropped |
74			// The block id is not known to the pool.
75			// The node might be lagging behind, or during a warp sync.
76			Error::InvalidBlockId(_) |
77			// The pool is configured to not accept future transactions.
78			Error::RejectedFutureTransaction => {
79				true
80			}
81			_ => false
82		}
83	}
84}
85
86/// Transaction pool error conversion.
87pub trait IntoPoolError: std::error::Error + Send + Sized + Sync {
88	/// Try to extract original `Error`
89	///
90	/// This implementation is optional and used only to
91	/// provide more descriptive error messages for end users
92	/// of RPC API.
93	fn into_pool_error(self) -> std::result::Result<Error, Self> {
94		Err(self)
95	}
96}
97
98impl IntoPoolError for Error {
99	fn into_pool_error(self) -> std::result::Result<Error, Self> {
100		Ok(self)
101	}
102}
103
104/// Provide a representation of the underlying instance as a prometheus metric label.
105pub trait IntoMetricsLabel {
106	/// Short string representation of the underlying instance.
107	///
108	/// This is intended to be used for a prometheus metric that tracks this instance
109	/// with the goal of distributing the observations over multiple groups, where an unique
110	/// label represents a group of same instance, observed many times.
111	fn label(&self) -> String;
112}
113
114impl IntoMetricsLabel for Error {
115	fn label(&self) -> String {
116		self.as_ref().to_string()
117	}
118}