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
184
use crate::errors;
use jsonrpc_core as rpc;
use sp_runtime::transaction_validity::InvalidTransaction;
pub type Result<T> = std::result::Result<T, Error>;
pub type FutureResult<T> = Box<dyn rpc::futures::Future<Item = T, Error = Error> + Send>;
#[derive(Debug, derive_more::Display, derive_more::From)]
pub enum Error {
#[display(fmt="Client error: {}", _0)]
#[from(ignore)]
Client(Box<dyn std::error::Error + Send>),
#[display(fmt="Transaction pool error: {}", _0)]
Pool(sp_transaction_pool::error::Error),
#[display(fmt="Extrinsic verification error: {}", _0)]
#[from(ignore)]
Verification(Box<dyn std::error::Error + Send>),
#[display(fmt="Invalid extrinsic format: {}", _0)]
BadFormat(codec::Error),
#[display(fmt="Invalid seed phrase/SURI")]
BadSeedPhrase,
#[display(fmt="Invalid key type ID format (should be of length four)")]
BadKeyType,
#[display(fmt="The crypto of key type ID is unknown")]
UnsupportedKeyType,
#[display(fmt="The key store is unavailable")]
KeyStoreUnavailable,
#[display(fmt="Session keys are not encoded correctly")]
InvalidSessionKeys,
UnsafeRpcCalled(crate::policy::UnsafeRpcError),
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::Client(ref err) => Some(&**err),
Error::Pool(ref err) => Some(err),
Error::Verification(ref err) => Some(&**err),
Error::UnsafeRpcCalled(ref err) => Some(err),
_ => None,
}
}
}
const BASE_ERROR: i64 = 1000;
const BAD_FORMAT: i64 = BASE_ERROR + 1;
const VERIFICATION_ERROR: i64 = BASE_ERROR + 2;
const POOL_INVALID_TX: i64 = BASE_ERROR + 10;
const POOL_UNKNOWN_VALIDITY: i64 = POOL_INVALID_TX + 1;
const POOL_TEMPORARILY_BANNED: i64 = POOL_INVALID_TX + 2;
const POOL_ALREADY_IMPORTED: i64 = POOL_INVALID_TX + 3;
const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4;
const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5;
const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6;
const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7;
const POOL_UNACTIONABLE: i64 = POOL_INVALID_TX + 8;
impl From<Error> for rpc::Error {
fn from(e: Error) -> Self {
use sp_transaction_pool::error::{Error as PoolError};
match e {
Error::BadFormat(e) => rpc::Error {
code: rpc::ErrorCode::ServerError(BAD_FORMAT),
message: format!("Extrinsic has invalid format: {}", e).into(),
data: None,
},
Error::Verification(e) => rpc::Error {
code: rpc::ErrorCode::ServerError(VERIFICATION_ERROR),
message: format!("Verification Error: {}", e).into(),
data: Some(format!("{:?}", e).into()),
},
Error::Pool(PoolError::InvalidTransaction(InvalidTransaction::Custom(e))) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_INVALID_TX),
message: "Invalid Transaction".into(),
data: Some(format!("Custom error: {}", e).into()),
},
Error::Pool(PoolError::InvalidTransaction(e)) => {
let msg: &str = e.into();
rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_INVALID_TX),
message: "Invalid Transaction".into(),
data: Some(msg.into()),
}
},
Error::Pool(PoolError::UnknownTransaction(e)) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY),
message: "Unknown Transaction Validity".into(),
data: serde_json::to_value(e).ok(),
},
Error::Pool(PoolError::TemporarilyBanned) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED),
message: "Transaction is temporarily banned".into(),
data: None,
},
Error::Pool(PoolError::AlreadyImported(hash)) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_ALREADY_IMPORTED),
message: "Transaction Already Imported".into(),
data: Some(format!("{:?}", hash).into()),
},
Error::Pool(PoolError::TooLowPriority { old, new }) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_TOO_LOW_PRIORITY),
message: format!("Priority is too low: ({} vs {})", old, new),
data: Some("The transaction has too low priority to replace another transaction already in the pool.".into()),
},
Error::Pool(PoolError::CycleDetected) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_CYCLE_DETECTED),
message: "Cycle Detected".into(),
data: None,
},
Error::Pool(PoolError::ImmediatelyDropped) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED),
message: "Immediately Dropped".into(),
data: Some("The transaction couldn't enter the pool because of the limit".into()),
},
Error::Pool(PoolError::Unactionable) => rpc::Error {
code: rpc::ErrorCode::ServerError(POOL_UNACTIONABLE),
message: "Unactionable".into(),
data: Some(
"The transaction is unactionable since it is not propagable and \
the local node does not author blocks".into(),
),
},
Error::UnsupportedKeyType => rpc::Error {
code: rpc::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE),
message: "Unknown key type crypto" .into(),
data: Some(
"The crypto for the given key type is unknown, please add the public key to the \
request to insert the key successfully.".into()
),
},
Error::UnsafeRpcCalled(e) => e.into(),
e => errors::internal(e),
}
}
}