-
Notifications
You must be signed in to change notification settings - Fork 33
blockstore_processor: advance migration during startup #608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -1579,7 +1579,7 @@ pub fn confirm_slot( | |||||||
| .on_marker( | ||||||||
| bank.clone_without_scheduler(), | ||||||||
| parent_bank, | ||||||||
| &marker, | ||||||||
| marker, | ||||||||
| migration_status, | ||||||||
| is_final, | ||||||||
| ) | ||||||||
|
|
@@ -1856,6 +1856,54 @@ fn process_bank_0( | |||||||
| Ok(()) | ||||||||
| } | ||||||||
|
|
||||||||
| /// Clean up a failed slot and restart processing from the given genesis slot | ||||||||
| fn cleanup_and_populate_pending_from_alpenglow_genesis( | ||||||||
| first_alpenglow_bank: &BankWithScheduler, | ||||||||
| genesis_slot: Slot, | ||||||||
| bank_forks: &RwLock<BankForks>, | ||||||||
| blockstore: &Blockstore, | ||||||||
| leader_schedule_cache: &LeaderScheduleCache, | ||||||||
| pending_slots: &mut Vec<(SlotMeta, Bank, Hash)>, | ||||||||
| opts: &ProcessOptions, | ||||||||
| migration_status: &MigrationStatus, | ||||||||
| ) -> result::Result<(), BlockstoreProcessorError> { | ||||||||
| // `first_alpenglow_bank` was processed as a TowerBFT bank. Reset it. | ||||||||
| let root_bank = bank_forks.read().unwrap().root_bank(); | ||||||||
| root_bank | ||||||||
| .remove_unrooted_slots(&[(first_alpenglow_bank.slot(), first_alpenglow_bank.bank_id())]); | ||||||||
| root_bank.clear_slot_signatures(first_alpenglow_bank.slot()); | ||||||||
| root_bank.prune_program_cache_by_deployment_slot(first_alpenglow_bank.slot()); | ||||||||
| blockstore | ||||||||
| .remove_dead_slot(first_alpenglow_bank.slot()) | ||||||||
| .unwrap(); | ||||||||
|
|
||||||||
| let genesis_slot_meta = blockstore | ||||||||
| .meta(genesis_slot) | ||||||||
| .map_err(|err| { | ||||||||
| warn!("Failed to load meta for slot {genesis_slot}: {err:?}"); | ||||||||
| BlockstoreProcessorError::FailedToLoadMeta | ||||||||
| })? | ||||||||
| .unwrap(); | ||||||||
|
|
||||||||
| warn!( | ||||||||
| "{}: load_frozen_forks() restart processing from {genesis_slot} treating further blocks \ | ||||||||
| as Alpenglow banks", | ||||||||
| migration_status.my_pubkey() | ||||||||
| ); | ||||||||
| pending_slots.clear(); | ||||||||
| process_next_slots( | ||||||||
| &bank_forks.read().unwrap().get(genesis_slot).unwrap(), | ||||||||
| &genesis_slot_meta, | ||||||||
| blockstore, | ||||||||
| leader_schedule_cache, | ||||||||
| pending_slots, | ||||||||
| opts, | ||||||||
| migration_status, | ||||||||
| )?; | ||||||||
|
|
||||||||
| Ok(()) | ||||||||
| } | ||||||||
|
|
||||||||
| // Given a bank, add its children to the pending slots queue if those children slots are | ||||||||
| // complete | ||||||||
| fn process_next_slots( | ||||||||
|
|
@@ -1959,8 +2007,8 @@ fn load_frozen_forks( | |||||||
| let mut root = bank_forks.read().unwrap().root(); | ||||||||
| let max_root = std::cmp::max(root, blockstore_max_root); | ||||||||
| info!( | ||||||||
| "load_frozen_forks() latest root from blockstore: {blockstore_max_root}, max_root: \ | ||||||||
| {max_root}", | ||||||||
| "load_frozen_forks() bank forks root {root}, latest root from blockstore: \ | ||||||||
| {blockstore_max_root}, max_root: {max_root}", | ||||||||
| ); | ||||||||
|
|
||||||||
| // The total number of slots processed | ||||||||
|
|
@@ -2043,6 +2091,31 @@ fn load_frozen_forks( | |||||||
| if opts.abort_on_invalid_block { | ||||||||
| Err(error)? | ||||||||
| } | ||||||||
|
|
||||||||
| // If this block was the first alpenglow block and advanced the migration phase, we can enable alpenglow. | ||||||||
| // | ||||||||
| // Note: since this code is all startup code we don't have to worry about shutting down `PohService` or any | ||||||||
| // in flight activity of `ReplayStage`. This bank must have failed to freeze as it is an Alpenglow block | ||||||||
| // being verified as a TowerBFT one. | ||||||||
| // | ||||||||
| // We are safe to cleanly transition to alpenglow here | ||||||||
| if migration_status.is_ready_to_enable() { | ||||||||
| let genesis_slot = migration_status.enable_alpenglow_during_startup(); | ||||||||
|
|
||||||||
| // We need to clear pending_slots as it might contain Alpenglow blocks initialized as TowerBFT banks. | ||||||||
| // Clear and populate pending slots from alpenglow genesis | ||||||||
| cleanup_and_populate_pending_from_alpenglow_genesis( | ||||||||
| &bank, | ||||||||
| genesis_slot, | ||||||||
| bank_forks, | ||||||||
| blockstore, | ||||||||
| leader_schedule_cache, | ||||||||
| &mut pending_slots, | ||||||||
| opts, | ||||||||
| &migration_status, | ||||||||
| )?; | ||||||||
| } | ||||||||
|
|
||||||||
| continue; | ||||||||
| } | ||||||||
| txs += progress.num_txs; | ||||||||
|
|
@@ -2105,7 +2178,11 @@ fn load_frozen_forks( | |||||||
| } else { | ||||||||
| None | ||||||||
| } | ||||||||
| }; | ||||||||
| }.filter(|new_root_bank| { | ||||||||
| // In the case that we've restarted while the migrationary period is going on but before alpenglow | ||||||||
| // is enabled, don't root blocks past the migration slot | ||||||||
| migration_status.should_root_during_startup(new_root_bank.slot()) | ||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. startup equivalent of alpenglow/core/src/replay_stage.rs Lines 2814 to 2816 in d6f08a5
|
||||||||
| }); | ||||||||
| m.stop(); | ||||||||
| voting_us += m.as_us(); | ||||||||
|
|
||||||||
|
|
@@ -2129,6 +2206,19 @@ fn load_frozen_forks( | |||||||
| all_banks.retain(|_, bank| bank.ancestors.contains_key(&root)); | ||||||||
| m.stop(); | ||||||||
| root_retain_us += m.as_us(); | ||||||||
|
|
||||||||
| // If this root bank activated the feature flag, update migration status | ||||||||
| if migration_status.is_pre_feature_activation() { | ||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. startup equivalent of alpenglow/core/src/replay_stage.rs Lines 2843 to 2844 in d6f08a5
|
||||||||
| if let Some(slot) = bank_forks | ||||||||
| .read() | ||||||||
| .unwrap() | ||||||||
| .root_bank() | ||||||||
| .feature_set | ||||||||
| .activated_slot(&agave_feature_set::alpenglow::id()) | ||||||||
| { | ||||||||
| migration_status.record_feature_activation(slot); | ||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| slots_processed += 1; | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically analogous to when we enable alpenglow during steady state in replay.
Difference here is:
ReadyToEnableby trying to process the first alpenglow block as a TowerBFT block and failing. While processing we observed theGenesisCertificatemarker so we know that the migration happened, and which block is the genesis.