Implement PeerDAS Fulu fork activation (#6795)

Addresses #6706


  This PR activates PeerDAS at the Fulu fork epoch instead of `EIP_7594_FORK_EPOCH`. This means we no longer support testing PeerDAS with Deneb / Electrs, as it's now part of a hard fork.
This commit is contained in:
Jimmy Chen
2025-01-30 18:01:34 +11:00
committed by GitHub
parent 7d54a43243
commit 70194dfc6a
54 changed files with 1126 additions and 640 deletions

View File

@@ -339,9 +339,9 @@ mod test {
type E = MainnetEthSpec;
fn make_eip7594_spec() -> ChainSpec {
fn make_fulu_spec() -> ChainSpec {
let mut spec = E::default_spec();
spec.eip7594_fork_epoch = Some(Epoch::new(10));
spec.fulu_fork_epoch = Some(Epoch::new(10));
spec
}
@@ -359,7 +359,7 @@ mod test {
subscribe_all_data_column_subnets: false,
..NetworkConfig::default()
};
let spec = make_eip7594_spec();
let spec = make_fulu_spec();
let enr = build_enr_with_config(config, &spec).0;
@@ -375,7 +375,7 @@ mod test {
subscribe_all_data_column_subnets: true,
..NetworkConfig::default()
};
let spec = make_eip7594_spec();
let spec = make_fulu_spec();
let enr = build_enr_with_config(config, &spec).0;
assert_eq!(

View File

@@ -485,17 +485,9 @@ fn context_bytes<E: EthSpec>(
RpcSuccessResponse::BlobsByRange(_) | RpcSuccessResponse::BlobsByRoot(_) => {
return fork_context.to_context_bytes(ForkName::Deneb);
}
RpcSuccessResponse::DataColumnsByRoot(d)
| RpcSuccessResponse::DataColumnsByRange(d) => {
// TODO(das): Remove deneb fork after `peerdas-devnet-2`.
return if matches!(
fork_context.spec.fork_name_at_slot::<E>(d.slot()),
ForkName::Deneb
) {
fork_context.to_context_bytes(ForkName::Deneb)
} else {
fork_context.to_context_bytes(ForkName::Electra)
};
RpcSuccessResponse::DataColumnsByRoot(_)
| RpcSuccessResponse::DataColumnsByRange(_) => {
return fork_context.to_context_bytes(ForkName::Fulu);
}
RpcSuccessResponse::LightClientBootstrap(lc_bootstrap) => {
return lc_bootstrap
@@ -730,10 +722,7 @@ fn handle_rpc_response<E: EthSpec>(
},
SupportedProtocol::DataColumnsByRootV1 => match fork_name {
Some(fork_name) => {
// TODO(das): PeerDAS is currently supported for both deneb and electra. This check
// does not advertise the topic on deneb, simply allows it to decode it. Advertise
// logic is in `SupportedTopic::currently_supported`.
if fork_name.deneb_enabled() {
if fork_name.fulu_enabled() {
Ok(Some(RpcSuccessResponse::DataColumnsByRoot(Arc::new(
DataColumnSidecar::from_ssz_bytes(decoded_buffer)?,
))))
@@ -754,7 +743,7 @@ fn handle_rpc_response<E: EthSpec>(
},
SupportedProtocol::DataColumnsByRangeV1 => match fork_name {
Some(fork_name) => {
if fork_name.deneb_enabled() {
if fork_name.fulu_enabled() {
Ok(Some(RpcSuccessResponse::DataColumnsByRange(Arc::new(
DataColumnSidecar::from_ssz_bytes(decoded_buffer)?,
))))
@@ -945,9 +934,10 @@ mod tests {
use crate::rpc::protocol::*;
use crate::types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield};
use types::{
blob_sidecar::BlobIdentifier, BeaconBlock, BeaconBlockAltair, BeaconBlockBase,
BeaconBlockBellatrix, DataColumnIdentifier, EmptyBlock, Epoch, FixedBytesExtended,
FullPayload, Signature, Slot,
blob_sidecar::BlobIdentifier, data_column_sidecar::Cell, BeaconBlock, BeaconBlockAltair,
BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader, DataColumnIdentifier, EmptyBlock,
Epoch, FixedBytesExtended, FullPayload, KzgCommitment, KzgProof, Signature,
SignedBeaconBlockHeader, Slot,
};
type Spec = types::MainnetEthSpec;
@@ -998,7 +988,17 @@ mod tests {
}
fn empty_data_column_sidecar() -> Arc<DataColumnSidecar<Spec>> {
Arc::new(DataColumnSidecar::empty())
Arc::new(DataColumnSidecar {
index: 0,
column: VariableList::new(vec![Cell::<Spec>::default()]).unwrap(),
kzg_commitments: VariableList::new(vec![KzgCommitment::empty_for_testing()]).unwrap(),
kzg_proofs: VariableList::new(vec![KzgProof::empty()]).unwrap(),
signed_block_header: SignedBeaconBlockHeader {
message: BeaconBlockHeader::empty(),
signature: Signature::empty(),
},
kzg_commitments_inclusion_proof: Default::default(),
})
}
/// Bellatrix block with length < max_rpc_size.

View File

@@ -554,9 +554,11 @@ impl ProtocolId {
Protocol::BlocksByRoot => rpc_block_limits_by_fork(fork_context.current_fork()),
Protocol::BlobsByRange => rpc_blob_limits::<E>(),
Protocol::BlobsByRoot => rpc_blob_limits::<E>(),
Protocol::DataColumnsByRoot => rpc_data_column_limits::<E>(fork_context.current_fork()),
Protocol::DataColumnsByRoot => {
rpc_data_column_limits::<E>(fork_context.current_fork(), &fork_context.spec)
}
Protocol::DataColumnsByRange => {
rpc_data_column_limits::<E>(fork_context.current_fork())
rpc_data_column_limits::<E>(fork_context.current_fork(), &fork_context.spec)
}
Protocol::Ping => RpcLimits::new(
<Ping as Encode>::ssz_fixed_len(),
@@ -637,13 +639,10 @@ pub fn rpc_blob_limits<E: EthSpec>() -> RpcLimits {
}
}
// TODO(das): fix hardcoded max here
pub fn rpc_data_column_limits<E: EthSpec>(fork_name: ForkName) -> RpcLimits {
pub fn rpc_data_column_limits<E: EthSpec>(fork_name: ForkName, spec: &ChainSpec) -> RpcLimits {
RpcLimits::new(
DataColumnSidecar::<E>::empty().as_ssz_bytes().len(),
DataColumnSidecar::<E>::max_size(
E::default_spec().max_blobs_per_block_by_fork(fork_name) as usize
),
DataColumnSidecar::<E>::min_size(),
DataColumnSidecar::<E>::max_size(spec.max_blobs_per_block_by_fork(fork_name) as usize),
)
}

View File

@@ -223,7 +223,7 @@ mod test {
fn test_sampling_subnets() {
let log = logging::test_logger();
let mut spec = E::default_spec();
spec.eip7594_fork_epoch = Some(Epoch::new(0));
spec.fulu_fork_epoch = Some(Epoch::new(0));
let custody_group_count = spec.number_of_custody_groups / 2;
let subnet_sampling_size = spec.sampling_size(custody_group_count).unwrap();
@@ -247,7 +247,7 @@ mod test {
fn test_sampling_columns() {
let log = logging::test_logger();
let mut spec = E::default_spec();
spec.eip7594_fork_epoch = Some(Epoch::new(0));
spec.fulu_fork_epoch = Some(Epoch::new(0));
let custody_group_count = spec.number_of_custody_groups / 2;
let subnet_sampling_size = spec.sampling_size(custody_group_count).unwrap();

View File

@@ -283,27 +283,15 @@ impl<E: EthSpec> PubsubMessage<E> {
}
GossipKind::DataColumnSidecar(subnet_id) => {
match fork_context.from_context_bytes(gossip_topic.fork_digest) {
// TODO(das): Remove Deneb fork
Some(fork) if fork.deneb_enabled() => {
Some(fork) if fork.fulu_enabled() => {
let col_sidecar = Arc::new(
DataColumnSidecar::from_ssz_bytes(data)
.map_err(|e| format!("{:?}", e))?,
);
let peer_das_enabled =
fork_context.spec.is_peer_das_enabled_for_epoch(
col_sidecar.slot().epoch(E::slots_per_epoch()),
);
if peer_das_enabled {
Ok(PubsubMessage::DataColumnSidecar(Box::new((
*subnet_id,
col_sidecar,
))))
} else {
Err(format!(
"data_column_sidecar topic invalid for given fork digest {:?}",
gossip_topic.fork_digest
))
}
Ok(PubsubMessage::DataColumnSidecar(Box::new((
*subnet_id,
col_sidecar,
))))
}
Some(_) | None => Err(format!(
"data_column_sidecar topic invalid for given fork digest {:?}",