8
8
cache_block_meta_service:: { CacheBlockMetaSender , CacheBlockMetaService } ,
9
9
cluster_info_vote_listener:: VoteTracker ,
10
10
completed_data_sets_service:: CompletedDataSetsService ,
11
- consensus:: { reconcile_blockstore_roots_with_tower , Tower } ,
11
+ consensus:: { reconcile_blockstore_roots_with_external_source , ExternalRootSource , Tower } ,
12
12
ledger_metric_report_service:: LedgerMetricReportService ,
13
13
poh_timing_report_service:: PohTimingReportService ,
14
14
rewards_recorder_service:: { RewardsRecorderSender , RewardsRecorderService } ,
@@ -512,6 +512,7 @@ impl Validator {
512
512
genesis_config,
513
513
bank_forks,
514
514
blockstore,
515
+ original_blockstore_root,
515
516
ledger_signal_receiver,
516
517
completed_slots_receiver,
517
518
leader_schedule_cache,
@@ -667,6 +668,7 @@ impl Validator {
667
668
vote_account,
668
669
& start_progress,
669
670
& blockstore,
671
+ original_blockstore_root,
670
672
& bank_forks,
671
673
& leader_schedule_cache,
672
674
& blockstore_process_options,
@@ -1224,6 +1226,17 @@ fn check_poh_speed(genesis_config: &GenesisConfig, maybe_hash_samples: Option<u6
1224
1226
}
1225
1227
}
1226
1228
1229
+ fn maybe_cluster_restart_with_hard_fork ( config : & ValidatorConfig , root_slot : Slot ) -> Option < Slot > {
1230
+ // detect cluster restart (hard fork) indirectly via wait_for_supermajority...
1231
+ if let Some ( wait_slot_for_supermajority) = config. wait_for_supermajority {
1232
+ if wait_slot_for_supermajority == root_slot {
1233
+ return Some ( wait_slot_for_supermajority) ;
1234
+ }
1235
+ }
1236
+
1237
+ None
1238
+ }
1239
+
1227
1240
fn post_process_restored_tower (
1228
1241
restored_tower : crate :: consensus:: Result < Tower > ,
1229
1242
validator_identity : & Pubkey ,
@@ -1237,29 +1250,28 @@ fn post_process_restored_tower(
1237
1250
. and_then ( |tower| {
1238
1251
let root_bank = bank_forks. root_bank ( ) ;
1239
1252
let slot_history = root_bank. get_slot_history ( ) ;
1253
+ // make sure tower isn't corrupted first before the following hard fork check
1240
1254
let tower = tower. adjust_lockouts_after_replay ( root_bank. slot ( ) , & slot_history) ;
1241
1255
1242
- if let Some ( wait_slot_for_supermajority) = config. wait_for_supermajority {
1243
- if root_bank. slot ( ) == wait_slot_for_supermajority {
1244
- // intentionally fail to restore tower; we're supposedly in a new hard fork; past
1245
- // out-of-chain vote state doesn't make sense at all
1246
- // what if --wait-for-supermajority again if the validator restarted?
1247
- let message = format ! ( "Hardfork is detected; discarding tower restoration result: {:?}" , tower) ;
1248
- datapoint_error ! (
1249
- "tower_error" ,
1250
- (
1251
- "error" ,
1252
- message,
1253
- String
1254
- ) ,
1255
- ) ;
1256
- error ! ( "{}" , message) ;
1256
+ if let Some ( hard_fork_restart_slot) = maybe_cluster_restart_with_hard_fork ( config, root_bank. slot ( ) ) {
1257
+ // intentionally fail to restore tower; we're supposedly in a new hard fork; past
1258
+ // out-of-chain vote state doesn't make sense at all
1259
+ // what if --wait-for-supermajority again if the validator restarted?
1260
+ let message = format ! ( "Hard fork is detected; discarding tower restoration result: {:?}" , tower) ;
1261
+ datapoint_error ! (
1262
+ "tower_error" ,
1263
+ (
1264
+ "error" ,
1265
+ message,
1266
+ String
1267
+ ) ,
1268
+ ) ;
1269
+ error ! ( "{}" , message) ;
1257
1270
1258
- // unconditionally relax tower requirement so that we can always restore tower
1259
- // from root bank.
1260
- should_require_tower = false ;
1261
- return Err ( crate :: consensus:: TowerError :: HardFork ( wait_slot_for_supermajority) ) ;
1262
- }
1271
+ // unconditionally relax tower requirement so that we can always restore tower
1272
+ // from root bank.
1273
+ should_require_tower = false ;
1274
+ return Err ( crate :: consensus:: TowerError :: HardFork ( hard_fork_restart_slot) ) ;
1263
1275
}
1264
1276
1265
1277
if let Some ( warp_slot) = config. warp_slot {
@@ -1326,6 +1338,7 @@ fn load_blockstore(
1326
1338
GenesisConfig ,
1327
1339
Arc < RwLock < BankForks > > ,
1328
1340
Arc < Blockstore > ,
1341
+ Slot ,
1329
1342
Receiver < bool > ,
1330
1343
CompletedSlotsReceiver ,
1331
1344
LeaderScheduleCache ,
@@ -1378,6 +1391,9 @@ fn load_blockstore(
1378
1391
. expect ( "Failed to open ledger database" ) ;
1379
1392
blockstore. set_no_compaction ( config. no_rocksdb_compaction ) ;
1380
1393
blockstore. shred_timing_point_sender = poh_timing_point_sender;
1394
+ // following boot sequence (esp BankForks) could set root. so stash the original value
1395
+ // of blockstore root away here as soon as possible.
1396
+ let original_blockstore_root = blockstore. last_root ( ) ;
1381
1397
1382
1398
let blockstore = Arc :: new ( blockstore) ;
1383
1399
let blockstore_root_scan = BlockstoreRootScan :: new ( config, & blockstore, exit) ;
@@ -1482,6 +1498,7 @@ fn load_blockstore(
1482
1498
genesis_config,
1483
1499
bank_forks,
1484
1500
blockstore,
1501
+ original_blockstore_root,
1485
1502
ledger_signal_receiver,
1486
1503
completed_slots_receiver,
1487
1504
leader_schedule_cache,
@@ -1521,6 +1538,7 @@ struct ProcessBlockStore<'a> {
1521
1538
vote_account : & ' a Pubkey ,
1522
1539
start_progress : & ' a Arc < RwLock < ValidatorStartProgress > > ,
1523
1540
blockstore : & ' a Blockstore ,
1541
+ original_blockstore_root : Slot ,
1524
1542
bank_forks : & ' a Arc < RwLock < BankForks > > ,
1525
1543
leader_schedule_cache : & ' a LeaderScheduleCache ,
1526
1544
process_options : & ' a blockstore_processor:: ProcessOptions ,
@@ -1539,6 +1557,7 @@ impl<'a> ProcessBlockStore<'a> {
1539
1557
vote_account : & ' a Pubkey ,
1540
1558
start_progress : & ' a Arc < RwLock < ValidatorStartProgress > > ,
1541
1559
blockstore : & ' a Blockstore ,
1560
+ original_blockstore_root : Slot ,
1542
1561
bank_forks : & ' a Arc < RwLock < BankForks > > ,
1543
1562
leader_schedule_cache : & ' a LeaderScheduleCache ,
1544
1563
process_options : & ' a blockstore_processor:: ProcessOptions ,
@@ -1553,6 +1572,7 @@ impl<'a> ProcessBlockStore<'a> {
1553
1572
vote_account,
1554
1573
start_progress,
1555
1574
blockstore,
1575
+ original_blockstore_root,
1556
1576
bank_forks,
1557
1577
leader_schedule_cache,
1558
1578
process_options,
@@ -1622,12 +1642,30 @@ impl<'a> ProcessBlockStore<'a> {
1622
1642
self . tower = Some ( {
1623
1643
let restored_tower = Tower :: restore ( self . config . tower_storage . as_ref ( ) , self . id ) ;
1624
1644
if let Ok ( tower) = & restored_tower {
1625
- reconcile_blockstore_roots_with_tower ( tower, self . blockstore ) . unwrap_or_else (
1626
- |err| {
1627
- error ! ( "Failed to reconcile blockstore with tower: {:?}" , err) ;
1628
- abort ( )
1629
- } ,
1630
- ) ;
1645
+ reconcile_blockstore_roots_with_external_source (
1646
+ ExternalRootSource :: Tower ( tower. root ( ) ) ,
1647
+ self . blockstore ,
1648
+ & mut self . original_blockstore_root ,
1649
+ )
1650
+ . unwrap_or_else ( |err| {
1651
+ error ! ( "Failed to reconcile blockstore with tower: {:?}" , err) ;
1652
+ abort ( )
1653
+ } ) ;
1654
+ }
1655
+
1656
+ if let Some ( hard_fork_restart_slot) = maybe_cluster_restart_with_hard_fork (
1657
+ self . config ,
1658
+ self . bank_forks . read ( ) . unwrap ( ) . root_bank ( ) . slot ( ) ,
1659
+ ) {
1660
+ reconcile_blockstore_roots_with_external_source (
1661
+ ExternalRootSource :: HardFork ( hard_fork_restart_slot) ,
1662
+ self . blockstore ,
1663
+ & mut self . original_blockstore_root ,
1664
+ )
1665
+ . unwrap_or_else ( |err| {
1666
+ error ! ( "Failed to reconcile blockstore with hard fork: {:?}" , err) ;
1667
+ abort ( )
1668
+ } ) ;
1631
1669
}
1632
1670
1633
1671
post_process_restored_tower (
0 commit comments