Skip to content

Commit 4013fce

Browse files
committed
pr feedback: multi get, simplify error prop, debug_assert_eq
1 parent 2b29eba commit 4013fce

File tree

2 files changed

+55
-82
lines changed

2 files changed

+55
-82
lines changed

ledger/src/blockstore.rs

Lines changed: 54 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -874,73 +874,69 @@ impl Blockstore {
874874
}
875875
}
876876

877-
/// Fetches (and populates if needed) the DoubleMerkleMeta for the given block.
878-
/// Returns the double_merkle_root
879-
///
880-
/// Should only be used on full blocks.
881-
pub fn get_or_compute_double_merkle_root(
877+
/// Gets the double merkle root for the given block, computing it if necessary.
878+
/// Fails and returns `None` if the block is missing or not full
879+
pub fn get_double_merkle_root(
882880
&self,
883881
slot: Slot,
884882
block_location: BlockLocation,
885-
) -> std::result::Result<Hash, BlockstoreProcessorError> {
883+
) -> Option<Hash> {
886884
if let Some(double_merkle_meta) = self
887885
.double_merkle_meta_cf
888886
.get((slot, block_location))
889887
.expect("Blockstore operations must succeed")
890888
{
891-
return Ok(double_merkle_meta.double_merkle_root);
889+
return Some(double_merkle_meta.double_merkle_root);
892890
}
893891

894-
// Compute double merkle - slot must be full at this point
895-
let Some(slot_meta) = self
892+
self.compute_double_merkle_root(slot, block_location)
893+
}
894+
895+
/// Computes the double merkle root & proofs for the given block and inserts the DoubleMerkleMeta.
896+
/// Fails if the slot is not full returning `None` otherwise returns the double merkle root
897+
fn compute_double_merkle_root(
898+
&self,
899+
slot: Slot,
900+
block_location: BlockLocation,
901+
) -> Option<Hash> {
902+
let slot_meta = self
896903
.meta_cf
897904
.get(slot)
898-
.expect("Blockstore operations must succeed")
899-
else {
900-
return Err(BlockstoreProcessorError::FailedToLoadMeta);
901-
};
905+
.expect("Blockstore operations must succeed")?;
902906

903907
if !slot_meta.is_full() {
904-
return Err(BlockstoreProcessorError::SlotNotFull(slot, block_location));
908+
return None;
905909
}
906910

907-
let Some(last_index) = slot_meta.last_index else {
908-
return Err(BlockstoreProcessorError::SlotNotFull(slot, block_location));
909-
};
911+
let last_index = slot_meta.last_index.expect("Slot is full");
910912

911913
// This function is only used post Alpenglow, so implicitely gated by SIMD-0317 as that is a prereq
912914
let fec_set_count = (last_index / (DATA_SHREDS_PER_FEC_BLOCK as u64) + 1) as usize;
913915

914-
let Some(parent_meta) = self
916+
let parent_meta = self
915917
.parent_meta_cf
916918
.get((slot, block_location))
917919
.expect("Blockstore operations must succeed")
918-
else {
919-
return Err(BlockstoreProcessorError::MissingParent(
920-
slot,
921-
block_location,
922-
));
923-
};
920+
.expect("Slot cannot be full without parent");
924921

925922
// Collect merkle roots for each FEC set
926-
let mut merkle_tree_leaves = Vec::with_capacity(fec_set_count + 1);
927-
928-
for i in 0..fec_set_count {
929-
let fec_set_index = (i * DATA_SHREDS_PER_FEC_BLOCK) as u32;
930-
let erasure_set_id = ErasureSetId::new(slot, fec_set_index);
931-
932-
let Some(merkle_root) = self
933-
.merkle_root_meta_from_location(erasure_set_id, block_location)
934-
.expect("Blockstore operations must succeed")
935-
.and_then(|mrm| mrm.merkle_root())
936-
else {
937-
return Err(BlockstoreProcessorError::MissingMerkleRoot(
938-
slot,
939-
fec_set_index as u64,
940-
));
941-
};
942-
merkle_tree_leaves.push(Ok(merkle_root));
943-
}
923+
let fec_set_indices =
924+
(0..fec_set_count).map(|i| (slot, (i * DATA_SHREDS_PER_FEC_BLOCK) as u32));
925+
let keys = self.merkle_root_meta_cf.multi_get_keys(fec_set_indices);
926+
let mut merkle_tree_leaves = self
927+
.merkle_root_meta_cf
928+
.multi_get_bytes(&keys)
929+
.map(|get_result| {
930+
let bytes = get_result
931+
.expect("Blockstore operations must succeed")
932+
.expect("Merkle root meta must exist for all fec sets in full slot");
933+
let merkle_root = bincode::deserialize::<MerkleRootMeta>(bytes.as_ref())
934+
.expect("Merkle root meta column only contains valid MerkleRootMetas")
935+
.merkle_root()
936+
.expect("Legacy shreds no longer exist, merkle root must be present");
937+
Ok(merkle_root)
938+
})
939+
.collect::<Vec<_>>();
944940

945941
// Add parent info as the last leaf
946942
let parent_info_hash = hashv(&[
@@ -950,9 +946,8 @@ impl Blockstore {
950946
merkle_tree_leaves.push(Ok(parent_info_hash));
951947

952948
// Build the merkle tree
953-
let merkle_tree = make_merkle_tree(merkle_tree_leaves).map_err(|_| {
954-
BlockstoreProcessorError::FailedDoubleMerkleRootConstruction(slot, block_location)
955-
})?;
949+
let merkle_tree = make_merkle_tree(merkle_tree_leaves)
950+
.expect("Merkle tree construction cannot have failed");
956951
let double_merkle_root = *merkle_tree
957952
.last()
958953
.expect("Merkle tree cannot be empty as fec_set_count is > 0");
@@ -964,20 +959,16 @@ impl Blockstore {
964959
for leaf_index in 0..tree_size {
965960
let proof_iter = make_merkle_proof(leaf_index, tree_size, &merkle_tree);
966961
let proof: Vec<u8> = proof_iter
967-
.map(|proof| proof.map(|p| p.as_slice()))
968-
.collect::<std::result::Result<Vec<_>, _>>()
969-
.map_err(|_| {
970-
BlockstoreProcessorError::FailedDoubleMerkleRootConstruction(
971-
slot,
972-
block_location,
973-
)
974-
})?
975-
.into_iter()
976-
.flatten()
962+
.flat_map(|proof| {
963+
proof
964+
.expect("Merkle proof construction cannot have failed")
965+
.as_slice()
966+
})
977967
.copied()
978968
.collect();
979-
debug_assert!(
980-
proof.len() == get_proof_size(tree_size) as usize * SIZE_OF_MERKLE_PROOF_ENTRY
969+
debug_assert_eq!(
970+
proof.len(),
971+
get_proof_size(tree_size) as usize * SIZE_OF_MERKLE_PROOF_ENTRY
981972
);
982973
proofs.push(proof);
983974
}
@@ -993,7 +984,7 @@ impl Blockstore {
993984
.put((slot, block_location), &double_merkle_meta)
994985
.expect("Blockstore operations must succeed");
995986

996-
Ok(double_merkle_root)
987+
Some(double_merkle_root)
997988
}
998989

999990
/// Check whether the specified slot is an orphan slot which does not
@@ -12929,7 +12920,7 @@ pub mod tests {
1292912920
}
1293012921

1293112922
#[test]
12932-
fn test_get_or_compute_double_merkle_root() {
12923+
fn test_get_double_merkle_root() {
1293312924
let ledger_path = get_tmp_ledger_path_auto_delete!();
1293412925
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
1293512926

@@ -12971,7 +12962,7 @@ pub mod tests {
1297112962
// Test getting the double merkle root
1297212963
let block_location = BlockLocation::Original;
1297312964
let double_merkle_root = blockstore
12974-
.get_or_compute_double_merkle_root(slot, block_location)
12965+
.get_double_merkle_root(slot, block_location)
1297512966
.unwrap();
1297612967

1297712968
let double_merkle_meta = blockstore
@@ -13035,14 +13026,8 @@ pub mod tests {
1303513026
assert!(duplicates.is_empty());
1303613027
}
1303713028

13038-
let result = blockstore.get_or_compute_double_merkle_root(incomplete_slot, block_location);
13039-
match result {
13040-
Err(BlockstoreProcessorError::SlotNotFull(slot, loc)) => {
13041-
assert_eq!(slot, incomplete_slot);
13042-
assert_eq!(loc, block_location);
13043-
} // This is the expected error
13044-
Err(e) => panic!("Unexpected error: {e:?}"),
13045-
Ok(_) => panic!("Expected error but got Ok"),
13046-
}
13029+
assert!(blockstore
13030+
.get_double_merkle_root(incomplete_slot, block_location)
13031+
.is_none());
1304713032
}
1304813033
}

ledger/src/blockstore_processor.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use {
22
crate::{
33
block_error::BlockError,
44
blockstore::{Blockstore, BlockstoreError},
5-
blockstore_meta::{BlockLocation, SlotMeta},
5+
blockstore_meta::SlotMeta,
66
entry_notifier_service::{EntryNotification, EntryNotifierSender},
77
leader_schedule_cache::LeaderScheduleCache,
88
transaction_balances::compile_collected_balances,
@@ -845,18 +845,6 @@ pub enum BlockstoreProcessorError {
845845

846846
#[error("block component processor error: {0}")]
847847
BlockComponentProcessor(#[from] BlockComponentProcessorError),
848-
849-
#[error("slot {0} at location {1} not full")]
850-
SlotNotFull(Slot, BlockLocation),
851-
852-
#[error("slot {0} at location {1} missing parent")]
853-
MissingParent(Slot, BlockLocation),
854-
855-
#[error("missing merkle root for slot {0}, index {1}")]
856-
MissingMerkleRoot(Slot, u64),
857-
858-
#[error("double merkle root construction failure for slot {0} at location {1}")]
859-
FailedDoubleMerkleRootConstruction(Slot, BlockLocation),
860848
}
861849

862850
/// Callback for accessing bank state after each slot is confirmed while

0 commit comments

Comments
 (0)