mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 10:57:56 +00:00
babe: expose next epoch data (#7829)
* babe: expose next epoch data * babe: add runtime api for next_epoch * babe: avoid reading next authorities from storage unnecessarily * babe: add notes about epoch duration constraints * babe: guard against overflow * babe: add test for fetching current and next epoch data
This commit is contained in:
@@ -64,6 +64,8 @@ pub use equivocation::{BabeEquivocationOffence, EquivocationHandler, HandleEquiv
|
||||
|
||||
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>;
|
||||
|
||||
/// The expected average block time at which BABE should be creating
|
||||
@@ -192,6 +194,9 @@ decl_storage! {
|
||||
/// Next epoch randomness.
|
||||
NextRandomness: schnorrkel::Randomness;
|
||||
|
||||
/// Next epoch authorities.
|
||||
NextAuthorities: Vec<(AuthorityId, BabeAuthorityWeight)>;
|
||||
|
||||
/// Randomness under construction.
|
||||
///
|
||||
/// We make a tradeoff between storage accesses and list length.
|
||||
@@ -233,6 +238,9 @@ decl_module! {
|
||||
pub struct Module<T: Config> for enum Call where origin: T::Origin {
|
||||
/// The number of **slots** that an epoch takes. We couple sessions to
|
||||
/// epochs, i.e. we start a new session once the new epoch begins.
|
||||
/// NOTE: Currently it is not possible to change the epoch duration
|
||||
/// after the chain has started. Attempting to do so will brick block
|
||||
/// production.
|
||||
const EpochDuration: u64 = T::EpochDuration::get();
|
||||
|
||||
/// The expected average block time at which BABE should be creating
|
||||
@@ -464,6 +472,9 @@ impl<T: Config> Module<T> {
|
||||
let randomness = Self::randomness_change_epoch(next_epoch_index);
|
||||
Randomness::put(randomness);
|
||||
|
||||
// Update the next epoch authorities.
|
||||
NextAuthorities::put(&next_authorities);
|
||||
|
||||
// After we update the current epoch, we signal the *next* epoch change
|
||||
// so that nodes can track changes.
|
||||
let next_randomness = NextRandomness::get();
|
||||
@@ -483,7 +494,7 @@ impl<T: Config> Module<T> {
|
||||
// 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 {
|
||||
(EpochIndex::get() * T::EpochDuration::get()) + GenesisSlot::get()
|
||||
Self::epoch_start(EpochIndex::get())
|
||||
}
|
||||
|
||||
/// Produces information about the current epoch.
|
||||
@@ -497,6 +508,36 @@ impl<T: Config> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Produces information about the next epoch (which was already previously
|
||||
/// announced).
|
||||
pub fn next_epoch() -> Epoch {
|
||||
let next_epoch_index = EpochIndex::get().checked_add(1).expect(
|
||||
"epoch index is u64; it is always only incremented by one; \
|
||||
if u64 is not enough we should crash for safety; qed.",
|
||||
);
|
||||
|
||||
Epoch {
|
||||
epoch_index: next_epoch_index,
|
||||
start_slot: Self::epoch_start(next_epoch_index),
|
||||
duration: T::EpochDuration::get(),
|
||||
authorities: NextAuthorities::get(),
|
||||
randomness: NextRandomness::get(),
|
||||
}
|
||||
}
|
||||
|
||||
fn epoch_start(epoch_index: u64) -> SlotNumber {
|
||||
// (epoch_index * epoch_duration) + genesis_slot
|
||||
|
||||
const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
|
||||
if u64 is not enough we should crash for safety; qed.";
|
||||
|
||||
let epoch_start = epoch_index
|
||||
.checked_mul(T::EpochDuration::get())
|
||||
.expect(PROOF);
|
||||
|
||||
epoch_start.checked_add(GenesisSlot::get()).expect(PROOF)
|
||||
}
|
||||
|
||||
fn deposit_consensus<U: Encode>(new: U) {
|
||||
let log: DigestItem<T::Hash> = DigestItem::Consensus(BABE_ENGINE_ID, new.encode());
|
||||
<frame_system::Module<T>>::deposit_log(log.into())
|
||||
|
||||
@@ -295,7 +295,7 @@ pub fn start_era(era_index: EraIndex) {
|
||||
assert_eq!(Staking::current_era(), Some(era_index));
|
||||
}
|
||||
|
||||
pub fn make_pre_digest(
|
||||
pub fn make_primary_pre_digest(
|
||||
authority_index: sp_consensus_babe::AuthorityIndex,
|
||||
slot_number: sp_consensus_babe::SlotNumber,
|
||||
vrf_output: VRFOutput,
|
||||
|
||||
@@ -66,7 +66,7 @@ fn first_block_epoch_zero_start() {
|
||||
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
|
||||
|
||||
let first_vrf = vrf_output;
|
||||
let pre_digest = make_pre_digest(
|
||||
let pre_digest = make_primary_pre_digest(
|
||||
0,
|
||||
genesis_slot,
|
||||
first_vrf.clone(),
|
||||
@@ -122,7 +122,7 @@ fn author_vrf_output_for_primary() {
|
||||
ext.execute_with(|| {
|
||||
let genesis_slot = 10;
|
||||
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
|
||||
let primary_pre_digest = make_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
|
||||
let primary_pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
|
||||
|
||||
System::initialize(
|
||||
&1,
|
||||
@@ -252,6 +252,33 @@ fn can_enact_next_config() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_fetch_current_and_next_epoch_data() {
|
||||
new_test_ext(5).execute_with(|| {
|
||||
// 1 era = 3 epochs
|
||||
// 1 epoch = 3 slots
|
||||
// Eras start from 0.
|
||||
// Therefore at era 1 we should be starting epoch 3 with slot 10.
|
||||
start_era(1);
|
||||
|
||||
let current_epoch = Babe::current_epoch();
|
||||
assert_eq!(current_epoch.epoch_index, 3);
|
||||
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.authorities.len(), 5);
|
||||
|
||||
// the on-chain randomness should always change across epochs
|
||||
assert!(current_epoch.randomness != next_epoch.randomness);
|
||||
|
||||
// but in this case the authorities stay the same
|
||||
assert!(current_epoch.authorities == next_epoch.authorities);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn report_equivocation_current_session_works() {
|
||||
let (pairs, mut ext) = new_test_ext_with_pairs(3);
|
||||
|
||||
Reference in New Issue
Block a user