From c545344c60a8b78f1b64c00628c254681ddd3c8e Mon Sep 17 00:00:00 2001 From: Ashley <ashley.ruglys@gmail.com> Date: Tue, 1 Oct 2019 17:42:11 +1300 Subject: [PATCH] Add an Error type to Aura (#3688) * Add an Error type to Aura * Add Cargo.lock * AuRa -> Aura Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- substrate/Cargo.lock | 1 + substrate/core/consensus/aura/Cargo.toml | 1 + substrate/core/consensus/aura/src/lib.rs | 67 +++++++++++++++--------- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 0787d7faec4..27066afe3c0 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -4771,6 +4771,7 @@ dependencies = [ name = "substrate-consensus-aura" version = "2.0.0" dependencies = [ + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures-preview 0.3.0-alpha.18 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/core/consensus/aura/Cargo.toml b/substrate/core/consensus/aura/Cargo.toml index c3aaeb3d56f..724b720f4fe 100644 --- a/substrate/core/consensus/aura/Cargo.toml +++ b/substrate/core/consensus/aura/Cargo.toml @@ -26,6 +26,7 @@ futures01 = { package = "futures", version = "0.1" } futures-timer = "0.3" parking_lot = "0.9.0" log = "0.4" +derive_more = "0.15.0" [dev-dependencies] keyring = { package = "substrate-keyring", path = "../../keyring" } diff --git a/substrate/core/consensus/aura/src/lib.rs b/substrate/core/consensus/aura/src/lib.rs index a61eb6da721..eb2d1dba20f 100644 --- a/substrate/core/consensus/aura/src/lib.rs +++ b/substrate/core/consensus/aura/src/lib.rs @@ -48,7 +48,7 @@ use sr_primitives::{generic::{BlockId, OpaqueDigestItemId}, Justification}; use sr_primitives::traits::{Block as BlockT, Header, DigestItemFor, ProvideRuntimeApi, Zero, Member}; use primitives::crypto::Pair; -use inherents::{InherentDataProviders, InherentData}; +use inherents::{InherentDataProviders, InherentData, RuntimeString}; use futures::prelude::*; use parking_lot::Mutex; @@ -308,16 +308,33 @@ impl<H, B: BlockT, C, E, I, P, Error, SO> SlotWorker<B> for AuraWorker<C, E, I, } } -macro_rules! aura_err { - ($($i: expr),+) => { - { - debug!(target: "aura", $( $i ),+); - format!($( $i ),+) - } - }; +fn aura_err<B: BlockT>(error: Error<B>) -> Error<B> { + debug!(target: "aura", "{}", error); + error +} + +#[derive(derive_more::Display)] +enum Error<B: BlockT> { + #[display(fmt = "Multiple Aura pre-runtime headers")] + MultipleHeaders, + #[display(fmt = "No Aura pre-runtime digest found")] + NoDigestFound, + #[display(fmt = "Header {:?} is unsealed", _0)] + HeaderUnsealed(B::Hash), + #[display(fmt = "Header {:?} has a bad seal", _0)] + HeaderBadSeal(B::Hash), + #[display(fmt = "Slot Author not found")] + SlotAuthorNotFound, + #[display(fmt = "Bad signature on {:?}", _0)] + BadSignature(B::Hash), + #[display(fmt = "Rejecting block too far in future")] + TooFarInFuture, + Client(client::error::Error), + DataProvider(String), + Runtime(RuntimeString) } -fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<u64, String> +fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<u64, Error<B>> where DigestItemFor<B>: CompatibleDigestItem<P>, P::Signature: Decode, P::Public: Encode + Decode + PartialEq + Clone, @@ -326,12 +343,12 @@ fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<u64, String for log in header.digest().logs() { trace!(target: "aura", "Checking log {:?}", log); match (log.as_aura_pre_digest(), pre_digest.is_some()) { - (Some(_), true) => Err(aura_err!("Multiple AuRa pre-runtime headers, rejecting!"))?, + (Some(_), true) => Err(aura_err(Error::MultipleHeaders))?, (None, _) => trace!(target: "aura", "Ignoring digest not meant for us"), (s, false) => pre_digest = s, } } - pre_digest.ok_or_else(|| aura_err!("No AuRa pre-runtime digest found")) + pre_digest.ok_or_else(|| aura_err(Error::NoDigestFound)) } /// check a header has been signed by the right key. If the slot is too far in the future, an error will be returned. @@ -348,7 +365,7 @@ fn check_header<C, B: BlockT, P: Pair, T>( hash: B::Hash, authorities: &[AuthorityId<P>], _transaction_pool: Option<&T>, -) -> Result<CheckedHeader<B::Header, (u64, DigestItemFor<B>)>, String> where +) -> Result<CheckedHeader<B::Header, (u64, DigestItemFor<B>)>, Error<B>> where DigestItemFor<B>: CompatibleDigestItem<P>, P::Signature: Decode, C: client::backend::AuxStore, @@ -357,11 +374,11 @@ fn check_header<C, B: BlockT, P: Pair, T>( { let seal = match header.digest_mut().pop() { Some(x) => x, - None => return Err(format!("Header {:?} is unsealed", hash)), + None => return Err(Error::HeaderUnsealed(hash)), }; let sig = seal.as_aura_seal().ok_or_else(|| { - aura_err!("Header {:?} has a bad seal", hash) + aura_err(Error::HeaderBadSeal(hash)) })?; let slot_num = find_pre_digest::<B, _>(&header)?; @@ -373,7 +390,7 @@ fn check_header<C, B: BlockT, P: Pair, T>( // check the signature is valid under the expected authority and // chain state. let expected_author = match slot_author::<P>(slot_num, &authorities) { - None => return Err("Slot Author not found".to_string()), + None => return Err(Error::SlotAuthorNotFound), Some(author) => author, }; @@ -386,7 +403,7 @@ fn check_header<C, B: BlockT, P: Pair, T>( slot_num, &header, expected_author, - ).map_err(|e| e.to_string())? { + ).map_err(Error::Client)? { info!( "Slot author is equivocating at slot {} with headers {:?} and {:?}", slot_num, @@ -397,7 +414,7 @@ fn check_header<C, B: BlockT, P: Pair, T>( Ok(CheckedHeader::Checked(header, (slot_num, seal))) } else { - Err(format!("Bad signature on {:?}", hash)) + Err(Error::BadSignature(hash)) } } } @@ -419,7 +436,7 @@ impl<C, P, T> AuraVerifier<C, P, T> block_id: BlockId<B>, inherent_data: InherentData, timestamp_now: u64, - ) -> Result<(), String> + ) -> Result<(), Error<B>> where C: ProvideRuntimeApi, C::Api: BlockBuilderApi<B> { const MAX_TIMESTAMP_DRIFT_SECS: u64 = 60; @@ -428,7 +445,7 @@ impl<C, P, T> AuraVerifier<C, P, T> &block_id, block, inherent_data, - ).map_err(|e| format!("{:?}", e))?; + ).map_err(Error::Client)?; if !inherent_res.ok() { inherent_res @@ -438,7 +455,7 @@ impl<C, P, T> AuraVerifier<C, P, T> // halt import until timestamp is valid. // reject when too far ahead. if timestamp > timestamp_now + MAX_TIMESTAMP_DRIFT_SECS { - return Err("Rejecting block too far in future".into()); + return Err(Error::TooFarInFuture); } let diff = timestamp.saturating_sub(timestamp_now); @@ -453,8 +470,10 @@ impl<C, P, T> AuraVerifier<C, P, T> thread::sleep(Duration::from_secs(diff)); Ok(()) }, - Some(TIError::Other(e)) => Err(e.into()), - None => Err(self.inherent_data_providers.error_to_string(&i, &e)), + Some(TIError::Other(e)) => Err(Error::Runtime(e)), + None => Err(Error::DataProvider( + self.inherent_data_providers.error_to_string(&i, &e) + )), }) } else { Ok(()) @@ -497,7 +516,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where hash, &authorities[..], self.transaction_pool.as_ref().map(|x| &**x), - )?; + ).map_err(|e| e.to_string())?; match checked_header { CheckedHeader::Checked(pre_header, (slot_num, seal)) => { // if the body is passed through, we need to use the runtime @@ -518,7 +537,7 @@ impl<B: BlockT, C, P, T> Verifier<B> for AuraVerifier<C, P, T> where BlockId::Hash(parent_hash), inherent_data, timestamp_now, - )?; + ).map_err(|e| e.to_string())?; } let (_, inner_body) = block.deconstruct(); -- GitLab