referrerpolicy=no-referrer-when-downgrade

relay_substrate_client/
error.rs

1// Copyright 2019-2021 Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Substrate node RPC errors.
18
19use crate::{BlockNumberOf, Chain, HashOf, SimpleRuntimeVersion};
20use bp_header_chain::SubmitFinalityProofCallExtras;
21use bp_polkadot_core::parachains::ParaId;
22use jsonrpsee::core::ClientError as RpcError;
23use relay_utils::MaybeConnectionError;
24use sc_rpc_api::system::Health;
25use sp_core::{storage::StorageKey, Bytes};
26use sp_runtime::transaction_validity::TransactionValidityError;
27use thiserror::Error;
28
29/// Result type used by Substrate client.
30pub type Result<T> = std::result::Result<T, Error>;
31
32/// Errors that can occur only when interacting with
33/// a Substrate node through RPC.
34#[derive(Error, Debug)]
35pub enum Error {
36	/// IO error.
37	#[error("IO error: {0}")]
38	Io(#[from] std::io::Error),
39	/// An error that can occur when making a request to
40	/// an JSON-RPC server.
41	#[error("RPC error: {0}")]
42	RpcError(#[from] RpcError),
43	/// The response from the server could not be SCALE decoded.
44	#[error("Response parse failed: {0}")]
45	ResponseParseFailed(#[from] codec::Error),
46	/// Internal channel error - communication channel is either closed, or full.
47	/// It can be solved with reconnect.
48	#[error("Internal communication channel error: {0:?}.")]
49	ChannelError(String),
50	/// Required parachain head is not present at the relay chain.
51	#[error("Parachain {0:?} head {1} is missing from the relay chain storage.")]
52	MissingRequiredParachainHead(ParaId, u64),
53	/// Failed to find finality proof for the given header.
54	#[error("Failed to find finality proof for header {0}.")]
55	FinalityProofNotFound(u64),
56	/// The client we're connected to is not synced, so we can't rely on its state.
57	#[error("Substrate client is not synced {0}.")]
58	ClientNotSynced(Health),
59	/// Failed to get system health.
60	#[error("Failed to get system health of {chain} node: {error:?}.")]
61	FailedToGetSystemHealth {
62		/// Name of the chain where the error has happened.
63		chain: String,
64		/// Underlying error.
65		error: Box<Error>,
66	},
67	/// Failed to read best finalized header hash from given chain.
68	#[error("Failed to read best finalized header hash of {chain}: {error:?}.")]
69	FailedToReadBestFinalizedHeaderHash {
70		/// Name of the chain where the error has happened.
71		chain: String,
72		/// Underlying error.
73		error: Box<Error>,
74	},
75	/// Failed to read best finalized header from given chain.
76	#[error("Failed to read best header of {chain}: {error:?}.")]
77	FailedToReadBestHeader {
78		/// Name of the chain where the error has happened.
79		chain: String,
80		/// Underlying error.
81		error: Box<Error>,
82	},
83	/// Failed to read header hash by number from given chain.
84	#[error("Failed to read header hash by number {number} of {chain}: {error:?}.")]
85	FailedToReadHeaderHashByNumber {
86		/// Name of the chain where the error has happened.
87		chain: String,
88		/// Number of the header we've tried to read.
89		number: String,
90		/// Underlying error.
91		error: Box<Error>,
92	},
93	/// Failed to read header by hash from given chain.
94	#[error("Failed to read header {hash} of {chain}: {error:?}.")]
95	FailedToReadHeaderByHash {
96		/// Name of the chain where the error has happened.
97		chain: String,
98		/// Hash of the header we've tried to read.
99		hash: String,
100		/// Underlying error.
101		error: Box<Error>,
102	},
103	/// Failed to read block by hash from given chain.
104	#[error("Failed to read block {hash} of {chain}: {error:?}.")]
105	FailedToReadBlockByHash {
106		/// Name of the chain where the error has happened.
107		chain: String,
108		/// Hash of the header we've tried to read.
109		hash: String,
110		/// Underlying error.
111		error: Box<Error>,
112	},
113	/// Failed to read sotrage value at given chain.
114	#[error("Failed to read storage value {key:?} at {chain}: {error:?}.")]
115	FailedToReadStorageValue {
116		/// Name of the chain where the error has happened.
117		chain: String,
118		/// Hash of the block we've tried to read value from.
119		hash: String,
120		/// Runtime storage key
121		key: StorageKey,
122		/// Underlying error.
123		error: Box<Error>,
124	},
125	/// Failed to read runtime version of given chain.
126	#[error("Failed to read runtime version of {chain}: {error:?}.")]
127	FailedToReadRuntimeVersion {
128		/// Name of the chain where the error has happened.
129		chain: String,
130		/// Underlying error.
131		error: Box<Error>,
132	},
133	/// Failed to get pending extrinsics.
134	#[error("Failed to get pending extrinsics of {chain}: {error:?}.")]
135	FailedToGetPendingExtrinsics {
136		/// Name of the chain where the error has happened.
137		chain: String,
138		/// Underlying error.
139		error: Box<Error>,
140	},
141	/// Failed to submit transaction.
142	#[error("Failed to submit {chain} transaction: {error:?}.")]
143	FailedToSubmitTransaction {
144		/// Name of the chain where the error has happened.
145		chain: String,
146		/// Underlying error.
147		error: Box<Error>,
148	},
149	/// Runtime call has failed.
150	#[error("Runtime call {method} with arguments {arguments:?} of chain {chain} at {hash} has failed: {error:?}.")]
151	FailedStateCall {
152		/// Name of the chain where the error has happened.
153		chain: String,
154		/// Hash of the block we've tried to call at.
155		hash: String,
156		/// Runtime API method.
157		method: String,
158		/// Encoded method arguments.
159		arguments: Bytes,
160		/// Underlying error.
161		error: Box<Error>,
162	},
163	/// Failed to prove storage keys.
164	#[error("Failed to prove storage keys {storage_keys:?} of {chain} at {hash}: {error:?}.")]
165	FailedToProveStorage {
166		/// Name of the chain where the error has happened.
167		chain: String,
168		/// Hash of the block we've tried to prove keys at.
169		hash: String,
170		/// Storage keys we have tried to prove.
171		storage_keys: Vec<StorageKey>,
172		/// Underlying error.
173		error: Box<Error>,
174	},
175	/// Failed to subscribe to GRANDPA justifications stream.
176	#[error("Failed to subscribe to {chain} best headers: {error:?}.")]
177	FailedToSubscribeBestHeaders {
178		/// Name of the chain where the error has happened.
179		chain: String,
180		/// Underlying error.
181		error: Box<Error>,
182	},
183	/// Failed to subscribe to GRANDPA justifications stream.
184	#[error("Failed to subscribe to {chain} finalized headers: {error:?}.")]
185	FailedToSubscribeFinalizedHeaders {
186		/// Name of the chain where the error has happened.
187		chain: String,
188		/// Underlying error.
189		error: Box<Error>,
190	},
191	/// Failed to subscribe to GRANDPA justifications stream.
192	#[error("Failed to subscribe to {chain} justifications: {error:?}.")]
193	FailedToSubscribeJustifications {
194		/// Name of the chain where the error has happened.
195		chain: String,
196		/// Underlying error.
197		error: Box<Error>,
198	},
199	/// Headers of the chain are finalized out of order. Maybe chain has been
200	/// restarted?
201	#[error("Finalized headers of {chain} are unordered: previously finalized {prev_number} vs new {next_number}")]
202	UnorderedFinalizedHeaders {
203		/// Name of the chain where the error has happened.
204		chain: String,
205		/// Previously finalized header number.
206		prev_number: String,
207		/// New finalized header number.
208		next_number: String,
209	},
210	/// The bridge pallet is halted and all transactions will be rejected.
211	#[error("Bridge pallet is halted.")]
212	BridgePalletIsHalted,
213	/// The bridge pallet is not yet initialized and all transactions will be rejected.
214	#[error("Bridge pallet is not initialized.")]
215	BridgePalletIsNotInitialized,
216	/// The Substrate transaction is invalid.
217	#[error("Substrate transaction is invalid: {0:?}")]
218	TransactionInvalid(#[from] TransactionValidityError),
219	/// The client is configured to use newer runtime version than the connected chain uses.
220	/// The client will keep waiting until chain is upgraded to given version.
221	#[error("Waiting for {chain} runtime upgrade: expected {expected:?} actual {actual:?}")]
222	WaitingForRuntimeUpgrade {
223		/// Name of the chain where the error has happened.
224		chain: String,
225		/// Expected runtime version.
226		expected: SimpleRuntimeVersion,
227		/// Actual runtime version.
228		actual: SimpleRuntimeVersion,
229	},
230	/// Finality proof submission exceeds size and/or weight limits.
231	#[error("Finality proof submission exceeds limits: {extras:?}")]
232	FinalityProofWeightLimitExceeded {
233		/// Finality proof submission extras.
234		extras: SubmitFinalityProofCallExtras,
235	},
236	/// Custom logic error.
237	#[error("{0}")]
238	Custom(String),
239}
240
241impl From<tokio::task::JoinError> for Error {
242	fn from(error: tokio::task::JoinError) -> Self {
243		Error::ChannelError(format!("failed to wait tokio task: {error}"))
244	}
245}
246
247impl<T> From<async_std::channel::TrySendError<T>> for Error {
248	fn from(error: async_std::channel::TrySendError<T>) -> Self {
249		Error::ChannelError(format!("`try_send` has failed: {error:?}"))
250	}
251}
252
253impl From<async_std::channel::RecvError> for Error {
254	fn from(error: async_std::channel::RecvError) -> Self {
255		Error::ChannelError(format!("`recv` has failed: {error:?}"))
256	}
257}
258
259impl Error {
260	/// Box the error.
261	pub fn boxed(self) -> Box<Self> {
262		Box::new(self)
263	}
264
265	/// Returns nested error reference.
266	pub fn nested(&self) -> Option<&Self> {
267		match *self {
268			Self::FailedToReadBestFinalizedHeaderHash { ref error, .. } => Some(&**error),
269			Self::FailedToReadBestHeader { ref error, .. } => Some(&**error),
270			Self::FailedToReadHeaderHashByNumber { ref error, .. } => Some(&**error),
271			Self::FailedToReadHeaderByHash { ref error, .. } => Some(&**error),
272			Self::FailedToReadBlockByHash { ref error, .. } => Some(&**error),
273			Self::FailedToReadStorageValue { ref error, .. } => Some(&**error),
274			Self::FailedToReadRuntimeVersion { ref error, .. } => Some(&**error),
275			Self::FailedToGetPendingExtrinsics { ref error, .. } => Some(&**error),
276			Self::FailedToSubmitTransaction { ref error, .. } => Some(&**error),
277			Self::FailedStateCall { ref error, .. } => Some(&**error),
278			Self::FailedToProveStorage { ref error, .. } => Some(&**error),
279			Self::FailedToGetSystemHealth { ref error, .. } => Some(&**error),
280			Self::FailedToSubscribeBestHeaders { ref error, .. } => Some(&**error),
281			Self::FailedToSubscribeFinalizedHeaders { ref error, .. } => Some(&**error),
282			Self::FailedToSubscribeJustifications { ref error, .. } => Some(&**error),
283			_ => None,
284		}
285	}
286
287	/// Constructs `FailedToReadHeaderHashByNumber` variant.
288	pub fn failed_to_read_header_hash_by_number<C: Chain>(
289		number: BlockNumberOf<C>,
290		e: Error,
291	) -> Self {
292		Error::FailedToReadHeaderHashByNumber {
293			chain: C::NAME.into(),
294			number: format!("{number}"),
295			error: e.boxed(),
296		}
297	}
298
299	/// Constructs `FailedToReadHeaderByHash` variant.
300	pub fn failed_to_read_header_by_hash<C: Chain>(hash: HashOf<C>, e: Error) -> Self {
301		Error::FailedToReadHeaderByHash {
302			chain: C::NAME.into(),
303			hash: format!("{hash}"),
304			error: e.boxed(),
305		}
306	}
307
308	/// Constructs `FailedToReadBlockByHash` variant.
309	pub fn failed_to_read_block_by_hash<C: Chain>(hash: HashOf<C>, e: Error) -> Self {
310		Error::FailedToReadHeaderByHash {
311			chain: C::NAME.into(),
312			hash: format!("{hash}"),
313			error: e.boxed(),
314		}
315	}
316
317	/// Constructs `FailedToReadBestFinalizedHeaderHash` variant.
318	pub fn failed_to_read_best_finalized_header_hash<C: Chain>(e: Error) -> Self {
319		Error::FailedToReadBestFinalizedHeaderHash { chain: C::NAME.into(), error: e.boxed() }
320	}
321
322	/// Constructs `FailedToReadBestHeader` variant.
323	pub fn failed_to_read_best_header<C: Chain>(e: Error) -> Self {
324		Error::FailedToReadBestHeader { chain: C::NAME.into(), error: e.boxed() }
325	}
326
327	/// Constructs `FailedToReadRuntimeVersion` variant.
328	pub fn failed_to_read_runtime_version<C: Chain>(e: Error) -> Self {
329		Error::FailedToReadRuntimeVersion { chain: C::NAME.into(), error: e.boxed() }
330	}
331
332	/// Constructs `FailedToReadStorageValue` variant.
333	pub fn failed_to_read_storage_value<C: Chain>(
334		at: HashOf<C>,
335		key: StorageKey,
336		e: Error,
337	) -> Self {
338		Error::FailedToReadStorageValue {
339			chain: C::NAME.into(),
340			hash: format!("{at}"),
341			key,
342			error: e.boxed(),
343		}
344	}
345
346	/// Constructs `FailedToGetPendingExtrinsics` variant.
347	pub fn failed_to_get_pending_extrinsics<C: Chain>(e: Error) -> Self {
348		Error::FailedToGetPendingExtrinsics { chain: C::NAME.into(), error: e.boxed() }
349	}
350
351	/// Constructs `FailedToSubmitTransaction` variant.
352	pub fn failed_to_submit_transaction<C: Chain>(e: Error) -> Self {
353		Error::FailedToSubmitTransaction { chain: C::NAME.into(), error: e.boxed() }
354	}
355
356	/// Constructs `FailedStateCall` variant.
357	pub fn failed_state_call<C: Chain>(
358		at: HashOf<C>,
359		method: String,
360		arguments: Bytes,
361		e: Error,
362	) -> Self {
363		Error::FailedStateCall {
364			chain: C::NAME.into(),
365			hash: format!("{at}"),
366			method,
367			arguments,
368			error: e.boxed(),
369		}
370	}
371
372	/// Constructs `FailedToProveStorage` variant.
373	pub fn failed_to_prove_storage<C: Chain>(
374		at: HashOf<C>,
375		storage_keys: Vec<StorageKey>,
376		e: Error,
377	) -> Self {
378		Error::FailedToProveStorage {
379			chain: C::NAME.into(),
380			hash: format!("{at}"),
381			storage_keys,
382			error: e.boxed(),
383		}
384	}
385
386	/// Constructs `FailedToGetSystemHealth` variant.
387	pub fn failed_to_get_system_health<C: Chain>(e: Error) -> Self {
388		Error::FailedToGetSystemHealth { chain: C::NAME.into(), error: e.boxed() }
389	}
390
391	/// Constructs `FailedToSubscribeBestHeaders` variant.
392	pub fn failed_to_subscribe_best_headers<C: Chain>(e: Error) -> Self {
393		Error::FailedToSubscribeBestHeaders { chain: C::NAME.into(), error: e.boxed() }
394	}
395
396	/// Constructs `FailedToSubscribeFinalizedHeaders` variant.
397	pub fn failed_to_subscribe_finalized_headers<C: Chain>(e: Error) -> Self {
398		Error::FailedToSubscribeFinalizedHeaders { chain: C::NAME.into(), error: e.boxed() }
399	}
400
401	/// Constructs `FailedToSubscribeJustifications` variant.
402	pub fn failed_to_subscribe_justification<C: Chain>(e: Error) -> Self {
403		Error::FailedToSubscribeJustifications { chain: C::NAME.into(), error: e.boxed() }
404	}
405
406	/// Constructs `Un`
407	pub fn unordered_finalized_headers<C: Chain>(
408		prev_number: BlockNumberOf<C>,
409		next_number: BlockNumberOf<C>,
410	) -> Self {
411		Error::UnorderedFinalizedHeaders {
412			chain: C::NAME.into(),
413			prev_number: format!("{}", prev_number),
414			next_number: format!("{}", next_number),
415		}
416	}
417}
418
419impl MaybeConnectionError for Error {
420	fn is_connection_error(&self) -> bool {
421		match *self {
422			Error::ChannelError(_) => true,
423			Error::RpcError(ref e) =>
424				matches!(*e, RpcError::Transport(_) | RpcError::RestartNeeded(_),),
425			Error::ClientNotSynced(_) => true,
426			Error::UnorderedFinalizedHeaders { .. } => true,
427			_ => self.nested().map(|e| e.is_connection_error()).unwrap_or(false),
428		}
429	}
430}