Fix timestamp handling on ledger warp (#14210)

* Reset timestamp for slot and epoch-start on warp

* Fix genesis timestamp metric source

* Remove check that timestamp > unix_timestamp_from_genesis

Default to previous timestamp, not genesis timestamp

* Move timestamp metrics to report even on warp

* Initialize slot 0 timestamps correctly

* Add feature gate to warp testnet timestamp

* Review suggestion: simplify warp-timestamp slot check
This commit is contained in:
Tyera Eulberg
2020-12-20 14:36:56 -07:00
committed by GitHub
parent b3dc988564
commit e15f95a36f
2 changed files with 58 additions and 25 deletions

View File

@ -1075,10 +1075,22 @@ impl Bank {
/// * Adjusts the new bank's tick height to avoid having to run PoH for millions of slots /// * Adjusts the new bank's tick height to avoid having to run PoH for millions of slots
/// * Freezes the new bank, assuming that the user will `Bank::new_from_parent` from this bank /// * Freezes the new bank, assuming that the user will `Bank::new_from_parent` from this bank
pub fn warp_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self { pub fn warp_from_parent(parent: &Arc<Bank>, collector_id: &Pubkey, slot: Slot) -> Self {
let parent_timestamp = parent.clock().unix_timestamp;
let mut new = Bank::new_from_parent(parent, collector_id, slot); let mut new = Bank::new_from_parent(parent, collector_id, slot);
new.apply_feature_activations(true); new.apply_feature_activations(true);
new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot)); new.update_epoch_stakes(new.epoch_schedule().get_epoch(slot));
new.tick_height.store(new.max_tick_height(), Relaxed); new.tick_height.store(new.max_tick_height(), Relaxed);
let mut clock = new.clock();
clock.epoch_start_timestamp = parent_timestamp;
clock.unix_timestamp = parent_timestamp;
new.update_sysvar_account(&sysvar::clock::id(), |account| {
create_account(
&clock,
new.inherit_specially_retained_account_balance(account),
)
});
new.freeze(); new.freeze();
new new
} }
@ -1310,6 +1322,7 @@ impl Bank {
.feature_set .feature_set
.is_active(&feature_set::timestamp_correction::id()) .is_active(&feature_set::timestamp_correction::id())
{ {
unix_timestamp = self.clock().unix_timestamp;
let (estimate_type, epoch_start_timestamp) = let (estimate_type, epoch_start_timestamp) =
if let Some(timestamp_bounding_activation_slot) = self if let Some(timestamp_bounding_activation_slot) = self
.feature_set .feature_set
@ -1319,14 +1332,23 @@ impl Bank {
// needed for timestamp bounding, but isn't yet corrected for the activation slot // needed for timestamp bounding, but isn't yet corrected for the activation slot
let epoch_start_timestamp = if self.slot() > timestamp_bounding_activation_slot let epoch_start_timestamp = if self.slot() > timestamp_bounding_activation_slot
{ {
let epoch = if let Some(epoch) = parent_epoch { let warp_testnet_timestamp = self
epoch .feature_set
.activated_slot(&feature_set::warp_testnet_timestamp::id());
if warp_testnet_timestamp == Some(self.slot())
&& self.cluster_type() == ClusterType::Testnet
{
None
} else { } else {
self.epoch() let epoch = if let Some(epoch) = parent_epoch {
}; epoch
let first_slot_in_epoch = } else {
self.epoch_schedule.get_first_slot_in_epoch(epoch); self.epoch()
Some((first_slot_in_epoch, self.clock().epoch_start_timestamp)) };
let first_slot_in_epoch =
self.epoch_schedule.get_first_slot_in_epoch(epoch);
Some((first_slot_in_epoch, self.clock().epoch_start_timestamp))
}
} else { } else {
None None
}; };
@ -1334,30 +1356,29 @@ impl Bank {
} else { } else {
(EstimateType::Unbounded, None) (EstimateType::Unbounded, None)
}; };
let ancestor_timestamp = self.clock().unix_timestamp;
if let Some(timestamp_estimate) = if let Some(timestamp_estimate) =
self.get_timestamp_estimate(estimate_type, epoch_start_timestamp) self.get_timestamp_estimate(estimate_type, epoch_start_timestamp)
{ {
if timestamp_estimate > unix_timestamp { unix_timestamp = timestamp_estimate;
unix_timestamp = timestamp_estimate; if self
let ancestor_timestamp = self.clock().unix_timestamp; .feature_set
if self .is_active(&feature_set::timestamp_bounding::id())
.feature_set && timestamp_estimate < ancestor_timestamp
.is_active(&feature_set::timestamp_bounding::id()) {
&& timestamp_estimate < ancestor_timestamp unix_timestamp = ancestor_timestamp;
{
unix_timestamp = ancestor_timestamp;
}
datapoint_info!(
"bank-timestamp-correction",
("slot", self.slot(), i64),
("from_genesis", unix_timestamp, i64),
("corrected", timestamp_estimate, i64),
("ancestor_timestamp", ancestor_timestamp, i64),
);
} }
} }
datapoint_info!(
"bank-timestamp-correction",
("slot", self.slot(), i64),
("from_genesis", self.unix_timestamp_from_genesis(), i64),
("corrected", unix_timestamp, i64),
("ancestor_timestamp", ancestor_timestamp, i64),
);
} }
let epoch_start_timestamp = if self let mut epoch_start_timestamp = if self
.feature_set .feature_set
.is_active(&feature_set::timestamp_bounding::id()) .is_active(&feature_set::timestamp_bounding::id())
{ {
@ -1370,6 +1391,10 @@ impl Bank {
} else { } else {
Self::get_unused_from_slot(self.slot, self.unused) as i64 Self::get_unused_from_slot(self.slot, self.unused) as i64
}; };
if self.slot == 0 {
unix_timestamp = self.unix_timestamp_from_genesis();
epoch_start_timestamp = self.unix_timestamp_from_genesis();
}
let clock = sysvar::clock::Clock { let clock = sysvar::clock::Clock {
slot: self.slot, slot: self.slot,
epoch_start_timestamp, epoch_start_timestamp,
@ -11146,6 +11171,9 @@ pub(crate) mod tests {
.. ..
} = create_genesis_config_with_leader(5, &leader_pubkey, 3); } = create_genesis_config_with_leader(5, &leader_pubkey, 3);
let mut bank = Bank::new(&genesis_config); let mut bank = Bank::new(&genesis_config);
// Advance past slot 0, which has special handling.
bank = new_from_parent(&Arc::new(bank));
bank = new_from_parent(&Arc::new(bank));
assert_eq!( assert_eq!(
bank.clock().unix_timestamp, bank.clock().unix_timestamp,
bank.unix_timestamp_from_genesis() bank.unix_timestamp_from_genesis()

View File

@ -110,6 +110,10 @@ pub mod try_find_program_address_syscall_enabled {
solana_sdk::declare_id!("EMsMNadQNhCYDyGpYH5Tx6dGHxiUqKHk782PU5XaWfmi"); solana_sdk::declare_id!("EMsMNadQNhCYDyGpYH5Tx6dGHxiUqKHk782PU5XaWfmi");
} }
pub mod warp_testnet_timestamp {
solana_sdk::declare_id!("Bfqm7fGk5MBptqa2WHXWFLH7uJvq8hkJcAQPipy2bAMk");
}
lazy_static! { lazy_static! {
/// Map of feature identifiers to user-visible description /// Map of feature identifiers to user-visible description
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [ pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@ -139,6 +143,7 @@ lazy_static! {
(simple_capitalization::id(), "simple capitalization"), (simple_capitalization::id(), "simple capitalization"),
(bpf_loader_upgradeable_program::id(), "upgradeable bpf loader"), (bpf_loader_upgradeable_program::id(), "upgradeable bpf loader"),
(try_find_program_address_syscall_enabled::id(), "add try_find_program_address syscall"), (try_find_program_address_syscall_enabled::id(), "add try_find_program_address syscall"),
(warp_testnet_timestamp::id(), "warp testnet timestamp to current #TODO"),
/*************** ADD NEW FEATURES HERE ***************/ /*************** ADD NEW FEATURES HERE ***************/
] ]
.iter() .iter()