@@ -47,7 +47,6 @@ use sp_blockchain::{
4747use sp_consensus:: { Error as ConsensusError , SyncOracle } ;
4848use sp_consensus_beefy:: {
4949 crypto:: AuthorityId , BeefyApi , MmrRootHash , PayloadProvider , ValidatorSet , BEEFY_ENGINE_ID ,
50- GENESIS_AUTHORITY_SET_ID ,
5150} ;
5251use sp_keystore:: KeystorePtr ;
5352use sp_mmr_primitives:: MmrApi ;
@@ -282,8 +281,14 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
282281 let persisted_state =
283282 match wait_for_runtime_pallet ( & * runtime, & mut gossip_engine, & mut finality_notifications)
284283 . await
285- . and_then ( |best_grandpa| {
286- load_or_init_voter_state ( & * backend, & * runtime, best_grandpa, min_block_delta)
284+ . and_then ( |( beefy_genesis, best_grandpa) | {
285+ load_or_init_voter_state (
286+ & * backend,
287+ & * runtime,
288+ beefy_genesis,
289+ best_grandpa,
290+ min_block_delta,
291+ )
287292 } ) {
288293 Ok ( state) => state,
289294 Err ( e) => {
@@ -316,16 +321,17 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
316321 persisted_state,
317322 } ;
318323
319- futures:: future:: join (
320- worker. run ( block_import_justif, finality_notifications) ,
321- on_demand_justifications_handler. run ( ) ,
324+ futures:: future:: select (
325+ Box :: pin ( worker. run ( block_import_justif, finality_notifications) ) ,
326+ Box :: pin ( on_demand_justifications_handler. run ( ) ) ,
322327 )
323328 . await ;
324329}
325330
326331fn load_or_init_voter_state < B , BE , R > (
327332 backend : & BE ,
328333 runtime : & R ,
334+ beefy_genesis : NumberFor < B > ,
329335 best_grandpa : <B as Block >:: Header ,
330336 min_block_delta : u32 ,
331337) -> ClientResult < PersistedState < B > >
@@ -335,17 +341,22 @@ where
335341 R : ProvideRuntimeApi < B > ,
336342 R :: Api : BeefyApi < B > ,
337343{
338- // Initialize voter state from AUX DB or from pallet genesis.
339- if let Some ( mut state) = crate :: aux_schema:: load_persistent ( backend) ? {
340- // Overwrite persisted state with current best GRANDPA block.
341- state. set_best_grandpa ( best_grandpa) ;
342- // Overwrite persisted data with newly provided `min_block_delta`.
343- state. set_min_block_delta ( min_block_delta) ;
344- info ! ( target: LOG_TARGET , "🥩 Loading BEEFY voter state from db: {:?}." , state) ;
345- Ok ( state)
346- } else {
347- initialize_voter_state ( backend, runtime, best_grandpa, min_block_delta)
348- }
344+ // Initialize voter state from AUX DB if compatible.
345+ crate :: aux_schema:: load_persistent ( backend) ?
346+ // Verify state pallet genesis matches runtime.
347+ . filter ( |state| state. pallet_genesis ( ) == beefy_genesis)
348+ . and_then ( |mut state| {
349+ // Overwrite persisted state with current best GRANDPA block.
350+ state. set_best_grandpa ( best_grandpa. clone ( ) ) ;
351+ // Overwrite persisted data with newly provided `min_block_delta`.
352+ state. set_min_block_delta ( min_block_delta) ;
353+ info ! ( target: LOG_TARGET , "🥩 Loading BEEFY voter state from db: {:?}." , state) ;
354+ Some ( Ok ( state) )
355+ } )
356+ // No valid voter-state persisted, re-initialize from pallet genesis.
357+ . unwrap_or_else ( || {
358+ initialize_voter_state ( backend, runtime, beefy_genesis, best_grandpa, min_block_delta)
359+ } )
349360}
350361
351362// If no persisted state present, walk back the chain from first GRANDPA notification to either:
@@ -355,6 +366,7 @@ where
355366fn initialize_voter_state < B , BE , R > (
356367 backend : & BE ,
357368 runtime : & R ,
369+ beefy_genesis : NumberFor < B > ,
358370 best_grandpa : <B as Block >:: Header ,
359371 min_block_delta : u32 ,
360372) -> ClientResult < PersistedState < B > >
@@ -369,6 +381,7 @@ where
369381 . beefy_genesis ( best_grandpa. hash ( ) )
370382 . ok ( )
371383 . flatten ( )
384+ . filter ( |genesis| * genesis == beefy_genesis)
372385 . ok_or_else ( || ClientError :: Backend ( "BEEFY pallet expected to be active." . into ( ) ) ) ?;
373386 // Walk back the imported blocks and initialize voter either, at the last block with
374387 // a BEEFY justification, or at pallet genesis block; voter will resume from there.
@@ -396,16 +409,20 @@ where
396409 rounds. conclude ( best_beefy) ;
397410 sessions. push_front ( rounds) ;
398411 }
399- let state =
400- PersistedState :: checked_new ( best_grandpa, best_beefy, sessions, min_block_delta)
401- . ok_or_else ( || ClientError :: Backend ( "Invalid BEEFY chain" . into ( ) ) ) ?;
412+ let state = PersistedState :: checked_new (
413+ best_grandpa,
414+ best_beefy,
415+ sessions,
416+ min_block_delta,
417+ beefy_genesis,
418+ )
419+ . ok_or_else ( || ClientError :: Backend ( "Invalid BEEFY chain" . into ( ) ) ) ?;
402420 break state
403421 }
404422
405423 if * header. number ( ) == beefy_genesis {
406424 // We've reached BEEFY genesis, initialize voter here.
407- let genesis_set =
408- expect_validator_set ( runtime, header. hash ( ) ) . and_then ( genesis_set_sanity_check) ?;
425+ let genesis_set = expect_validator_set ( runtime, header. hash ( ) ) ?;
409426 info ! (
410427 target: LOG_TARGET ,
411428 "🥩 Loading BEEFY voter state from genesis on what appears to be first startup. \
@@ -415,8 +432,14 @@ where
415432 ) ;
416433
417434 sessions. push_front ( Rounds :: new ( beefy_genesis, genesis_set) ) ;
418- break PersistedState :: checked_new ( best_grandpa, Zero :: zero ( ) , sessions, min_block_delta)
419- . ok_or_else ( || ClientError :: Backend ( "Invalid BEEFY chain" . into ( ) ) ) ?
435+ break PersistedState :: checked_new (
436+ best_grandpa,
437+ Zero :: zero ( ) ,
438+ sessions,
439+ min_block_delta,
440+ beefy_genesis,
441+ )
442+ . ok_or_else ( || ClientError :: Backend ( "Invalid BEEFY chain" . into ( ) ) ) ?
420443 }
421444
422445 if let Some ( active) = worker:: find_authorities_change :: < B > ( & header) {
@@ -451,7 +474,7 @@ async fn wait_for_runtime_pallet<B, R>(
451474 runtime : & R ,
452475 mut gossip_engine : & mut GossipEngine < B > ,
453476 finality : & mut Fuse < FinalityNotifications < B > > ,
454- ) -> ClientResult < < B as Block >:: Header >
477+ ) -> ClientResult < ( NumberFor < B > , < B as Block >:: Header ) >
455478where
456479 B : Block ,
457480 R : ProvideRuntimeApi < B > ,
@@ -474,7 +497,7 @@ where
474497 "🥩 BEEFY pallet available: block {:?} beefy genesis {:?}" ,
475498 notif. header. number( ) , start
476499 ) ;
477- return Ok ( notif. header)
500+ return Ok ( ( start , notif. header) )
478501 }
479502 }
480503 } ,
@@ -488,17 +511,6 @@ where
488511 Err ( ClientError :: Backend ( err_msg) )
489512}
490513
491- fn genesis_set_sanity_check (
492- active : ValidatorSet < AuthorityId > ,
493- ) -> ClientResult < ValidatorSet < AuthorityId > > {
494- if active. id ( ) == GENESIS_AUTHORITY_SET_ID {
495- Ok ( active)
496- } else {
497- error ! ( target: LOG_TARGET , "🥩 Unexpected ID for genesis validator set {:?}." , active) ;
498- Err ( ClientError :: Backend ( "BEEFY Genesis sanity check failed." . into ( ) ) )
499- }
500- }
501-
502514fn expect_validator_set < B , R > (
503515 runtime : & R ,
504516 at_hash : B :: Hash ,
0 commit comments