1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
use jsonrpsee::{
core::Error as JsonRpseeError,
types::error::{CallError, ErrorObject},
};
use sp_runtime::transaction_validity::InvalidTransaction;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Client error: {}", .0)]
Client(Box<dyn std::error::Error + Send + Sync>),
#[error("Transaction pool error: {}", .0)]
Pool(#[from] sc_transaction_pool_api::error::Error),
#[error("Extrinsic verification error: {}", .0)]
Verification(Box<dyn std::error::Error + Send + Sync>),
#[error("Invalid extrinsic format: {}", .0)]
BadFormat(#[from] codec::Error),
#[error("Invalid key type ID format (should be of length four)")]
BadKeyType,
#[error("The key store is unavailable")]
KeyStoreUnavailable,
#[error("Session keys are not encoded correctly")]
InvalidSessionKeys,
#[error(transparent)]
UnsafeRpcCalled(#[from] crate::policy::UnsafeRpcError),
}
const BASE_ERROR: i32 = 1000;
const BAD_FORMAT: i32 = BASE_ERROR + 1;
const VERIFICATION_ERROR: i32 = BASE_ERROR + 2;
const POOL_INVALID_TX: i32 = BASE_ERROR + 10;
const POOL_UNKNOWN_VALIDITY: i32 = POOL_INVALID_TX + 1;
const POOL_TEMPORARILY_BANNED: i32 = POOL_INVALID_TX + 2;
const POOL_ALREADY_IMPORTED: i32 = POOL_INVALID_TX + 3;
const POOL_TOO_LOW_PRIORITY: i32 = POOL_INVALID_TX + 4;
const POOL_CYCLE_DETECTED: i32 = POOL_INVALID_TX + 5;
const POOL_IMMEDIATELY_DROPPED: i32 = POOL_INVALID_TX + 6;
const POOL_UNACTIONABLE: i32 = POOL_INVALID_TX + 8;
const POOL_NO_TAGS: i32 = POOL_INVALID_TX + 9;
const POOL_INVALID_BLOCK_ID: i32 = POOL_INVALID_TX + 10;
const POOL_FUTURE_TX: i32 = POOL_INVALID_TX + 11;
impl From<Error> for JsonRpseeError {
fn from(e: Error) -> Self {
use sc_transaction_pool_api::error::Error as PoolError;
match e {
Error::BadFormat(e) => CallError::Custom(ErrorObject::owned(
BAD_FORMAT,
format!("Extrinsic has invalid format: {}", e),
None::<()>,
)),
Error::Verification(e) => CallError::Custom(ErrorObject::owned(
VERIFICATION_ERROR,
format!("Verification Error: {}", e),
Some(format!("{:?}", e)),
)),
Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => {
CallError::Custom(ErrorObject::owned(
POOL_INVALID_TX,
"Invalid Transaction",
Some(format!("Custom error: {}", e)),
))
},
Error::Pool(PoolError::InvalidTransaction(e)) => {
let msg: &str = e.into();
CallError::Custom(ErrorObject::owned(
POOL_INVALID_TX,
"Invalid Transaction",
Some(msg),
))
},
Error::Pool(PoolError::UnknownTransaction(e)) => {
CallError::Custom(ErrorObject::owned(
POOL_UNKNOWN_VALIDITY,
"Unknown Transaction Validity",
Some(format!("{:?}", e)),
))
},
Error::Pool(PoolError::TemporarilyBanned) =>
CallError::Custom(ErrorObject::owned(
POOL_TEMPORARILY_BANNED,
"Transaction is temporarily banned",
None::<()>,
)),
Error::Pool(PoolError::AlreadyImported(hash)) =>
CallError::Custom(ErrorObject::owned(
POOL_ALREADY_IMPORTED,
"Transaction Already Imported",
Some(format!("{:?}", hash)),
)),
Error::Pool(PoolError::TooLowPriority { old, new }) => CallError::Custom(ErrorObject::owned(
POOL_TOO_LOW_PRIORITY,
format!("Priority is too low: ({} vs {})", old, new),
Some("The transaction has too low priority to replace another transaction already in the pool.")
)),
Error::Pool(PoolError::CycleDetected) =>
CallError::Custom(ErrorObject::owned(
POOL_CYCLE_DETECTED,
"Cycle Detected",
None::<()>
)),
Error::Pool(PoolError::ImmediatelyDropped) => CallError::Custom(ErrorObject::owned(
POOL_IMMEDIATELY_DROPPED,
"Immediately Dropped",
Some("The transaction couldn't enter the pool because of the limit"),
)),
Error::Pool(PoolError::Unactionable) => CallError::Custom(ErrorObject::owned(
POOL_UNACTIONABLE,
"Unactionable",
Some("The transaction is unactionable since it is not propagable and \
the local node does not author blocks")
)),
Error::Pool(PoolError::NoTagsProvided) => CallError::Custom(ErrorObject::owned(
POOL_NO_TAGS,
"No tags provided",
Some("Transaction does not provide any tags, so the pool can't identify it")
)),
Error::Pool(PoolError::InvalidBlockId(_)) =>
CallError::Custom(ErrorObject::owned(
POOL_INVALID_BLOCK_ID,
"The provided block ID is not valid",
None::<()>
)),
Error::Pool(PoolError::RejectedFutureTransaction) => {
CallError::Custom(ErrorObject::owned(
POOL_FUTURE_TX,
"The pool is not accepting future transactions",
None::<()>,
))
},
Error::UnsafeRpcCalled(e) => e.into(),
e => CallError::Failed(e.into()),
}.into()
}
}