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

Commit

Permalink
babe: expose next epoch data (#7829)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
andresilva authored Jan 6, 2021
1 parent 71e47d7 commit 8927543
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 4 deletions.
4 changes: 4 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,10 @@ impl_runtime_apis! {
Babe::current_epoch()
}

fn next_epoch() -> sp_consensus_babe::Epoch {
Babe::next_epoch()
}

fn generate_key_ownership_proof(
_slot_number: sp_consensus_babe::SlotNumber,
authority_id: sp_consensus_babe::AuthorityId,
Expand Down
43 changes: 42 additions & 1 deletion frame/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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.
Expand All @@ -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())
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
31 changes: 29 additions & 2 deletions frame/babe/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions primitives/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ sp_api::decl_runtime_apis! {
/// Returns information regarding the current epoch.
fn current_epoch() -> Epoch;

/// Returns information regarding the next epoch (which was already
/// previously announced).
fn next_epoch() -> Epoch;

/// Generates a proof of key ownership for the given authority in the
/// current epoch. An example usage of this module is coupled with the
/// session historical module to prove that a given authority key is
Expand Down
8 changes: 8 additions & 0 deletions test-utils/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,10 @@ cfg_if! {
<pallet_babe::Module<Runtime>>::current_epoch()
}

fn next_epoch() -> sp_consensus_babe::Epoch {
<pallet_babe::Module<Runtime>>::next_epoch()
}

fn submit_report_equivocation_unsigned_extrinsic(
_equivocation_proof: sp_consensus_babe::EquivocationProof<
<Block as BlockT>::Header,
Expand Down Expand Up @@ -996,6 +1000,10 @@ cfg_if! {
<pallet_babe::Module<Runtime>>::current_epoch()
}

fn next_epoch() -> sp_consensus_babe::Epoch {
<pallet_babe::Module<Runtime>>::next_epoch()
}

fn submit_report_equivocation_unsigned_extrinsic(
_equivocation_proof: sp_consensus_babe::EquivocationProof<
<Block as BlockT>::Header,
Expand Down

0 comments on commit 8927543

Please sign in to comment.