Skip to content

Commit a9c2f78

Browse files
committed
Merge remote-tracking branch 'origin/unstable' into keep-execution-payload
2 parents 9d85619 + 87b72de commit a9c2f78

File tree

10 files changed

+240
-48
lines changed

10 files changed

+240
-48
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
beacon_node/network/ @jxs
2+
beacon_node/lighthouse_network/ @jxs

.github/workflows/test-suite.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ jobs:
350350
- name: Check formatting with cargo fmt
351351
run: make cargo-fmt
352352
- name: Lint code for quality and style with Clippy
353-
run: make lint
353+
run: make lint-full
354354
- name: Certify Cargo.lock freshness
355355
run: git diff --exit-code Cargo.lock
356356
- name: Typecheck benchmark code without running it

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ test-full: cargo-fmt test-release test-debug test-ef test-exec-engine
204204
# Lints the code for bad style and potentially unsafe arithmetic using Clippy.
205205
# Clippy lints are opt-in per-crate for now. By default, everything is allowed except for performance and correctness lints.
206206
lint:
207-
RUSTFLAGS="-C debug-assertions=no $(RUSTFLAGS)" cargo clippy --workspace --benches --tests $(EXTRA_CLIPPY_OPTS) --features "$(TEST_FEATURES)" -- \
207+
cargo clippy --workspace --benches --tests $(EXTRA_CLIPPY_OPTS) --features "$(TEST_FEATURES)" -- \
208208
-D clippy::fn_to_numeric_cast_any \
209209
-D clippy::manual_let_else \
210210
-D clippy::large_stack_frames \
@@ -220,6 +220,10 @@ lint:
220220
lint-fix:
221221
EXTRA_CLIPPY_OPTS="--fix --allow-staged --allow-dirty" $(MAKE) lint
222222

223+
# Also run the lints on the optimized-only tests
224+
lint-full:
225+
RUSTFLAGS="-C debug-assertions=no $(RUSTFLAGS)" $(MAKE) lint
226+
223227
# Runs the makefile in the `ef_tests` repo.
224228
#
225229
# May download and extract an archive of test vectors from the ethereum

beacon_node/beacon_chain/src/kzg_utils.rs

Lines changed: 132 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use std::sync::Arc;
77
use types::beacon_block_body::KzgCommitments;
88
use types::data_column_sidecar::{Cell, DataColumn, DataColumnSidecarError};
99
use types::{
10-
Blob, ChainSpec, ColumnIndex, DataColumnSidecar, DataColumnSidecarList, EthSpec, Hash256,
11-
KzgCommitment, KzgProof, KzgProofs, SignedBeaconBlock, SignedBeaconBlockHeader,
10+
Blob, BlobSidecar, BlobSidecarList, ChainSpec, ColumnIndex, DataColumnSidecar,
11+
DataColumnSidecarList, EthSpec, Hash256, KzgCommitment, KzgProof, KzgProofs, SignedBeaconBlock,
12+
SignedBeaconBlockHeader, SignedBlindedBeaconBlock,
1213
};
1314

1415
/// Converts a blob ssz List object to an array to be used with the kzg
@@ -243,6 +244,83 @@ fn build_data_column_sidecars<E: EthSpec>(
243244
Ok(sidecars)
244245
}
245246

247+
/// Reconstruct blobs from a subset of data column sidecars (requires at least 50%).
248+
///
249+
/// If `blob_indices_opt` is `None`, this function attempts to reconstruct all blobs associated
250+
/// with the block.
251+
pub fn reconstruct_blobs<E: EthSpec>(
252+
kzg: &Kzg,
253+
data_columns: &[Arc<DataColumnSidecar<E>>],
254+
blob_indices_opt: Option<Vec<u64>>,
255+
signed_block: &SignedBlindedBeaconBlock<E>,
256+
) -> Result<BlobSidecarList<E>, String> {
257+
// The data columns are from the database, so we assume their correctness.
258+
let first_data_column = data_columns
259+
.first()
260+
.ok_or("data_columns should have at least one element".to_string())?;
261+
262+
let blob_indices: Vec<usize> = match blob_indices_opt {
263+
Some(indices) => indices.into_iter().map(|i| i as usize).collect(),
264+
None => {
265+
let num_of_blobs = first_data_column.kzg_commitments.len();
266+
(0..num_of_blobs).collect()
267+
}
268+
};
269+
270+
let blob_sidecars = blob_indices
271+
.into_par_iter()
272+
.map(|row_index| {
273+
let mut cells: Vec<KzgCellRef> = vec![];
274+
let mut cell_ids: Vec<u64> = vec![];
275+
for data_column in data_columns {
276+
let cell = data_column
277+
.column
278+
.get(row_index)
279+
.ok_or(format!("Missing data column at row index {row_index}"))
280+
.and_then(|cell| {
281+
ssz_cell_to_crypto_cell::<E>(cell).map_err(|e| format!("{e:?}"))
282+
})?;
283+
284+
cells.push(cell);
285+
cell_ids.push(data_column.index);
286+
}
287+
288+
let (cells, _kzg_proofs) = kzg
289+
.recover_cells_and_compute_kzg_proofs(&cell_ids, &cells)
290+
.map_err(|e| format!("Failed to recover cells and compute KZG proofs: {e:?}"))?;
291+
292+
let num_cells_original_blob = cells.len() / 2;
293+
let blob_bytes = cells
294+
.into_iter()
295+
.take(num_cells_original_blob)
296+
.flat_map(|cell| cell.into_iter())
297+
.collect();
298+
299+
let blob = Blob::<E>::new(blob_bytes).map_err(|e| format!("{e:?}"))?;
300+
let kzg_commitment = first_data_column
301+
.kzg_commitments
302+
.get(row_index)
303+
.ok_or(format!("Missing KZG commitment for blob {row_index}"))?;
304+
let kzg_proof = compute_blob_kzg_proof::<E>(kzg, &blob, *kzg_commitment)
305+
.map_err(|e| format!("{e:?}"))?;
306+
307+
BlobSidecar::<E>::new_with_existing_proof(
308+
row_index,
309+
blob,
310+
signed_block,
311+
first_data_column.signed_block_header.clone(),
312+
&first_data_column.kzg_commitments_inclusion_proof,
313+
kzg_proof,
314+
)
315+
.map(Arc::new)
316+
.map_err(|e| format!("{e:?}"))
317+
})
318+
.collect::<Result<Vec<_>, _>>()?
319+
.into();
320+
321+
Ok(blob_sidecars)
322+
}
323+
246324
/// Reconstruct all data columns from a subset of data column sidecars (requires at least 50%).
247325
pub fn reconstruct_data_columns<E: EthSpec>(
248326
kzg: &Kzg,
@@ -265,7 +343,7 @@ pub fn reconstruct_data_columns<E: EthSpec>(
265343
for data_column in data_columns {
266344
let cell = data_column.column.get(row_index).ok_or(
267345
KzgError::InconsistentArrayLength(format!(
268-
"Missing data column at index {row_index}"
346+
"Missing data column at row index {row_index}"
269347
)),
270348
)?;
271349

@@ -289,12 +367,16 @@ pub fn reconstruct_data_columns<E: EthSpec>(
289367

290368
#[cfg(test)]
291369
mod test {
292-
use crate::kzg_utils::{blobs_to_data_column_sidecars, reconstruct_data_columns};
370+
use crate::kzg_utils::{
371+
blobs_to_data_column_sidecars, reconstruct_blobs, reconstruct_data_columns,
372+
};
293373
use bls::Signature;
374+
use eth2::types::BlobsBundle;
375+
use execution_layer::test_utils::generate_blobs;
294376
use kzg::{trusted_setup::get_trusted_setup, Kzg, KzgCommitment, TrustedSetup};
295377
use types::{
296-
beacon_block_body::KzgCommitments, BeaconBlock, BeaconBlockDeneb, Blob, BlobsList,
297-
ChainSpec, EmptyBlock, EthSpec, MainnetEthSpec, SignedBeaconBlock,
378+
beacon_block_body::KzgCommitments, BeaconBlock, BeaconBlockDeneb, BlobsList, ChainSpec,
379+
EmptyBlock, EthSpec, MainnetEthSpec, SignedBeaconBlock,
298380
};
299381

300382
type E = MainnetEthSpec;
@@ -308,6 +390,7 @@ mod test {
308390
test_build_data_columns_empty(&kzg, &spec);
309391
test_build_data_columns(&kzg, &spec);
310392
test_reconstruct_data_columns(&kzg, &spec);
393+
test_reconstruct_blobs_from_data_columns(&kzg, &spec);
311394
}
312395

313396
#[track_caller]
@@ -379,6 +462,36 @@ mod test {
379462
}
380463
}
381464

465+
#[track_caller]
466+
fn test_reconstruct_blobs_from_data_columns(kzg: &Kzg, spec: &ChainSpec) {
467+
let num_of_blobs = 6;
468+
let (signed_block, blobs) = create_test_block_and_blobs::<E>(num_of_blobs, spec);
469+
let blob_refs = blobs.iter().collect::<Vec<_>>();
470+
let column_sidecars =
471+
blobs_to_data_column_sidecars(&blob_refs, &signed_block, kzg, spec).unwrap();
472+
473+
// Now reconstruct
474+
let signed_blinded_block = signed_block.into();
475+
let blob_indices = vec![3, 4, 5];
476+
let reconstructed_blobs = reconstruct_blobs(
477+
kzg,
478+
&column_sidecars.iter().as_slice()[0..column_sidecars.len() / 2],
479+
Some(blob_indices.clone()),
480+
&signed_blinded_block,
481+
)
482+
.unwrap();
483+
484+
for i in blob_indices {
485+
let reconstructed_blob = &reconstructed_blobs
486+
.iter()
487+
.find(|sidecar| sidecar.index == i)
488+
.map(|sidecar| sidecar.blob.clone())
489+
.expect("reconstructed blob should exist");
490+
let original_blob = blobs.get(i as usize).unwrap();
491+
assert_eq!(reconstructed_blob, original_blob, "{i}");
492+
}
493+
}
494+
382495
fn get_kzg() -> Kzg {
383496
let trusted_setup: TrustedSetup = serde_json::from_reader(get_trusted_setup().as_slice())
384497
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
@@ -397,12 +510,20 @@ mod test {
397510
KzgCommitments::<E>::new(vec![KzgCommitment::empty_for_testing(); num_of_blobs])
398511
.unwrap();
399512

400-
let signed_block = SignedBeaconBlock::from_block(block, Signature::empty());
513+
let mut signed_block = SignedBeaconBlock::from_block(block, Signature::empty());
514+
515+
let (blobs_bundle, _) = generate_blobs::<E>(num_of_blobs).unwrap();
516+
let BlobsBundle {
517+
blobs,
518+
commitments,
519+
proofs: _,
520+
} = blobs_bundle;
401521

402-
let blobs = (0..num_of_blobs)
403-
.map(|_| Blob::<E>::default())
404-
.collect::<Vec<_>>()
405-
.into();
522+
*signed_block
523+
.message_mut()
524+
.body_mut()
525+
.blob_kzg_commitments_mut()
526+
.unwrap() = commitments;
406527

407528
(signed_block, blobs)
408529
}

beacon_node/beacon_chain/src/metrics.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ pub static BLOB_SIDECAR_INCLUSION_PROOF_COMPUTATION: LazyLock<Result<Histogram>>
16561656
});
16571657
pub static DATA_COLUMN_SIDECAR_COMPUTATION: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
16581658
try_create_histogram_vec_with_buckets(
1659-
"data_column_sidecar_computation_seconds",
1659+
"beacon_data_column_sidecar_computation_seconds",
16601660
"Time taken to compute data column sidecar, including cells, proofs and inclusion proof",
16611661
Ok(vec![0.1, 0.15, 0.25, 0.35, 0.5, 0.7, 1.0, 2.5, 5.0, 10.0]),
16621662
&["blob_count"],
@@ -1665,7 +1665,7 @@ pub static DATA_COLUMN_SIDECAR_COMPUTATION: LazyLock<Result<HistogramVec>> = Laz
16651665
pub static DATA_COLUMN_SIDECAR_INCLUSION_PROOF_VERIFICATION: LazyLock<Result<Histogram>> =
16661666
LazyLock::new(|| {
16671667
try_create_histogram(
1668-
"data_column_sidecar_inclusion_proof_verification_seconds",
1668+
"beacon_data_column_sidecar_inclusion_proof_verification_seconds",
16691669
"Time taken to verify data_column sidecar inclusion proof",
16701670
)
16711671
});
@@ -1693,7 +1693,7 @@ pub static DATA_COLUMN_SIDECAR_GOSSIP_VERIFICATION_TIMES: LazyLock<Result<Histog
16931693
pub static DATA_COLUMNS_SIDECAR_PROCESSING_SUCCESSES: LazyLock<Result<IntCounter>> =
16941694
LazyLock::new(|| {
16951695
try_create_int_counter(
1696-
"beacon_blobs_column_sidecar_processing_successes_total",
1696+
"beacon_data_column_sidecar_processing_successes_total",
16971697
"Number of data column sidecars verified for gossip",
16981698
)
16991699
});
@@ -1847,7 +1847,7 @@ pub static KZG_VERIFICATION_BATCH_TIMES: LazyLock<Result<Histogram>> = LazyLock:
18471847
pub static KZG_VERIFICATION_DATA_COLUMN_SINGLE_TIMES: LazyLock<Result<Histogram>> =
18481848
LazyLock::new(|| {
18491849
try_create_histogram_with_buckets(
1850-
"kzg_verification_data_column_single_seconds",
1850+
"beacon_kzg_verification_data_column_single_seconds",
18511851
"Runtime of single data column kzg verification",
18521852
Ok(vec![
18531853
0.0005, 0.001, 0.0015, 0.002, 0.003, 0.004, 0.005, 0.007, 0.01, 0.02, 0.05,
@@ -1857,7 +1857,7 @@ pub static KZG_VERIFICATION_DATA_COLUMN_SINGLE_TIMES: LazyLock<Result<Histogram>
18571857
pub static KZG_VERIFICATION_DATA_COLUMN_BATCH_TIMES: LazyLock<Result<Histogram>> =
18581858
LazyLock::new(|| {
18591859
try_create_histogram_with_buckets(
1860-
"kzg_verification_data_column_batch_seconds",
1860+
"beacon_kzg_verification_data_column_batch_seconds",
18611861
"Runtime of batched data column kzg verification",
18621862
Ok(vec![
18631863
0.002, 0.004, 0.006, 0.008, 0.01, 0.012, 0.015, 0.02, 0.03, 0.05, 0.07,
@@ -1910,38 +1910,38 @@ pub static DATA_AVAILABILITY_OVERFLOW_STORE_CACHE_SIZE: LazyLock<Result<IntGauge
19101910
pub static DATA_AVAILABILITY_RECONSTRUCTION_TIME: LazyLock<Result<Histogram>> =
19111911
LazyLock::new(|| {
19121912
try_create_histogram(
1913-
"data_availability_reconstruction_time_seconds",
1913+
"beacon_data_availability_reconstruction_time_seconds",
19141914
"Time taken to reconstruct columns",
19151915
)
19161916
});
19171917
pub static DATA_AVAILABILITY_RECONSTRUCTED_COLUMNS: LazyLock<Result<IntCounter>> =
19181918
LazyLock::new(|| {
19191919
try_create_int_counter(
1920-
"data_availability_reconstructed_columns_total",
1920+
"beacon_data_availability_reconstructed_columns_total",
19211921
"Total count of reconstructed columns",
19221922
)
19231923
});
19241924

19251925
pub static KZG_DATA_COLUMN_RECONSTRUCTION_ATTEMPTS: LazyLock<Result<IntCounter>> =
19261926
LazyLock::new(|| {
19271927
try_create_int_counter(
1928-
"kzg_data_column_reconstruction_attempts",
1928+
"beacon_kzg_data_column_reconstruction_attempts",
19291929
"Count of times data column reconstruction has been attempted",
19301930
)
19311931
});
19321932

19331933
pub static KZG_DATA_COLUMN_RECONSTRUCTION_FAILURES: LazyLock<Result<IntCounter>> =
19341934
LazyLock::new(|| {
19351935
try_create_int_counter(
1936-
"kzg_data_column_reconstruction_failures",
1936+
"beacon_kzg_data_column_reconstruction_failures",
19371937
"Count of times data column reconstruction has failed",
19381938
)
19391939
});
19401940

19411941
pub static KZG_DATA_COLUMN_RECONSTRUCTION_INCOMPLETE_TOTAL: LazyLock<Result<IntCounterVec>> =
19421942
LazyLock::new(|| {
19431943
try_create_int_counter_vec(
1944-
"kzg_data_column_reconstruction_incomplete_total",
1944+
"beacon_kzg_data_column_reconstruction_incomplete_total",
19451945
"Count of times data column reconstruction attempts did not result in an import",
19461946
&["reason"],
19471947
)

0 commit comments

Comments
 (0)