@@ -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}
0 commit comments