Skip to content

Commit 6b2edb9

Browse files
authored
feat(alpenglow): enable blockstore BlockComponent parsing (#10566)
* alpenglow: enable blockstore BlockComponent parsing * inline process_slot_data_in_block * style fix * address comments
1 parent 2202b1a commit 6b2edb9

1 file changed

Lines changed: 91 additions & 21 deletions

File tree

ledger/src/blockstore.rs

Lines changed: 91 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ use {
3737
solana_account::ReadableAccount,
3838
solana_address_lookup_table_interface::state::AddressLookupTable,
3939
solana_clock::{Slot, UnixTimestamp, DEFAULT_TICKS_PER_SECOND},
40-
solana_entry::entry::{create_ticks, Entry, MaxDataShredsLen},
40+
solana_entry::{
41+
block_component::BlockComponent,
42+
entry::{create_ticks, Entry, MaxDataShredsLen},
43+
},
4144
solana_genesis_config::{GenesisConfig, DEFAULT_GENESIS_ARCHIVE, DEFAULT_GENESIS_FILE},
4245
solana_hash::Hash,
4346
solana_keypair::Keypair,
@@ -3523,14 +3526,13 @@ impl Blockstore {
35233526
.map(|x| x.0)
35243527
}
35253528

3526-
/// Returns the entry vector for the slot starting with `shred_start_index`, the number of
3527-
/// shreds that comprise the entry vector, and whether the slot is full (consumed all shreds).
3528-
pub fn get_slot_entries_with_shred_info(
3529+
/// Helper function that contains the common logic for getting slot data with shred info
3530+
fn get_slot_data_with_shred_info_common(
35293531
&self,
35303532
slot: Slot,
35313533
start_index: u64,
35323534
allow_dead_slots: bool,
3533-
) -> Result<(Vec<Entry>, u64, bool)> {
3535+
) -> Result<Option<(CompletedRanges, SlotMeta, u64)>> {
35343536
let (completed_ranges, slot_meta) = self.get_completed_ranges(slot, start_index)?;
35353537

35363538
// Check if the slot is dead *after* fetching completed ranges to avoid a race
@@ -3540,7 +3542,7 @@ impl Blockstore {
35403542
if self.is_dead(slot) && !allow_dead_slots {
35413543
return Err(BlockstoreError::DeadSlot);
35423544
} else if completed_ranges.is_empty() {
3543-
return Ok((vec![], 0, false));
3545+
return Ok(None);
35443546
}
35453547

35463548
let slot_meta = slot_meta.unwrap();
@@ -3549,10 +3551,48 @@ impl Blockstore {
35493551
.map(|&Range { end, .. }| u64::from(end) - start_index)
35503552
.unwrap_or(0);
35513553

3552-
let entries = self.get_slot_entries_in_block(slot, completed_ranges, Some(&slot_meta))?;
3554+
Ok(Some((completed_ranges, slot_meta, num_shreds)))
3555+
}
3556+
3557+
/// Returns the entry vector for the slot starting with `shred_start_index`, the number of
3558+
/// shreds that comprise the entry vector, and whether the slot is full (consumed all shreds).
3559+
pub fn get_slot_entries_with_shred_info(
3560+
&self,
3561+
slot: Slot,
3562+
start_index: u64,
3563+
allow_dead_slots: bool,
3564+
) -> Result<(Vec<Entry>, u64, bool)> {
3565+
let Some((completed_ranges, slot_meta, num_shreds)) =
3566+
self.get_slot_data_with_shred_info_common(slot, start_index, allow_dead_slots)?
3567+
else {
3568+
return Ok((vec![], 0, false));
3569+
};
3570+
3571+
let entries = self.get_slot_entries_in_block(slot, &completed_ranges, Some(&slot_meta))?;
35533572
Ok((entries, num_shreds, slot_meta.is_full()))
35543573
}
35553574

3575+
/// Returns the components vector for the slot starting with `shred_start_index`, the number of
3576+
/// shreds that comprise the components vector, and whether the slot is full (consumed all
3577+
/// shreds).
3578+
pub fn get_slot_components_with_shred_info(
3579+
&self,
3580+
slot: Slot,
3581+
start_index: u64,
3582+
allow_dead_slots: bool,
3583+
) -> Result<(Vec<BlockComponent>, Vec<Range<u32>>, bool)> {
3584+
let Some((completed_ranges, slot_meta, _)) =
3585+
self.get_slot_data_with_shred_info_common(slot, start_index, allow_dead_slots)?
3586+
else {
3587+
return Ok((vec![], vec![], false));
3588+
};
3589+
3590+
let components =
3591+
self.get_slot_components_in_block(slot, &completed_ranges, Some(&slot_meta))?;
3592+
debug_assert_eq!(completed_ranges.len(), components.len());
3593+
Ok((components, completed_ranges, slot_meta.is_full()))
3594+
}
3595+
35563596
/// Gets accounts used in transactions in the slot range [starting_slot, ending_slot].
35573597
/// Additionally returns a bool indicating if the set may be incomplete.
35583598
/// Used by ledger-tool to create a minimized snapshot
@@ -3656,18 +3696,19 @@ impl Blockstore {
36563696
.collect()
36573697
}
36583698

3659-
/// Fetch the entries corresponding to all of the shred indices in `completed_ranges`
3699+
/// Fetch the data corresponding to all of the shred indices in `completed_ranges`
36603700
/// This function takes advantage of the fact that `completed_ranges` are both
36613701
/// contiguous and in sorted order. To clarify, suppose completed_ranges is as follows:
36623702
/// completed_ranges = [..., (s_i..e_i), (s_i+1..e_i+1), ...]
36633703
/// Then, the following statements are true:
36643704
/// s_i < e_i == s_i+1 < e_i+1
3665-
fn get_slot_entries_in_block(
3705+
fn get_slot_data_in_block<T>(
36663706
&self,
36673707
slot: Slot,
3668-
completed_ranges: CompletedRanges,
3708+
completed_ranges: &CompletedRanges,
36693709
slot_meta: Option<&SlotMeta>,
3670-
) -> Result<Vec<Entry>> {
3710+
mut deserialize: impl FnMut(Vec<u8>) -> Result<Vec<T>>,
3711+
) -> Result<Vec<T>> {
36713712
debug_assert!(completed_ranges
36723713
.iter()
36733714
.tuple_windows()
@@ -3698,7 +3739,7 @@ impl Blockstore {
36983739
})
36993740
});
37003741
completed_ranges
3701-
.into_iter()
3742+
.iter()
37023743
.map(|Range { start, end }| end - start)
37033744
.map(|num_shreds| {
37043745
shreds
@@ -3707,28 +3748,57 @@ impl Blockstore {
37073748
.process_results(|shreds| Shredder::deshred(shreds))?
37083749
.map_err(|e| {
37093750
BlockstoreError::InvalidShredData(Box::new(bincode::ErrorKind::Custom(
3710-
format!("could not reconstruct entries buffer from shreds: {e:?}"),
3751+
format!("could not reconstruct data buffer from shreds: {e:?}"),
37113752
)))
37123753
})
3713-
.and_then(|payload| {
3714-
<WincodeVec<Entry, MaxDataShredsLen>>::deserialize(&payload).map_err(|e| {
3715-
BlockstoreError::InvalidShredData(Box::new(bincode::ErrorKind::Custom(
3716-
format!("could not reconstruct entries: {e:?}"),
3717-
)))
3718-
})
3719-
})
3754+
.and_then(&mut deserialize)
37203755
})
37213756
.flatten_ok()
37223757
.collect()
37233758
}
37243759

3760+
/// Fetch the components corresponding to all of the shred indices in `completed_ranges`.
3761+
/// Note that one range in CompletedRanges corresponds to one BlockComponent.
3762+
fn get_slot_components_in_block(
3763+
&self,
3764+
slot: Slot,
3765+
completed_ranges: &CompletedRanges,
3766+
slot_meta: Option<&SlotMeta>,
3767+
) -> Result<Vec<BlockComponent>> {
3768+
self.get_slot_data_in_block(slot, completed_ranges, slot_meta, |payload| {
3769+
wincode::deserialize(&payload)
3770+
.map(|component| vec![component])
3771+
.map_err(|e| {
3772+
BlockstoreError::InvalidShredData(Box::new(bincode::ErrorKind::Custom(
3773+
format!("could not reconstruct block component: {e:?}"),
3774+
)))
3775+
})
3776+
})
3777+
}
3778+
3779+
/// Fetch the entries corresponding to all of the shred indices in `completed_ranges`.
3780+
fn get_slot_entries_in_block(
3781+
&self,
3782+
slot: Slot,
3783+
completed_ranges: &CompletedRanges,
3784+
slot_meta: Option<&SlotMeta>,
3785+
) -> Result<Vec<Entry>> {
3786+
self.get_slot_data_in_block(slot, completed_ranges, slot_meta, |payload| {
3787+
<WincodeVec<Entry, MaxDataShredsLen>>::deserialize(&payload).map_err(|e| {
3788+
BlockstoreError::InvalidShredData(Box::new(bincode::ErrorKind::Custom(format!(
3789+
"could not reconstruct entries: {e:?}"
3790+
))))
3791+
})
3792+
})
3793+
}
3794+
37253795
pub fn get_entries_in_data_block(
37263796
&self,
37273797
slot: Slot,
37283798
range: Range<u32>,
37293799
slot_meta: Option<&SlotMeta>,
37303800
) -> Result<Vec<Entry>> {
3731-
self.get_slot_entries_in_block(slot, vec![range], slot_meta)
3801+
self.get_slot_entries_in_block(slot, &vec![range], slot_meta)
37323802
}
37333803

37343804
/// Performs checks on the last fec set of a replayed slot, and returns the block_id.

0 commit comments

Comments
 (0)