mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 13:31:10 +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:
Generated
+5
@@ -6724,6 +6724,7 @@ dependencies = [
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-consensus-aura",
|
||||
"sp-consensus-slots",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
"sp-io",
|
||||
@@ -6776,6 +6777,7 @@ dependencies = [
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-consensus-babe",
|
||||
"sp-consensus-slots",
|
||||
"sp-consensus-vrf",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
@@ -6856,6 +6858,7 @@ dependencies = [
|
||||
"sp-blockchain",
|
||||
"sp-consensus",
|
||||
"sp-consensus-babe",
|
||||
"sp-consensus-slots",
|
||||
"sp-core",
|
||||
"sp-inherents",
|
||||
"sp-keyring",
|
||||
@@ -8247,6 +8250,7 @@ dependencies = [
|
||||
"parity-scale-codec",
|
||||
"sp-api",
|
||||
"sp-application-crypto",
|
||||
"sp-consensus-slots",
|
||||
"sp-inherents",
|
||||
"sp-runtime",
|
||||
"sp-std",
|
||||
@@ -8288,6 +8292,7 @@ name = "sp-consensus-slots"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"parity-scale-codec",
|
||||
"sp-arithmetic",
|
||||
"sp-runtime",
|
||||
]
|
||||
|
||||
|
||||
@@ -514,7 +514,7 @@ mod tests {
|
||||
let chain_spec = crate::chain_spec::tests::integration_test_config_with_single_authority();
|
||||
|
||||
// For the block factory
|
||||
let mut slot_num = 1u64;
|
||||
let mut slot = 1u64;
|
||||
|
||||
// For the extrinsics factory
|
||||
let bob = Arc::new(AccountKeyring::Bob.pair());
|
||||
@@ -575,7 +575,7 @@ mod tests {
|
||||
descendent_query(&*service.client()),
|
||||
&parent_hash,
|
||||
parent_number,
|
||||
slot_num,
|
||||
slot.into(),
|
||||
).unwrap().unwrap();
|
||||
|
||||
let mut digest = Digest::<H256>::default();
|
||||
@@ -583,9 +583,9 @@ mod tests {
|
||||
// even though there's only one authority some slots might be empty,
|
||||
// so we must keep trying the next slots until we can claim one.
|
||||
let babe_pre_digest = loop {
|
||||
inherent_data.replace_data(sp_timestamp::INHERENT_IDENTIFIER, &(slot_num * SLOT_DURATION));
|
||||
inherent_data.replace_data(sp_timestamp::INHERENT_IDENTIFIER, &(slot * SLOT_DURATION));
|
||||
if let Some(babe_pre_digest) = sc_consensus_babe::test_helpers::claim_slot(
|
||||
slot_num,
|
||||
slot.into(),
|
||||
&parent_header,
|
||||
&*service.client(),
|
||||
keystore.clone(),
|
||||
@@ -594,7 +594,7 @@ mod tests {
|
||||
break babe_pre_digest;
|
||||
}
|
||||
|
||||
slot_num += 1;
|
||||
slot += 1;
|
||||
};
|
||||
|
||||
digest.push(<DigestItem as CompatibleDigestItem>::babe_pre_digest(babe_pre_digest));
|
||||
@@ -625,7 +625,7 @@ mod tests {
|
||||
let item = <DigestItem as CompatibleDigestItem>::babe_seal(
|
||||
signature,
|
||||
);
|
||||
slot_num += 1;
|
||||
slot += 1;
|
||||
|
||||
let mut params = BlockImportParams::new(BlockOrigin::File, new_header);
|
||||
params.post_digests.push(item);
|
||||
|
||||
@@ -1200,7 +1200,7 @@ impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
fn current_epoch_start() -> sp_consensus_babe::SlotNumber {
|
||||
fn current_epoch_start() -> sp_consensus_babe::Slot {
|
||||
Babe::current_epoch_start()
|
||||
}
|
||||
|
||||
@@ -1213,7 +1213,7 @@ impl_runtime_apis! {
|
||||
}
|
||||
|
||||
fn generate_key_ownership_proof(
|
||||
_slot_number: sp_consensus_babe::SlotNumber,
|
||||
_slot: sp_consensus_babe::Slot,
|
||||
authority_id: sp_consensus_babe::AuthorityId,
|
||||
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
|
||||
use codec::Encode;
|
||||
|
||||
@@ -20,6 +20,7 @@ sc-block-builder = { version = "0.8.0", path = "../../block-builder" }
|
||||
sc-client-api = { version = "2.0.0", path = "../../api" }
|
||||
codec = { package = "parity-scale-codec", version = "1.3.6" }
|
||||
sp-consensus = { version = "0.8.0", path = "../../../primitives/consensus/common" }
|
||||
sp-consensus-slots = { version = "0.8.0", path = "../../../primitives/consensus/slots" }
|
||||
derive_more = "0.99.2"
|
||||
futures = "0.3.9"
|
||||
futures-timer = "3.0.1"
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ sp-api = { version = "2.0.0", path = "../../../primitives/api" }
|
||||
sp-block-builder = { version = "2.0.0", path = "../../../primitives/block-builder" }
|
||||
sp-blockchain = { version = "2.0.0", path = "../../../primitives/blockchain" }
|
||||
sp-consensus = { version = "0.8.0", path = "../../../primitives/consensus/common" }
|
||||
sp-consensus-slots = { version = "0.8.0", path = "../../../primitives/consensus/slots" }
|
||||
sp-consensus-vrf = { version = "0.8.0", path = "../../../primitives/consensus/vrf" }
|
||||
sc-consensus-uncles = { version = "0.8.0", path = "../uncles" }
|
||||
sc-consensus-slots = { version = "0.8.0", path = "../slots" }
|
||||
|
||||
@@ -124,7 +124,13 @@ impl<B, C, SC> BabeApi for BabeRpcHandler<B, C, SC>
|
||||
.map_err(|err| {
|
||||
Error::StringError(format!("{:?}", err))
|
||||
})?;
|
||||
let epoch = epoch_data(&shared_epoch, &client, &babe_config, epoch_start, &select_chain)?;
|
||||
let epoch = epoch_data(
|
||||
&shared_epoch,
|
||||
&client,
|
||||
&babe_config,
|
||||
*epoch_start,
|
||||
&select_chain,
|
||||
)?;
|
||||
let (epoch_start, epoch_end) = (epoch.start_slot(), epoch.end_slot());
|
||||
|
||||
let mut claims: HashMap<AuthorityId, EpochAuthorship> = HashMap::new();
|
||||
@@ -142,19 +148,19 @@ impl<B, C, SC> BabeApi for BabeRpcHandler<B, C, SC>
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
for slot_number in epoch_start..epoch_end {
|
||||
for slot in *epoch_start..*epoch_end {
|
||||
if let Some((claim, key)) =
|
||||
authorship::claim_slot_using_keys(slot_number, &epoch, &keystore, &keys)
|
||||
authorship::claim_slot_using_keys(slot.into(), &epoch, &keystore, &keys)
|
||||
{
|
||||
match claim {
|
||||
PreDigest::Primary { .. } => {
|
||||
claims.entry(key).or_default().primary.push(slot_number);
|
||||
claims.entry(key).or_default().primary.push(slot);
|
||||
}
|
||||
PreDigest::SecondaryPlain { .. } => {
|
||||
claims.entry(key).or_default().secondary.push(slot_number);
|
||||
claims.entry(key).or_default().secondary.push(slot);
|
||||
}
|
||||
PreDigest::SecondaryVRF { .. } => {
|
||||
claims.entry(key).or_default().secondary_vrf.push(slot_number);
|
||||
claims.entry(key).or_default().secondary_vrf.push(slot.into());
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -167,7 +173,7 @@ impl<B, C, SC> BabeApi for BabeRpcHandler<B, C, SC>
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds information about the `slot_number`'s that can be claimed by a given key.
|
||||
/// Holds information about the `slot`'s that can be claimed by a given key.
|
||||
#[derive(Default, Debug, Deserialize, Serialize)]
|
||||
pub struct EpochAuthorship {
|
||||
/// the array of primary slots that can be claimed
|
||||
@@ -197,12 +203,12 @@ impl From<Error> for jsonrpc_core::Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// fetches the epoch data for a given slot_number.
|
||||
/// fetches the epoch data for a given slot.
|
||||
fn epoch_data<B, C, SC>(
|
||||
epoch_changes: &SharedEpochChanges<B, Epoch>,
|
||||
client: &Arc<C>,
|
||||
babe_config: &Config,
|
||||
slot_number: u64,
|
||||
slot: u64,
|
||||
select_chain: &SC,
|
||||
) -> Result<Epoch, Error>
|
||||
where
|
||||
@@ -215,7 +221,7 @@ fn epoch_data<B, C, SC>(
|
||||
descendent_query(&**client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot.into(),
|
||||
|slot| Epoch::genesis(&babe_config, slot),
|
||||
)
|
||||
.map_err(|e| Error::Consensus(ConsensusError::ChainLookup(format!("{:?}", e))))?
|
||||
|
||||
@@ -20,11 +20,8 @@
|
||||
|
||||
use sp_application_crypto::AppKey;
|
||||
use sp_consensus_babe::{
|
||||
BABE_VRF_PREFIX,
|
||||
AuthorityId, BabeAuthorityWeight,
|
||||
SlotNumber,
|
||||
make_transcript,
|
||||
make_transcript_data,
|
||||
BABE_VRF_PREFIX, AuthorityId, BabeAuthorityWeight, make_transcript, make_transcript_data,
|
||||
Slot,
|
||||
};
|
||||
use sp_consensus_babe::digests::{
|
||||
PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest,
|
||||
@@ -106,7 +103,7 @@ pub(super) fn check_primary_threshold(inout: &VRFInOut, threshold: u128) -> bool
|
||||
/// authorities. This should always assign the slot to some authority unless the
|
||||
/// authorities list is empty.
|
||||
pub(super) fn secondary_slot_author(
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
authorities: &[(AuthorityId, BabeAuthorityWeight)],
|
||||
randomness: [u8; 32],
|
||||
) -> Option<&AuthorityId> {
|
||||
@@ -114,7 +111,7 @@ pub(super) fn secondary_slot_author(
|
||||
return None;
|
||||
}
|
||||
|
||||
let rand = U256::from((randomness, slot_number).using_encoded(blake2_256));
|
||||
let rand = U256::from((randomness, slot).using_encoded(blake2_256));
|
||||
|
||||
let authorities_len = U256::from(authorities.len());
|
||||
let idx = rand % authorities_len;
|
||||
@@ -130,7 +127,7 @@ pub(super) fn secondary_slot_author(
|
||||
/// pre-digest to use when authoring the block, or `None` if it is not our turn
|
||||
/// to propose.
|
||||
fn claim_secondary_slot(
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch: &Epoch,
|
||||
keys: &[(AuthorityId, usize)],
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
@@ -143,7 +140,7 @@ fn claim_secondary_slot(
|
||||
}
|
||||
|
||||
let expected_author = super::authorship::secondary_slot_author(
|
||||
slot_number,
|
||||
slot,
|
||||
authorities,
|
||||
*randomness,
|
||||
)?;
|
||||
@@ -153,7 +150,7 @@ fn claim_secondary_slot(
|
||||
let pre_digest = if author_secondary_vrf {
|
||||
let transcript_data = super::authorship::make_transcript_data(
|
||||
randomness,
|
||||
slot_number,
|
||||
slot,
|
||||
*epoch_index,
|
||||
);
|
||||
let result = SyncCryptoStore::sr25519_vrf_sign(
|
||||
@@ -164,7 +161,7 @@ fn claim_secondary_slot(
|
||||
);
|
||||
if let Ok(signature) = result {
|
||||
Some(PreDigest::SecondaryVRF(SecondaryVRFPreDigest {
|
||||
slot_number,
|
||||
slot,
|
||||
vrf_output: VRFOutput(signature.output),
|
||||
vrf_proof: VRFProof(signature.proof),
|
||||
authority_index: *authority_index as u32,
|
||||
@@ -174,7 +171,7 @@ fn claim_secondary_slot(
|
||||
}
|
||||
} else if SyncCryptoStore::has_keys(&**keystore, &[(authority_id.to_raw_vec(), AuthorityId::ID)]) {
|
||||
Some(PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
|
||||
slot_number,
|
||||
slot,
|
||||
authority_index: *authority_index as u32,
|
||||
}))
|
||||
} else {
|
||||
@@ -195,7 +192,7 @@ fn claim_secondary_slot(
|
||||
/// secondary slots enabled for the given epoch, we will fallback to trying to
|
||||
/// claim a secondary slot.
|
||||
pub fn claim_slot(
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch: &Epoch,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
) -> Option<(PreDigest, AuthorityId)> {
|
||||
@@ -203,24 +200,24 @@ pub fn claim_slot(
|
||||
.enumerate()
|
||||
.map(|(index, a)| (a.0.clone(), index))
|
||||
.collect::<Vec<_>>();
|
||||
claim_slot_using_keys(slot_number, epoch, keystore, &authorities)
|
||||
claim_slot_using_keys(slot, epoch, keystore, &authorities)
|
||||
}
|
||||
|
||||
/// Like `claim_slot`, but allows passing an explicit set of key pairs. Useful if we intend
|
||||
/// to make repeated calls for different slots using the same key pairs.
|
||||
pub fn claim_slot_using_keys(
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch: &Epoch,
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
keys: &[(AuthorityId, usize)],
|
||||
) -> Option<(PreDigest, AuthorityId)> {
|
||||
claim_primary_slot(slot_number, epoch, epoch.config.c, keystore, &keys)
|
||||
claim_primary_slot(slot, epoch, epoch.config.c, keystore, &keys)
|
||||
.or_else(|| {
|
||||
if epoch.config.allowed_slots.is_secondary_plain_slots_allowed() ||
|
||||
epoch.config.allowed_slots.is_secondary_vrf_slots_allowed()
|
||||
{
|
||||
claim_secondary_slot(
|
||||
slot_number,
|
||||
slot,
|
||||
&epoch,
|
||||
keys,
|
||||
&keystore,
|
||||
@@ -237,7 +234,7 @@ pub fn claim_slot_using_keys(
|
||||
/// the VRF. If the VRF produces a value less than `threshold`, it is our turn,
|
||||
/// so it returns `Some(_)`. Otherwise, it returns `None`.
|
||||
fn claim_primary_slot(
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch: &Epoch,
|
||||
c: (u64, u64),
|
||||
keystore: &SyncCryptoStorePtr,
|
||||
@@ -248,12 +245,12 @@ fn claim_primary_slot(
|
||||
for (authority_id, authority_index) in keys {
|
||||
let transcript = super::authorship::make_transcript(
|
||||
randomness,
|
||||
slot_number,
|
||||
slot,
|
||||
*epoch_index
|
||||
);
|
||||
let transcript_data = super::authorship::make_transcript_data(
|
||||
randomness,
|
||||
slot_number,
|
||||
slot,
|
||||
*epoch_index
|
||||
);
|
||||
// Compute the threshold we will use.
|
||||
@@ -276,7 +273,7 @@ fn claim_primary_slot(
|
||||
};
|
||||
if super::authorship::check_primary_threshold(&inout, threshold) {
|
||||
let pre_digest = PreDigest::Primary(PrimaryPreDigest {
|
||||
slot_number,
|
||||
slot,
|
||||
vrf_output: VRFOutput(signature.output),
|
||||
vrf_proof: VRFProof(signature.proof),
|
||||
authority_index: *authority_index as u32,
|
||||
@@ -314,7 +311,7 @@ mod tests {
|
||||
|
||||
let mut epoch = Epoch {
|
||||
epoch_index: 10,
|
||||
start_slot: 0,
|
||||
start_slot: 0.into(),
|
||||
duration: 20,
|
||||
authorities: authorities.clone(),
|
||||
randomness: Default::default(),
|
||||
@@ -324,9 +321,9 @@ mod tests {
|
||||
},
|
||||
};
|
||||
|
||||
assert!(claim_slot(10, &epoch, &keystore).is_none());
|
||||
assert!(claim_slot(10.into(), &epoch, &keystore).is_none());
|
||||
|
||||
epoch.authorities.push((valid_public_key.clone().into(), 10));
|
||||
assert_eq!(claim_slot(10, &epoch, &keystore).unwrap().1, valid_public_key.into());
|
||||
assert_eq!(claim_slot(10.into(), &epoch, &keystore).unwrap().1, valid_public_key.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ mod test {
|
||||
#[test]
|
||||
fn load_decode_from_v0_epoch_changes() {
|
||||
let epoch = EpochV0 {
|
||||
start_slot: 0,
|
||||
start_slot: 0.into(),
|
||||
authorities: vec![],
|
||||
randomness: [0; 32],
|
||||
epoch_index: 1,
|
||||
@@ -195,8 +195,8 @@ mod test {
|
||||
.map(|(_, _, epoch)| epoch.clone())
|
||||
.collect::<Vec<_>>() ==
|
||||
vec![PersistedEpochHeader::Regular(EpochHeader {
|
||||
start_slot: 0,
|
||||
end_slot: 100,
|
||||
start_slot: 0.into(),
|
||||
end_slot: 100.into(),
|
||||
})],
|
||||
); // PersistedEpochHeader does not implement Debug, so we use assert! directly.
|
||||
|
||||
|
||||
@@ -66,10 +66,8 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![warn(missing_docs)]
|
||||
pub use sp_consensus_babe::{
|
||||
BabeApi, ConsensusLog, BABE_ENGINE_ID, SlotNumber,
|
||||
BabeEpochConfiguration, BabeGenesisConfiguration,
|
||||
AuthorityId, AuthorityPair, AuthoritySignature,
|
||||
BabeAuthorityWeight, VRF_OUTPUT_LENGTH,
|
||||
BabeApi, ConsensusLog, BABE_ENGINE_ID, BabeEpochConfiguration, BabeGenesisConfiguration,
|
||||
AuthorityId, AuthorityPair, AuthoritySignature, BabeAuthorityWeight, VRF_OUTPUT_LENGTH,
|
||||
digests::{
|
||||
CompatibleDigestItem, NextEpochDescriptor, NextConfigDescriptor, PreDigest,
|
||||
PrimaryPreDigest, SecondaryPlainPreDigest,
|
||||
@@ -80,8 +78,7 @@ use std::{
|
||||
collections::HashMap, sync::Arc, u64, pin::Pin, time::{Instant, Duration},
|
||||
any::Any, borrow::Cow, convert::TryInto,
|
||||
};
|
||||
use sp_consensus::{ImportResult, CanAuthorWith};
|
||||
use sp_consensus::import_queue::BoxJustificationImport;
|
||||
use sp_consensus::{ImportResult, CanAuthorWith, import_queue::BoxJustificationImport};
|
||||
use sp_core::crypto::Public;
|
||||
use sp_application_crypto::AppKey;
|
||||
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
|
||||
@@ -94,16 +91,14 @@ use parking_lot::Mutex;
|
||||
use sp_inherents::{InherentDataProviders, InherentData};
|
||||
use sc_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG};
|
||||
use sp_consensus::{
|
||||
self, BlockImport, Environment, Proposer, BlockCheckParams,
|
||||
BlockImport, Environment, Proposer, BlockCheckParams,
|
||||
ForkChoiceStrategy, BlockImportParams, BlockOrigin, Error as ConsensusError,
|
||||
SelectChain, SlotData,
|
||||
SelectChain, SlotData, import_queue::{Verifier, BasicQueue, DefaultImportQueue, CacheKeyId},
|
||||
};
|
||||
use sp_consensus_babe::inherents::BabeInherentData;
|
||||
use sp_timestamp::{TimestampInherentData, InherentType as TimestampInherent};
|
||||
use sp_consensus::import_queue::{Verifier, BasicQueue, DefaultImportQueue, CacheKeyId};
|
||||
use sc_client_api::{
|
||||
backend::AuxStore,
|
||||
BlockchainEvents, ProvideUncles,
|
||||
backend::AuxStore, BlockchainEvents, ProvideUncles,
|
||||
};
|
||||
use sp_block_builder::BlockBuilder as BlockBuilderApi;
|
||||
use futures::channel::mpsc::{channel, Sender, Receiver};
|
||||
@@ -114,7 +109,7 @@ use log::{debug, info, log, trace, warn};
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_consensus_slots::{
|
||||
SlotInfo, SlotCompatible, StorageChanges, CheckedHeader, check_equivocation,
|
||||
BackoffAuthoringBlocksStrategy,
|
||||
BackoffAuthoringBlocksStrategy
|
||||
};
|
||||
use sc_consensus_epochs::{
|
||||
descendent_query, SharedEpochChanges, EpochChangesFor, Epoch as EpochT, ViableEpochDescriptor,
|
||||
@@ -126,6 +121,7 @@ use sp_blockchain::{
|
||||
use schnorrkel::SignatureError;
|
||||
use codec::{Encode, Decode};
|
||||
use sp_api::ApiExt;
|
||||
use sp_consensus_slots::Slot;
|
||||
|
||||
mod verification;
|
||||
mod migration;
|
||||
@@ -141,9 +137,9 @@ pub struct Epoch {
|
||||
/// The epoch index.
|
||||
pub epoch_index: u64,
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: SlotNumber,
|
||||
pub start_slot: Slot,
|
||||
/// The duration of this epoch.
|
||||
pub duration: SlotNumber,
|
||||
pub duration: u64,
|
||||
/// The authorities and their weights.
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
/// Randomness for this epoch.
|
||||
@@ -154,7 +150,7 @@ pub struct Epoch {
|
||||
|
||||
impl EpochT for Epoch {
|
||||
type NextEpochDescriptor = (NextEpochDescriptor, BabeEpochConfiguration);
|
||||
type SlotNumber = SlotNumber;
|
||||
type Slot = Slot;
|
||||
|
||||
fn increment(
|
||||
&self,
|
||||
@@ -170,11 +166,11 @@ impl EpochT for Epoch {
|
||||
}
|
||||
}
|
||||
|
||||
fn start_slot(&self) -> SlotNumber {
|
||||
fn start_slot(&self) -> Slot {
|
||||
self.start_slot
|
||||
}
|
||||
|
||||
fn end_slot(&self) -> SlotNumber {
|
||||
fn end_slot(&self) -> Slot {
|
||||
self.start_slot + self.duration
|
||||
}
|
||||
}
|
||||
@@ -184,11 +180,11 @@ impl Epoch {
|
||||
/// the first block, so that has to be provided.
|
||||
pub fn genesis(
|
||||
genesis_config: &BabeGenesisConfiguration,
|
||||
slot_number: SlotNumber
|
||||
slot: Slot,
|
||||
) -> Epoch {
|
||||
Epoch {
|
||||
epoch_index: 0,
|
||||
start_slot: slot_number,
|
||||
start_slot: slot,
|
||||
duration: genesis_config.epoch_length,
|
||||
authorities: genesis_config.genesis_authorities.clone(),
|
||||
randomness: genesis_config.randomness,
|
||||
@@ -229,7 +225,7 @@ pub enum Error<B: BlockT> {
|
||||
ParentUnavailable(B::Hash, B::Hash),
|
||||
/// Slot number must increase
|
||||
#[display(fmt = "Slot number must increase: parent slot: {}, this slot: {}", _0, _1)]
|
||||
SlotNumberMustIncrease(u64, u64),
|
||||
SlotMustIncrease(Slot, Slot),
|
||||
/// Header has a bad seal
|
||||
#[display(fmt = "Header {:?} has a bad seal", _0)]
|
||||
HeaderBadSeal(B::Hash),
|
||||
@@ -262,7 +258,7 @@ pub enum Error<B: BlockT> {
|
||||
FetchParentHeader(sp_blockchain::Error),
|
||||
/// Expected epoch change to happen.
|
||||
#[display(fmt = "Expected epoch change to happen at {:?}, s{}", _0, _1)]
|
||||
ExpectedEpochChange(B::Hash, u64),
|
||||
ExpectedEpochChange(B::Hash, Slot),
|
||||
/// Unexpected config change.
|
||||
#[display(fmt = "Unexpected config change")]
|
||||
UnexpectedConfigChange,
|
||||
@@ -471,7 +467,7 @@ pub fn start_babe<B, C, SC, E, I, SO, CAW, BS, Error>(BabeParams {
|
||||
#[must_use]
|
||||
pub struct BabeWorker<B: BlockT> {
|
||||
inner: Pin<Box<dyn futures::Future<Output=()> + Send + 'static>>,
|
||||
slot_notification_sinks: Arc<Mutex<Vec<Sender<(u64, ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>)>>>>,
|
||||
slot_notification_sinks: SlotNotificationSinks<B>,
|
||||
}
|
||||
|
||||
impl<B: BlockT> BabeWorker<B> {
|
||||
@@ -479,7 +475,7 @@ impl<B: BlockT> BabeWorker<B> {
|
||||
/// epoch descriptor.
|
||||
pub fn slot_notification_stream(
|
||||
&self
|
||||
) -> Receiver<(u64, ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>)> {
|
||||
) -> Receiver<(Slot, ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>)> {
|
||||
const CHANNEL_BUFFER_SIZE: usize = 1024;
|
||||
|
||||
let (sink, stream) = channel(CHANNEL_BUFFER_SIZE);
|
||||
@@ -500,7 +496,9 @@ impl<B: BlockT> futures::Future for BabeWorker<B> {
|
||||
}
|
||||
|
||||
/// Slot notification sinks.
|
||||
type SlotNotificationSinks<B> = Arc<Mutex<Vec<Sender<(u64, ViableEpochDescriptor<<B as BlockT>::Hash, NumberFor<B>, Epoch>)>>>>;
|
||||
type SlotNotificationSinks<B> = Arc<
|
||||
Mutex<Vec<Sender<(Slot, ViableEpochDescriptor<<B as BlockT>::Hash, NumberFor<B>, Epoch>)>>>
|
||||
>;
|
||||
|
||||
struct BabeSlotWorker<B: BlockT, C, E, I, SO, BS> {
|
||||
client: Arc<C>,
|
||||
@@ -551,13 +549,13 @@ where
|
||||
fn epoch_data(
|
||||
&self,
|
||||
parent: &B::Header,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
) -> Result<Self::EpochData, ConsensusError> {
|
||||
self.epoch_changes.lock().epoch_descriptor_for_child_of(
|
||||
descendent_query(&*self.client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot,
|
||||
)
|
||||
.map_err(|e| ConsensusError::ChainLookup(format!("{:?}", e)))?
|
||||
.ok_or(sp_consensus::Error::InvalidAuthoritiesSet)
|
||||
@@ -572,12 +570,12 @@ where
|
||||
fn claim_slot(
|
||||
&self,
|
||||
_parent_header: &B::Header,
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch_descriptor: &ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>,
|
||||
) -> Option<Self::Claim> {
|
||||
debug!(target: "babe", "Attempting to claim slot {}", slot_number);
|
||||
debug!(target: "babe", "Attempting to claim slot {}", slot);
|
||||
let s = authorship::claim_slot(
|
||||
slot_number,
|
||||
slot,
|
||||
self.epoch_changes.lock().viable_epoch(
|
||||
&epoch_descriptor,
|
||||
|slot| Epoch::genesis(&self.config, slot)
|
||||
@@ -586,7 +584,7 @@ where
|
||||
);
|
||||
|
||||
if s.is_some() {
|
||||
debug!(target: "babe", "Claimed slot {}", slot_number);
|
||||
debug!(target: "babe", "Claimed slot {}", slot);
|
||||
}
|
||||
|
||||
s
|
||||
@@ -595,12 +593,12 @@ where
|
||||
fn notify_slot(
|
||||
&self,
|
||||
_parent_header: &B::Header,
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
epoch_descriptor: &ViableEpochDescriptor<B::Hash, NumberFor<B>, Epoch>,
|
||||
) {
|
||||
self.slot_notification_sinks.lock()
|
||||
.retain_mut(|sink| {
|
||||
match sink.try_send((slot_number, epoch_descriptor.clone())) {
|
||||
match sink.try_send((slot, epoch_descriptor.clone())) {
|
||||
Ok(()) => true,
|
||||
Err(e) => {
|
||||
if e.is_full() {
|
||||
@@ -616,7 +614,7 @@ where
|
||||
|
||||
fn pre_digest_data(
|
||||
&self,
|
||||
_slot_number: u64,
|
||||
_slot: Slot,
|
||||
claim: &Self::Claim,
|
||||
) -> Vec<sp_runtime::DigestItem<B::Hash>> {
|
||||
vec![
|
||||
@@ -673,16 +671,16 @@ 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>(chain_head)
|
||||
.map(|digest| digest.slot_number())
|
||||
.map(|digest| digest.slot())
|
||||
{
|
||||
return strategy.should_backoff(
|
||||
*chain_head.number(),
|
||||
chain_head_slot,
|
||||
self.client.info().finalized_number,
|
||||
slot_number,
|
||||
slot,
|
||||
self.logging_target(),
|
||||
);
|
||||
}
|
||||
@@ -714,7 +712,7 @@ where
|
||||
|
||||
let parent_slot = match find_pre_digest::<B>(parent_head) {
|
||||
Err(_) => return Some(slot_remaining),
|
||||
Ok(d) => d.slot_number(),
|
||||
Ok(d) => d.slot(),
|
||||
};
|
||||
|
||||
if let Some(slot_lenience) =
|
||||
@@ -723,7 +721,7 @@ where
|
||||
debug!(
|
||||
target: "babe",
|
||||
"No block for {} slots. Applying exponential lenience of {}s",
|
||||
slot_info.number.saturating_sub(parent_slot + 1),
|
||||
slot_info.slot.saturating_sub(parent_slot + 1),
|
||||
slot_lenience.as_secs(),
|
||||
);
|
||||
|
||||
@@ -741,7 +739,7 @@ pub fn find_pre_digest<B: BlockT>(header: &B::Header) -> Result<PreDigest, Error
|
||||
// dummy one to not break any invariants in the rest of the code
|
||||
if header.number().is_zero() {
|
||||
return Ok(PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
|
||||
slot_number: 0,
|
||||
slot: 0.into(),
|
||||
authority_index: 0,
|
||||
}));
|
||||
}
|
||||
@@ -803,7 +801,7 @@ impl SlotCompatible for TimeSource {
|
||||
fn extract_timestamp_and_slot(
|
||||
&self,
|
||||
data: &InherentData,
|
||||
) -> Result<(TimestampInherent, u64, std::time::Duration), sp_consensus::Error> {
|
||||
) -> Result<(TimestampInherent, Slot, std::time::Duration), sp_consensus::Error> {
|
||||
trace!(target: "babe", "extract timestamp");
|
||||
data.timestamp_inherent_data()
|
||||
.and_then(|t| data.babe_inherent_data().map(|a| (t, a)))
|
||||
@@ -888,8 +886,8 @@ where
|
||||
|
||||
fn check_and_report_equivocation(
|
||||
&self,
|
||||
slot_now: SlotNumber,
|
||||
slot: SlotNumber,
|
||||
slot_now: Slot,
|
||||
slot: Slot,
|
||||
header: &Block::Header,
|
||||
author: &AuthorityId,
|
||||
origin: &BlockOrigin,
|
||||
@@ -1014,7 +1012,7 @@ where
|
||||
descendent_query(&*self.client),
|
||||
&parent_hash,
|
||||
parent_header_metadata.number,
|
||||
pre_digest.slot_number(),
|
||||
pre_digest.slot(),
|
||||
)
|
||||
.map_err(|e| Error::<Block>::ForkTree(Box::new(e)))?
|
||||
.ok_or_else(|| Error::<Block>::FetchEpoch(parent_hash))?;
|
||||
@@ -1036,14 +1034,14 @@ where
|
||||
CheckedHeader::Checked(pre_header, verified_info) => {
|
||||
let babe_pre_digest = verified_info.pre_digest.as_babe_pre_digest()
|
||||
.expect("check_header always returns a pre-digest digest item; qed");
|
||||
let slot_number = babe_pre_digest.slot_number();
|
||||
let slot = babe_pre_digest.slot();
|
||||
|
||||
// the header is valid but let's check if there was something else already
|
||||
// proposed at the same slot by the given author. if there was, we will
|
||||
// report the equivocation to the runtime.
|
||||
if let Err(err) = self.check_and_report_equivocation(
|
||||
slot_now,
|
||||
slot_number,
|
||||
slot,
|
||||
&header,
|
||||
&verified_info.author,
|
||||
&origin,
|
||||
@@ -1055,7 +1053,7 @@ where
|
||||
// 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.babe_replace_inherent_data(slot_number);
|
||||
inherent_data.babe_replace_inherent_data(slot);
|
||||
let block = Block::new(pre_header.clone(), inner_body);
|
||||
|
||||
self.check_inherents(
|
||||
@@ -1185,7 +1183,7 @@ impl<Block, Client, Inner> BlockImport<Block> for BabeBlockImport<Block, Client,
|
||||
let pre_digest = find_pre_digest::<Block>(&block.header)
|
||||
.expect("valid babe headers must contain a predigest; \
|
||||
header has been already verified; qed");
|
||||
let slot_number = pre_digest.slot_number();
|
||||
let slot = pre_digest.slot();
|
||||
|
||||
let parent_hash = *block.header.parent_hash();
|
||||
let parent_header = self.client.header(BlockId::Hash(parent_hash))
|
||||
@@ -1195,15 +1193,15 @@ impl<Block, Client, Inner> BlockImport<Block> for BabeBlockImport<Block, Client,
|
||||
).into()))?;
|
||||
|
||||
let parent_slot = find_pre_digest::<Block>(&parent_header)
|
||||
.map(|d| d.slot_number())
|
||||
.map(|d| d.slot())
|
||||
.expect("parent is non-genesis; valid BABE headers contain a pre-digest; \
|
||||
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(babe_err(
|
||||
Error::<Block>::SlotNumberMustIncrease(parent_slot, slot_number)
|
||||
Error::<Block>::SlotMustIncrease(parent_slot, slot)
|
||||
).into())
|
||||
);
|
||||
}
|
||||
@@ -1256,7 +1254,7 @@ impl<Block, Client, Inner> BlockImport<Block> for BabeBlockImport<Block, Client,
|
||||
(true, false, _) => {
|
||||
return Err(
|
||||
ConsensusError::ClientImport(
|
||||
babe_err(Error::<Block>::ExpectedEpochChange(hash, slot_number)).into(),
|
||||
babe_err(Error::<Block>::ExpectedEpochChange(hash, slot)).into(),
|
||||
)
|
||||
)
|
||||
},
|
||||
@@ -1301,7 +1299,7 @@ impl<Block, Client, Inner> BlockImport<Block> for BabeBlockImport<Block, Client,
|
||||
"👶 New epoch {} launching at block {} (block slot {} >= start slot {}).",
|
||||
viable_epoch.as_ref().epoch_index,
|
||||
hash,
|
||||
slot_number,
|
||||
slot,
|
||||
viable_epoch.as_ref().start_slot,
|
||||
);
|
||||
|
||||
@@ -1426,7 +1424,7 @@ fn prune_finalized<Block, Client>(
|
||||
find_pre_digest::<Block>(&finalized_header)
|
||||
.expect("finalized header must be valid; \
|
||||
valid blocks have a pre-digest; qed")
|
||||
.slot_number()
|
||||
.slot()
|
||||
};
|
||||
|
||||
epoch_changes.prune_finalized(
|
||||
@@ -1533,7 +1531,7 @@ pub mod test_helpers {
|
||||
/// Try to claim the given slot and return a `BabePreDigest` if
|
||||
/// successful.
|
||||
pub fn claim_slot<B, C>(
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
parent: &B::Header,
|
||||
client: &C,
|
||||
keystore: SyncCryptoStorePtr,
|
||||
@@ -1551,12 +1549,12 @@ pub mod test_helpers {
|
||||
descendent_query(client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot,
|
||||
|slot| Epoch::genesis(&link.config, slot),
|
||||
).unwrap().unwrap();
|
||||
|
||||
authorship::claim_slot(
|
||||
slot_number,
|
||||
slot,
|
||||
&epoch,
|
||||
&keystore,
|
||||
).map(|(digest, _)| digest)
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use codec::{Encode, Decode};
|
||||
use sc_consensus_epochs::Epoch as EpochT;
|
||||
use crate::{
|
||||
Epoch, SlotNumber, AuthorityId, BabeAuthorityWeight, BabeGenesisConfiguration,
|
||||
Epoch, AuthorityId, BabeAuthorityWeight, BabeGenesisConfiguration,
|
||||
BabeEpochConfiguration, VRF_OUTPUT_LENGTH, NextEpochDescriptor,
|
||||
};
|
||||
use sp_consensus_slots::Slot;
|
||||
|
||||
/// BABE epoch information, version 0.
|
||||
#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug)]
|
||||
@@ -11,9 +30,9 @@ pub struct EpochV0 {
|
||||
/// The epoch index.
|
||||
pub epoch_index: u64,
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: SlotNumber,
|
||||
pub start_slot: Slot,
|
||||
/// The duration of this epoch.
|
||||
pub duration: SlotNumber,
|
||||
pub duration: u64,
|
||||
/// The authorities and their weights.
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
/// Randomness for this epoch.
|
||||
@@ -22,7 +41,7 @@ pub struct EpochV0 {
|
||||
|
||||
impl EpochT for EpochV0 {
|
||||
type NextEpochDescriptor = NextEpochDescriptor;
|
||||
type SlotNumber = SlotNumber;
|
||||
type Slot = Slot;
|
||||
|
||||
fn increment(
|
||||
&self,
|
||||
@@ -37,11 +56,11 @@ impl EpochT for EpochV0 {
|
||||
}
|
||||
}
|
||||
|
||||
fn start_slot(&self) -> SlotNumber {
|
||||
fn start_slot(&self) -> Slot {
|
||||
self.start_slot
|
||||
}
|
||||
|
||||
fn end_slot(&self) -> SlotNumber {
|
||||
fn end_slot(&self) -> Slot {
|
||||
self.start_slot + self.duration
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,7 @@ use sp_keystore::{
|
||||
SyncCryptoStore,
|
||||
vrf::make_transcript as transcript_from_data,
|
||||
};
|
||||
use sp_consensus_babe::{
|
||||
AuthorityPair,
|
||||
SlotNumber,
|
||||
AllowedSlots,
|
||||
make_transcript,
|
||||
make_transcript_data,
|
||||
};
|
||||
use sp_consensus_babe::{AuthorityPair, Slot, AllowedSlots, make_transcript, make_transcript_data};
|
||||
use sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging;
|
||||
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
|
||||
use sp_consensus::{
|
||||
@@ -87,7 +81,7 @@ struct DummyProposer {
|
||||
factory: DummyFactory,
|
||||
parent_hash: Hash,
|
||||
parent_number: u64,
|
||||
parent_slot: SlotNumber,
|
||||
parent_slot: Slot,
|
||||
}
|
||||
|
||||
impl Environment<TestBlock> for DummyFactory {
|
||||
@@ -101,7 +95,7 @@ impl Environment<TestBlock> for DummyFactory {
|
||||
|
||||
let parent_slot = crate::find_pre_digest::<TestBlock>(parent_header)
|
||||
.expect("parent header has a pre-digest")
|
||||
.slot_number();
|
||||
.slot();
|
||||
|
||||
future::ready(Ok(DummyProposer {
|
||||
factory: self.clone(),
|
||||
@@ -137,7 +131,7 @@ impl DummyProposer {
|
||||
|
||||
let this_slot = crate::find_pre_digest::<TestBlock>(block.header())
|
||||
.expect("baked block has valid pre-digest")
|
||||
.slot_number();
|
||||
.slot();
|
||||
|
||||
// figure out if we should add a consensus digest, since the test runtime
|
||||
// doesn't.
|
||||
@@ -529,7 +523,7 @@ fn can_author_block() {
|
||||
|
||||
let mut i = 0;
|
||||
let epoch = Epoch {
|
||||
start_slot: 0,
|
||||
start_slot: 0.into(),
|
||||
authorities: vec![(public.into(), 1)],
|
||||
randomness: [0; 32],
|
||||
epoch_index: 1,
|
||||
@@ -550,7 +544,7 @@ fn can_author_block() {
|
||||
};
|
||||
|
||||
// with secondary slots enabled it should never be empty
|
||||
match claim_slot(i, &epoch, &keystore) {
|
||||
match claim_slot(i.into(), &epoch, &keystore) {
|
||||
None => i += 1,
|
||||
Some(s) => debug!(target: "babe", "Authored block {:?}", s.0),
|
||||
}
|
||||
@@ -559,7 +553,7 @@ fn can_author_block() {
|
||||
// of times.
|
||||
config.allowed_slots = AllowedSlots::PrimarySlots;
|
||||
loop {
|
||||
match claim_slot(i, &epoch, &keystore) {
|
||||
match claim_slot(i.into(), &epoch, &keystore) {
|
||||
None => i += 1,
|
||||
Some(s) => {
|
||||
debug!(target: "babe", "Authored block {:?}", s.0);
|
||||
@@ -572,15 +566,15 @@ fn can_author_block() {
|
||||
// Propose and import a new BABE block on top of the given parent.
|
||||
fn propose_and_import_block<Transaction>(
|
||||
parent: &TestHeader,
|
||||
slot_number: Option<SlotNumber>,
|
||||
slot: Option<Slot>,
|
||||
proposer_factory: &mut DummyFactory,
|
||||
block_import: &mut BoxBlockImport<TestBlock, Transaction>,
|
||||
) -> sp_core::H256 {
|
||||
let mut proposer = futures::executor::block_on(proposer_factory.init(parent)).unwrap();
|
||||
|
||||
let slot_number = slot_number.unwrap_or_else(|| {
|
||||
let slot = slot.unwrap_or_else(|| {
|
||||
let parent_pre_digest = find_pre_digest::<TestBlock>(parent).unwrap();
|
||||
parent_pre_digest.slot_number() + 1
|
||||
parent_pre_digest.slot() + 1
|
||||
});
|
||||
|
||||
let pre_digest = sp_runtime::generic::Digest {
|
||||
@@ -588,7 +582,7 @@ fn propose_and_import_block<Transaction>(
|
||||
Item::babe_pre_digest(
|
||||
PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
|
||||
authority_index: 0,
|
||||
slot_number,
|
||||
slot,
|
||||
}),
|
||||
),
|
||||
],
|
||||
@@ -602,7 +596,7 @@ fn propose_and_import_block<Transaction>(
|
||||
descendent_query(&*proposer_factory.client),
|
||||
&parent_hash,
|
||||
*parent.number(),
|
||||
slot_number,
|
||||
slot,
|
||||
).unwrap().unwrap();
|
||||
|
||||
let seal = {
|
||||
@@ -660,19 +654,19 @@ fn importing_block_one_sets_genesis_epoch() {
|
||||
|
||||
let block_hash = propose_and_import_block(
|
||||
&genesis_header,
|
||||
Some(999),
|
||||
Some(999.into()),
|
||||
&mut proposer_factory,
|
||||
&mut block_import,
|
||||
);
|
||||
|
||||
let genesis_epoch = Epoch::genesis(&data.link.config, 999);
|
||||
let genesis_epoch = Epoch::genesis(&data.link.config, 999.into());
|
||||
|
||||
let epoch_changes = data.link.epoch_changes.lock();
|
||||
let epoch_for_second_block = epoch_changes.epoch_data_for_child_of(
|
||||
descendent_query(&*client),
|
||||
&block_hash,
|
||||
1,
|
||||
1000,
|
||||
1000.into(),
|
||||
|slot| Epoch::genesis(&data.link.config, slot),
|
||||
).unwrap().unwrap();
|
||||
|
||||
@@ -809,7 +803,7 @@ fn verify_slots_are_strictly_increasing() {
|
||||
// we should have no issue importing this block
|
||||
let b1 = propose_and_import_block(
|
||||
&genesis_header,
|
||||
Some(999),
|
||||
Some(999.into()),
|
||||
&mut proposer_factory,
|
||||
&mut block_import,
|
||||
);
|
||||
@@ -820,7 +814,7 @@ fn verify_slots_are_strictly_increasing() {
|
||||
// we will panic due to the `PanickingBlockImport` defined above.
|
||||
propose_and_import_block(
|
||||
&b1,
|
||||
Some(999),
|
||||
Some(999.into()),
|
||||
&mut proposer_factory,
|
||||
&mut block_import,
|
||||
);
|
||||
@@ -836,7 +830,7 @@ fn babe_transcript_generation_match() {
|
||||
.expect("Generates authority pair");
|
||||
|
||||
let epoch = Epoch {
|
||||
start_slot: 0,
|
||||
start_slot: 0.into(),
|
||||
authorities: vec![(public.into(), 1)],
|
||||
randomness: [0; 32],
|
||||
epoch_index: 1,
|
||||
@@ -847,8 +841,8 @@ fn babe_transcript_generation_match() {
|
||||
},
|
||||
};
|
||||
|
||||
let orig_transcript = make_transcript(&epoch.randomness.clone(), 1, epoch.epoch_index);
|
||||
let new_transcript = make_transcript_data(&epoch.randomness, 1, epoch.epoch_index);
|
||||
let orig_transcript = make_transcript(&epoch.randomness.clone(), 1.into(), epoch.epoch_index);
|
||||
let new_transcript = make_transcript_data(&epoch.randomness, 1.into(), epoch.epoch_index);
|
||||
|
||||
let test = |t: merlin::Transcript| -> [u8; 16] {
|
||||
let mut b = [0u8; 16];
|
||||
|
||||
@@ -19,12 +19,13 @@
|
||||
//! Verification for BABE headers.
|
||||
use sp_runtime::{traits::Header, traits::DigestItemFor};
|
||||
use sp_core::{Pair, Public};
|
||||
use sp_consensus_babe::{make_transcript, AuthoritySignature, SlotNumber, AuthorityPair, AuthorityId};
|
||||
use sp_consensus_babe::{make_transcript, AuthoritySignature, AuthorityPair, AuthorityId};
|
||||
use sp_consensus_babe::digests::{
|
||||
PreDigest, PrimaryPreDigest, SecondaryPlainPreDigest, SecondaryVRFPreDigest,
|
||||
CompatibleDigestItem
|
||||
};
|
||||
use sc_consensus_slots::CheckedHeader;
|
||||
use sp_consensus_slots::Slot;
|
||||
use log::{debug, trace};
|
||||
use super::{find_pre_digest, babe_err, Epoch, BlockT, Error};
|
||||
use super::authorship::{calculate_primary_threshold, check_primary_threshold, secondary_slot_author};
|
||||
@@ -38,7 +39,7 @@ pub(super) struct VerificationParams<'a, B: 'a + BlockT> {
|
||||
/// work.
|
||||
pub(super) pre_digest: Option<PreDigest>,
|
||||
/// The slot number of the current time.
|
||||
pub(super) slot_now: SlotNumber,
|
||||
pub(super) slot_now: Slot,
|
||||
/// Epoch descriptor of the epoch this block _should_ be under, if it's valid.
|
||||
pub(super) epoch: &'a Epoch,
|
||||
}
|
||||
@@ -83,9 +84,9 @@ pub(super) fn check_header<B: BlockT + Sized>(
|
||||
// and that's what we sign
|
||||
let pre_hash = header.hash();
|
||||
|
||||
if pre_digest.slot_number() > slot_now {
|
||||
if pre_digest.slot() > slot_now {
|
||||
header.digest_mut().push(seal);
|
||||
return Ok(CheckedHeader::Deferred(header, pre_digest.slot_number()));
|
||||
return Ok(CheckedHeader::Deferred(header, pre_digest.slot()));
|
||||
}
|
||||
|
||||
let author = match authorities.get(pre_digest.authority_index() as usize) {
|
||||
@@ -98,7 +99,7 @@ pub(super) fn check_header<B: BlockT + Sized>(
|
||||
debug!(target: "babe",
|
||||
"Verifying primary block #{} at slot: {}",
|
||||
header.number(),
|
||||
primary.slot_number,
|
||||
primary.slot,
|
||||
);
|
||||
|
||||
check_primary_header::<B>(
|
||||
@@ -113,7 +114,7 @@ pub(super) fn check_header<B: BlockT + Sized>(
|
||||
debug!(target: "babe",
|
||||
"Verifying secondary plain block #{} at slot: {}",
|
||||
header.number(),
|
||||
secondary.slot_number,
|
||||
secondary.slot,
|
||||
);
|
||||
|
||||
check_secondary_plain_header::<B>(
|
||||
@@ -127,7 +128,7 @@ pub(super) fn check_header<B: BlockT + Sized>(
|
||||
debug!(target: "babe",
|
||||
"Verifying secondary VRF block #{} at slot: {}",
|
||||
header.number(),
|
||||
secondary.slot_number,
|
||||
secondary.slot,
|
||||
);
|
||||
|
||||
check_secondary_vrf_header::<B>(
|
||||
@@ -173,7 +174,7 @@ fn check_primary_header<B: BlockT + Sized>(
|
||||
let (inout, _) = {
|
||||
let transcript = make_transcript(
|
||||
&epoch.randomness,
|
||||
pre_digest.slot_number,
|
||||
pre_digest.slot,
|
||||
epoch.epoch_index,
|
||||
);
|
||||
|
||||
@@ -213,7 +214,7 @@ fn check_secondary_plain_header<B: BlockT>(
|
||||
// check the signature is valid under the expected authority and
|
||||
// chain state.
|
||||
let expected_author = secondary_slot_author(
|
||||
pre_digest.slot_number,
|
||||
pre_digest.slot,
|
||||
&epoch.authorities,
|
||||
epoch.randomness,
|
||||
).ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
|
||||
@@ -241,7 +242,7 @@ fn check_secondary_vrf_header<B: BlockT>(
|
||||
// check the signature is valid under the expected authority and
|
||||
// chain state.
|
||||
let expected_author = secondary_slot_author(
|
||||
pre_digest.slot_number,
|
||||
pre_digest.slot,
|
||||
&epoch.authorities,
|
||||
epoch.randomness,
|
||||
).ok_or_else(|| Error::NoSecondaryAuthorExpected)?;
|
||||
@@ -255,7 +256,7 @@ fn check_secondary_vrf_header<B: BlockT>(
|
||||
if AuthorityPair::verify(&signature, pre_hash.as_ref(), author) {
|
||||
let transcript = make_transcript(
|
||||
&epoch.randomness,
|
||||
pre_digest.slot_number,
|
||||
pre_digest.slot,
|
||||
epoch.epoch_index,
|
||||
);
|
||||
|
||||
|
||||
@@ -78,13 +78,13 @@ pub trait Epoch {
|
||||
/// Descriptor for the next epoch.
|
||||
type NextEpochDescriptor;
|
||||
/// Type of the slot number.
|
||||
type SlotNumber: Ord + Copy;
|
||||
type Slot: Ord + Copy;
|
||||
|
||||
/// The starting slot of the epoch.
|
||||
fn start_slot(&self) -> Self::SlotNumber;
|
||||
fn start_slot(&self) -> Self::Slot;
|
||||
/// Produce the "end slot" of the epoch. This is NOT inclusive to the epoch,
|
||||
/// i.e. the slots covered by the epoch are `self.start_slot() .. self.end_slot()`.
|
||||
fn end_slot(&self) -> Self::SlotNumber;
|
||||
fn end_slot(&self) -> Self::Slot;
|
||||
/// Increment the epoch data, using the next epoch descriptor.
|
||||
fn increment(&self, descriptor: Self::NextEpochDescriptor) -> Self;
|
||||
}
|
||||
@@ -102,10 +102,10 @@ impl<'a, E: Epoch> From<&'a E> for EpochHeader<E> {
|
||||
#[derive(Eq, PartialEq, Encode, Decode, Debug)]
|
||||
pub struct EpochHeader<E: Epoch> {
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: E::SlotNumber,
|
||||
pub start_slot: E::Slot,
|
||||
/// The end slot of the epoch. This is NOT inclusive to the epoch,
|
||||
/// i.e. the slots covered by the epoch are `self.start_slot() .. self.end_slot()`.
|
||||
pub end_slot: E::SlotNumber,
|
||||
pub end_slot: E::Slot,
|
||||
}
|
||||
|
||||
impl<E: Epoch> Clone for EpochHeader<E> {
|
||||
@@ -215,14 +215,14 @@ impl<E, ERef> ViableEpoch<E, ERef> where
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub enum ViableEpochDescriptor<Hash, Number, E: Epoch> {
|
||||
/// The epoch is an unimported genesis, with given start slot number.
|
||||
UnimportedGenesis(E::SlotNumber),
|
||||
UnimportedGenesis(E::Slot),
|
||||
/// The epoch is signaled and has been imported, with given identifier and header.
|
||||
Signaled(EpochIdentifier<Hash, Number>, EpochHeader<E>)
|
||||
}
|
||||
|
||||
impl<Hash, Number, E: Epoch> ViableEpochDescriptor<Hash, Number, E> {
|
||||
/// Start slot of the descriptor.
|
||||
pub fn start_slot(&self) -> E::SlotNumber {
|
||||
pub fn start_slot(&self) -> E::Slot {
|
||||
match self {
|
||||
Self::UnimportedGenesis(start_slot) => *start_slot,
|
||||
Self::Signaled(_, header) => header.start_slot,
|
||||
@@ -339,7 +339,7 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
|
||||
/// Map the epoch changes from one storing data to a different one.
|
||||
pub fn map<B, F>(self, mut f: F) -> EpochChanges<Hash, Number, B> where
|
||||
B: Epoch<SlotNumber=E::SlotNumber>,
|
||||
B: Epoch<Slot=E::Slot>,
|
||||
F: FnMut(&Hash, &Number, E) -> B,
|
||||
{
|
||||
EpochChanges {
|
||||
@@ -394,7 +394,7 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descendent_of_builder: D,
|
||||
hash: &Hash,
|
||||
number: Number,
|
||||
slot: E::SlotNumber,
|
||||
slot: E::Slot,
|
||||
) -> Result<(), fork_tree::Error<D::Error>> {
|
||||
let is_descendent_of = descendent_of_builder
|
||||
.build_is_descendent_of(None);
|
||||
@@ -445,11 +445,11 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descriptor: &ViableEpochDescriptor<Hash, Number, E>,
|
||||
make_genesis: G,
|
||||
) -> Option<ViableEpoch<E, &E>> where
|
||||
G: FnOnce(E::SlotNumber) -> E
|
||||
G: FnOnce(E::Slot) -> E
|
||||
{
|
||||
match descriptor {
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot_number) => {
|
||||
Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot_number)))
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot) => {
|
||||
Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot)))
|
||||
},
|
||||
ViableEpochDescriptor::Signaled(identifier, _) => {
|
||||
self.epoch(&identifier).map(ViableEpoch::Signaled)
|
||||
@@ -479,11 +479,11 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descriptor: &ViableEpochDescriptor<Hash, Number, E>,
|
||||
make_genesis: G,
|
||||
) -> Option<ViableEpoch<E, &mut E>> where
|
||||
G: FnOnce(E::SlotNumber) -> E
|
||||
G: FnOnce(E::Slot) -> E
|
||||
{
|
||||
match descriptor {
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot_number) => {
|
||||
Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot_number)))
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot) => {
|
||||
Some(ViableEpoch::UnimportedGenesis(make_genesis(*slot)))
|
||||
},
|
||||
ViableEpochDescriptor::Signaled(identifier, _) => {
|
||||
self.epoch_mut(&identifier).map(ViableEpoch::Signaled)
|
||||
@@ -500,12 +500,12 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descriptor: &ViableEpochDescriptor<Hash, Number, E>,
|
||||
make_genesis: G
|
||||
) -> Option<E> where
|
||||
G: FnOnce(E::SlotNumber) -> E,
|
||||
G: FnOnce(E::Slot) -> E,
|
||||
E: Clone,
|
||||
{
|
||||
match descriptor {
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot_number) => {
|
||||
Some(make_genesis(*slot_number))
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot) => {
|
||||
Some(make_genesis(*slot))
|
||||
},
|
||||
ViableEpochDescriptor::Signaled(identifier, _) => {
|
||||
self.epoch(&identifier).cloned()
|
||||
@@ -523,17 +523,17 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descendent_of_builder: D,
|
||||
parent_hash: &Hash,
|
||||
parent_number: Number,
|
||||
slot_number: E::SlotNumber,
|
||||
slot: E::Slot,
|
||||
make_genesis: G,
|
||||
) -> Result<Option<E>, fork_tree::Error<D::Error>> where
|
||||
G: FnOnce(E::SlotNumber) -> E,
|
||||
G: FnOnce(E::Slot) -> E,
|
||||
E: Clone,
|
||||
{
|
||||
let descriptor = self.epoch_descriptor_for_child_of(
|
||||
descendent_of_builder,
|
||||
parent_hash,
|
||||
parent_number,
|
||||
slot_number
|
||||
slot
|
||||
)?;
|
||||
|
||||
Ok(descriptor.and_then(|des| self.epoch_data(&des, make_genesis)))
|
||||
@@ -548,7 +548,7 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
descendent_of_builder: D,
|
||||
parent_hash: &Hash,
|
||||
parent_number: Number,
|
||||
slot_number: E::SlotNumber,
|
||||
slot: E::Slot,
|
||||
) -> Result<Option<ViableEpochDescriptor<Hash, Number, E>>, fork_tree::Error<D::Error>> {
|
||||
// find_node_where will give you the node in the fork-tree which is an ancestor
|
||||
// of the `parent_hash` by default. if the last epoch was signalled at the parent_hash,
|
||||
@@ -561,7 +561,7 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
|
||||
if parent_number == Zero::zero() {
|
||||
// need to insert the genesis epoch.
|
||||
return Ok(Some(ViableEpochDescriptor::UnimportedGenesis(slot_number)))
|
||||
return Ok(Some(ViableEpochDescriptor::UnimportedGenesis(slot)))
|
||||
}
|
||||
|
||||
// We want to find the deepest node in the tree which is an ancestor
|
||||
@@ -571,9 +571,9 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
// we need.
|
||||
let predicate = |epoch: &PersistedEpochHeader<E>| match *epoch {
|
||||
PersistedEpochHeader::Genesis(ref epoch_0, _) =>
|
||||
epoch_0.start_slot <= slot_number,
|
||||
epoch_0.start_slot <= slot,
|
||||
PersistedEpochHeader::Regular(ref epoch_n) =>
|
||||
epoch_n.start_slot <= slot_number,
|
||||
epoch_n.start_slot <= slot,
|
||||
};
|
||||
|
||||
self.inner.find_node_where(
|
||||
@@ -588,7 +588,7 @@ impl<Hash, Number, E: Epoch> EpochChanges<Hash, Number, E> where
|
||||
// and here we figure out which of the internal epochs
|
||||
// of a genesis node to use based on their start slot.
|
||||
PersistedEpochHeader::Genesis(ref epoch_0, ref epoch_1) =>
|
||||
if epoch_1.start_slot <= slot_number {
|
||||
if epoch_1.start_slot <= slot {
|
||||
(EpochIdentifierPosition::Genesis1, epoch_1.clone())
|
||||
} else {
|
||||
(EpochIdentifierPosition::Genesis0, epoch_0.clone())
|
||||
@@ -695,17 +695,17 @@ mod tests {
|
||||
}
|
||||
|
||||
type Hash = [u8; 1];
|
||||
type SlotNumber = u64;
|
||||
type Slot = u64;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
struct Epoch {
|
||||
start_slot: SlotNumber,
|
||||
duration: SlotNumber,
|
||||
start_slot: Slot,
|
||||
duration: Slot,
|
||||
}
|
||||
|
||||
impl EpochT for Epoch {
|
||||
type NextEpochDescriptor = ();
|
||||
type SlotNumber = SlotNumber;
|
||||
type Slot = Slot;
|
||||
|
||||
fn increment(&self, _: ()) -> Self {
|
||||
Epoch {
|
||||
@@ -714,11 +714,11 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn end_slot(&self) -> SlotNumber {
|
||||
fn end_slot(&self) -> Slot {
|
||||
self.start_slot + self.duration
|
||||
}
|
||||
|
||||
fn start_slot(&self) -> SlotNumber {
|
||||
fn start_slot(&self) -> Slot {
|
||||
self.start_slot
|
||||
}
|
||||
}
|
||||
@@ -748,8 +748,8 @@ mod tests {
|
||||
).unwrap().unwrap();
|
||||
|
||||
match genesis_epoch {
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot_number) => {
|
||||
assert_eq!(slot_number, 10101u64);
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot) => {
|
||||
assert_eq!(slot, 10101u64);
|
||||
},
|
||||
_ => panic!("should be unimported genesis"),
|
||||
};
|
||||
@@ -762,8 +762,8 @@ mod tests {
|
||||
).unwrap().unwrap();
|
||||
|
||||
match genesis_epoch_2 {
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot_number) => {
|
||||
assert_eq!(slot_number, 10102u64);
|
||||
ViableEpochDescriptor::UnimportedGenesis(slot) => {
|
||||
assert_eq!(slot, 10102u64);
|
||||
},
|
||||
_ => panic!("should be unimported genesis"),
|
||||
};
|
||||
|
||||
@@ -31,7 +31,8 @@ sp-consensus-babe = { path = "../../../primitives/consensus/babe", version = "0.
|
||||
|
||||
sc-transaction-pool = { path = "../../transaction-pool", version = "2.0.0" }
|
||||
sp-blockchain = { path = "../../../primitives/blockchain", version = "2.0.0" }
|
||||
sp-consensus = { package = "sp-consensus", path = "../../../primitives/consensus/common", version = "0.8.0" }
|
||||
sp-consensus = { path = "../../../primitives/consensus/common", version = "0.8.0" }
|
||||
sp-consensus-slots = { path = "../../../primitives/consensus/slots", version = "0.8.1" }
|
||||
sp-inherents = { path = "../../../primitives/inherents", version = "2.0.0" }
|
||||
sp-runtime = { path = "../../../primitives/runtime", version = "2.0.0" }
|
||||
sp-core = { path = "../../../primitives/core", version = "2.0.0" }
|
||||
|
||||
@@ -38,6 +38,7 @@ use sp_keystore::SyncCryptoStorePtr;
|
||||
use sp_api::{ProvideRuntimeApi, TransactionFor};
|
||||
use sp_blockchain::{HeaderBackend, HeaderMetadata};
|
||||
use sp_consensus::BlockImportParams;
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_consensus_babe::{
|
||||
BabeApi, inherents::BabeInherentData, ConsensusLog, BABE_ENGINE_ID, AuthorityId,
|
||||
digests::{PreDigest, SecondaryPlainPreDigest, NextEpochDescriptor}, BabeAuthorityWeight,
|
||||
@@ -100,14 +101,14 @@ impl<B, C> BabeConsensusDataProvider<B, C>
|
||||
})
|
||||
}
|
||||
|
||||
fn epoch(&self, parent: &B::Header, slot_number: u64) -> Result<Epoch, Error> {
|
||||
fn epoch(&self, parent: &B::Header, slot: Slot) -> Result<Epoch, Error> {
|
||||
let epoch_changes = self.epoch_changes.lock();
|
||||
let epoch_descriptor = epoch_changes
|
||||
.epoch_descriptor_for_child_of(
|
||||
descendent_query(&*self.client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot,
|
||||
)
|
||||
.map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
@@ -135,11 +136,15 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
type Transaction = TransactionFor<C, B>;
|
||||
|
||||
fn create_digest(&self, parent: &B::Header, inherents: &InherentData) -> Result<DigestFor<B>, Error> {
|
||||
let slot_number = inherents.babe_inherent_data()?;
|
||||
let epoch = self.epoch(parent, slot_number)?;
|
||||
let slot = inherents.babe_inherent_data()?;
|
||||
let epoch = self.epoch(parent, slot)?;
|
||||
|
||||
// this is a dev node environment, we should always be able to claim a slot.
|
||||
let logs = if let Some((predigest, _)) = authorship::claim_slot(slot_number, &epoch, &self.keystore) {
|
||||
let logs = if let Some((predigest, _)) = authorship::claim_slot(
|
||||
slot,
|
||||
&epoch,
|
||||
&self.keystore,
|
||||
) {
|
||||
vec![
|
||||
<DigestItemFor<B> as CompatibleDigestItem>::babe_pre_digest(predigest),
|
||||
]
|
||||
@@ -147,7 +152,7 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
// well we couldn't claim a slot because this is an existing chain and we're not in the authorities.
|
||||
// we need to tell BabeBlockImport that the epoch has changed, and we put ourselves in the authorities.
|
||||
let predigest = PreDigest::SecondaryPlain(SecondaryPlainPreDigest {
|
||||
slot_number,
|
||||
slot,
|
||||
authority_index: 0_u32,
|
||||
});
|
||||
|
||||
@@ -157,7 +162,7 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
descendent_query(&*self.client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot,
|
||||
)
|
||||
.map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
@@ -194,21 +199,21 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
params: &mut BlockImportParams<B, Self::Transaction>,
|
||||
inherents: &InherentData
|
||||
) -> Result<(), Error> {
|
||||
let slot_number = inherents.babe_inherent_data()?;
|
||||
let slot = inherents.babe_inherent_data()?;
|
||||
let epoch_changes = self.epoch_changes.lock();
|
||||
let mut epoch_descriptor = epoch_changes
|
||||
.epoch_descriptor_for_child_of(
|
||||
descendent_query(&*self.client),
|
||||
&parent.hash(),
|
||||
parent.number().clone(),
|
||||
slot_number,
|
||||
slot,
|
||||
)
|
||||
.map_err(|e| Error::StringError(format!("failed to fetch epoch_descriptor: {}", e)))?
|
||||
.ok_or_else(|| sp_consensus::Error::InvalidAuthoritiesSet)?;
|
||||
// drop the lock
|
||||
drop(epoch_changes);
|
||||
// a quick check to see if we're in the authorities
|
||||
let epoch = self.epoch(parent, slot_number)?;
|
||||
let epoch = self.epoch(parent, slot)?;
|
||||
let (authority, _) = self.authorities.first().expect("authorities is non-emptyp; qed");
|
||||
let has_authority = epoch.authorities.iter()
|
||||
.find(|(id, _)| *id == *authority)
|
||||
@@ -216,15 +221,15 @@ impl<B, C> ConsensusDataProvider<B> for BabeConsensusDataProvider<B, C>
|
||||
|
||||
if !has_authority {
|
||||
log::info!(target: "manual-seal", "authority not found");
|
||||
let slot_number = inherents.timestamp_inherent_data()? / self.config.slot_duration;
|
||||
let slot = inherents.timestamp_inherent_data()? / self.config.slot_duration;
|
||||
// manually hard code epoch descriptor
|
||||
epoch_descriptor = match epoch_descriptor {
|
||||
ViableEpochDescriptor::Signaled(identifier, _header) => {
|
||||
ViableEpochDescriptor::Signaled(
|
||||
identifier,
|
||||
EpochHeader {
|
||||
start_slot: slot_number,
|
||||
end_slot: slot_number * self.config.epoch_length,
|
||||
start_slot: slot.into(),
|
||||
end_slot: (slot * self.config.epoch_length).into(),
|
||||
},
|
||||
)
|
||||
},
|
||||
@@ -263,9 +268,9 @@ impl SlotTimestampProvider {
|
||||
// otherwise we'd be producing blocks for older slots.
|
||||
let duration = if info.best_number != Zero::zero() {
|
||||
let header = client.header(BlockId::Hash(info.best_hash))?.unwrap();
|
||||
let slot_number = find_pre_digest::<B>(&header).unwrap().slot_number();
|
||||
let slot = find_pre_digest::<B>(&header).unwrap().slot();
|
||||
// add the slot duration so there's no collision of slots
|
||||
(slot_number * slot_duration) + slot_duration
|
||||
(*slot * slot_duration) + slot_duration
|
||||
} else {
|
||||
// this is the first block, use the correct time.
|
||||
let now = SystemTime::now();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
use codec::{Encode, Decode};
|
||||
use sc_client_api::backend::AuxStore;
|
||||
use sp_blockchain::{Result as ClientResult, Error as ClientError};
|
||||
use sp_consensus_slots::EquivocationProof;
|
||||
use sp_consensus_slots::{EquivocationProof, Slot};
|
||||
use sp_runtime::traits::Header;
|
||||
|
||||
const SLOT_HEADER_MAP_KEY: &[u8] = b"slot_header_map";
|
||||
@@ -52,8 +52,8 @@ fn load_decode<C, T>(backend: &C, key: &[u8]) -> ClientResult<Option<T>>
|
||||
/// Note: it detects equivocations only when slot_now - slot <= MAX_SLOT_CAPACITY.
|
||||
pub fn check_equivocation<C, H, P>(
|
||||
backend: &C,
|
||||
slot_now: u64,
|
||||
slot: u64,
|
||||
slot_now: Slot,
|
||||
slot: Slot,
|
||||
header: &H,
|
||||
signer: &P,
|
||||
) -> ClientResult<Option<EquivocationProof<H, P>>>
|
||||
@@ -63,7 +63,7 @@ pub fn check_equivocation<C, H, P>(
|
||||
P: Clone + Encode + Decode + PartialEq,
|
||||
{
|
||||
// We don't check equivocations for old headers out of our capacity.
|
||||
if slot_now.saturating_sub(slot) > MAX_SLOT_CAPACITY {
|
||||
if slot_now.saturating_sub(*slot) > Slot::from(MAX_SLOT_CAPACITY) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ pub fn check_equivocation<C, H, P>(
|
||||
|
||||
// Get first slot saved.
|
||||
let slot_header_start = SLOT_HEADER_START.to_vec();
|
||||
let first_saved_slot = load_decode::<_, u64>(backend, &slot_header_start[..])?
|
||||
let first_saved_slot = load_decode::<_, Slot>(backend, &slot_header_start[..])?
|
||||
.unwrap_or(slot);
|
||||
|
||||
if slot_now < first_saved_slot {
|
||||
@@ -92,7 +92,7 @@ pub fn check_equivocation<C, H, P>(
|
||||
// 2) with different hash
|
||||
if header.hash() != prev_header.hash() {
|
||||
return Ok(Some(EquivocationProof {
|
||||
slot_number: slot,
|
||||
slot,
|
||||
offender: signer.clone(),
|
||||
first_header: prev_header.clone(),
|
||||
second_header: header.clone(),
|
||||
@@ -109,11 +109,11 @@ pub fn check_equivocation<C, H, P>(
|
||||
let mut keys_to_delete = vec![];
|
||||
let mut new_first_saved_slot = first_saved_slot;
|
||||
|
||||
if slot_now - first_saved_slot >= PRUNING_BOUND {
|
||||
if *slot_now - *first_saved_slot >= PRUNING_BOUND {
|
||||
let prefix = SLOT_HEADER_MAP_KEY.to_vec();
|
||||
new_first_saved_slot = slot_now.saturating_sub(MAX_SLOT_CAPACITY);
|
||||
|
||||
for s in first_saved_slot..new_first_saved_slot {
|
||||
for s in u64::from(first_saved_slot)..new_first_saved_slot.into() {
|
||||
let mut p = prefix.clone();
|
||||
s.using_encoded(|s| p.extend(s));
|
||||
keys_to_delete.push(p);
|
||||
@@ -174,8 +174,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
2,
|
||||
2,
|
||||
2.into(),
|
||||
2.into(),
|
||||
&header1,
|
||||
&public,
|
||||
).unwrap().is_none(),
|
||||
@@ -184,8 +184,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
3,
|
||||
2,
|
||||
3.into(),
|
||||
2.into(),
|
||||
&header1,
|
||||
&public,
|
||||
).unwrap().is_none(),
|
||||
@@ -195,8 +195,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
4,
|
||||
2,
|
||||
4.into(),
|
||||
2.into(),
|
||||
&header2,
|
||||
&public,
|
||||
).unwrap().is_some(),
|
||||
@@ -206,8 +206,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
5,
|
||||
4,
|
||||
5.into(),
|
||||
4.into(),
|
||||
&header3,
|
||||
&public,
|
||||
).unwrap().is_none(),
|
||||
@@ -217,8 +217,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
PRUNING_BOUND + 2,
|
||||
MAX_SLOT_CAPACITY + 4,
|
||||
(PRUNING_BOUND + 2).into(),
|
||||
(MAX_SLOT_CAPACITY + 4).into(),
|
||||
&header4,
|
||||
&public,
|
||||
).unwrap().is_none(),
|
||||
@@ -228,8 +228,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
PRUNING_BOUND + 3,
|
||||
MAX_SLOT_CAPACITY + 4,
|
||||
(PRUNING_BOUND + 3).into(),
|
||||
(MAX_SLOT_CAPACITY + 4).into(),
|
||||
&header5,
|
||||
&public,
|
||||
).unwrap().is_some(),
|
||||
@@ -239,8 +239,8 @@ mod test {
|
||||
assert!(
|
||||
check_equivocation(
|
||||
&client,
|
||||
PRUNING_BOUND + 4,
|
||||
4,
|
||||
(PRUNING_BOUND + 4).into(),
|
||||
4.into(),
|
||||
&header6,
|
||||
&public,
|
||||
).unwrap().is_none(),
|
||||
|
||||
@@ -41,6 +41,7 @@ use parking_lot::Mutex;
|
||||
use sp_api::{ProvideRuntimeApi, ApiRef};
|
||||
use sp_arithmetic::traits::BaseArithmetic;
|
||||
use sp_consensus::{BlockImport, Proposer, SyncOracle, SelectChain, CanAuthorWith, SlotData, RecordProof};
|
||||
use sp_consensus_slots::Slot;
|
||||
use sp_inherents::{InherentData, InherentDataProviders};
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
@@ -115,7 +116,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
fn epoch_data(
|
||||
&self,
|
||||
header: &B::Header,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
) -> Result<Self::EpochData, sp_consensus::Error>;
|
||||
|
||||
/// Returns the number of authorities given the epoch data.
|
||||
@@ -126,7 +127,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
fn claim_slot(
|
||||
&self,
|
||||
header: &B::Header,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
epoch_data: &Self::EpochData,
|
||||
) -> Option<Self::Claim>;
|
||||
|
||||
@@ -135,14 +136,14 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
fn notify_slot(
|
||||
&self,
|
||||
_header: &B::Header,
|
||||
_slot_number: u64,
|
||||
_slot: Slot,
|
||||
_epoch_data: &Self::EpochData,
|
||||
) {}
|
||||
|
||||
/// Return the pre digest data to include in a block authored with the given claim.
|
||||
fn pre_digest_data(
|
||||
&self,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
claim: &Self::Claim,
|
||||
) -> Vec<sp_runtime::DigestItem<B::Hash>>;
|
||||
|
||||
@@ -170,7 +171,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
///
|
||||
/// An example strategy that back offs if the finalized head is lagging too much behind the tip
|
||||
/// is implemented by [`BackoffAuthoringOnFinalizedHeadLagging`].
|
||||
fn should_backoff(&self, _slot_number: u64, _chain_head: &B::Header) -> bool {
|
||||
fn should_backoff(&self, _slot: Slot, _chain_head: &B::Header) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
where
|
||||
<Self::Proposer as Proposer<B>>::Proposal: Unpin + Send + 'static,
|
||||
{
|
||||
let (timestamp, slot_number) = (slot_info.timestamp, slot_info.number);
|
||||
let (timestamp, slot) = (slot_info.timestamp, slot_info.slot);
|
||||
|
||||
let slot_remaining_duration = self.slot_remaining_duration(&slot_info);
|
||||
let proposing_remaining_duration = self.proposing_remaining_duration(&chain_head, &slot_info);
|
||||
@@ -218,7 +219,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
debug!(
|
||||
target: self.logging_target(),
|
||||
"Skipping proposal slot {} since there's no time left to propose",
|
||||
slot_number,
|
||||
slot,
|
||||
);
|
||||
|
||||
return Box::pin(future::ready(None));
|
||||
@@ -227,7 +228,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
None => Box::new(future::pending()) as Box<_>,
|
||||
};
|
||||
|
||||
let epoch_data = match self.epoch_data(&chain_head, slot_number) {
|
||||
let epoch_data = match self.epoch_data(&chain_head, slot) {
|
||||
Ok(epoch_data) => epoch_data,
|
||||
Err(err) => {
|
||||
warn!("Unable to fetch epoch data at block {:?}: {:?}", chain_head.hash(), err);
|
||||
@@ -242,7 +243,7 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
}
|
||||
};
|
||||
|
||||
self.notify_slot(&chain_head, slot_number, &epoch_data);
|
||||
self.notify_slot(&chain_head, slot, &epoch_data);
|
||||
|
||||
let authorities_len = self.authorities_len(&epoch_data);
|
||||
|
||||
@@ -260,38 +261,43 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
return Box::pin(future::ready(None));
|
||||
}
|
||||
|
||||
let claim = match self.claim_slot(&chain_head, slot_number, &epoch_data) {
|
||||
let claim = match self.claim_slot(&chain_head, slot, &epoch_data) {
|
||||
None => return Box::pin(future::ready(None)),
|
||||
Some(claim) => claim,
|
||||
};
|
||||
|
||||
if self.should_backoff(slot_number, &chain_head) {
|
||||
if self.should_backoff(slot, &chain_head) {
|
||||
return Box::pin(future::ready(None));
|
||||
}
|
||||
|
||||
debug!(
|
||||
target: self.logging_target(),
|
||||
"Starting authorship at slot {}; timestamp = {}",
|
||||
slot_number,
|
||||
slot,
|
||||
timestamp,
|
||||
);
|
||||
|
||||
telemetry!(CONSENSUS_DEBUG; "slots.starting_authorship";
|
||||
"slot_num" => slot_number,
|
||||
telemetry!(
|
||||
CONSENSUS_DEBUG;
|
||||
"slots.starting_authorship";
|
||||
"slot_num" => *slot,
|
||||
"timestamp" => timestamp,
|
||||
);
|
||||
|
||||
let awaiting_proposer = self.proposer(&chain_head).map_err(move |err| {
|
||||
warn!("Unable to author block in slot {:?}: {:?}", slot_number, err);
|
||||
warn!("Unable to author block in slot {:?}: {:?}", slot, err);
|
||||
|
||||
telemetry!(CONSENSUS_WARN; "slots.unable_authoring_block";
|
||||
"slot" => slot_number, "err" => ?err
|
||||
telemetry!(
|
||||
CONSENSUS_WARN;
|
||||
"slots.unable_authoring_block";
|
||||
"slot" => *slot,
|
||||
"err" => ?err
|
||||
);
|
||||
|
||||
err
|
||||
});
|
||||
|
||||
let logs = self.pre_digest_data(slot_number, &claim);
|
||||
let logs = self.pre_digest_data(slot, &claim);
|
||||
|
||||
// deadline our production to approx. the end of the slot
|
||||
let proposing = awaiting_proposer.and_then(move |proposer| proposer.propose(
|
||||
@@ -307,12 +313,14 @@ pub trait SimpleSlotWorker<B: BlockT> {
|
||||
futures::future::select(proposing, proposing_remaining).map(move |v| match v {
|
||||
Either::Left((b, _)) => b.map(|b| (b, claim)),
|
||||
Either::Right(_) => {
|
||||
info!("⌛️ Discarding proposal for slot {}; block production took too long", slot_number);
|
||||
info!("⌛️ Discarding proposal for slot {}; block production took too long", slot);
|
||||
// If the node was compiled with debug, tell the user to use release optimizations.
|
||||
#[cfg(build_type="debug")]
|
||||
info!("👉 Recompile your node in `--release` mode to mitigate this problem.");
|
||||
telemetry!(CONSENSUS_INFO; "slots.discarding_proposal_took_too_long";
|
||||
"slot" => slot_number,
|
||||
telemetry!(
|
||||
CONSENSUS_INFO;
|
||||
"slots.discarding_proposal_took_too_long";
|
||||
"slot" => *slot,
|
||||
);
|
||||
|
||||
Err(sp_consensus::Error::ClientImport("Timeout in the Slots proposer".into()))
|
||||
@@ -388,7 +396,7 @@ pub trait SlotCompatible {
|
||||
fn extract_timestamp_and_slot(
|
||||
&self,
|
||||
inherent: &InherentData,
|
||||
) -> Result<(u64, u64, std::time::Duration), sp_consensus::Error>;
|
||||
) -> Result<(u64, Slot, std::time::Duration), sp_consensus::Error>;
|
||||
}
|
||||
|
||||
/// Start a new slot worker.
|
||||
@@ -429,12 +437,12 @@ where
|
||||
return Either::Right(future::ready(Ok(())));
|
||||
}
|
||||
|
||||
let slot_num = slot_info.number;
|
||||
let slot = slot_info.slot;
|
||||
let chain_head = match client.best_chain() {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
warn!(target: "slots", "Unable to author block in slot {}. \
|
||||
no best block header: {:?}", slot_num, e);
|
||||
no best block header: {:?}", slot, e);
|
||||
return Either::Right(future::ready(Ok(())));
|
||||
}
|
||||
};
|
||||
@@ -444,7 +452,7 @@ where
|
||||
target: "slots",
|
||||
"Unable to author block in slot {},. `can_author_with` returned: {} \
|
||||
Probably a node update is required!",
|
||||
slot_num,
|
||||
slot,
|
||||
err,
|
||||
);
|
||||
Either::Right(future::ready(Ok(())))
|
||||
@@ -465,7 +473,7 @@ where
|
||||
pub enum CheckedHeader<H, S> {
|
||||
/// A header which has slot in the future. this is the full header (not stripped)
|
||||
/// and the slot in which it should be processed.
|
||||
Deferred(H, u64),
|
||||
Deferred(H, Slot),
|
||||
/// A header which is fully checked, including signature. This is the pre-header
|
||||
/// accompanied by the seal components.
|
||||
///
|
||||
@@ -473,8 +481,6 @@ pub enum CheckedHeader<H, S> {
|
||||
Checked(H, S),
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Error<T> where T: Debug {
|
||||
@@ -561,7 +567,7 @@ impl<T: Clone + Send + Sync + 'static> SlotDuration<T> {
|
||||
/// to parent. If the number of skipped slots is greated than 0 this method will apply
|
||||
/// an exponential backoff of at most `2^7 * slot_duration`, if no slots were skipped
|
||||
/// this method will return `None.`
|
||||
pub fn slot_lenience_exponential(parent_slot: u64, slot_info: &SlotInfo) -> Option<Duration> {
|
||||
pub fn slot_lenience_exponential(parent_slot: Slot, slot_info: &SlotInfo) -> Option<Duration> {
|
||||
// never give more than 2^this times the lenience.
|
||||
const BACKOFF_CAP: u64 = 7;
|
||||
|
||||
@@ -574,7 +580,7 @@ pub fn slot_lenience_exponential(parent_slot: u64, slot_info: &SlotInfo) -> Opti
|
||||
// exponential back-off.
|
||||
// in normal cases we only attempt to issue blocks up to the end of the slot.
|
||||
// when the chain has been stalled for a few slots, we give more lenience.
|
||||
let skipped_slots = slot_info.number.saturating_sub(parent_slot + 1);
|
||||
let skipped_slots = *slot_info.slot.saturating_sub(parent_slot + 1);
|
||||
|
||||
if skipped_slots == 0 {
|
||||
None
|
||||
@@ -590,7 +596,7 @@ pub fn slot_lenience_exponential(parent_slot: u64, slot_info: &SlotInfo) -> Opti
|
||||
/// to parent. If the number of skipped slots is greated than 0 this method will apply
|
||||
/// a linear backoff of at most `20 * slot_duration`, if no slots were skipped
|
||||
/// this method will return `None.`
|
||||
pub fn slot_lenience_linear(parent_slot: u64, slot_info: &SlotInfo) -> Option<Duration> {
|
||||
pub fn slot_lenience_linear(parent_slot: Slot, slot_info: &SlotInfo) -> Option<Duration> {
|
||||
// never give more than 20 times more lenience.
|
||||
const BACKOFF_CAP: u64 = 20;
|
||||
|
||||
@@ -600,7 +606,7 @@ pub fn slot_lenience_linear(parent_slot: u64, slot_info: &SlotInfo) -> Option<Du
|
||||
// linear back-off.
|
||||
// in normal cases we only attempt to issue blocks up to the end of the slot.
|
||||
// when the chain has been stalled for a few slots, we give more lenience.
|
||||
let skipped_slots = slot_info.number.saturating_sub(parent_slot + 1);
|
||||
let skipped_slots = *slot_info.slot.saturating_sub(parent_slot + 1);
|
||||
|
||||
if skipped_slots == 0 {
|
||||
None
|
||||
@@ -616,9 +622,9 @@ pub trait BackoffAuthoringBlocksStrategy<N> {
|
||||
fn should_backoff(
|
||||
&self,
|
||||
chain_head_number: N,
|
||||
chain_head_slot: u64,
|
||||
chain_head_slot: Slot,
|
||||
finalized_number: N,
|
||||
slow_now: u64,
|
||||
slow_now: Slot,
|
||||
logging_target: &str,
|
||||
) -> bool;
|
||||
}
|
||||
@@ -663,9 +669,9 @@ where
|
||||
fn should_backoff(
|
||||
&self,
|
||||
chain_head_number: N,
|
||||
chain_head_slot: u64,
|
||||
chain_head_slot: Slot,
|
||||
finalized_number: N,
|
||||
slot_now: u64,
|
||||
slot_now: Slot,
|
||||
logging_target: &str,
|
||||
) -> bool {
|
||||
// This should not happen, but we want to keep the previous behaviour if it does.
|
||||
@@ -683,7 +689,7 @@ where
|
||||
|
||||
// If interval is nonzero we backoff if the current slot isn't far enough ahead of the chain
|
||||
// head.
|
||||
if slot_now <= chain_head_slot + interval {
|
||||
if *slot_now <= *chain_head_slot + interval {
|
||||
info!(
|
||||
target: logging_target,
|
||||
"Backing off claiming new slot for block authorship: finality is lagging.",
|
||||
@@ -699,9 +705,9 @@ impl<N> BackoffAuthoringBlocksStrategy<N> for () {
|
||||
fn should_backoff(
|
||||
&self,
|
||||
_chain_head_number: N,
|
||||
_chain_head_slot: u64,
|
||||
_chain_head_slot: Slot,
|
||||
_finalized_number: N,
|
||||
_slot_now: u64,
|
||||
_slot_now: Slot,
|
||||
_logging_target: &str,
|
||||
) -> bool {
|
||||
false
|
||||
@@ -717,9 +723,9 @@ mod test {
|
||||
|
||||
const SLOT_DURATION: Duration = Duration::from_millis(6000);
|
||||
|
||||
fn slot(n: u64) -> super::slots::SlotInfo {
|
||||
fn slot(slot: u64) -> super::slots::SlotInfo {
|
||||
super::slots::SlotInfo {
|
||||
number: n,
|
||||
slot: slot.into(),
|
||||
duration: SLOT_DURATION.as_millis() as u64,
|
||||
timestamp: Default::default(),
|
||||
inherent_data: Default::default(),
|
||||
@@ -730,20 +736,20 @@ mod test {
|
||||
#[test]
|
||||
fn linear_slot_lenience() {
|
||||
// if no slots are skipped there should be no lenience
|
||||
assert_eq!(super::slot_lenience_linear(1, &slot(2)), None);
|
||||
assert_eq!(super::slot_lenience_linear(1.into(), &slot(2)), None);
|
||||
|
||||
// otherwise the lenience is incremented linearly with
|
||||
// the number of skipped slots.
|
||||
for n in 3..=22 {
|
||||
assert_eq!(
|
||||
super::slot_lenience_linear(1, &slot(n)),
|
||||
super::slot_lenience_linear(1.into(), &slot(n)),
|
||||
Some(SLOT_DURATION * (n - 2) as u32),
|
||||
);
|
||||
}
|
||||
|
||||
// but we cap it to a maximum of 20 slots
|
||||
assert_eq!(
|
||||
super::slot_lenience_linear(1, &slot(23)),
|
||||
super::slot_lenience_linear(1.into(), &slot(23)),
|
||||
Some(SLOT_DURATION * 20),
|
||||
);
|
||||
}
|
||||
@@ -751,24 +757,24 @@ mod test {
|
||||
#[test]
|
||||
fn exponential_slot_lenience() {
|
||||
// if no slots are skipped there should be no lenience
|
||||
assert_eq!(super::slot_lenience_exponential(1, &slot(2)), None);
|
||||
assert_eq!(super::slot_lenience_exponential(1.into(), &slot(2)), None);
|
||||
|
||||
// otherwise the lenience is incremented exponentially every two slots
|
||||
for n in 3..=17 {
|
||||
assert_eq!(
|
||||
super::slot_lenience_exponential(1, &slot(n)),
|
||||
super::slot_lenience_exponential(1.into(), &slot(n)),
|
||||
Some(SLOT_DURATION * 2u32.pow((n / 2 - 1) as u32)),
|
||||
);
|
||||
}
|
||||
|
||||
// but we cap it to a maximum of 14 slots
|
||||
assert_eq!(
|
||||
super::slot_lenience_exponential(1, &slot(18)),
|
||||
super::slot_lenience_exponential(1.into(), &slot(18)),
|
||||
Some(SLOT_DURATION * 2u32.pow(7)),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
super::slot_lenience_exponential(1, &slot(19)),
|
||||
super::slot_lenience_exponential(1.into(), &slot(19)),
|
||||
Some(SLOT_DURATION * 2u32.pow(7)),
|
||||
);
|
||||
}
|
||||
@@ -808,7 +814,7 @@ mod test {
|
||||
let slot_now = 2;
|
||||
|
||||
let should_backoff: Vec<bool> = (slot_now..1000)
|
||||
.map(|s| strategy.should_backoff(head_number, head_slot, finalized_number, s, "slots"))
|
||||
.map(|s| strategy.should_backoff(head_number, head_slot.into(), finalized_number, s.into(), "slots"))
|
||||
.collect();
|
||||
|
||||
// Should always be false, since the head isn't advancing
|
||||
@@ -833,9 +839,9 @@ mod test {
|
||||
.map(move |s| {
|
||||
let b = strategy.should_backoff(
|
||||
head_number,
|
||||
head_slot,
|
||||
head_slot.into(),
|
||||
finalized_number,
|
||||
s,
|
||||
s.into(),
|
||||
"slots",
|
||||
);
|
||||
// Chain is still advancing (by someone else)
|
||||
@@ -872,7 +878,7 @@ mod test {
|
||||
let max_interval = strategy.max_interval;
|
||||
|
||||
let should_backoff: Vec<bool> = (slot_now..200)
|
||||
.map(|s| strategy.should_backoff(head_number, head_slot, finalized_number, s, "slots"))
|
||||
.map(|s| strategy.should_backoff(head_number, head_slot.into(), finalized_number, s.into(), "slots"))
|
||||
.collect();
|
||||
|
||||
// Should backoff (true) until we are `max_interval` number of slots ahead of the chain
|
||||
@@ -900,9 +906,9 @@ mod test {
|
||||
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
|
||||
¶m,
|
||||
head_state.head_number,
|
||||
head_state.head_slot,
|
||||
head_state.head_slot.into(),
|
||||
finalized_number,
|
||||
head_state.slot_now,
|
||||
head_state.slot_now.into(),
|
||||
"slots",
|
||||
)
|
||||
};
|
||||
@@ -972,9 +978,9 @@ mod test {
|
||||
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
|
||||
¶m,
|
||||
head_state.head_number,
|
||||
head_state.head_slot,
|
||||
head_state.head_slot.into(),
|
||||
finalized_number,
|
||||
head_state.slot_now,
|
||||
head_state.slot_now.into(),
|
||||
"slots",
|
||||
)
|
||||
};
|
||||
@@ -1036,9 +1042,9 @@ mod test {
|
||||
<dyn BackoffAuthoringBlocksStrategy<NumberFor<Block>>>::should_backoff(
|
||||
¶m,
|
||||
head_state.head_number,
|
||||
head_state.head_slot,
|
||||
head_state.head_slot.into(),
|
||||
finalized_number,
|
||||
head_state.slot_now,
|
||||
head_state.slot_now.into(),
|
||||
"slots",
|
||||
)
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
//!
|
||||
//! This is used instead of `futures_timer::Interval` because it was unreliable.
|
||||
|
||||
use super::SlotCompatible;
|
||||
use super::{SlotCompatible, Slot};
|
||||
use sp_consensus::Error;
|
||||
use futures::{prelude::*, task::Context, task::Poll};
|
||||
use sp_inherents::{InherentData, InherentDataProviders};
|
||||
@@ -48,7 +48,7 @@ pub fn time_until_next(now: Duration, slot_duration: u64) -> Duration {
|
||||
/// Information about a slot.
|
||||
pub struct SlotInfo {
|
||||
/// The slot number.
|
||||
pub number: u64,
|
||||
pub slot: Slot,
|
||||
/// Current timestamp.
|
||||
pub timestamp: u64,
|
||||
/// The instant at which the slot ends.
|
||||
@@ -61,7 +61,7 @@ pub struct SlotInfo {
|
||||
|
||||
/// A stream that returns every time there is a new slot.
|
||||
pub(crate) struct Slots<SC> {
|
||||
last_slot: u64,
|
||||
last_slot: Slot,
|
||||
slot_duration: u64,
|
||||
inner_delay: Option<Delay>,
|
||||
inherent_data_providers: InherentDataProviders,
|
||||
@@ -76,7 +76,7 @@ impl<SC> Slots<SC> {
|
||||
timestamp_extractor: SC,
|
||||
) -> Self {
|
||||
Slots {
|
||||
last_slot: 0,
|
||||
last_slot: 0.into(),
|
||||
slot_duration,
|
||||
inner_delay: None,
|
||||
inherent_data_providers,
|
||||
@@ -114,7 +114,7 @@ impl<SC: SlotCompatible> Stream for Slots<SC> {
|
||||
Err(err) => return Poll::Ready(Some(Err(sp_consensus::Error::InherentData(err)))),
|
||||
};
|
||||
let result = self.timestamp_extractor.extract_timestamp_and_slot(&inherent_data);
|
||||
let (timestamp, slot_num, offset) = match result {
|
||||
let (timestamp, slot, offset) = match result {
|
||||
Ok(v) => v,
|
||||
Err(err) => return Poll::Ready(Some(Err(err))),
|
||||
};
|
||||
@@ -125,11 +125,11 @@ impl<SC: SlotCompatible> Stream for Slots<SC> {
|
||||
self.inner_delay = Some(Delay::new(ends_in));
|
||||
|
||||
// never yield the same slot twice.
|
||||
if slot_num > self.last_slot {
|
||||
self.last_slot = slot_num;
|
||||
if slot > self.last_slot {
|
||||
self.last_slot = slot;
|
||||
|
||||
break Poll::Ready(Some(Ok(SlotInfo {
|
||||
number: slot_num,
|
||||
slot,
|
||||
duration: self.slot_duration,
|
||||
timestamp,
|
||||
ends_at,
|
||||
|
||||
@@ -151,8 +151,8 @@ impl<T: Config> FindAuthor<u32> for Module<T> {
|
||||
{
|
||||
for (id, mut data) in digests.into_iter() {
|
||||
if id == AURA_ENGINE_ID {
|
||||
if let Ok(slot_num) = u64::decode(&mut data) {
|
||||
let author_index = slot_num % Self::authorities().len() as u64;
|
||||
if let Ok(slot) = u64::decode(&mut data) {
|
||||
let author_index = slot % Self::authorities().len() as u64;
|
||||
return Some(author_index as u32)
|
||||
}
|
||||
}
|
||||
@@ -242,7 +242,7 @@ impl<T: Config> ProvideInherent for Module<T> {
|
||||
|
||||
let timestamp_based_slot = timestamp / Self::slot_duration();
|
||||
|
||||
let seal_slot = data.aura_inherent_data()?.saturated_into();
|
||||
let seal_slot = u64::from(data.aura_inherent_data()?).saturated_into();
|
||||
|
||||
if timestamp_based_slot == seal_slot {
|
||||
Ok(())
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
//!
|
||||
|
||||
use frame_support::{debug, traits::KeyOwnerProofSystem};
|
||||
use sp_consensus_babe::{EquivocationProof, SlotNumber};
|
||||
use sp_consensus_babe::{EquivocationProof, Slot};
|
||||
use sp_runtime::transaction_validity::{
|
||||
InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity,
|
||||
TransactionValidityError, ValidTransaction,
|
||||
@@ -63,7 +63,7 @@ pub trait HandleEquivocation<T: Config> {
|
||||
) -> Result<(), OffenceError>;
|
||||
|
||||
/// Returns true if all of the offenders at the given time slot have already been reported.
|
||||
fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &SlotNumber) -> bool;
|
||||
fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &Slot) -> bool;
|
||||
|
||||
/// Create and dispatch an equivocation report extrinsic.
|
||||
fn submit_unsigned_equivocation_report(
|
||||
@@ -83,7 +83,7 @@ impl<T: Config> HandleEquivocation<T> for () {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_known_offence(_offenders: &[T::KeyOwnerIdentification], _time_slot: &SlotNumber) -> bool {
|
||||
fn is_known_offence(_offenders: &[T::KeyOwnerIdentification], _time_slot: &Slot) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ where
|
||||
R::report_offence(reporters, offence)
|
||||
}
|
||||
|
||||
fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &SlotNumber) -> bool {
|
||||
fn is_known_offence(offenders: &[T::KeyOwnerIdentification], time_slot: &Slot) -> bool {
|
||||
R::is_known_offence(offenders, time_slot)
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
|
||||
// Only one equivocation report for the same offender at the same slot.
|
||||
.and_provides((
|
||||
equivocation_proof.offender.clone(),
|
||||
equivocation_proof.slot_number,
|
||||
*equivocation_proof.slot,
|
||||
))
|
||||
// We don't propagate this. This can never be included on a remote node.
|
||||
.propagate(false)
|
||||
@@ -212,7 +212,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
|
||||
// and if so then we can discard the report.
|
||||
let is_known_offence = T::HandleEquivocation::is_known_offence(
|
||||
&[offender],
|
||||
&equivocation_proof.slot_number,
|
||||
&equivocation_proof.slot,
|
||||
);
|
||||
|
||||
if is_known_offence {
|
||||
@@ -230,8 +230,8 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
|
||||
///
|
||||
/// When a validator released two or more blocks at the same slot.
|
||||
pub struct BabeEquivocationOffence<FullIdentification> {
|
||||
/// A babe slot number in which this incident happened.
|
||||
pub slot: SlotNumber,
|
||||
/// A babe slot in which this incident happened.
|
||||
pub slot: Slot,
|
||||
/// The session index in which the incident happened.
|
||||
pub session_index: SessionIndex,
|
||||
/// The size of the validator set at the time of the offence.
|
||||
@@ -244,7 +244,7 @@ impl<FullIdentification: Clone> Offence<FullIdentification>
|
||||
for BabeEquivocationOffence<FullIdentification>
|
||||
{
|
||||
const ID: Kind = *b"babe:equivocatio";
|
||||
type TimeSlot = SlotNumber;
|
||||
type TimeSlot = Slot;
|
||||
|
||||
fn offenders(&self) -> Vec<FullIdentification> {
|
||||
vec![self.offender.clone()]
|
||||
|
||||
@@ -43,7 +43,7 @@ use sp_timestamp::OnTimestampSet;
|
||||
use sp_consensus_babe::{
|
||||
digests::{NextConfigDescriptor, NextEpochDescriptor, PreDigest},
|
||||
inherents::{BabeInherentData, INHERENT_IDENTIFIER},
|
||||
BabeAuthorityWeight, ConsensusLog, Epoch, EquivocationProof, SlotNumber, BABE_ENGINE_ID,
|
||||
BabeAuthorityWeight, ConsensusLog, Epoch, EquivocationProof, Slot, BABE_ENGINE_ID,
|
||||
};
|
||||
use sp_consensus_vrf::schnorrkel;
|
||||
use sp_inherents::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent};
|
||||
@@ -66,7 +66,7 @@ pub trait Config: pallet_timestamp::Config {
|
||||
/// The amount of time, in slots, that each epoch should last.
|
||||
/// NOTE: Currently it is not possible to change the epoch duration after
|
||||
/// the chain has started. Attempting to do so will brick block production.
|
||||
type EpochDuration: Get<SlotNumber>;
|
||||
type EpochDuration: Get<u64>;
|
||||
|
||||
/// The expected average block time at which BABE should be creating
|
||||
/// blocks. Since BABE is probabilistic it is not trivial to figure out
|
||||
@@ -168,10 +168,10 @@ decl_storage! {
|
||||
|
||||
/// The slot at which the first epoch actually started. This is 0
|
||||
/// until the first block of the chain.
|
||||
pub GenesisSlot get(fn genesis_slot): u64;
|
||||
pub GenesisSlot get(fn genesis_slot): Slot;
|
||||
|
||||
/// Current slot number.
|
||||
pub CurrentSlot get(fn current_slot): u64;
|
||||
pub CurrentSlot get(fn current_slot): Slot;
|
||||
|
||||
/// The epoch randomness for the *current* epoch.
|
||||
///
|
||||
@@ -403,7 +403,7 @@ impl<T: Config> Module<T> {
|
||||
// so we don't rotate the epoch.
|
||||
now != One::one() && {
|
||||
let diff = CurrentSlot::get().saturating_sub(Self::current_epoch_start());
|
||||
diff >= T::EpochDuration::get()
|
||||
*diff >= T::EpochDuration::get()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ impl<T: Config> Module<T> {
|
||||
pub fn next_expected_epoch_change(now: T::BlockNumber) -> Option<T::BlockNumber> {
|
||||
let next_slot = Self::current_epoch_start().saturating_add(T::EpochDuration::get());
|
||||
next_slot
|
||||
.checked_sub(CurrentSlot::get())
|
||||
.checked_sub(*CurrentSlot::get())
|
||||
.map(|slots_remaining| {
|
||||
// This is a best effort guess. Drifts in the slot/block ratio will cause errors here.
|
||||
let blocks_remaining: T::BlockNumber = slots_remaining.saturated_into();
|
||||
@@ -490,10 +490,10 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// finds the start slot of the current epoch. only guaranteed to
|
||||
// give correct results after `do_initialize` of the first block
|
||||
// in the chain (as its result is based off of `GenesisSlot`).
|
||||
pub fn current_epoch_start() -> SlotNumber {
|
||||
/// Finds the start slot of the current epoch. only guaranteed to
|
||||
/// give correct results after `do_initialize` of the first block
|
||||
/// in the chain (as its result is based off of `GenesisSlot`).
|
||||
pub fn current_epoch_start() -> Slot {
|
||||
Self::epoch_start(EpochIndex::get())
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fn epoch_start(epoch_index: u64) -> SlotNumber {
|
||||
fn epoch_start(epoch_index: u64) -> Slot {
|
||||
// (epoch_index * epoch_duration) + genesis_slot
|
||||
|
||||
const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
|
||||
@@ -535,7 +535,7 @@ impl<T: Config> Module<T> {
|
||||
.checked_mul(T::EpochDuration::get())
|
||||
.expect(PROOF);
|
||||
|
||||
epoch_start.checked_add(GenesisSlot::get()).expect(PROOF)
|
||||
epoch_start.checked_add(*GenesisSlot::get()).expect(PROOF).into()
|
||||
}
|
||||
|
||||
fn deposit_consensus<U: Encode>(new: U) {
|
||||
@@ -583,9 +583,9 @@ impl<T: Config> Module<T> {
|
||||
// on the first non-zero block (i.e. block #1)
|
||||
// this is where the first epoch (epoch #0) actually starts.
|
||||
// we need to adjust internal storage accordingly.
|
||||
if GenesisSlot::get() == 0 {
|
||||
GenesisSlot::put(digest.slot_number());
|
||||
debug_assert_ne!(GenesisSlot::get(), 0);
|
||||
if *GenesisSlot::get() == 0 {
|
||||
GenesisSlot::put(digest.slot());
|
||||
debug_assert_ne!(*GenesisSlot::get(), 0);
|
||||
|
||||
// deposit a log because this is the first block in epoch #0
|
||||
// we use the same values as genesis because we haven't collected any
|
||||
@@ -599,11 +599,11 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
|
||||
// the slot number of the current block being initialized
|
||||
let current_slot = digest.slot_number();
|
||||
let current_slot = digest.slot();
|
||||
|
||||
// how many slots were skipped between current and last block
|
||||
let lateness = current_slot.saturating_sub(CurrentSlot::get() + 1);
|
||||
let lateness = T::BlockNumber::from(lateness as u32);
|
||||
let lateness = T::BlockNumber::from(*lateness as u32);
|
||||
|
||||
Lateness::<T>::put(lateness);
|
||||
CurrentSlot::put(current_slot);
|
||||
@@ -684,7 +684,7 @@ impl<T: Config> Module<T> {
|
||||
key_owner_proof: T::KeyOwnerProof,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
let offender = equivocation_proof.offender.clone();
|
||||
let slot_number = equivocation_proof.slot_number;
|
||||
let slot = equivocation_proof.slot;
|
||||
|
||||
// validate the equivocation proof
|
||||
if !sp_consensus_babe::check_equivocation_proof(equivocation_proof) {
|
||||
@@ -694,7 +694,7 @@ impl<T: Config> Module<T> {
|
||||
let validator_set_count = key_owner_proof.validator_count();
|
||||
let session_index = key_owner_proof.session();
|
||||
|
||||
let epoch_index = (slot_number.saturating_sub(GenesisSlot::get()) / T::EpochDuration::get())
|
||||
let epoch_index = (*slot.saturating_sub(GenesisSlot::get()) / T::EpochDuration::get())
|
||||
.saturated_into::<u32>();
|
||||
|
||||
// check that the slot number is consistent with the session index
|
||||
@@ -709,7 +709,7 @@ impl<T: Config> Module<T> {
|
||||
.ok_or(Error::<T>::InvalidKeyOwnershipProof)?;
|
||||
|
||||
let offence = BabeEquivocationOffence {
|
||||
slot: slot_number,
|
||||
slot,
|
||||
validator_set_count,
|
||||
offender,
|
||||
session_index,
|
||||
@@ -837,7 +837,7 @@ impl<T: Config> ProvideInherent for Module<T> {
|
||||
let timestamp_based_slot = (timestamp / Self::slot_duration()).saturated_into::<u64>();
|
||||
let seal_slot = data.babe_inherent_data()?;
|
||||
|
||||
if timestamp_based_slot == seal_slot {
|
||||
if timestamp_based_slot == *seal_slot {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(sp_inherents::Error::from("timestamp set in block doesn't match slot in seal").into())
|
||||
|
||||
@@ -33,7 +33,7 @@ use frame_support::{
|
||||
};
|
||||
use sp_io;
|
||||
use sp_core::{H256, U256, crypto::{IsWrappedBy, KeyTypeId, Pair}};
|
||||
use sp_consensus_babe::{AuthorityId, AuthorityPair, SlotNumber};
|
||||
use sp_consensus_babe::{AuthorityId, AuthorityPair, Slot};
|
||||
use sp_consensus_vrf::schnorrkel::{VRFOutput, VRFProof};
|
||||
use sp_staking::SessionIndex;
|
||||
use pallet_staking::EraIndex;
|
||||
@@ -255,14 +255,14 @@ pub fn go_to_block(n: u64, s: u64) {
|
||||
System::parent_hash()
|
||||
};
|
||||
|
||||
let pre_digest = make_secondary_plain_pre_digest(0, s);
|
||||
let pre_digest = make_secondary_plain_pre_digest(0, s.into());
|
||||
|
||||
System::initialize(&n, &parent_hash, &pre_digest, InitKind::Full);
|
||||
System::set_block_number(n);
|
||||
Timestamp::set_timestamp(n);
|
||||
|
||||
if s > 1 {
|
||||
CurrentSlot::put(s);
|
||||
CurrentSlot::put(Slot::from(s));
|
||||
}
|
||||
|
||||
System::on_initialize(n);
|
||||
@@ -272,8 +272,8 @@ pub fn go_to_block(n: u64, s: u64) {
|
||||
|
||||
/// Slots will grow accordingly to blocks
|
||||
pub fn progress_to_block(n: u64) {
|
||||
let mut slot = Babe::current_slot() + 1;
|
||||
for i in System::block_number()+1..=n {
|
||||
let mut slot = u64::from(Babe::current_slot()) + 1;
|
||||
for i in System::block_number() + 1 ..= n {
|
||||
go_to_block(i, slot);
|
||||
slot += 1;
|
||||
}
|
||||
@@ -294,14 +294,14 @@ pub fn start_era(era_index: EraIndex) {
|
||||
|
||||
pub fn make_primary_pre_digest(
|
||||
authority_index: sp_consensus_babe::AuthorityIndex,
|
||||
slot_number: sp_consensus_babe::SlotNumber,
|
||||
slot: sp_consensus_babe::Slot,
|
||||
vrf_output: VRFOutput,
|
||||
vrf_proof: VRFProof,
|
||||
) -> Digest {
|
||||
let digest_data = sp_consensus_babe::digests::PreDigest::Primary(
|
||||
sp_consensus_babe::digests::PrimaryPreDigest {
|
||||
authority_index,
|
||||
slot_number,
|
||||
slot,
|
||||
vrf_output,
|
||||
vrf_proof,
|
||||
}
|
||||
@@ -312,12 +312,12 @@ pub fn make_primary_pre_digest(
|
||||
|
||||
pub fn make_secondary_plain_pre_digest(
|
||||
authority_index: sp_consensus_babe::AuthorityIndex,
|
||||
slot_number: sp_consensus_babe::SlotNumber,
|
||||
slot: sp_consensus_babe::Slot,
|
||||
) -> Digest {
|
||||
let digest_data = sp_consensus_babe::digests::PreDigest::SecondaryPlain(
|
||||
sp_consensus_babe::digests::SecondaryPlainPreDigest {
|
||||
authority_index,
|
||||
slot_number,
|
||||
slot,
|
||||
}
|
||||
);
|
||||
let log = DigestItem::PreRuntime(sp_consensus_babe::BABE_ENGINE_ID, digest_data.encode());
|
||||
@@ -326,14 +326,14 @@ pub fn make_secondary_plain_pre_digest(
|
||||
|
||||
pub fn make_secondary_vrf_pre_digest(
|
||||
authority_index: sp_consensus_babe::AuthorityIndex,
|
||||
slot_number: sp_consensus_babe::SlotNumber,
|
||||
slot: sp_consensus_babe::Slot,
|
||||
vrf_output: VRFOutput,
|
||||
vrf_proof: VRFProof,
|
||||
) -> Digest {
|
||||
let digest_data = sp_consensus_babe::digests::PreDigest::SecondaryVRF(
|
||||
sp_consensus_babe::digests::SecondaryVRFPreDigest {
|
||||
authority_index,
|
||||
slot_number,
|
||||
slot,
|
||||
vrf_output,
|
||||
vrf_proof,
|
||||
}
|
||||
@@ -343,11 +343,11 @@ pub fn make_secondary_vrf_pre_digest(
|
||||
}
|
||||
|
||||
pub fn make_vrf_output(
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
pair: &sp_consensus_babe::AuthorityPair
|
||||
) -> (VRFOutput, VRFProof, [u8; 32]) {
|
||||
let pair = sp_core::sr25519::Pair::from_ref(pair).as_ref();
|
||||
let transcript = sp_consensus_babe::make_transcript(&Babe::randomness(), slot_number, 0);
|
||||
let transcript = sp_consensus_babe::make_transcript(&Babe::randomness(), slot, 0);
|
||||
let vrf_inout = pair.vrf_sign(transcript);
|
||||
let vrf_randomness: sp_consensus_vrf::schnorrkel::Randomness = vrf_inout.0
|
||||
.make_bytes::<[u8; 32]>(&sp_consensus_babe::BABE_VRF_INOUT_CONTEXT);
|
||||
@@ -435,7 +435,7 @@ pub fn new_test_ext_raw_authorities(authorities: Vec<AuthorityId>) -> sp_io::Tes
|
||||
pub fn generate_equivocation_proof(
|
||||
offender_authority_index: u32,
|
||||
offender_authority_pair: &AuthorityPair,
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
) -> sp_consensus_babe::EquivocationProof<Header> {
|
||||
use sp_consensus_babe::digests::CompatibleDigestItem;
|
||||
|
||||
@@ -444,7 +444,7 @@ pub fn generate_equivocation_proof(
|
||||
|
||||
let make_header = || {
|
||||
let parent_hash = System::parent_hash();
|
||||
let pre_digest = make_secondary_plain_pre_digest(offender_authority_index, slot_number);
|
||||
let pre_digest = make_secondary_plain_pre_digest(offender_authority_index, slot);
|
||||
System::initialize(¤t_block, &parent_hash, &pre_digest, InitKind::Full);
|
||||
System::set_block_number(current_block);
|
||||
Timestamp::set_timestamp(current_block);
|
||||
@@ -469,10 +469,10 @@ pub fn generate_equivocation_proof(
|
||||
seal_header(&mut h2);
|
||||
|
||||
// restore previous runtime state
|
||||
go_to_block(current_block, current_slot);
|
||||
go_to_block(current_block, *current_slot);
|
||||
|
||||
sp_consensus_babe::EquivocationProof {
|
||||
slot_number,
|
||||
slot,
|
||||
offender: offender_authority_pair.public(),
|
||||
first_header: h1,
|
||||
second_header: h2,
|
||||
|
||||
@@ -25,7 +25,7 @@ use frame_support::{
|
||||
};
|
||||
use mock::*;
|
||||
use pallet_session::ShouldEndSession;
|
||||
use sp_consensus_babe::AllowedSlots;
|
||||
use sp_consensus_babe::{AllowedSlots, Slot};
|
||||
use sp_core::crypto::Pair;
|
||||
|
||||
const EMPTY_RANDOMNESS: [u8; 32] = [
|
||||
@@ -62,7 +62,7 @@ fn first_block_epoch_zero_start() {
|
||||
let (pairs, mut ext) = new_test_ext_with_pairs(4);
|
||||
|
||||
ext.execute_with(|| {
|
||||
let genesis_slot = 100;
|
||||
let genesis_slot = Slot::from(100);
|
||||
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
|
||||
|
||||
let first_vrf = vrf_output;
|
||||
@@ -73,7 +73,7 @@ fn first_block_epoch_zero_start() {
|
||||
vrf_proof,
|
||||
);
|
||||
|
||||
assert_eq!(Babe::genesis_slot(), 0);
|
||||
assert_eq!(Babe::genesis_slot(), Slot::from(0));
|
||||
System::initialize(
|
||||
&1,
|
||||
&Default::default(),
|
||||
@@ -120,7 +120,7 @@ fn author_vrf_output_for_primary() {
|
||||
let (pairs, mut ext) = new_test_ext_with_pairs(1);
|
||||
|
||||
ext.execute_with(|| {
|
||||
let genesis_slot = 10;
|
||||
let genesis_slot = Slot::from(10);
|
||||
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
|
||||
let primary_pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
|
||||
|
||||
@@ -146,7 +146,7 @@ fn author_vrf_output_for_secondary_vrf() {
|
||||
let (pairs, mut ext) = new_test_ext_with_pairs(1);
|
||||
|
||||
ext.execute_with(|| {
|
||||
let genesis_slot = 10;
|
||||
let genesis_slot = Slot::from(10);
|
||||
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
|
||||
let secondary_vrf_pre_digest = make_secondary_vrf_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
|
||||
|
||||
@@ -170,7 +170,7 @@ fn author_vrf_output_for_secondary_vrf() {
|
||||
#[test]
|
||||
fn no_author_vrf_output_for_secondary_plain() {
|
||||
new_test_ext(1).execute_with(|| {
|
||||
let genesis_slot = 10;
|
||||
let genesis_slot = Slot::from(10);
|
||||
let secondary_plain_pre_digest = make_secondary_plain_pre_digest(0, genesis_slot);
|
||||
|
||||
System::initialize(
|
||||
@@ -205,17 +205,17 @@ fn can_predict_next_epoch_change() {
|
||||
assert_eq!(<Test as Config>::EpochDuration::get(), 3);
|
||||
// this sets the genesis slot to 6;
|
||||
go_to_block(1, 6);
|
||||
assert_eq!(Babe::genesis_slot(), 6);
|
||||
assert_eq!(Babe::current_slot(), 6);
|
||||
assert_eq!(*Babe::genesis_slot(), 6);
|
||||
assert_eq!(*Babe::current_slot(), 6);
|
||||
assert_eq!(Babe::epoch_index(), 0);
|
||||
|
||||
progress_to_block(5);
|
||||
|
||||
assert_eq!(Babe::epoch_index(), 5 / 3);
|
||||
assert_eq!(Babe::current_slot(), 10);
|
||||
assert_eq!(*Babe::current_slot(), 10);
|
||||
|
||||
// next epoch change will be at
|
||||
assert_eq!(Babe::current_epoch_start(), 9); // next change will be 12, 2 slots from now
|
||||
assert_eq!(*Babe::current_epoch_start(), 9); // next change will be 12, 2 slots from now
|
||||
assert_eq!(Babe::next_expected_epoch_change(System::block_number()), Some(5 + 2));
|
||||
})
|
||||
}
|
||||
@@ -226,8 +226,8 @@ fn can_enact_next_config() {
|
||||
assert_eq!(<Test as Config>::EpochDuration::get(), 3);
|
||||
// this sets the genesis slot to 6;
|
||||
go_to_block(1, 6);
|
||||
assert_eq!(Babe::genesis_slot(), 6);
|
||||
assert_eq!(Babe::current_slot(), 6);
|
||||
assert_eq!(*Babe::genesis_slot(), 6);
|
||||
assert_eq!(*Babe::current_slot(), 6);
|
||||
assert_eq!(Babe::epoch_index(), 0);
|
||||
go_to_block(2, 7);
|
||||
|
||||
@@ -269,12 +269,12 @@ fn can_fetch_current_and_next_epoch_data() {
|
||||
|
||||
let current_epoch = Babe::current_epoch();
|
||||
assert_eq!(current_epoch.epoch_index, 3);
|
||||
assert_eq!(current_epoch.start_slot, 10);
|
||||
assert_eq!(*current_epoch.start_slot, 10);
|
||||
assert_eq!(current_epoch.authorities.len(), 5);
|
||||
|
||||
let next_epoch = Babe::next_epoch();
|
||||
assert_eq!(next_epoch.epoch_index, 4);
|
||||
assert_eq!(next_epoch.start_slot, 13);
|
||||
assert_eq!(*next_epoch.start_slot, 13);
|
||||
assert_eq!(next_epoch.authorities.len(), 5);
|
||||
|
||||
// the on-chain randomness should always change across epochs
|
||||
@@ -572,7 +572,7 @@ fn report_equivocation_invalid_equivocation_proof() {
|
||||
&offending_authority_pair,
|
||||
CurrentSlot::get(),
|
||||
);
|
||||
equivocation_proof.slot_number = 0;
|
||||
equivocation_proof.slot = Slot::from(0);
|
||||
assert_invalid_equivocation(equivocation_proof.clone());
|
||||
|
||||
// different slot numbers in headers
|
||||
|
||||
@@ -31,7 +31,7 @@ use frame_support::traits::{Currency, OnInitialize};
|
||||
use sp_runtime::{Perbill, traits::{Convert, StaticLookup, Saturating, UniqueSaturatedInto}};
|
||||
use sp_staking::offence::{ReportOffence, Offence, OffenceDetails};
|
||||
|
||||
use pallet_balances::{Config as BalancesConfig};
|
||||
use pallet_balances::Config as BalancesConfig;
|
||||
use pallet_babe::BabeEquivocationOffence;
|
||||
use pallet_grandpa::{GrandpaEquivocationOffence, GrandpaTimeSlot};
|
||||
use pallet_im_online::{Config as ImOnlineConfig, Module as ImOnline, UnresponsivenessOffence};
|
||||
@@ -331,7 +331,7 @@ benchmarks! {
|
||||
let keys = ImOnline::<T>::keys();
|
||||
|
||||
let offence = BabeEquivocationOffence {
|
||||
slot: 0,
|
||||
slot: 0u64.into(),
|
||||
session_index: 0,
|
||||
validator_set_count: keys.len() as u32,
|
||||
offender: T::convert(offenders.pop().unwrap()),
|
||||
|
||||
@@ -20,6 +20,7 @@ sp-api = { version = "2.0.0", default-features = false, path = "../../api" }
|
||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../runtime" }
|
||||
sp-inherents = { version = "2.0.0", default-features = false, path = "../../inherents" }
|
||||
sp-timestamp = { version = "2.0.0", default-features = false, path = "../../timestamp" }
|
||||
sp-consensus-slots = { version = "0.8.1", default-features = false, path = "../slots" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -26,7 +26,7 @@ use sp_inherents::{InherentDataProviders, ProvideInherentData};
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"auraslot";
|
||||
|
||||
/// The type of the Aura inherent.
|
||||
pub type InherentType = u64;
|
||||
pub type InherentType = sp_consensus_slots::Slot;
|
||||
|
||||
/// Auxiliary trait to extract Aura inherent data.
|
||||
pub trait AuraInherentData {
|
||||
@@ -87,8 +87,8 @@ impl ProvideInherentData for InherentDataProvider {
|
||||
use sp_timestamp::TimestampInherentData;
|
||||
|
||||
let timestamp = inherent_data.timestamp_inherent_data()?;
|
||||
let slot_num = timestamp / self.slot_duration;
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &slot_num)
|
||||
let slot = timestamp / self.slot_duration;
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &slot)
|
||||
}
|
||||
|
||||
fn error_to_string(&self, error: &[u8]) -> Option<String> {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use super::{
|
||||
AllowedSlots, AuthorityId, AuthorityIndex, AuthoritySignature, BabeAuthorityWeight,
|
||||
BabeEpochConfiguration, SlotNumber, BABE_ENGINE_ID,
|
||||
BabeEpochConfiguration, Slot, BABE_ENGINE_ID,
|
||||
};
|
||||
use codec::{Codec, Decode, Encode};
|
||||
use sp_std::vec::Vec;
|
||||
@@ -32,8 +32,8 @@ use sp_consensus_vrf::schnorrkel::{Randomness, VRFOutput, VRFProof};
|
||||
pub struct PrimaryPreDigest {
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
pub slot_number: SlotNumber,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
/// VRF output
|
||||
pub vrf_output: VRFOutput,
|
||||
/// VRF proof
|
||||
@@ -50,8 +50,8 @@ pub struct SecondaryPlainPreDigest {
|
||||
/// it makes things easier for higher-level users of the chain data to
|
||||
/// be aware of the author of a secondary-slot block.
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
pub slot_number: SlotNumber,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
}
|
||||
|
||||
/// BABE secondary deterministic slot assignment with VRF outputs.
|
||||
@@ -59,8 +59,8 @@ pub struct SecondaryPlainPreDigest {
|
||||
pub struct SecondaryVRFPreDigest {
|
||||
/// Authority index
|
||||
pub authority_index: super::AuthorityIndex,
|
||||
/// Slot number
|
||||
pub slot_number: SlotNumber,
|
||||
/// Slot
|
||||
pub slot: Slot,
|
||||
/// VRF output
|
||||
pub vrf_output: VRFOutput,
|
||||
/// VRF proof
|
||||
@@ -93,12 +93,12 @@ impl PreDigest {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the slot number of the pre digest.
|
||||
pub fn slot_number(&self) -> SlotNumber {
|
||||
/// Returns the slot of the pre digest.
|
||||
pub fn slot(&self) -> Slot {
|
||||
match self {
|
||||
PreDigest::Primary(primary) => primary.slot_number,
|
||||
PreDigest::SecondaryPlain(secondary) => secondary.slot_number,
|
||||
PreDigest::SecondaryVRF(secondary) => secondary.slot_number,
|
||||
PreDigest::Primary(primary) => primary.slot,
|
||||
PreDigest::SecondaryPlain(secondary) => secondary.slot,
|
||||
PreDigest::SecondaryVRF(secondary) => secondary.slot,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ use sp_std::result::Result;
|
||||
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot";
|
||||
|
||||
/// The type of the BABE inherent.
|
||||
pub type InherentType = u64;
|
||||
pub type InherentType = sp_consensus_slots::Slot;
|
||||
/// Auxiliary trait to extract BABE inherent data.
|
||||
pub trait BabeInherentData {
|
||||
/// Get BABE inherent data.
|
||||
@@ -82,8 +82,8 @@ impl ProvideInherentData for InherentDataProvider {
|
||||
|
||||
fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> {
|
||||
let timestamp = inherent_data.timestamp_inherent_data()?;
|
||||
let slot_number = timestamp / self.slot_duration;
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &slot_number)
|
||||
let slot = timestamp / self.slot_duration;
|
||||
inherent_data.put_data(INHERENT_IDENTIFIER, &slot)
|
||||
}
|
||||
|
||||
fn error_to_string(&self, error: &[u8]) -> Option<String> {
|
||||
|
||||
@@ -76,8 +76,7 @@ pub const MEDIAN_ALGORITHM_CARDINALITY: usize = 1200; // arbitrary suggestion by
|
||||
/// The index of an authority.
|
||||
pub type AuthorityIndex = u32;
|
||||
|
||||
/// A slot number.
|
||||
pub use sp_consensus_slots::SlotNumber;
|
||||
pub use sp_consensus_slots::Slot;
|
||||
|
||||
/// An equivocation proof for multiple block authorships on the same slot (i.e. double vote).
|
||||
pub type EquivocationProof<H> = sp_consensus_slots::EquivocationProof<H, AuthorityId>;
|
||||
@@ -93,11 +92,11 @@ pub type BabeBlockWeight = u32;
|
||||
/// Make a VRF transcript from given randomness, slot number and epoch.
|
||||
pub fn make_transcript(
|
||||
randomness: &Randomness,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
epoch: u64,
|
||||
) -> Transcript {
|
||||
let mut transcript = Transcript::new(&BABE_ENGINE_ID);
|
||||
transcript.append_u64(b"slot number", slot_number);
|
||||
transcript.append_u64(b"slot number", *slot);
|
||||
transcript.append_u64(b"current epoch", epoch);
|
||||
transcript.append_message(b"chain randomness", &randomness[..]);
|
||||
transcript
|
||||
@@ -107,13 +106,13 @@ pub fn make_transcript(
|
||||
#[cfg(feature = "std")]
|
||||
pub fn make_transcript_data(
|
||||
randomness: &Randomness,
|
||||
slot_number: u64,
|
||||
slot: Slot,
|
||||
epoch: u64,
|
||||
) -> VRFTranscriptData {
|
||||
VRFTranscriptData {
|
||||
label: &BABE_ENGINE_ID,
|
||||
items: vec![
|
||||
("slot number", VRFTranscriptValue::U64(slot_number)),
|
||||
("slot number", VRFTranscriptValue::U64(*slot)),
|
||||
("current epoch", VRFTranscriptValue::U64(epoch)),
|
||||
("chain randomness", VRFTranscriptValue::Bytes(randomness.to_vec())),
|
||||
]
|
||||
@@ -147,7 +146,7 @@ pub struct BabeGenesisConfigurationV1 {
|
||||
pub slot_duration: u64,
|
||||
|
||||
/// The duration of epochs in slots.
|
||||
pub epoch_length: SlotNumber,
|
||||
pub epoch_length: u64,
|
||||
|
||||
/// A constant value that is used in the threshold calculation formula.
|
||||
/// Expressed as a rational where the first member of the tuple is the
|
||||
@@ -195,7 +194,7 @@ pub struct BabeGenesisConfiguration {
|
||||
pub slot_duration: u64,
|
||||
|
||||
/// The duration of epochs in slots.
|
||||
pub epoch_length: SlotNumber,
|
||||
pub epoch_length: u64,
|
||||
|
||||
/// A constant value that is used in the threshold calculation formula.
|
||||
/// Expressed as a rational where the first member of the tuple is the
|
||||
@@ -303,8 +302,8 @@ where
|
||||
|
||||
// both headers must be targetting the same slot and it must
|
||||
// be the same as the one in the proof.
|
||||
if proof.slot_number != first_pre_digest.slot_number() ||
|
||||
first_pre_digest.slot_number() != second_pre_digest.slot_number()
|
||||
if proof.slot != first_pre_digest.slot() ||
|
||||
first_pre_digest.slot() != second_pre_digest.slot()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
@@ -356,9 +355,9 @@ pub struct Epoch {
|
||||
/// The epoch index.
|
||||
pub epoch_index: u64,
|
||||
/// The starting slot of the epoch.
|
||||
pub start_slot: SlotNumber,
|
||||
pub start_slot: Slot,
|
||||
/// The duration of this epoch.
|
||||
pub duration: SlotNumber,
|
||||
pub duration: u64,
|
||||
/// The authorities and their weights.
|
||||
pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,
|
||||
/// Randomness for this epoch.
|
||||
@@ -376,8 +375,8 @@ sp_api::decl_runtime_apis! {
|
||||
#[changed_in(2)]
|
||||
fn configuration() -> BabeGenesisConfigurationV1;
|
||||
|
||||
/// Returns the slot number that started the current epoch.
|
||||
fn current_epoch_start() -> SlotNumber;
|
||||
/// Returns the slot that started the current epoch.
|
||||
fn current_epoch_start() -> Slot;
|
||||
|
||||
/// Returns information regarding the current epoch.
|
||||
fn current_epoch() -> Epoch;
|
||||
@@ -391,14 +390,14 @@ sp_api::decl_runtime_apis! {
|
||||
/// session historical module to prove that a given authority key is
|
||||
/// tied to a given staking identity during a specific session. Proofs
|
||||
/// of key ownership are necessary for submitting equivocation reports.
|
||||
/// NOTE: even though the API takes a `slot_number` as parameter the current
|
||||
/// NOTE: even though the API takes a `slot` as parameter the current
|
||||
/// implementations ignores this parameter and instead relies on this
|
||||
/// method being called at the correct block height, i.e. any point at
|
||||
/// which the epoch for the given slot is live on-chain. Future
|
||||
/// implementations will instead use indexed data through an offchain
|
||||
/// worker, not requiring older states to be available.
|
||||
fn generate_key_ownership_proof(
|
||||
slot_number: SlotNumber,
|
||||
slot: Slot,
|
||||
authority_id: AuthorityId,
|
||||
) -> Option<OpaqueKeyOwnershipProof>;
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@ targets = ["x86_64-unknown-linux-gnu"]
|
||||
[dependencies]
|
||||
codec = { package = "parity-scale-codec", version = "1.3.6", default-features = false, features = ["derive"] }
|
||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../runtime" }
|
||||
sp-arithmetic = { version = "2.0.0", default-features = false, path = "../../arithmetic" }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"codec/std",
|
||||
"sp-runtime/std",
|
||||
"sp-arithmetic/std",
|
||||
]
|
||||
|
||||
@@ -21,8 +21,76 @@
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
|
||||
/// A slot number.
|
||||
pub type SlotNumber = u64;
|
||||
/// Unit type wrapper that represents a slot.
|
||||
#[derive(Debug, Encode, Decode, Eq, Clone, Copy, Default, Ord)]
|
||||
pub struct Slot(u64);
|
||||
|
||||
impl core::ops::Deref for Slot {
|
||||
type Target = u64;
|
||||
|
||||
fn deref(&self) -> &u64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Add for Slot {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Add<u64> for Slot {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: u64) -> Self {
|
||||
Self(self.0 + other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<u64> + Copy> core::cmp::PartialEq<T> for Slot {
|
||||
fn eq(&self, eq: &T) -> bool {
|
||||
self.0 == (*eq).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<u64> + Copy> core::cmp::PartialOrd<T> for Slot {
|
||||
fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
|
||||
self.0.partial_cmp(&(*other).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Slot {
|
||||
/// Saturating addition.
|
||||
pub fn saturating_add<T: Into<u64>>(self, rhs: T) -> Self {
|
||||
Self(self.0.saturating_add(rhs.into()))
|
||||
}
|
||||
|
||||
/// Saturating subtraction.
|
||||
pub fn saturating_sub<T: Into<u64>>(self, rhs: T) -> Self {
|
||||
Self(self.0.saturating_sub(rhs.into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Display for Slot {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Slot {
|
||||
fn from(slot: u64) -> Slot {
|
||||
Slot(slot)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Slot> for u64 {
|
||||
fn from(slot: Slot) -> u64 {
|
||||
slot.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an equivocation proof. An equivocation happens when a validator
|
||||
/// produces more than one block on the same slot. The proof of equivocation
|
||||
@@ -32,8 +100,8 @@ pub type SlotNumber = u64;
|
||||
pub struct EquivocationProof<Header, Id> {
|
||||
/// Returns the authority id of the equivocator.
|
||||
pub offender: Id,
|
||||
/// The slot number at which the equivocation happened.
|
||||
pub slot_number: SlotNumber,
|
||||
/// The slot at which the equivocation happened.
|
||||
pub slot: Slot,
|
||||
/// The first header involved in the equivocation.
|
||||
pub first_header: Header,
|
||||
/// The second header involved in the equivocation.
|
||||
|
||||
@@ -61,7 +61,7 @@ use sp_inherents::{CheckInherentsResult, InherentData};
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
// Ensure Babe and Aura use the same crypto to simplify things a bit.
|
||||
pub use sp_consensus_babe::{AuthorityId, SlotNumber, AllowedSlots};
|
||||
pub use sp_consensus_babe::{AuthorityId, Slot, AllowedSlots};
|
||||
|
||||
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
|
||||
|
||||
@@ -739,7 +739,7 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
fn current_epoch_start() -> sp_consensus_babe::SlotNumber {
|
||||
fn current_epoch_start() -> Slot {
|
||||
<pallet_babe::Module<Runtime>>::current_epoch_start()
|
||||
}
|
||||
|
||||
@@ -761,7 +761,7 @@ cfg_if! {
|
||||
}
|
||||
|
||||
fn generate_key_ownership_proof(
|
||||
_slot_number: sp_consensus_babe::SlotNumber,
|
||||
_slot: sp_consensus_babe::Slot,
|
||||
_authority_id: sp_consensus_babe::AuthorityId,
|
||||
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
|
||||
None
|
||||
@@ -998,7 +998,7 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
fn current_epoch_start() -> sp_consensus_babe::SlotNumber {
|
||||
fn current_epoch_start() -> Slot {
|
||||
<pallet_babe::Module<Runtime>>::current_epoch_start()
|
||||
}
|
||||
|
||||
@@ -1020,7 +1020,7 @@ cfg_if! {
|
||||
}
|
||||
|
||||
fn generate_key_ownership_proof(
|
||||
_slot_number: sp_consensus_babe::SlotNumber,
|
||||
_slot: sp_consensus_babe::Slot,
|
||||
_authority_id: sp_consensus_babe::AuthorityId,
|
||||
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user