Skip to content

Commit 6217273

Browse files
carllinbw-solana
authored andcommitted
Modify ticks and hashes_per_tick check for alpenglow blocks (anza-xyz#98)
1 parent 769fcf0 commit 6217273

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

core/src/consensus/progress_map.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,31 @@ impl ForkProgress {
142142
}
143143
}
144144

145+
fn calculate_alpenglow_ticks(
146+
slot: Slot,
147+
first_alpenglow_slot: Slot,
148+
parent_slot: Slot,
149+
ticks_per_slot: u64,
150+
) -> Option<u64> {
151+
// Slots before alpenglow shouldn't have alpenglow ticks
152+
if slot < first_alpenglow_slot {
153+
return None;
154+
}
155+
156+
let alpenglow_ticks = if parent_slot < first_alpenglow_slot && slot >= first_alpenglow_slot
157+
{
158+
// 1. All slots between the parent and the first alpenglow slot need to
159+
// have `ticks_per_slot` ticks
160+
// 2. One extra tick for the actual alpenglow slot
161+
// 3. There are no ticks for any skipped alpenglow slots
162+
(first_alpenglow_slot - parent_slot - 1) * ticks_per_slot + 1
163+
} else {
164+
1
165+
};
166+
167+
Some(alpenglow_ticks)
168+
}
169+
145170
pub fn new_from_bank(
146171
bank: &Bank,
147172
validator_identity: &Pubkey,
@@ -170,6 +195,20 @@ impl ForkProgress {
170195
num_dropped_blocks_on_fork,
171196
);
172197

198+
if let Some(first_alpenglow_slot) = bank
199+
.feature_set
200+
.activated_slot(&solana_feature_set::secp256k1_program_enabled::id())
201+
{
202+
if let Some(num_expected_ticks) = Self::calculate_alpenglow_ticks(
203+
bank.slot(),
204+
first_alpenglow_slot,
205+
bank.parent_slot(),
206+
bank.ticks_per_slot(),
207+
) {
208+
bank.set_tick_height(bank.max_tick_height() - num_expected_ticks);
209+
}
210+
}
211+
173212
if bank.is_frozen() {
174213
new_progress.fork_stats.bank_hash = Some(bank.hash());
175214
}
@@ -613,4 +652,83 @@ mod test {
613652
.is_leader_slot = true;
614653
assert!(!progress_map.get_leader_propagation_slot_must_exist(10).0);
615654
}
655+
656+
#[test]
657+
fn test_calculate_alpenglow_ticks() {
658+
let first_alpenglow_slot = 10;
659+
let ticks_per_slot = 2;
660+
661+
// Slots before alpenglow don't have alpenglow ticks
662+
let slot = 9;
663+
let parent_slot = 8;
664+
assert!(ForkProgress::calculate_alpenglow_ticks(
665+
slot,
666+
first_alpenglow_slot,
667+
parent_slot,
668+
ticks_per_slot
669+
)
670+
.is_none());
671+
672+
// First alpenglow slot should only have 1 tick
673+
let slot = first_alpenglow_slot;
674+
let parent_slot = first_alpenglow_slot - 1;
675+
assert_eq!(
676+
ForkProgress::calculate_alpenglow_ticks(
677+
slot,
678+
first_alpenglow_slot,
679+
parent_slot,
680+
ticks_per_slot
681+
)
682+
.unwrap(),
683+
1
684+
);
685+
686+
// First alpenglow slot with skipped non-alpenglow slots
687+
// need to have `ticks_per_slot` ticks per skipped slot and
688+
// then one additional tick for the first alpenglow slot
689+
let slot = first_alpenglow_slot;
690+
let num_skipped_slots = 3;
691+
let parent_slot = first_alpenglow_slot - num_skipped_slots - 1;
692+
assert_eq!(
693+
ForkProgress::calculate_alpenglow_ticks(
694+
slot,
695+
first_alpenglow_slot,
696+
parent_slot,
697+
ticks_per_slot
698+
)
699+
.unwrap(),
700+
num_skipped_slots * ticks_per_slot + 1
701+
);
702+
703+
// Skipped alpenglow slots don't need any additional ticks
704+
let slot = first_alpenglow_slot + 2;
705+
let parent_slot = first_alpenglow_slot;
706+
assert_eq!(
707+
ForkProgress::calculate_alpenglow_ticks(
708+
slot,
709+
first_alpenglow_slot,
710+
parent_slot,
711+
ticks_per_slot
712+
)
713+
.unwrap(),
714+
1
715+
);
716+
717+
// Skipped alpenglow slots along skipped non-alpenglow slots
718+
// need to have `ticks_per_slot` ticks per skipped non-alpenglow
719+
// slot only and then one additional tick for the alpenglow slot
720+
let slot = first_alpenglow_slot + 2;
721+
let num_skipped_non_alpenglow_slots = 4;
722+
let parent_slot = first_alpenglow_slot - num_skipped_non_alpenglow_slots - 1;
723+
assert_eq!(
724+
ForkProgress::calculate_alpenglow_ticks(
725+
slot,
726+
first_alpenglow_slot,
727+
parent_slot,
728+
ticks_per_slot
729+
)
730+
.unwrap(),
731+
num_skipped_non_alpenglow_slots * ticks_per_slot + 1
732+
);
733+
}
616734
}

ledger/src/blockstore_processor.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,7 @@ pub fn process_blockstore_from_root(
10561056
/// Verify that a segment of entries has the correct number of ticks and hashes
10571057
fn verify_ticks(
10581058
bank: &Bank,
1059-
entries: &[Entry],
1059+
mut entries: &[Entry],
10601060
slot_full: bool,
10611061
tick_hash_count: &mut u64,
10621062
) -> std::result::Result<(), BlockError> {
@@ -1086,6 +1086,28 @@ fn verify_ticks(
10861086
}
10871087
}
10881088

1089+
if let Some(first_alpenglow_slot) = bank
1090+
.feature_set
1091+
.activated_slot(&solana_feature_set::secp256k1_program_enabled::id())
1092+
{
1093+
if bank.parent_slot() >= first_alpenglow_slot {
1094+
return Ok(());
1095+
}
1096+
1097+
if bank.slot() >= first_alpenglow_slot && next_bank_tick_height == max_bank_tick_height {
1098+
if entries.is_empty() {
1099+
// This shouldn't happen, but good to double check
1100+
error!("Processing empty entries in verify_ticks()");
1101+
return Ok(());
1102+
}
1103+
// last entry must be a tick, as verified by the `has_trailing_entry`
1104+
// check above. Because in Alpenglow the last tick does not have any
1105+
// hashing guarantees, we pass everything but that last tick to the
1106+
// entry verification.
1107+
entries = &entries[..entries.len() - 1];
1108+
}
1109+
}
1110+
10891111
let hashes_per_tick = bank.hashes_per_tick().unwrap_or(0);
10901112
if !entries.verify_tick_hash_count(tick_hash_count, hashes_per_tick) {
10911113
warn!(

0 commit comments

Comments
 (0)