Unify error enums in substrate and ethereum clients with thiserror (#1094)

* Unify error enums in substrate and ethereum clients with `thiserror`

Related to https://github.com/paritytech/parity-bridges-common/issues/857

* Add license pre-amble

* rustfmt

* Fix spelling
This commit is contained in:
Vladislav
2021-10-22 13:15:50 +03:00
committed by Bastian Köcher
parent 7b4f1c2236
commit 5842968273
48 changed files with 482 additions and 381 deletions
@@ -21,6 +21,8 @@
//! and authorities set from source to target chain. The headers sync starts
//! with this header.
use crate::error::Error;
use bp_header_chain::{
find_grandpa_authorities_scheduled_change,
justification::{verify_justification, GrandpaJustification},
@@ -32,7 +34,7 @@ use num_traits::{One, Zero};
use relay_substrate_client::{Chain, Client};
use sp_core::Bytes;
use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet;
use sp_runtime::traits::Header as HeaderT;
use sp_runtime::traits::{Header as HeaderT, Header};
/// Submit headers-bridge initialization transaction.
pub async fn initialize<SourceChain: Chain, TargetChain: Chain>(
@@ -77,7 +79,7 @@ async fn do_initialize<SourceChain: Chain, TargetChain: Chain>(
prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData<SourceChain::Header>) -> Bytes
+ Send
+ 'static,
) -> Result<TargetChain::Hash, String> {
) -> Result<TargetChain::Hash, Error<SourceChain::Hash, <SourceChain::Header as Header>::Number>> {
let initialization_data = prepare_initialization_data(source_client).await?;
log::info!(
target: "bridge",
@@ -92,41 +94,40 @@ async fn do_initialize<SourceChain: Chain, TargetChain: Chain>(
prepare_initialize_transaction(transaction_nonce, initialization_data)
})
.await
.map_err(|err| format!("Failed to submit {} transaction: {:?}", TargetChain::NAME, err))?;
.map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?;
Ok(initialization_tx_hash)
}
/// Prepare initialization data for the GRANDPA verifier pallet.
async fn prepare_initialization_data<SourceChain: Chain>(
source_client: Client<SourceChain>,
) -> Result<InitializationData<SourceChain::Header>, String> {
) -> Result<
InitializationData<SourceChain::Header>,
Error<SourceChain::Hash, <SourceChain::Header as Header>::Number>,
> {
// In ideal world we just need to get best finalized header and then to read GRANDPA authorities
// set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header.
//
// But now there are problems with this approach - `CurrentSetId` may return invalid value. So
// here we're waiting for the next justification, read the authorities set and then try to
// figure out the set id with bruteforce.
let justifications = source_client.subscribe_justifications().await.map_err(|err| {
format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err)
})?;
let justifications = source_client
.subscribe_justifications()
.await
.map_err(|err| Error::Subscribe(SourceChain::NAME, err))?;
// Read next justification - the header that it finalizes will be used as initial header.
let justification = justifications
.next()
.await
.map_err(|err| err.to_string())
.map_err(|e| Error::ReadJustification(SourceChain::NAME, e))
.and_then(|justification| {
justification.ok_or_else(|| "stream has ended unexpectedly".into())
})
.map_err(|err| {
format!("Failed to read {} justification from the stream: {}", SourceChain::NAME, err,)
justification.ok_or_else(|| Error::ReadJustificationStreamEnded(SourceChain::NAME))
})?;
// Read initial header.
let justification: GrandpaJustification<SourceChain::Header> =
Decode::decode(&mut &justification.0[..]).map_err(|err| {
format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err)
})?;
Decode::decode(&mut &justification.0[..])
.map_err(|err| Error::DecodeJustification(SourceChain::NAME, err))?;
let (initial_header_hash, initial_header_number) =
(justification.commit.target_hash, justification.commit.target_number);
@@ -174,11 +175,7 @@ async fn prepare_initialization_data<SourceChain: Chain>(
let mut min_possible_block_number = SourceChain::BlockNumber::zero();
let authorities_for_verification = VoterSet::new(authorities_for_verification.clone())
.ok_or_else(|| {
format!(
"Read invalid {} authorities set: {:?}",
SourceChain::NAME,
authorities_for_verification,
)
Error::ReadInvalidAuthorities(SourceChain::NAME, authorities_for_verification)
})?;
loop {
log::trace!(
@@ -205,12 +202,7 @@ async fn prepare_initialization_data<SourceChain: Chain>(
// there can't be more authorities set changes than headers => if we have reached
// `initial_block_number` and still have not found correct value of
// `initial_authorities_set_id`, then something else is broken => fail
return Err(format!(
"Failed to guess initial {} GRANDPA authorities set id: checked all\
possible ids in range [0; {}]",
SourceChain::NAME,
initial_header_number
))
return Err(Error::GuessInitialAuthorities(SourceChain::NAME, initial_header_number))
}
}
@@ -230,37 +222,24 @@ async fn prepare_initialization_data<SourceChain: Chain>(
async fn source_header<SourceChain: Chain>(
source_client: &Client<SourceChain>,
header_hash: SourceChain::Hash,
) -> Result<SourceChain::Header, String> {
source_client.header_by_hash(header_hash).await.map_err(|err| {
format!(
"Failed to retrive {} header with hash {}: {:?}",
SourceChain::NAME,
header_hash,
err,
)
})
) -> Result<SourceChain::Header, Error<SourceChain::Hash, <SourceChain::Header as Header>::Number>>
{
source_client
.header_by_hash(header_hash)
.await
.map_err(|err| Error::RetrieveHeader(SourceChain::NAME, header_hash, err))
}
/// Read GRANDPA authorities set at given header.
async fn source_authorities_set<SourceChain: Chain>(
source_client: &Client<SourceChain>,
header_hash: SourceChain::Hash,
) -> Result<GrandpaAuthoritiesSet, String> {
let raw_authorities_set =
source_client.grandpa_authorities_set(header_hash).await.map_err(|err| {
format!(
"Failed to retrive {} GRANDPA authorities set at header {}: {:?}",
SourceChain::NAME,
header_hash,
err,
)
})?;
GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]).map_err(|err| {
format!(
"Failed to decode {} GRANDPA authorities set at header {}: {:?}",
SourceChain::NAME,
header_hash,
err,
)
})
) -> Result<GrandpaAuthoritiesSet, Error<SourceChain::Hash, <SourceChain::Header as Header>::Number>>
{
let raw_authorities_set = source_client
.grandpa_authorities_set(header_hash)
.await
.map_err(|err| Error::RetrieveAuthorities(SourceChain::NAME, header_hash, err))?;
GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..])
.map_err(|err| Error::DecodeAuthorities(SourceChain::NAME, header_hash, err))
}