1
+ use crate :: blob_verification:: GossipVerifiedBlob ;
1
2
use crate :: block_verification_types:: { AsBlock , RpcBlock } ;
2
3
use crate :: data_column_verification:: CustodyDataColumn ;
3
4
use crate :: kzg_utils:: blobs_to_data_column_sidecars;
4
5
use crate :: observed_operations:: ObservationOutcome ;
5
6
pub use crate :: persisted_beacon_chain:: PersistedBeaconChain ;
6
- use crate :: BeaconBlockResponseWrapper ;
7
7
pub use crate :: {
8
8
beacon_chain:: { BEACON_CHAIN_DB_KEY , ETH1_CACHE_DB_KEY , FORK_CHOICE_DB_KEY , OP_POOL_DB_KEY } ,
9
9
migrate:: MigratorConfig ,
@@ -17,6 +17,7 @@ use crate::{
17
17
BeaconChain , BeaconChainTypes , BlockError , ChainConfig , ServerSentEventHandler ,
18
18
StateSkipConfig ,
19
19
} ;
20
+ use crate :: { get_block_root, BeaconBlockResponseWrapper } ;
20
21
use bls:: get_withdrawal_credentials;
21
22
use eth2:: types:: SignedBlockContentsTuple ;
22
23
use execution_layer:: test_utils:: generate_genesis_header;
@@ -756,15 +757,13 @@ where
756
757
pub fn get_head_block ( & self ) -> RpcBlock < E > {
757
758
let block = self . chain . head_beacon_block ( ) ;
758
759
let block_root = block. canonical_root ( ) ;
759
- let blobs = self . chain . get_blobs ( & block_root) . unwrap ( ) . blobs ( ) ;
760
- RpcBlock :: new ( Some ( block_root) , block, blobs) . unwrap ( )
760
+ self . build_rpc_block_from_store_blobs ( Some ( block_root) , block)
761
761
}
762
762
763
763
pub fn get_full_block ( & self , block_root : & Hash256 ) -> RpcBlock < E > {
764
764
let block = self . chain . get_blinded_block ( block_root) . unwrap ( ) . unwrap ( ) ;
765
765
let full_block = self . chain . store . make_full_block ( block_root, block) . unwrap ( ) ;
766
- let blobs = self . chain . get_blobs ( block_root) . unwrap ( ) . blobs ( ) ;
767
- RpcBlock :: new ( Some ( * block_root) , Arc :: new ( full_block) , blobs) . unwrap ( )
766
+ self . build_rpc_block_from_store_blobs ( Some ( * block_root) , Arc :: new ( full_block) )
768
767
}
769
768
770
769
pub fn get_all_validators ( & self ) -> Vec < usize > {
@@ -2265,7 +2264,7 @@ where
2265
2264
self . set_current_slot ( slot) ;
2266
2265
let ( block, blob_items) = block_contents;
2267
2266
2268
- let rpc_block = self . build_rpc_block ( block_root, block, blob_items) ?;
2267
+ let rpc_block = self . build_rpc_block_from_blobs ( block_root, block, blob_items) ?;
2269
2268
let block_hash: SignedBeaconBlockHash = self
2270
2269
. chain
2271
2270
. process_block (
@@ -2289,7 +2288,7 @@ where
2289
2288
let ( block, blob_items) = block_contents;
2290
2289
2291
2290
let block_root = block. canonical_root ( ) ;
2292
- let rpc_block = self . build_rpc_block ( block_root, block, blob_items) ?;
2291
+ let rpc_block = self . build_rpc_block_from_blobs ( block_root, block, blob_items) ?;
2293
2292
let block_hash: SignedBeaconBlockHash = self
2294
2293
. chain
2295
2294
. process_block (
@@ -2306,13 +2305,51 @@ where
2306
2305
Ok ( block_hash)
2307
2306
}
2308
2307
2309
- fn build_rpc_block (
2308
+ /// Builds an `Rpc` block from a `SignedBeaconBlock` and blobs or data columns retrieved from
2309
+ /// the database.
2310
+ pub fn build_rpc_block_from_store_blobs (
2311
+ & self ,
2312
+ block_root : Option < Hash256 > ,
2313
+ block : Arc < SignedBeaconBlock < E > > ,
2314
+ ) -> RpcBlock < E > {
2315
+ let block_root = block_root. unwrap_or_else ( || get_block_root ( & block) ) ;
2316
+ let has_blobs = block
2317
+ . message ( )
2318
+ . body ( )
2319
+ . blob_kzg_commitments ( )
2320
+ . is_ok_and ( |c| !c. is_empty ( ) ) ;
2321
+ if !has_blobs {
2322
+ return RpcBlock :: new_without_blobs ( Some ( block_root) , block) ;
2323
+ }
2324
+
2325
+ // Blobs are stored as data columns from Fulu (PeerDAS)
2326
+ if self . spec . is_peer_das_enabled_for_epoch ( block. epoch ( ) ) {
2327
+ let columns = self . chain . get_data_columns ( & block_root) . unwrap ( ) . unwrap ( ) ;
2328
+ let custody_columns = columns
2329
+ . into_iter ( )
2330
+ . map ( CustodyDataColumn :: from_asserted_custody)
2331
+ . collect :: < Vec < _ > > ( ) ;
2332
+ RpcBlock :: new_with_custody_columns ( Some ( block_root) , block, custody_columns, & self . spec )
2333
+ . unwrap ( )
2334
+ } else {
2335
+ let blobs = self . chain . get_blobs ( & block_root) . unwrap ( ) . blobs ( ) ;
2336
+ RpcBlock :: new ( Some ( block_root) , block, blobs) . unwrap ( )
2337
+ }
2338
+ }
2339
+
2340
+ /// Builds an `RpcBlock` from a `SignedBeaconBlock` and `BlobsList`.
2341
+ fn build_rpc_block_from_blobs (
2310
2342
& self ,
2311
2343
block_root : Hash256 ,
2312
2344
block : Arc < SignedBeaconBlock < E , FullPayload < E > > > ,
2313
2345
blob_items : Option < ( KzgProofs < E > , BlobsList < E > ) > ,
2314
2346
) -> Result < RpcBlock < E > , BlockError > {
2315
2347
Ok ( if self . spec . is_peer_das_enabled_for_epoch ( block. epoch ( ) ) {
2348
+ let sampling_column_count = self
2349
+ . chain
2350
+ . data_availability_checker
2351
+ . get_sampling_column_count ( ) ;
2352
+
2316
2353
let columns = blob_items
2317
2354
. map ( |( _proofs, blobs) | {
2318
2355
blobs_to_data_column_sidecars (
@@ -2324,6 +2361,7 @@ where
2324
2361
. map ( |column_sidecars| {
2325
2362
column_sidecars
2326
2363
. into_iter ( )
2364
+ . take ( sampling_column_count)
2327
2365
. map ( CustodyDataColumn :: from_asserted_custody)
2328
2366
. collect :: < Vec < _ > > ( )
2329
2367
} )
@@ -3016,6 +3054,56 @@ where
3016
3054
3017
3055
Ok ( ( ) )
3018
3056
}
3057
+
3058
+ /// Simulate some of the blobs / data columns being seen on gossip.
3059
+ /// Converts the blobs to data columns if the slot is Fulu or later.
3060
+ pub async fn process_gossip_blobs_or_columns < ' a > (
3061
+ & self ,
3062
+ block : & SignedBeaconBlock < E > ,
3063
+ blobs : impl Iterator < Item = & ' a Blob < E > > ,
3064
+ proofs : impl Iterator < Item = & ' a KzgProof > ,
3065
+ custody_columns_opt : Option < HashSet < ColumnIndex > > ,
3066
+ ) {
3067
+ let is_peerdas_enabled = self . chain . spec . is_peer_das_enabled_for_epoch ( block. epoch ( ) ) ;
3068
+ if is_peerdas_enabled {
3069
+ let sidecars = blobs_to_data_column_sidecars (
3070
+ & blobs. collect :: < Vec < _ > > ( ) ,
3071
+ block,
3072
+ & self . chain . kzg ,
3073
+ & self . spec ,
3074
+ )
3075
+ . unwrap ( ) ;
3076
+
3077
+ let custody_columns = custody_columns_opt. unwrap_or_else ( || {
3078
+ let spec = & self . chain . spec ;
3079
+ let sampling_size = spec. sampling_size ( spec. custody_requirement ) . unwrap ( ) ;
3080
+ ( 0 ..sampling_size) . collect ( )
3081
+ } ) ;
3082
+
3083
+ let verified_columns = sidecars
3084
+ . into_iter ( )
3085
+ . filter ( |c| custody_columns. contains ( & c. index ) )
3086
+ . map ( |sidecar| {
3087
+ let column_index = sidecar. index ;
3088
+ self . chain
3089
+ . verify_data_column_sidecar_for_gossip ( sidecar, column_index)
3090
+ } )
3091
+ . collect :: < Result < Vec < _ > , _ > > ( )
3092
+ . unwrap ( ) ;
3093
+
3094
+ self . chain
3095
+ . process_gossip_data_columns ( verified_columns, || Ok ( ( ) ) )
3096
+ . await
3097
+ . unwrap ( ) ;
3098
+ } else {
3099
+ for ( i, ( kzg_proof, blob) ) in proofs. into_iter ( ) . zip ( blobs) . enumerate ( ) {
3100
+ let sidecar =
3101
+ Arc :: new ( BlobSidecar :: new ( i, blob. clone ( ) , block, * kzg_proof) . unwrap ( ) ) ;
3102
+ let gossip_blob = GossipVerifiedBlob :: new ( sidecar, i as u64 , & self . chain ) . unwrap ( ) ;
3103
+ self . chain . process_gossip_blob ( gossip_blob) . await . unwrap ( ) ;
3104
+ }
3105
+ }
3106
+ }
3019
3107
}
3020
3108
3021
3109
// Junk `Debug` impl to satistfy certain trait bounds during testing.
0 commit comments