Skip to content

Commit 4fbe517

Browse files
authored
Fix data columns sorting when reconstructing blobs (#8510)
Closes #8509 Co-Authored-By: Antoine James <[email protected]>
1 parent f42b14a commit 4fbe517

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
12481248
let num_required_columns = T::EthSpec::number_of_columns() / 2;
12491249
let reconstruction_possible = columns.len() >= num_required_columns;
12501250
if reconstruction_possible {
1251-
reconstruct_blobs(&self.kzg, &columns, None, &block, &self.spec)
1251+
reconstruct_blobs(&self.kzg, columns, None, &block, &self.spec)
12521252
.map(Some)
12531253
.map_err(Error::FailedToReconstructBlobs)
12541254
} else {

beacon_node/beacon_chain/src/kzg_utils.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,14 @@ pub(crate) fn build_data_column_sidecars<E: EthSpec>(
308308
/// and it will be slow if the node needs to reconstruct the blobs
309309
pub fn reconstruct_blobs<E: EthSpec>(
310310
kzg: &Kzg,
311-
data_columns: &[Arc<DataColumnSidecar<E>>],
311+
mut data_columns: Vec<Arc<DataColumnSidecar<E>>>,
312312
blob_indices_opt: Option<Vec<u64>>,
313313
signed_block: &SignedBlindedBeaconBlock<E>,
314314
spec: &ChainSpec,
315315
) -> Result<BlobSidecarList<E>, String> {
316-
// The data columns are from the database, so we assume their correctness.
316+
// Sort data columns by index to ensure ascending order for KZG operations
317+
data_columns.sort_unstable_by_key(|dc| dc.index);
318+
317319
let first_data_column = data_columns
318320
.first()
319321
.ok_or("data_columns should have at least one element".to_string())?;
@@ -331,7 +333,7 @@ pub fn reconstruct_blobs<E: EthSpec>(
331333
.map(|row_index| {
332334
let mut cells: Vec<KzgCellRef> = vec![];
333335
let mut cell_ids: Vec<u64> = vec![];
334-
for data_column in data_columns {
336+
for data_column in &data_columns {
335337
let cell = data_column
336338
.column
337339
.get(row_index)
@@ -463,6 +465,7 @@ mod test {
463465
test_reconstruct_data_columns(&kzg, &spec);
464466
test_reconstruct_data_columns_unordered(&kzg, &spec);
465467
test_reconstruct_blobs_from_data_columns(&kzg, &spec);
468+
test_reconstruct_blobs_from_data_columns_unordered(&kzg, &spec);
466469
test_validate_data_columns(&kzg, &spec);
467470
}
468471

@@ -595,7 +598,7 @@ mod test {
595598
let blob_indices = vec![1, 2];
596599
let reconstructed_blobs = reconstruct_blobs(
597600
kzg,
598-
&column_sidecars.iter().as_slice()[0..column_sidecars.len() / 2],
601+
column_sidecars[0..column_sidecars.len() / 2].to_vec(),
599602
Some(blob_indices.clone()),
600603
&signed_blinded_block,
601604
spec,
@@ -613,6 +616,31 @@ mod test {
613616
}
614617
}
615618

619+
#[track_caller]
620+
fn test_reconstruct_blobs_from_data_columns_unordered(kzg: &Kzg, spec: &ChainSpec) {
621+
let num_of_blobs = 2;
622+
let (signed_block, blobs, proofs) =
623+
create_test_fulu_block_and_blobs::<E>(num_of_blobs, spec);
624+
let blob_refs = blobs.iter().collect::<Vec<_>>();
625+
let column_sidecars =
626+
blobs_to_data_column_sidecars(&blob_refs, proofs.to_vec(), &signed_block, kzg, spec)
627+
.unwrap();
628+
629+
// Test reconstruction with columns in reverse order (non-ascending)
630+
let mut subset_columns: Vec<_> =
631+
column_sidecars.iter().as_slice()[0..column_sidecars.len() / 2].to_vec();
632+
subset_columns.reverse(); // This would fail without proper sorting in reconstruct_blobs
633+
634+
let signed_blinded_block = signed_block.into();
635+
let reconstructed_blobs =
636+
reconstruct_blobs(kzg, subset_columns, None, &signed_blinded_block, spec).unwrap();
637+
638+
for (i, original_blob) in blobs.iter().enumerate() {
639+
let reconstructed_blob = &reconstructed_blobs.get(i).unwrap().blob;
640+
assert_eq!(reconstructed_blob, original_blob, "{i}");
641+
}
642+
}
643+
616644
fn get_kzg() -> Kzg {
617645
Kzg::new_from_trusted_setup(&get_trusted_setup()).expect("should create kzg")
618646
}

beacon_node/http_api/src/block_id.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ impl BlockId {
474474
)
475475
.collect::<Result<Vec<_>, _>>()?;
476476

477-
reconstruct_blobs(&chain.kzg, &data_columns, blob_indices, block, &chain.spec).map_err(
477+
reconstruct_blobs(&chain.kzg, data_columns, blob_indices, block, &chain.spec).map_err(
478478
|e| {
479479
warp_utils::reject::custom_server_error(format!(
480480
"Error reconstructing data columns: {e:?}"

0 commit comments

Comments
 (0)