Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit a7bc9c2

Browse files
rphmeierbkchr
andauthored
Refactor: extract most aura logic out to standalone module, make use of these (#13764)
* Extract most aura logic out to standalone module, make use of these * Update client/consensus/aura/src/standalone.rs improve docs Co-authored-by: Bastian Köcher <[email protected]> * add slot_duration_at * ".git/.scripts/commands/fmt/fmt.sh" --------- Co-authored-by: Bastian Köcher <[email protected]> Co-authored-by: parity-processbot <>
1 parent de4cca4 commit a7bc9c2

File tree

3 files changed

+393
-137
lines changed

3 files changed

+393
-137
lines changed

client/consensus/aura/src/import_queue.rs

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
//! Module implementing the logic for verifying and importing AuRa blocks.
2020
2121
use crate::{
22-
aura_err, authorities, find_pre_digest, slot_author, AuthorityId, CompatibilityMode, Error,
22+
authorities, standalone::SealVerificationError, AuthorityId, CompatibilityMode, Error,
2323
LOG_TARGET,
2424
};
2525
use codec::{Codec, Decode, Encode};
@@ -36,7 +36,7 @@ use sp_api::{ApiExt, ProvideRuntimeApi};
3636
use sp_block_builder::BlockBuilder as BlockBuilderApi;
3737
use sp_blockchain::HeaderBackend;
3838
use sp_consensus::Error as ConsensusError;
39-
use sp_consensus_aura::{digests::CompatibleDigestItem, inherents::AuraInherentData, AuraApi};
39+
use sp_consensus_aura::{inherents::AuraInherentData, AuraApi};
4040
use sp_consensus_slots::Slot;
4141
use sp_core::{crypto::Pair, ExecutionContext};
4242
use sp_inherents::{CreateInherentDataProviders, InherentDataProvider as _};
@@ -54,7 +54,7 @@ use std::{fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc};
5454
fn check_header<C, B: BlockT, P: Pair>(
5555
client: &C,
5656
slot_now: Slot,
57-
mut header: B::Header,
57+
header: B::Header,
5858
hash: B::Hash,
5959
authorities: &[AuthorityId<P>],
6060
check_for_equivocation: CheckForEquivocation,
@@ -64,27 +64,16 @@ where
6464
C: sc_client_api::backend::AuxStore,
6565
P::Public: Encode + Decode + PartialEq + Clone,
6666
{
67-
let seal = header.digest_mut().pop().ok_or(Error::HeaderUnsealed(hash))?;
68-
69-
let sig = seal.as_aura_seal().ok_or_else(|| aura_err(Error::HeaderBadSeal(hash)))?;
70-
71-
let slot = find_pre_digest::<B, P::Signature>(&header)?;
72-
73-
if slot > slot_now {
74-
header.digest_mut().push(seal);
75-
Ok(CheckedHeader::Deferred(header, slot))
76-
} else {
77-
// check the signature is valid under the expected authority and
78-
// chain state.
79-
let expected_author =
80-
slot_author::<P>(slot, authorities).ok_or(Error::SlotAuthorNotFound)?;
81-
82-
let pre_hash = header.hash();
83-
84-
if P::verify(&sig, pre_hash.as_ref(), expected_author) {
85-
if check_for_equivocation.check_for_equivocation() {
67+
let check_result =
68+
crate::standalone::check_header_slot_and_seal::<B, P>(slot_now, header, authorities);
69+
70+
match check_result {
71+
Ok((header, slot, seal)) => {
72+
let expected_author = crate::standalone::slot_author::<P>(slot, &authorities);
73+
let should_equiv_check = check_for_equivocation.check_for_equivocation();
74+
if let (true, Some(expected)) = (should_equiv_check, expected_author) {
8675
if let Some(equivocation_proof) =
87-
check_equivocation(client, slot_now, slot, &header, expected_author)
76+
check_equivocation(client, slot_now, slot, &header, expected)
8877
.map_err(Error::Client)?
8978
{
9079
info!(
@@ -98,9 +87,14 @@ where
9887
}
9988

10089
Ok(CheckedHeader::Checked(header, (slot, seal)))
101-
} else {
102-
Err(Error::BadSignature(hash))
103-
}
90+
},
91+
Err(SealVerificationError::Deferred(header, slot)) =>
92+
Ok(CheckedHeader::Deferred(header, slot)),
93+
Err(SealVerificationError::Unsealed) => Err(Error::HeaderUnsealed(hash)),
94+
Err(SealVerificationError::BadSeal) => Err(Error::HeaderBadSeal(hash)),
95+
Err(SealVerificationError::BadSignature) => Err(Error::BadSignature(hash)),
96+
Err(SealVerificationError::SlotAuthorNotFound) => Err(Error::SlotAuthorNotFound),
97+
Err(SealVerificationError::InvalidPreDigest(e)) => Err(Error::from(e)),
10498
}
10599
}
106100

client/consensus/aura/src/lib.rs

Lines changed: 16 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -33,32 +33,30 @@
3333
use std::{fmt::Debug, hash::Hash, marker::PhantomData, pin::Pin, sync::Arc};
3434

3535
use futures::prelude::*;
36-
use log::{debug, trace};
3736

3837
use codec::{Codec, Decode, Encode};
3938

40-
use sc_client_api::{backend::AuxStore, BlockOf, UsageProvider};
39+
use sc_client_api::{backend::AuxStore, BlockOf};
4140
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, StateAction};
4241
use sc_consensus_slots::{
4342
BackoffAuthoringBlocksStrategy, InherentDataProviderExt, SimpleSlotWorkerToSlotWorker,
4443
SlotInfo, StorageChanges,
4544
};
4645
use sc_telemetry::TelemetryHandle;
4746
use sp_api::{Core, ProvideRuntimeApi};
48-
use sp_application_crypto::{AppCrypto, AppPublic};
49-
use sp_blockchain::{HeaderBackend, Result as CResult};
47+
use sp_application_crypto::AppPublic;
48+
use sp_blockchain::HeaderBackend;
5049
use sp_consensus::{BlockOrigin, Environment, Error as ConsensusError, Proposer, SelectChain};
5150
use sp_consensus_slots::Slot;
52-
use sp_core::crypto::{ByteArray, Pair, Public};
51+
use sp_core::crypto::{Pair, Public};
5352
use sp_inherents::CreateInherentDataProviders;
5453
use sp_keystore::KeystorePtr;
55-
use sp_runtime::{
56-
traits::{Block as BlockT, Header, Member, NumberFor, Zero},
57-
DigestItem,
58-
};
54+
use sp_runtime::traits::{Block as BlockT, Header, Member, NumberFor};
5955

6056
mod import_queue;
57+
pub mod standalone;
6158

59+
pub use crate::standalone::{find_pre_digest, slot_duration};
6260
pub use import_queue::{
6361
build_verifier, import_queue, AuraVerifier, BuildVerifierParams, CheckForEquivocation,
6462
ImportQueueParams,
@@ -112,39 +110,6 @@ impl<N> Default for CompatibilityMode<N> {
112110
}
113111
}
114112

115-
/// Get the slot duration for Aura.
116-
pub fn slot_duration<A, B, C>(client: &C) -> CResult<SlotDuration>
117-
where
118-
A: Codec,
119-
B: BlockT,
120-
C: AuxStore + ProvideRuntimeApi<B> + UsageProvider<B>,
121-
C::Api: AuraApi<B, A>,
122-
{
123-
client
124-
.runtime_api()
125-
.slot_duration(client.usage_info().chain.best_hash)
126-
.map_err(|err| err.into())
127-
}
128-
129-
/// Get slot author for given block along with authorities.
130-
fn slot_author<P: Pair>(slot: Slot, authorities: &[AuthorityId<P>]) -> Option<&AuthorityId<P>> {
131-
if authorities.is_empty() {
132-
return None
133-
}
134-
135-
let idx = *slot % (authorities.len() as u64);
136-
assert!(
137-
idx <= usize::MAX as u64,
138-
"It is impossible to have a vector with length beyond the address space; qed",
139-
);
140-
141-
let current_author = authorities.get(idx as usize).expect(
142-
"authorities not empty; index constrained to list length;this is a valid index; qed",
143-
);
144-
145-
Some(current_author)
146-
}
147-
148113
/// Parameters of [`start_aura`].
149114
pub struct StartAuraParams<C, SC, I, PF, SO, L, CIDP, BS, N> {
150115
/// The duration of a slot.
@@ -412,21 +377,11 @@ where
412377
slot: Slot,
413378
authorities: &Self::AuxData,
414379
) -> Option<Self::Claim> {
415-
let expected_author = slot_author::<P>(slot, authorities);
416-
expected_author.and_then(|p| {
417-
if self
418-
.keystore
419-
.has_keys(&[(p.to_raw_vec(), sp_application_crypto::key_types::AURA)])
420-
{
421-
Some(p.clone())
422-
} else {
423-
None
424-
}
425-
})
380+
crate::standalone::claim_slot::<P>(slot, authorities, &self.keystore).await
426381
}
427382

428383
fn pre_digest_data(&self, slot: Slot, _claim: &Self::Claim) -> Vec<sp_runtime::DigestItem> {
429-
vec![<DigestItem as CompatibleDigestItem<P::Signature>>::aura_pre_digest(slot)]
384+
vec![crate::standalone::pre_digest::<P>(slot)]
430385
}
431386

432387
async fn block_import_params(
@@ -441,28 +396,8 @@ where
441396
sc_consensus::BlockImportParams<B, <Self::BlockImport as BlockImport<B>>::Transaction>,
442397
ConsensusError,
443398
> {
444-
let signature = self
445-
.keystore
446-
.sign_with(
447-
<AuthorityId<P> as AppCrypto>::ID,
448-
<AuthorityId<P> as AppCrypto>::CRYPTO_ID,
449-
public.as_slice(),
450-
header_hash.as_ref(),
451-
)
452-
.map_err(|e| ConsensusError::CannotSign(format!("{}. Key: {:?}", e, public)))?
453-
.ok_or_else(|| {
454-
ConsensusError::CannotSign(format!(
455-
"Could not find key in keystore. Key: {:?}",
456-
public
457-
))
458-
})?;
459-
let signature = signature
460-
.clone()
461-
.try_into()
462-
.map_err(|_| ConsensusError::InvalidSignature(signature, public.to_raw_vec()))?;
463-
464399
let signature_digest_item =
465-
<DigestItem as CompatibleDigestItem<P::Signature>>::aura_seal(signature);
400+
crate::standalone::seal::<_, P>(header_hash, &public, &self.keystore)?;
466401

467402
let mut import_block = BlockImportParams::new(BlockOrigin::Own, header);
468403
import_block.post_digests.push(signature_digest_item);
@@ -526,11 +461,6 @@ where
526461
}
527462
}
528463

529-
fn aura_err<B: BlockT>(error: Error<B>) -> Error<B> {
530-
debug!(target: LOG_TARGET, "{}", error);
531-
error
532-
}
533-
534464
/// Aura Errors
535465
#[derive(Debug, thiserror::Error)]
536466
pub enum Error<B: BlockT> {
@@ -569,22 +499,13 @@ impl<B: BlockT> From<Error<B>> for String {
569499
}
570500
}
571501

572-
/// Get pre-digests from the header
573-
pub fn find_pre_digest<B: BlockT, Signature: Codec>(header: &B::Header) -> Result<Slot, Error<B>> {
574-
if header.number().is_zero() {
575-
return Ok(0.into())
576-
}
577-
578-
let mut pre_digest: Option<Slot> = None;
579-
for log in header.digest().logs() {
580-
trace!(target: LOG_TARGET, "Checking log {:?}", log);
581-
match (CompatibleDigestItem::<Signature>::as_aura_pre_digest(log), pre_digest.is_some()) {
582-
(Some(_), true) => return Err(aura_err(Error::MultipleHeaders)),
583-
(None, _) => trace!(target: LOG_TARGET, "Ignoring digest not meant for us"),
584-
(s, false) => pre_digest = s,
502+
impl<B: BlockT> From<crate::standalone::PreDigestLookupError> for Error<B> {
503+
fn from(e: crate::standalone::PreDigestLookupError) -> Self {
504+
match e {
505+
crate::standalone::PreDigestLookupError::MultipleHeaders => Error::MultipleHeaders,
506+
crate::standalone::PreDigestLookupError::NoDigestFound => Error::NoDigestFound,
585507
}
586508
}
587-
pre_digest.ok_or_else(|| aura_err(Error::NoDigestFound))
588509
}
589510

590511
fn authorities<A, B, C>(
@@ -637,7 +558,7 @@ mod tests {
637558
use sc_consensus_slots::{BackoffAuthoringOnFinalizedHeadLagging, SimpleSlotWorker};
638559
use sc_keystore::LocalKeystore;
639560
use sc_network_test::{Block as TestBlock, *};
640-
use sp_application_crypto::key_types::AURA;
561+
use sp_application_crypto::{key_types::AURA, AppCrypto};
641562
use sp_consensus::{DisableProofRecording, NoNetwork as DummyOracle, Proposal};
642563
use sp_consensus_aura::sr25519::AuthorityPair;
643564
use sp_inherents::InherentData;
@@ -851,22 +772,6 @@ mod tests {
851772
.await;
852773
}
853774

854-
#[test]
855-
fn authorities_call_works() {
856-
let client = substrate_test_runtime_client::new();
857-
858-
assert_eq!(client.chain_info().best_number, 0);
859-
assert_eq!(
860-
authorities(&client, client.chain_info().best_hash, 1, &CompatibilityMode::None)
861-
.unwrap(),
862-
vec![
863-
Keyring::Alice.public().into(),
864-
Keyring::Bob.public().into(),
865-
Keyring::Charlie.public().into()
866-
]
867-
);
868-
}
869-
870775
#[tokio::test]
871776
async fn current_node_authority_should_claim_slot() {
872777
let net = AuraTestNet::new(4);

0 commit comments

Comments
 (0)