mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 16:51:03 +00:00
Introduce a Slot type (#7997)
* Introduce a `Slot` type Instead of having some type definition that only was used in half of the code or directly using `u64`, this adds a new unit type wrapper `Slot`. This makes it especially easy for the outside api to know what type is expected/returned. * Change epoch duratioC * rename all instances of slot number to slot * Make the constructor private Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
use sp_core::Pair;
|
||||
use sp_consensus_aura::AURA_ENGINE_ID;
|
||||
use sp_runtime::generic::{DigestItem, OpaqueDigestItemId};
|
||||
use sp_consensus_slots::Slot;
|
||||
use codec::{Encode, Codec};
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -38,10 +39,10 @@ pub trait CompatibleDigestItem<P: Pair>: Sized {
|
||||
fn as_aura_seal(&self) -> Option<Signature<P>>;
|
||||
|
||||
/// Construct a digest item which contains the slot number
|
||||
fn aura_pre_digest(slot_num: u64) -> Self;
|
||||
fn aura_pre_digest(slot: Slot) -> Self;
|
||||
|
||||
/// If this item is an AuRa pre-digest, return the slot number
|
||||
fn as_aura_pre_digest(&self) -> Option<u64>;
|
||||
fn as_aura_pre_digest(&self) -> Option<Slot>;
|
||||
}
|
||||
|
||||
impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash> where
|
||||
@@ -57,11 +58,11 @@ impl<P, Hash> CompatibleDigestItem<P> for DigestItem<Hash> where
|
||||
self.try_to(OpaqueDigestItemId::Seal(&AURA_ENGINE_ID))
|
||||
}
|
||||
|
||||
fn aura_pre_digest(slot_num: u64) -> Self {
|
||||
DigestItem::PreRuntime(AURA_ENGINE_ID, slot_num.encode())
|
||||
fn aura_pre_digest(slot: Slot) -> Self {
|
||||
DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())
|
||||
}
|
||||
|
||||
fn as_aura_pre_digest(&self) -> Option<u64> {
|
||||
fn as_aura_pre_digest(&self) -> Option<Slot> {
|
||||
self.try_to(OpaqueDigestItemId::PreRuntime(&AURA_ENGINE_ID))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ use prometheus_endpoint::Registry;
|
||||
use codec::{Encode, Decode, Codec};
|
||||
|
||||
use sp_consensus::{
|
||||
self, BlockImport, Environment, Proposer, CanAuthorWith, ForkChoiceStrategy, BlockImportParams,
|
||||
BlockOrigin, Error as ConsensusError, SelectChain, SlotData, BlockCheckParams, ImportResult
|
||||
};
|
||||
use sp_consensus::import_queue::{
|
||||
Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport,
|
||||
BlockImport, Environment, Proposer, CanAuthorWith, ForkChoiceStrategy, BlockImportParams,
|
||||
BlockOrigin, Error as ConsensusError, SelectChain, SlotData, BlockCheckParams, ImportResult,
|
||||
import_queue::{
|
||||
Verifier, BasicQueue, DefaultImportQueue, BoxJustificationImport,
|
||||
},
|
||||
};
|
||||
use sc_client_api::{backend::AuxStore, BlockOf};
|
||||
use sp_blockchain::{
|
||||
@@ -57,10 +57,7 @@ use sp_blockchain::{
|
||||
use sp_block_builder::BlockBuilder as BlockBuilderApi;
|
||||
use sp_core::crypto::Public;
|
||||
use sp_application_crypto::{AppKey, AppPublic};
|
||||
use sp_runtime::{
|
||||
generic::{BlockId, OpaqueDigestItemId},
|
||||
traits::NumberFor, Justification,
|
||||
};
|
||||
use sp_runtime::{generic::{BlockId, OpaqueDigestItemId}, traits::NumberFor, Justification};
|
||||
use sp_runtime::traits::{Block as BlockT, Header, DigestItemFor, Zero, Member};
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_core::crypto::Pair;
|
||||
@@ -75,6 +72,7 @@ use sc_consensus_slots::{
|
||||
CheckedHeader, SlotInfo, SlotCompatible, StorageChanges, check_equivocation,
|
||||
BackoffAuthoringBlocksStrategy,
|
||||
};
|
||||
use sp_consensus_slots::Slot;
|
||||
|
||||
use sp_api::ApiExt;
|
||||
|
||||
@@ -106,10 +104,10 @@ pub fn slot_duration<A, B, C>(client: &C) -> CResult<SlotDuration> where
|
||||
}
|
||||
|
||||
/// Get slot author for given block along with authorities.
|
||||
fn slot_author<P: Pair>(slot_num: u64, authorities: &[AuthorityId<P>]) -> Option<&AuthorityId<P>> {
|
||||
fn slot_author<P: Pair>(slot: Slot, authorities: &[AuthorityId<P>]) -> Option<&AuthorityId<P>> {
|
||||
if authorities.is_empty() { return None }
|
||||
|
||||
let idx = slot_num % (authorities.len() as u64);
|
||||
let idx = *slot % (authorities.len() as u64);
|
||||
assert!(
|
||||
idx <= usize::max_value() as u64,
|
||||
"It is impossible to have a vector with length beyond the address space; qed",
|
||||
@@ -239,7 +237,7 @@ where
|
||||
fn epoch_data(
|
||||
&self,
|
||||
header: &B::Header,
|
||||
_slot_number: u64,
|
||||
_slot: Slot,
|
||||
) -> Result<Self::EpochData, sp_consensus::Error> {
|
||||
authorities(self.client.as_ref(), &BlockId::Hash(header.hash()))
|
||||
}
|
||||
@@ -251,10 +249,10 @@ where
|
||||
fn claim_slot(
|
||||
&self,
|
||||
_header: &B::Header,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
epoch_data: &Self::EpochData,
|
||||
) -> Option<Self::Claim> {
|
||||
let expected_author = slot_author::<P>(slot_number, epoch_data);
|
||||
let expected_author = slot_author::<P>(slot, epoch_data);
|
||||
expected_author.and_then(|p| {
|
||||
if SyncCryptoStore::has_keys(
|
||||
&*self.keystore,
|
||||
@@ -269,11 +267,11 @@ where
|
||||
|
||||
fn pre_digest_data(
|
||||
&self,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
_claim: &Self::Claim,
|
||||
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
|
||||
vec![
|
||||
<DigestItemFor<B> as CompatibleDigestItem<P>>::aura_pre_digest(slot_number),
|
||||
<DigestItemFor<B> as CompatibleDigestItem<P>>::aura_pre_digest(slot),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -323,14 +321,14 @@ where
|
||||
self.force_authoring
|
||||
}
|
||||
|
||||
fn should_backoff(&self, slot_number: u64, chain_head: &B::Header) -> bool {
|
||||
fn should_backoff(&self, slot: Slot, chain_head: &B::Header) -> bool {
|
||||
if let Some(ref strategy) = self.backoff_authoring_blocks {
|
||||
if let Ok(chain_head_slot) = find_pre_digest::<B, P>(chain_head) {
|
||||
return strategy.should_backoff(
|
||||
*chain_head.number(),
|
||||
chain_head_slot,
|
||||
self.client.info().finalized_number,
|
||||
slot_number,
|
||||
slot,
|
||||
self.logging_target(),
|
||||
);
|
||||
}
|
||||
@@ -363,9 +361,10 @@ where
|
||||
if let Some(slot_lenience) =
|
||||
sc_consensus_slots::slot_lenience_exponential(parent_slot, slot_info)
|
||||
{
|
||||
debug!(target: "aura",
|
||||
debug!(
|
||||
target: "aura",
|
||||
"No block for {} slots. Applying linear lenience of {}s",
|
||||
slot_info.number.saturating_sub(parent_slot + 1),
|
||||
slot_info.slot.saturating_sub(parent_slot + 1),
|
||||
slot_lenience.as_secs(),
|
||||
);
|
||||
|
||||
@@ -401,7 +400,7 @@ enum Error<B: BlockT> {
|
||||
DataProvider(String),
|
||||
Runtime(String),
|
||||
#[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)]
|
||||
SlotNumberMustIncrease(u64, u64),
|
||||
SlotMustIncrease(Slot, Slot),
|
||||
#[display(fmt = "Parent ({}) of {} unavailable. Cannot import", _0, _1)]
|
||||
ParentUnavailable(B::Hash, B::Hash),
|
||||
}
|
||||
@@ -412,16 +411,16 @@ impl<B: BlockT> std::convert::From<Error<B>> for String {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<u64, Error<B>>
|
||||
fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<Slot, Error<B>>
|
||||
where DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P::Signature: Decode,
|
||||
P::Public: Encode + Decode + PartialEq + Clone,
|
||||
{
|
||||
if header.number().is_zero() {
|
||||
return Ok(0);
|
||||
return Ok(0.into());
|
||||
}
|
||||
|
||||
let mut pre_digest: Option<u64> = None;
|
||||
let mut pre_digest: Option<Slot> = None;
|
||||
for log in header.digest().logs() {
|
||||
trace!(target: "aura", "Checking log {:?}", log);
|
||||
match (log.as_aura_pre_digest(), pre_digest.is_some()) {
|
||||
@@ -440,11 +439,11 @@ fn find_pre_digest<B: BlockT, P: Pair>(header: &B::Header) -> Result<u64, Error<
|
||||
//
|
||||
fn check_header<C, B: BlockT, P: Pair>(
|
||||
client: &C,
|
||||
slot_now: u64,
|
||||
slot_now: Slot,
|
||||
mut header: B::Header,
|
||||
hash: B::Hash,
|
||||
authorities: &[AuthorityId<P>],
|
||||
) -> Result<CheckedHeader<B::Header, (u64, DigestItemFor<B>)>, Error<B>> where
|
||||
) -> Result<CheckedHeader<B::Header, (Slot, DigestItemFor<B>)>, Error<B>> where
|
||||
DigestItemFor<B>: CompatibleDigestItem<P>,
|
||||
P::Signature: Decode,
|
||||
C: sc_client_api::backend::AuxStore,
|
||||
@@ -459,15 +458,15 @@ fn check_header<C, B: BlockT, P: Pair>(
|
||||
aura_err(Error::HeaderBadSeal(hash))
|
||||
})?;
|
||||
|
||||
let slot_num = find_pre_digest::<B, _>(&header)?;
|
||||
let slot = find_pre_digest::<B, _>(&header)?;
|
||||
|
||||
if slot_num > slot_now {
|
||||
if slot > slot_now {
|
||||
header.digest_mut().push(seal);
|
||||
Ok(CheckedHeader::Deferred(header, slot_num))
|
||||
Ok(CheckedHeader::Deferred(header, slot))
|
||||
} else {
|
||||
// check the signature is valid under the expected authority and
|
||||
// chain state.
|
||||
let expected_author = match slot_author::<P>(slot_num, &authorities) {
|
||||
let expected_author = match slot_author::<P>(slot, &authorities) {
|
||||
None => return Err(Error::SlotAuthorNotFound),
|
||||
Some(author) => author,
|
||||
};
|
||||
@@ -478,19 +477,19 @@ fn check_header<C, B: BlockT, P: Pair>(
|
||||
if let Some(equivocation_proof) = check_equivocation(
|
||||
client,
|
||||
slot_now,
|
||||
slot_num,
|
||||
slot,
|
||||
&header,
|
||||
expected_author,
|
||||
).map_err(Error::Client)? {
|
||||
info!(
|
||||
"Slot author is equivocating at slot {} with headers {:?} and {:?}",
|
||||
slot_num,
|
||||
slot,
|
||||
equivocation_proof.first_header.hash(),
|
||||
equivocation_proof.second_header.hash(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(CheckedHeader::Checked(header, (slot_num, seal)))
|
||||
Ok(CheckedHeader::Checked(header, (slot, seal)))
|
||||
} else {
|
||||
Err(Error::BadSignature(hash))
|
||||
}
|
||||
@@ -614,12 +613,12 @@ impl<B: BlockT, C, P, CAW> Verifier<B> for AuraVerifier<C, P, CAW> where
|
||||
&authorities[..],
|
||||
).map_err(|e| e.to_string())?;
|
||||
match checked_header {
|
||||
CheckedHeader::Checked(pre_header, (slot_num, seal)) => {
|
||||
CheckedHeader::Checked(pre_header, (slot, seal)) => {
|
||||
// if the body is passed through, we need to use the runtime
|
||||
// to check that the internally-set timestamp in the inherents
|
||||
// actually matches the slot set in the seal.
|
||||
if let Some(inner_body) = body.take() {
|
||||
inherent_data.aura_replace_inherent_data(slot_num);
|
||||
inherent_data.aura_replace_inherent_data(slot);
|
||||
let block = B::new(pre_header.clone(), inner_body);
|
||||
|
||||
// skip the inherents verification if the runtime API is old.
|
||||
@@ -803,7 +802,7 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
|
||||
new_cache: HashMap<CacheKeyId, Vec<u8>>,
|
||||
) -> Result<ImportResult, Self::Error> {
|
||||
let hash = block.post_hash();
|
||||
let slot_number = find_pre_digest::<Block, P>(&block.header)
|
||||
let slot = find_pre_digest::<Block, P>(&block.header)
|
||||
.expect("valid Aura headers must contain a predigest; \
|
||||
header has been already verified; qed");
|
||||
|
||||
@@ -819,10 +818,10 @@ impl<Block: BlockT, C, I, P> BlockImport<Block> for AuraBlockImport<Block, C, I,
|
||||
parent header has already been verified; qed");
|
||||
|
||||
// make sure that slot number is strictly increasing
|
||||
if slot_number <= parent_slot {
|
||||
if slot <= parent_slot {
|
||||
return Err(
|
||||
ConsensusError::ClientImport(aura_err(
|
||||
Error::<Block>::SlotNumberMustIncrease(parent_slot, slot_number)
|
||||
Error::<Block>::SlotMustIncrease(parent_slot, slot)
|
||||
).into())
|
||||
);
|
||||
}
|
||||
@@ -1113,13 +1112,13 @@ mod tests {
|
||||
Default::default(),
|
||||
Default::default()
|
||||
);
|
||||
assert!(worker.claim_slot(&head, 0, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 1, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 2, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 3, &authorities).is_some());
|
||||
assert!(worker.claim_slot(&head, 4, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 5, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 6, &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 7, &authorities).is_some());
|
||||
assert!(worker.claim_slot(&head, 0.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 1.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 2.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 3.into(), &authorities).is_some());
|
||||
assert!(worker.claim_slot(&head, 4.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 5.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 6.into(), &authorities).is_none());
|
||||
assert!(worker.claim_slot(&head, 7.into(), &authorities).is_some());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user