Skip to content

Commit 1d8896e

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

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
@@ -140,6 +140,31 @@ impl ForkProgress {
140140
}
141141
}
142142

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

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

ledger/src/blockstore_processor.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@ pub fn process_blockstore_from_root(
10891089
/// Verify that a segment of entries has the correct number of ticks and hashes
10901090
fn verify_ticks(
10911091
bank: &Bank,
1092-
entries: &[Entry],
1092+
mut entries: &[Entry],
10931093
slot_full: bool,
10941094
tick_hash_count: &mut u64,
10951095
) -> std::result::Result<(), BlockError> {
@@ -1119,6 +1119,28 @@ fn verify_ticks(
11191119
}
11201120
}
11211121

1122+
if let Some(first_alpenglow_slot) = bank
1123+
.feature_set
1124+
.activated_slot(&solana_feature_set::secp256k1_program_enabled::id())
1125+
{
1126+
if bank.parent_slot() >= first_alpenglow_slot {
1127+
return Ok(());
1128+
}
1129+
1130+
if bank.slot() >= first_alpenglow_slot && next_bank_tick_height == max_bank_tick_height {
1131+
if entries.is_empty() {
1132+
// This shouldn't happen, but good to double check
1133+
error!("Processing empty entries in verify_ticks()");
1134+
return Ok(());
1135+
}
1136+
// last entry must be a tick, as verified by the `has_trailing_entry`
1137+
// check above. Because in Alpenglow the last tick does not have any
1138+
// hashing guarantees, we pass everything but that last tick to the
1139+
// entry verification.
1140+
entries = &entries[..entries.len() - 1];
1141+
}
1142+
}
1143+
11221144
let hashes_per_tick = bank.hashes_per_tick().unwrap_or(0);
11231145
if !entries.verify_tick_hash_count(tick_hash_count, hashes_per_tick) {
11241146
warn!(

0 commit comments

Comments
 (0)