Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c0901b6
Add SSZ requests to get head and post blinded payload
eserilev Jan 21, 2025
09c2cde
Add ssz decoding to builder bid
eserilev Jan 21, 2025
3b5c710
TODO: ssz decoding for FullPayloadContents
eserilev Jan 21, 2025
05c45da
Add SSZ decoding to payload blobs and bundle
eserilev Jan 21, 2025
de9a77d
DecodeWithFork trait
eserilev Jan 23, 2025
9238caa
Use data column batch verification consistently
dapplion Jan 20, 2025
7d524e5
add decode by fork trait
eserilev Jan 24, 2025
82765e8
add decode by fork trait
eserilev Jan 24, 2025
098d5b5
add encode to signed builder bid
eserilev Jan 24, 2025
6e664dc
merge conflicts
eserilev Jan 24, 2025
3876806
Add ssz to mock builder
eserilev Jan 24, 2025
a2f8dd1
TODOs
eserilev Jan 26, 2025
679a3a4
Add SSZ
eserilev Jan 27, 2025
2c180e5
Fix tests
eserilev Jan 27, 2025
f76b65a
cargo sort
eserilev Jan 27, 2025
c5b60d2
use accept header
eserilev Jan 27, 2025
eeca505
FMT
eserilev Jan 27, 2025
34713e1
progress
eserilev Jan 30, 2025
2a7f0f8
Subscribe to peerdas topics on Fulu fork
dapplion Jan 23, 2025
521cdd5
avoid double iteration by using lifetimes
jxs Jan 27, 2025
43ae790
Add fulu test
dapplion Jan 31, 2025
d77ce79
Penalize all invalid columns not only the first invalid
dapplion Feb 1, 2025
95c024f
fix tests
eserilev Feb 1, 2025
5fc89e4
revert
eserilev Feb 1, 2025
df16f95
refactor
eserilev Feb 1, 2025
3eee2d1
Minor cleanups
michaelsproul Feb 3, 2025
bc2a99a
Merge of #6849
mergify[bot] Feb 3, 2025
19adc85
Merge of #6859
mergify[bot] Feb 3, 2025
f5bb888
Merge of #6851
mergify[bot] Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 14 additions & 43 deletions beacon_node/beacon_chain/src/data_availability_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ mod overflow_lru_cache;
mod state_lru_cache;

use crate::data_column_verification::{
verify_kzg_for_data_column, verify_kzg_for_data_column_list, CustodyDataColumn,
GossipVerifiedDataColumn, KzgVerifiedCustodyDataColumn, KzgVerifiedDataColumn,
verify_kzg_for_data_column_list_with_scoring, CustodyDataColumn, GossipVerifiedDataColumn,
KzgVerifiedCustodyDataColumn, KzgVerifiedDataColumn,
};
use crate::metrics::{
KZG_DATA_COLUMN_RECONSTRUCTION_ATTEMPTS, KZG_DATA_COLUMN_RECONSTRUCTION_FAILURES,
Expand Down Expand Up @@ -230,19 +230,14 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
block_root: Hash256,
custody_columns: DataColumnSidecarList<T::EthSpec>,
) -> Result<Availability<T::EthSpec>, AvailabilityCheckError> {
// TODO(das): report which column is invalid for proper peer scoring
// TODO(das): batch KZG verification here, but fallback into checking each column
// individually to report which column(s) are invalid.
let verified_custody_columns = custody_columns
// Attributes fault to the specific peer that sent an invalid column
let kzg_verified_columns = KzgVerifiedDataColumn::from_batch(custody_columns, &self.kzg)
.map_err(AvailabilityCheckError::InvalidColumn)?;

let verified_custody_columns = kzg_verified_columns
.into_iter()
.map(|column| {
let index = column.index;
Ok(KzgVerifiedCustodyDataColumn::from_asserted_custody(
KzgVerifiedDataColumn::new(column, &self.kzg)
.map_err(|e| AvailabilityCheckError::InvalidColumn(index, e))?,
))
})
.collect::<Result<Vec<_>, AvailabilityCheckError>>()?;
.map(KzgVerifiedCustodyDataColumn::from_asserted_custody)
.collect::<Vec<_>>();

self.availability_cache.put_kzg_verified_data_columns(
block_root,
Expand Down Expand Up @@ -365,7 +360,8 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {
.iter()
.map(|custody_column| custody_column.as_data_column()),
&self.kzg,
)?;
)
.map_err(AvailabilityCheckError::InvalidColumn)?;
Ok(MaybeAvailableBlock::Available(AvailableBlock {
block_root,
block,
Expand Down Expand Up @@ -432,8 +428,9 @@ impl<T: BeaconChainTypes> DataAvailabilityChecker<T> {

// verify kzg for all data columns at once
if !all_data_columns.is_empty() {
// TODO: Need to also attribute which specific block is faulty
verify_kzg_for_data_column_list_with_scoring(all_data_columns.iter(), &self.kzg)?;
// Attributes fault to the specific peer that sent an invalid column
verify_kzg_for_data_column_list_with_scoring(all_data_columns.iter(), &self.kzg)
.map_err(AvailabilityCheckError::InvalidColumn)?;
}

for block in blocks {
Expand Down Expand Up @@ -716,32 +713,6 @@ async fn availability_cache_maintenance_service<T: BeaconChainTypes>(
}
}

fn verify_kzg_for_data_column_list_with_scoring<'a, E: EthSpec, I>(
data_column_iter: I,
kzg: &'a Kzg,
) -> Result<(), AvailabilityCheckError>
where
I: Iterator<Item = &'a Arc<DataColumnSidecar<E>>> + Clone,
{
let Err(batch_err) = verify_kzg_for_data_column_list(data_column_iter.clone(), kzg) else {
return Ok(());
};

let data_columns = data_column_iter.collect::<Vec<_>>();
// Find which column is invalid. If len is 1 or 0 continue to default case below.
// If len > 1 at least one column MUST fail.
if data_columns.len() > 1 {
for data_column in data_columns {
if let Err(e) = verify_kzg_for_data_column(data_column.clone(), kzg) {
return Err(AvailabilityCheckError::InvalidColumn(data_column.index, e));
}
}
}

// len 0 should never happen
Err(AvailabilityCheckError::InvalidColumn(0, batch_err))
}

/// A fully available block that is ready to be imported into fork choice.
#[derive(Clone, Debug, PartialEq)]
pub struct AvailableBlock<E: EthSpec> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use types::{BeaconStateError, ColumnIndex, Hash256};
#[derive(Debug)]
pub enum Error {
InvalidBlobs(KzgError),
InvalidColumn(ColumnIndex, KzgError),
InvalidColumn(Vec<(ColumnIndex, KzgError)>),
ReconstructColumnsError(KzgError),
KzgCommitmentMismatch {
blob_commitment: KzgCommitment,
Expand Down
44 changes: 44 additions & 0 deletions beacon_node/beacon_chain/src/data_column_verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ impl<E: EthSpec> KzgVerifiedDataColumn<E> {
pub fn new(data_column: Arc<DataColumnSidecar<E>>, kzg: &Kzg) -> Result<Self, KzgError> {
verify_kzg_for_data_column(data_column, kzg)
}

pub fn from_batch(
data_columns: Vec<Arc<DataColumnSidecar<E>>>,
kzg: &Kzg,
) -> Result<Vec<Self>, Vec<(ColumnIndex, KzgError)>> {
verify_kzg_for_data_column_list_with_scoring(data_columns.iter(), kzg)?;
Ok(data_columns
.into_iter()
.map(|column| Self { data: column })
.collect())
}

pub fn to_data_column(self) -> Arc<DataColumnSidecar<E>> {
self.data
}
Expand Down Expand Up @@ -378,6 +390,38 @@ where
Ok(())
}

/// Complete kzg verification for a list of `DataColumnSidecar`s.
///
/// If there's at least one invalid column, it re-verifies all columns individually to identify the
/// first column that is invalid. This is necessary to attribute fault to the specific peer that
/// sent bad data. The re-verification cost should not be significant. If a peer sends invalid data it
/// will be quickly banned.
pub fn verify_kzg_for_data_column_list_with_scoring<'a, E: EthSpec, I>(
data_column_iter: I,
kzg: &'a Kzg,
) -> Result<(), Vec<(ColumnIndex, KzgError)>>
where
I: Iterator<Item = &'a Arc<DataColumnSidecar<E>>> + Clone,
{
if verify_kzg_for_data_column_list(data_column_iter.clone(), kzg).is_ok() {
return Ok(());
};

// Find all columns that are invalid and identify by index. If we hit this condition there
// should be at least one invalid column
let errors = data_column_iter
.filter_map(|data_column| {
if let Err(e) = verify_kzg_for_data_column(data_column.clone(), kzg) {
Some((data_column.index, e))
} else {
None
}
})
.collect::<Vec<_>>();

Err(errors)
}

pub fn validate_data_column_sidecar_for_gossip<T: BeaconChainTypes, O: ObservationStrategy>(
data_column: Arc<DataColumnSidecar<T::EthSpec>>,
subnet: u64,
Expand Down
2 changes: 2 additions & 0 deletions beacon_node/builder_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ authors = ["Sean Anderson <sean@sigmaprime.io>"]

[dependencies]
eth2 = { workspace = true }
ethereum_ssz = { workspace = true }
lighthouse_version = { workspace = true }
reqwest = { workspace = true }
sensitive_url = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
Loading