1
1
use crate :: blob_verification:: GossipVerifiedBlob ;
2
2
use crate :: block_verification_types:: { AsBlock , RpcBlock } ;
3
3
use crate :: data_column_verification:: CustodyDataColumn ;
4
- use crate :: kzg_utils:: blobs_to_data_column_sidecars ;
4
+ use crate :: kzg_utils:: build_data_column_sidecars ;
5
5
use crate :: observed_operations:: ObservationOutcome ;
6
6
pub use crate :: persisted_beacon_chain:: PersistedBeaconChain ;
7
7
pub use crate :: {
@@ -76,6 +76,11 @@ pub const FORK_NAME_ENV_VAR: &str = "FORK_NAME";
76
76
// Environment variable to read if `ci_logger` feature is enabled.
77
77
pub const CI_LOGGER_DIR_ENV_VAR : & str = "CI_LOGGER_DIR" ;
78
78
79
+ // Pre-computed data column sidecar using a single static blob from:
80
+ // `beacon_node/execution_layer/src/test_utils/fixtures/mainnet/test_blobs_bundle.ssz`
81
+ const TEST_DATA_COLUMN_SIDECARS_SSZ : & [ u8 ] =
82
+ include_bytes ! ( "test_utils/fixtures/test_data_column_sidecars.ssz" ) ;
83
+
79
84
// Default target aggregators to set during testing, this ensures an aggregator at each slot.
80
85
//
81
86
// You should mutate the `ChainSpec` prior to initialising the harness if you would like to use
@@ -2357,26 +2362,19 @@ where
2357
2362
. data_availability_checker
2358
2363
. get_sampling_column_count ( ) ;
2359
2364
2360
- let columns = blob_items
2361
- . map ( |( _proofs, blobs) | {
2362
- blobs_to_data_column_sidecars (
2363
- & blobs. iter ( ) . collect :: < Vec < _ > > ( ) ,
2364
- & block,
2365
- & self . chain . kzg ,
2366
- & self . spec ,
2367
- )
2368
- . map ( |column_sidecars| {
2369
- column_sidecars
2370
- . into_iter ( )
2371
- . take ( sampling_column_count)
2372
- . map ( CustodyDataColumn :: from_asserted_custody)
2373
- . collect :: < Vec < _ > > ( )
2374
- } )
2375
- } )
2376
- . transpose ( )
2377
- . expect ( "should convert blobs to columns" )
2378
- . unwrap_or_default ( ) ;
2379
- RpcBlock :: new_with_custody_columns ( Some ( block_root) , block, columns, & self . spec ) ?
2365
+ if blob_items. is_some_and ( |( _, blobs) | !blobs. is_empty ( ) ) {
2366
+ // Note: this method ignores the actual custody columns and just take the first
2367
+ // `sampling_column_count` for testing purpose only, because the chain does not
2368
+ // currently have any knowledge of the columns being custodied.
2369
+ let columns = generate_data_column_sidecars_from_block ( & block, & self . spec )
2370
+ . into_iter ( )
2371
+ . take ( sampling_column_count)
2372
+ . map ( CustodyDataColumn :: from_asserted_custody)
2373
+ . collect :: < Vec < _ > > ( ) ;
2374
+ RpcBlock :: new_with_custody_columns ( Some ( block_root) , block, columns, & self . spec ) ?
2375
+ } else {
2376
+ RpcBlock :: new_without_blobs ( Some ( block_root) , block)
2377
+ }
2380
2378
} else {
2381
2379
let blobs = blob_items
2382
2380
. map ( |( proofs, blobs) | {
@@ -3073,21 +3071,15 @@ where
3073
3071
) {
3074
3072
let is_peerdas_enabled = self . chain . spec . is_peer_das_enabled_for_epoch ( block. epoch ( ) ) ;
3075
3073
if is_peerdas_enabled {
3076
- let sidecars = blobs_to_data_column_sidecars (
3077
- & blobs. collect :: < Vec < _ > > ( ) ,
3078
- block,
3079
- & self . chain . kzg ,
3080
- & self . spec ,
3081
- )
3082
- . unwrap ( ) ;
3083
-
3084
3074
let custody_columns = custody_columns_opt. unwrap_or_else ( || {
3085
- let spec = & self . chain . spec ;
3086
- let sampling_size = spec. sampling_size ( spec. custody_requirement ) . unwrap ( ) ;
3087
- ( 0 ..sampling_size) . collect ( )
3075
+ let sampling_column_count = self
3076
+ . chain
3077
+ . data_availability_checker
3078
+ . get_sampling_column_count ( ) as u64 ;
3079
+ ( 0 ..sampling_column_count) . collect ( )
3088
3080
} ) ;
3089
3081
3090
- let verified_columns = sidecars
3082
+ let verified_columns = generate_data_column_sidecars_from_block ( block , & self . spec )
3091
3083
. into_iter ( )
3092
3084
. filter ( |c| custody_columns. contains ( & c. index ) )
3093
3085
. map ( |sidecar| {
@@ -3098,10 +3090,12 @@ where
3098
3090
. collect :: < Result < Vec < _ > , _ > > ( )
3099
3091
. unwrap ( ) ;
3100
3092
3101
- self . chain
3102
- . process_gossip_data_columns ( verified_columns, || Ok ( ( ) ) )
3103
- . await
3104
- . unwrap ( ) ;
3093
+ if !verified_columns. is_empty ( ) {
3094
+ self . chain
3095
+ . process_gossip_data_columns ( verified_columns, || Ok ( ( ) ) )
3096
+ . await
3097
+ . unwrap ( ) ;
3098
+ }
3105
3099
} else {
3106
3100
for ( i, ( kzg_proof, blob) ) in proofs. into_iter ( ) . zip ( blobs) . enumerate ( ) {
3107
3101
let sidecar =
@@ -3300,10 +3294,59 @@ pub fn generate_rand_block_and_data_columns<E: EthSpec>(
3300
3294
SignedBeaconBlock < E , FullPayload < E > > ,
3301
3295
DataColumnSidecarList < E > ,
3302
3296
) {
3303
- let kzg = get_kzg ( spec) ;
3304
- let ( block, blobs) = generate_rand_block_and_blobs ( fork_name, num_blobs, rng, spec) ;
3305
- let blob_refs = blobs. iter ( ) . map ( |b| & b. blob ) . collect :: < Vec < _ > > ( ) ;
3306
- let data_columns = blobs_to_data_column_sidecars ( & blob_refs, & block, & kzg, spec) . unwrap ( ) ;
3307
-
3297
+ let ( block, _blobs) = generate_rand_block_and_blobs ( fork_name, num_blobs, rng, spec) ;
3298
+ let data_columns = generate_data_column_sidecars_from_block ( & block, spec) ;
3308
3299
( block, data_columns)
3309
3300
}
3301
+
3302
+ /// Generate data column sidecars from pre-computed cells and proofs.
3303
+ fn generate_data_column_sidecars_from_block < E : EthSpec > (
3304
+ block : & SignedBeaconBlock < E > ,
3305
+ spec : & ChainSpec ,
3306
+ ) -> DataColumnSidecarList < E > {
3307
+ let kzg_commitments = block. message ( ) . body ( ) . blob_kzg_commitments ( ) . unwrap ( ) ;
3308
+ if kzg_commitments. is_empty ( ) {
3309
+ return vec ! [ ] ;
3310
+ }
3311
+
3312
+ let kzg_commitments_inclusion_proof = block
3313
+ . message ( )
3314
+ . body ( )
3315
+ . kzg_commitments_merkle_proof ( )
3316
+ . unwrap ( ) ;
3317
+ let signed_block_header = block. signed_block_header ( ) ;
3318
+
3319
+ // load the precomputed column sidecar to avoid computing them for every block in the tests.
3320
+ let template_data_columns = RuntimeVariableList :: < DataColumnSidecar < E > > :: from_ssz_bytes (
3321
+ TEST_DATA_COLUMN_SIDECARS_SSZ ,
3322
+ spec. number_of_columns as usize ,
3323
+ )
3324
+ . unwrap ( ) ;
3325
+
3326
+ let ( cells, proofs) = template_data_columns
3327
+ . into_iter ( )
3328
+ . map ( |sidecar| {
3329
+ let DataColumnSidecar {
3330
+ column, kzg_proofs, ..
3331
+ } = sidecar;
3332
+ // There's only one cell per column for a single blob
3333
+ let cell_bytes: Vec < u8 > = column. into_iter ( ) . next ( ) . unwrap ( ) . into ( ) ;
3334
+ let kzg_cell = cell_bytes. try_into ( ) . unwrap ( ) ;
3335
+ let kzg_proof = kzg_proofs. into_iter ( ) . next ( ) . unwrap ( ) ;
3336
+ ( kzg_cell, kzg_proof)
3337
+ } )
3338
+ . collect :: < ( Vec < _ > , Vec < _ > ) > ( ) ;
3339
+
3340
+ // Repeat the cells and proofs for every blob
3341
+ let blob_cells_and_proofs_vec =
3342
+ vec ! [ ( cells. try_into( ) . unwrap( ) , proofs. try_into( ) . unwrap( ) ) ; kzg_commitments. len( ) ] ;
3343
+
3344
+ build_data_column_sidecars (
3345
+ kzg_commitments. clone ( ) ,
3346
+ kzg_commitments_inclusion_proof,
3347
+ signed_block_header,
3348
+ blob_cells_and_proofs_vec,
3349
+ spec,
3350
+ )
3351
+ . unwrap ( )
3352
+ }
0 commit comments