Skip to content
This repository was archived by the owner on Jul 4, 2022. It is now read-only.

Commit 8927543

Browse files
authored
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
1 parent 71e47d7 commit 8927543

File tree

6 files changed

+88
-4
lines changed

6 files changed

+88
-4
lines changed

bin/node/runtime/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,10 @@ impl_runtime_apis! {
11801180
Babe::current_epoch()
11811181
}
11821182

1183+
fn next_epoch() -> sp_consensus_babe::Epoch {
1184+
Babe::next_epoch()
1185+
}
1186+
11831187
fn generate_key_ownership_proof(
11841188
_slot_number: sp_consensus_babe::SlotNumber,
11851189
authority_id: sp_consensus_babe::AuthorityId,

frame/babe/src/lib.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub use equivocation::{BabeEquivocationOffence, EquivocationHandler, HandleEquiv
6464

6565
pub trait Config: pallet_timestamp::Config {
6666
/// The amount of time, in slots, that each epoch should last.
67+
/// NOTE: Currently it is not possible to change the epoch duration after
68+
/// the chain has started. Attempting to do so will brick block production.
6769
type EpochDuration: Get<SlotNumber>;
6870

6971
/// The expected average block time at which BABE should be creating
@@ -192,6 +194,9 @@ decl_storage! {
192194
/// Next epoch randomness.
193195
NextRandomness: schnorrkel::Randomness;
194196

197+
/// Next epoch authorities.
198+
NextAuthorities: Vec<(AuthorityId, BabeAuthorityWeight)>;
199+
195200
/// Randomness under construction.
196201
///
197202
/// We make a tradeoff between storage accesses and list length.
@@ -233,6 +238,9 @@ decl_module! {
233238
pub struct Module<T: Config> for enum Call where origin: T::Origin {
234239
/// The number of **slots** that an epoch takes. We couple sessions to
235240
/// epochs, i.e. we start a new session once the new epoch begins.
241+
/// NOTE: Currently it is not possible to change the epoch duration
242+
/// after the chain has started. Attempting to do so will brick block
243+
/// production.
236244
const EpochDuration: u64 = T::EpochDuration::get();
237245

238246
/// The expected average block time at which BABE should be creating
@@ -464,6 +472,9 @@ impl<T: Config> Module<T> {
464472
let randomness = Self::randomness_change_epoch(next_epoch_index);
465473
Randomness::put(randomness);
466474

475+
// Update the next epoch authorities.
476+
NextAuthorities::put(&next_authorities);
477+
467478
// After we update the current epoch, we signal the *next* epoch change
468479
// so that nodes can track changes.
469480
let next_randomness = NextRandomness::get();
@@ -483,7 +494,7 @@ impl<T: Config> Module<T> {
483494
// give correct results after `do_initialize` of the first block
484495
// in the chain (as its result is based off of `GenesisSlot`).
485496
pub fn current_epoch_start() -> SlotNumber {
486-
(EpochIndex::get() * T::EpochDuration::get()) + GenesisSlot::get()
497+
Self::epoch_start(EpochIndex::get())
487498
}
488499

489500
/// Produces information about the current epoch.
@@ -497,6 +508,36 @@ impl<T: Config> Module<T> {
497508
}
498509
}
499510

511+
/// Produces information about the next epoch (which was already previously
512+
/// announced).
513+
pub fn next_epoch() -> Epoch {
514+
let next_epoch_index = EpochIndex::get().checked_add(1).expect(
515+
"epoch index is u64; it is always only incremented by one; \
516+
if u64 is not enough we should crash for safety; qed.",
517+
);
518+
519+
Epoch {
520+
epoch_index: next_epoch_index,
521+
start_slot: Self::epoch_start(next_epoch_index),
522+
duration: T::EpochDuration::get(),
523+
authorities: NextAuthorities::get(),
524+
randomness: NextRandomness::get(),
525+
}
526+
}
527+
528+
fn epoch_start(epoch_index: u64) -> SlotNumber {
529+
// (epoch_index * epoch_duration) + genesis_slot
530+
531+
const PROOF: &str = "slot number is u64; it should relate in some way to wall clock time; \
532+
if u64 is not enough we should crash for safety; qed.";
533+
534+
let epoch_start = epoch_index
535+
.checked_mul(T::EpochDuration::get())
536+
.expect(PROOF);
537+
538+
epoch_start.checked_add(GenesisSlot::get()).expect(PROOF)
539+
}
540+
500541
fn deposit_consensus<U: Encode>(new: U) {
501542
let log: DigestItem<T::Hash> = DigestItem::Consensus(BABE_ENGINE_ID, new.encode());
502543
<frame_system::Module<T>>::deposit_log(log.into())

frame/babe/src/mock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ pub fn start_era(era_index: EraIndex) {
295295
assert_eq!(Staking::current_era(), Some(era_index));
296296
}
297297

298-
pub fn make_pre_digest(
298+
pub fn make_primary_pre_digest(
299299
authority_index: sp_consensus_babe::AuthorityIndex,
300300
slot_number: sp_consensus_babe::SlotNumber,
301301
vrf_output: VRFOutput,

frame/babe/src/tests.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn first_block_epoch_zero_start() {
6666
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
6767

6868
let first_vrf = vrf_output;
69-
let pre_digest = make_pre_digest(
69+
let pre_digest = make_primary_pre_digest(
7070
0,
7171
genesis_slot,
7272
first_vrf.clone(),
@@ -122,7 +122,7 @@ fn author_vrf_output_for_primary() {
122122
ext.execute_with(|| {
123123
let genesis_slot = 10;
124124
let (vrf_output, vrf_proof, vrf_randomness) = make_vrf_output(genesis_slot, &pairs[0]);
125-
let primary_pre_digest = make_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
125+
let primary_pre_digest = make_primary_pre_digest(0, genesis_slot, vrf_output, vrf_proof);
126126

127127
System::initialize(
128128
&1,
@@ -252,6 +252,33 @@ fn can_enact_next_config() {
252252
});
253253
}
254254

255+
#[test]
256+
fn can_fetch_current_and_next_epoch_data() {
257+
new_test_ext(5).execute_with(|| {
258+
// 1 era = 3 epochs
259+
// 1 epoch = 3 slots
260+
// Eras start from 0.
261+
// Therefore at era 1 we should be starting epoch 3 with slot 10.
262+
start_era(1);
263+
264+
let current_epoch = Babe::current_epoch();
265+
assert_eq!(current_epoch.epoch_index, 3);
266+
assert_eq!(current_epoch.start_slot, 10);
267+
assert_eq!(current_epoch.authorities.len(), 5);
268+
269+
let next_epoch = Babe::next_epoch();
270+
assert_eq!(next_epoch.epoch_index, 4);
271+
assert_eq!(next_epoch.start_slot, 13);
272+
assert_eq!(next_epoch.authorities.len(), 5);
273+
274+
// the on-chain randomness should always change across epochs
275+
assert!(current_epoch.randomness != next_epoch.randomness);
276+
277+
// but in this case the authorities stay the same
278+
assert!(current_epoch.authorities == next_epoch.authorities);
279+
});
280+
}
281+
255282
#[test]
256283
fn report_equivocation_current_session_works() {
257284
let (pairs, mut ext) = new_test_ext_with_pairs(3);

primitives/consensus/babe/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@ sp_api::decl_runtime_apis! {
382382
/// Returns information regarding the current epoch.
383383
fn current_epoch() -> Epoch;
384384

385+
/// Returns information regarding the next epoch (which was already
386+
/// previously announced).
387+
fn next_epoch() -> Epoch;
388+
385389
/// Generates a proof of key ownership for the given authority in the
386390
/// current epoch. An example usage of this module is coupled with the
387391
/// session historical module to prove that a given authority key is

test-utils/runtime/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,10 @@ cfg_if! {
741741
<pallet_babe::Module<Runtime>>::current_epoch()
742742
}
743743

744+
fn next_epoch() -> sp_consensus_babe::Epoch {
745+
<pallet_babe::Module<Runtime>>::next_epoch()
746+
}
747+
744748
fn submit_report_equivocation_unsigned_extrinsic(
745749
_equivocation_proof: sp_consensus_babe::EquivocationProof<
746750
<Block as BlockT>::Header,
@@ -996,6 +1000,10 @@ cfg_if! {
9961000
<pallet_babe::Module<Runtime>>::current_epoch()
9971001
}
9981002

1003+
fn next_epoch() -> sp_consensus_babe::Epoch {
1004+
<pallet_babe::Module<Runtime>>::next_epoch()
1005+
}
1006+
9991007
fn submit_report_equivocation_unsigned_extrinsic(
10001008
_equivocation_proof: sp_consensus_babe::EquivocationProof<
10011009
<Block as BlockT>::Header,

0 commit comments

Comments
 (0)