@@ -47,7 +47,6 @@ use sp_blockchain::{
47
47
use sp_consensus:: { Error as ConsensusError , SyncOracle } ;
48
48
use sp_consensus_beefy:: {
49
49
crypto:: AuthorityId , BeefyApi , MmrRootHash , PayloadProvider , ValidatorSet , BEEFY_ENGINE_ID ,
50
- GENESIS_AUTHORITY_SET_ID ,
51
50
} ;
52
51
use sp_keystore:: KeystorePtr ;
53
52
use sp_mmr_primitives:: MmrApi ;
@@ -282,8 +281,14 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
282
281
let persisted_state =
283
282
match wait_for_runtime_pallet ( & * runtime, & mut gossip_engine, & mut finality_notifications)
284
283
. 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
+ )
287
292
} ) {
288
293
Ok ( state) => state,
289
294
Err ( e) => {
@@ -316,16 +321,17 @@ pub async fn start_beefy_gadget<B, BE, C, N, P, R, S>(
316
321
persisted_state,
317
322
} ;
318
323
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 ( ) ) ,
322
327
)
323
328
. await ;
324
329
}
325
330
326
331
fn load_or_init_voter_state < B , BE , R > (
327
332
backend : & BE ,
328
333
runtime : & R ,
334
+ beefy_genesis : NumberFor < B > ,
329
335
best_grandpa : <B as Block >:: Header ,
330
336
min_block_delta : u32 ,
331
337
) -> ClientResult < PersistedState < B > >
@@ -335,17 +341,22 @@ where
335
341
R : ProvideRuntimeApi < B > ,
336
342
R :: Api : BeefyApi < B > ,
337
343
{
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
+ } )
349
360
}
350
361
351
362
// If no persisted state present, walk back the chain from first GRANDPA notification to either:
@@ -355,6 +366,7 @@ where
355
366
fn initialize_voter_state < B , BE , R > (
356
367
backend : & BE ,
357
368
runtime : & R ,
369
+ beefy_genesis : NumberFor < B > ,
358
370
best_grandpa : <B as Block >:: Header ,
359
371
min_block_delta : u32 ,
360
372
) -> ClientResult < PersistedState < B > >
@@ -369,6 +381,7 @@ where
369
381
. beefy_genesis ( best_grandpa. hash ( ) )
370
382
. ok ( )
371
383
. flatten ( )
384
+ . filter ( |genesis| * genesis == beefy_genesis)
372
385
. ok_or_else ( || ClientError :: Backend ( "BEEFY pallet expected to be active." . into ( ) ) ) ?;
373
386
// Walk back the imported blocks and initialize voter either, at the last block with
374
387
// a BEEFY justification, or at pallet genesis block; voter will resume from there.
@@ -396,16 +409,20 @@ where
396
409
rounds. conclude ( best_beefy) ;
397
410
sessions. push_front ( rounds) ;
398
411
}
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 ( ) ) ) ?;
402
420
break state
403
421
}
404
422
405
423
if * header. number ( ) == beefy_genesis {
406
424
// 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 ( ) ) ?;
409
426
info ! (
410
427
target: LOG_TARGET ,
411
428
"🥩 Loading BEEFY voter state from genesis on what appears to be first startup. \
@@ -415,8 +432,14 @@ where
415
432
) ;
416
433
417
434
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 ( ) ) ) ?
420
443
}
421
444
422
445
if let Some ( active) = worker:: find_authorities_change :: < B > ( & header) {
@@ -451,7 +474,7 @@ async fn wait_for_runtime_pallet<B, R>(
451
474
runtime : & R ,
452
475
mut gossip_engine : & mut GossipEngine < B > ,
453
476
finality : & mut Fuse < FinalityNotifications < B > > ,
454
- ) -> ClientResult < < B as Block >:: Header >
477
+ ) -> ClientResult < ( NumberFor < B > , < B as Block >:: Header ) >
455
478
where
456
479
B : Block ,
457
480
R : ProvideRuntimeApi < B > ,
@@ -474,7 +497,7 @@ where
474
497
"🥩 BEEFY pallet available: block {:?} beefy genesis {:?}" ,
475
498
notif. header. number( ) , start
476
499
) ;
477
- return Ok ( notif. header)
500
+ return Ok ( ( start , notif. header) )
478
501
}
479
502
}
480
503
} ,
@@ -488,17 +511,6 @@ where
488
511
Err ( ClientError :: Backend ( err_msg) )
489
512
}
490
513
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
-
502
514
fn expect_validator_set < B , R > (
503
515
runtime : & R ,
504
516
at_hash : B :: Hash ,
0 commit comments