mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
Add Gloas data column support (#8682)
Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu> Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>
This commit is contained in:
@@ -693,7 +693,7 @@ fn handle_rpc_response<E: EthSpec>(
|
||||
Some(fork_name) => {
|
||||
if fork_name.fulu_enabled() {
|
||||
Ok(Some(RpcSuccessResponse::DataColumnsByRoot(Arc::new(
|
||||
DataColumnSidecar::from_ssz_bytes(decoded_buffer)?,
|
||||
DataColumnSidecar::from_ssz_bytes_for_fork(decoded_buffer, fork_name)?,
|
||||
))))
|
||||
} else {
|
||||
Err(RPCError::ErrorResponse(
|
||||
@@ -714,7 +714,7 @@ fn handle_rpc_response<E: EthSpec>(
|
||||
Some(fork_name) => {
|
||||
if fork_name.fulu_enabled() {
|
||||
Ok(Some(RpcSuccessResponse::DataColumnsByRange(Arc::new(
|
||||
DataColumnSidecar::from_ssz_bytes(decoded_buffer)?,
|
||||
DataColumnSidecar::from_ssz_bytes_for_fork(decoded_buffer, fork_name)?,
|
||||
))))
|
||||
} else {
|
||||
Err(RPCError::ErrorResponse(
|
||||
@@ -916,6 +916,7 @@ mod tests {
|
||||
SignedBeaconBlockHeader, Slot,
|
||||
data::{BlobIdentifier, Cell},
|
||||
};
|
||||
use types::{BlobSidecar, DataColumnSidecarFulu};
|
||||
|
||||
type Spec = types::MainnetEthSpec;
|
||||
|
||||
@@ -977,7 +978,7 @@ mod tests {
|
||||
fn empty_data_column_sidecar(spec: &ChainSpec) -> Arc<DataColumnSidecar<Spec>> {
|
||||
// The context bytes are now derived from the block epoch, so we need to have the slot set
|
||||
// here.
|
||||
let data_column_sidecar = DataColumnSidecar {
|
||||
let data_column_sidecar = DataColumnSidecar::Fulu(DataColumnSidecarFulu {
|
||||
index: 0,
|
||||
column: VariableList::new(vec![Cell::<Spec>::default()]).unwrap(),
|
||||
kzg_commitments: VariableList::new(vec![KzgCommitment::empty_for_testing()]).unwrap(),
|
||||
@@ -993,7 +994,7 @@ mod tests {
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
kzg_commitments_inclusion_proof: Default::default(),
|
||||
};
|
||||
});
|
||||
Arc::new(data_column_sidecar)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ use superstruct::superstruct;
|
||||
use types::data::BlobIdentifier;
|
||||
use types::light_client::consts::MAX_REQUEST_LIGHT_CLIENT_UPDATES;
|
||||
use types::{
|
||||
ChainSpec, ColumnIndex, DataColumnSidecar, DataColumnsByRootIdentifier, Epoch, EthSpec,
|
||||
ForkContext, Hash256, LightClientBootstrap, LightClientFinalityUpdate,
|
||||
LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock, Slot, data::BlobSidecar,
|
||||
BlobSidecar, ChainSpec, ColumnIndex, DataColumnSidecar, DataColumnsByRootIdentifier, Epoch,
|
||||
EthSpec, ForkContext, Hash256, LightClientBootstrap, LightClientFinalityUpdate,
|
||||
LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
/// Maximum length of error message.
|
||||
@@ -762,12 +762,8 @@ impl<E: EthSpec> RpcSuccessResponse<E> {
|
||||
pub fn slot(&self) -> Option<Slot> {
|
||||
match self {
|
||||
Self::BlocksByRange(r) | Self::BlocksByRoot(r) => Some(r.slot()),
|
||||
Self::BlobsByRange(r) | Self::BlobsByRoot(r) => {
|
||||
Some(r.signed_block_header.message.slot)
|
||||
}
|
||||
Self::DataColumnsByRange(r) | Self::DataColumnsByRoot(r) => {
|
||||
Some(r.signed_block_header.message.slot)
|
||||
}
|
||||
Self::BlobsByRange(r) | Self::BlobsByRoot(r) => Some(r.slot()),
|
||||
Self::DataColumnsByRange(r) | Self::DataColumnsByRoot(r) => Some(r.slot()),
|
||||
Self::LightClientBootstrap(r) => Some(r.get_slot()),
|
||||
Self::LightClientFinalityUpdate(r) => Some(r.get_attested_header_slot()),
|
||||
Self::LightClientOptimisticUpdate(r) => Some(r.get_slot()),
|
||||
|
||||
@@ -17,11 +17,12 @@ use tokio_util::{
|
||||
compat::{Compat, FuturesAsyncReadCompatExt},
|
||||
};
|
||||
use types::{
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BlobSidecar, ChainSpec, DataColumnSidecar,
|
||||
EmptyBlock, Epoch, EthSpec, EthSpecId, ForkContext, ForkName, LightClientBootstrap,
|
||||
LightClientBootstrapAltair, LightClientFinalityUpdate, LightClientFinalityUpdateAltair,
|
||||
LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair, LightClientUpdate,
|
||||
MainnetEthSpec, MinimalEthSpec, SignedBeaconBlock,
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BlobSidecar, ChainSpec, DataColumnSidecarFulu,
|
||||
DataColumnSidecarGloas, EmptyBlock, Epoch, EthSpec, EthSpecId, ForkContext, ForkName,
|
||||
LightClientBootstrap, LightClientBootstrapAltair, LightClientFinalityUpdate,
|
||||
LightClientFinalityUpdateAltair, LightClientOptimisticUpdate,
|
||||
LightClientOptimisticUpdateAltair, LightClientUpdate, MainnetEthSpec, MinimalEthSpec,
|
||||
SignedBeaconBlock,
|
||||
};
|
||||
|
||||
// Note: Hardcoding the `EthSpec` type for `SignedBeaconBlock` as min/max values is
|
||||
@@ -640,10 +641,23 @@ pub fn rpc_data_column_limits<E: EthSpec>(
|
||||
current_digest_epoch: Epoch,
|
||||
spec: &ChainSpec,
|
||||
) -> RpcLimits {
|
||||
RpcLimits::new(
|
||||
DataColumnSidecar::<E>::min_size(),
|
||||
DataColumnSidecar::<E>::max_size(spec.max_blobs_per_block(current_digest_epoch) as usize),
|
||||
)
|
||||
let fork_name = spec.fork_name_at_epoch(current_digest_epoch);
|
||||
|
||||
if fork_name.gloas_enabled() {
|
||||
RpcLimits::new(
|
||||
DataColumnSidecarGloas::<E>::min_size(),
|
||||
DataColumnSidecarGloas::<E>::max_size(
|
||||
spec.max_blobs_per_block(current_digest_epoch) as usize
|
||||
),
|
||||
)
|
||||
} else {
|
||||
RpcLimits::new(
|
||||
DataColumnSidecarFulu::<E>::min_size(),
|
||||
DataColumnSidecarFulu::<E>::max_size(
|
||||
spec.max_blobs_per_block(current_digest_epoch) as usize
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* Inbound upgrade */
|
||||
|
||||
@@ -277,7 +277,7 @@ impl<E: EthSpec> PubsubMessage<E> {
|
||||
match fork_context.get_fork_from_context_bytes(gossip_topic.fork_digest) {
|
||||
Some(fork) if fork.fulu_enabled() => {
|
||||
let col_sidecar = Arc::new(
|
||||
DataColumnSidecar::from_ssz_bytes(data)
|
||||
DataColumnSidecar::from_ssz_bytes_for_fork(data, *fork)
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
);
|
||||
Ok(PubsubMessage::DataColumnSidecar(Box::new((
|
||||
@@ -437,7 +437,7 @@ impl<E: EthSpec> std::fmt::Display for PubsubMessage<E> {
|
||||
f,
|
||||
"DataColumnSidecar: slot: {}, column index: {}",
|
||||
data.1.slot(),
|
||||
data.1.index,
|
||||
data.1.index(),
|
||||
),
|
||||
PubsubMessage::AggregateAndProofAttestation(att) => write!(
|
||||
f,
|
||||
|
||||
@@ -17,9 +17,9 @@ use tokio::time::sleep;
|
||||
use tracing::{Instrument, debug, error, info, info_span, warn};
|
||||
use types::{
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader,
|
||||
BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnsByRootIdentifier, EmptyBlock, Epoch,
|
||||
EthSpec, ForkName, Hash256, KzgCommitment, KzgProof, MinimalEthSpec, SignedBeaconBlock,
|
||||
SignedBeaconBlockHeader, Slot,
|
||||
BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnSidecarFulu, DataColumnSidecarGloas,
|
||||
DataColumnsByRootIdentifier, EmptyBlock, Epoch, EthSpec, ForkName, Hash256, KzgCommitment,
|
||||
KzgProof, MinimalEthSpec, SignedBeaconBlock, SignedBeaconBlockHeader, Slot,
|
||||
};
|
||||
|
||||
type E = MinimalEthSpec;
|
||||
@@ -952,9 +952,7 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
fn test_tcp_columns_by_root_chunked_rpc_for_fork(fork_name: ForkName) {
|
||||
// Set up the logging.
|
||||
let log_level = "debug";
|
||||
let enable_logging = true;
|
||||
@@ -963,14 +961,17 @@ fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
let messages_to_send = 32 * num_of_columns;
|
||||
|
||||
let spec = Arc::new(spec_with_all_forks_enabled());
|
||||
let current_fork_name = ForkName::Fulu;
|
||||
let slot = spec
|
||||
.fork_epoch(fork_name)
|
||||
.expect("fork must be scheduled")
|
||||
.start_slot(E::slots_per_epoch());
|
||||
|
||||
let rt = Arc::new(Runtime::new().unwrap());
|
||||
// get sender/receiver
|
||||
rt.block_on(async {
|
||||
let (mut sender, mut receiver) = common::build_node_pair(
|
||||
Arc::downgrade(&rt),
|
||||
current_fork_name,
|
||||
fork_name,
|
||||
spec.clone(),
|
||||
Protocol::Tcp,
|
||||
false,
|
||||
@@ -980,7 +981,7 @@ fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
|
||||
// DataColumnsByRootRequest Request
|
||||
|
||||
let max_request_blocks = spec.max_request_blocks(current_fork_name);
|
||||
let max_request_blocks = spec.max_request_blocks(fork_name);
|
||||
let req = DataColumnsByRootRequest::new(
|
||||
vec![
|
||||
DataColumnsByRootIdentifier {
|
||||
@@ -999,7 +1000,7 @@ fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
let req_decoded = DataColumnsByRootRequest {
|
||||
data_column_ids: <RuntimeVariableList<DataColumnsByRootIdentifier<E>>>::from_ssz_bytes(
|
||||
&req_bytes,
|
||||
spec.max_request_blocks(current_fork_name),
|
||||
spec.max_request_blocks(fork_name),
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
@@ -1007,30 +1008,44 @@ fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
let rpc_request = RequestType::DataColumnsByRoot(req);
|
||||
|
||||
// DataColumnsByRoot Response
|
||||
let data_column = Arc::new(DataColumnSidecar {
|
||||
index: 1,
|
||||
signed_block_header: SignedBeaconBlockHeader {
|
||||
message: BeaconBlockHeader {
|
||||
slot: 320u64.into(),
|
||||
proposer_index: 1,
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body_root: Hash256::zero(),
|
||||
let data_column = if fork_name.gloas_enabled() {
|
||||
Arc::new(DataColumnSidecar::Gloas(DataColumnSidecarGloas {
|
||||
index: 1,
|
||||
slot,
|
||||
beacon_block_root: Hash256::zero(),
|
||||
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
}))
|
||||
} else {
|
||||
Arc::new(DataColumnSidecar::Fulu(DataColumnSidecarFulu {
|
||||
index: 1,
|
||||
signed_block_header: SignedBeaconBlockHeader {
|
||||
message: BeaconBlockHeader {
|
||||
slot,
|
||||
proposer_index: 1,
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body_root: Hash256::zero(),
|
||||
},
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
kzg_commitments_inclusion_proof: vec![
|
||||
Hash256::zero();
|
||||
E::kzg_commitments_inclusion_proof_depth()
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
kzg_commitments_inclusion_proof: vec![
|
||||
Hash256::zero();
|
||||
E::kzg_commitments_inclusion_proof_depth()
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
});
|
||||
}))
|
||||
};
|
||||
|
||||
let rpc_response = Response::DataColumnsByRoot(Some(data_column.clone()));
|
||||
|
||||
@@ -1120,7 +1135,17 @@ fn test_tcp_columns_by_root_chunked_rpc() {
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_tcp_columns_by_range_chunked_rpc() {
|
||||
fn test_tcp_columns_by_root_chunked_rpc_fulu() {
|
||||
test_tcp_columns_by_root_chunked_rpc_for_fork(ForkName::Fulu);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_tcp_columns_by_root_chunked_rpc_gloas() {
|
||||
test_tcp_columns_by_root_chunked_rpc_for_fork(ForkName::Gloas);
|
||||
}
|
||||
|
||||
fn test_tcp_columns_by_range_chunked_rpc_for_fork(fork_name: ForkName) {
|
||||
// Set up the logging.
|
||||
let log_level = "debug";
|
||||
let enable_logging = true;
|
||||
@@ -1129,14 +1154,17 @@ fn test_tcp_columns_by_range_chunked_rpc() {
|
||||
let messages_to_send = 32;
|
||||
|
||||
let spec = Arc::new(spec_with_all_forks_enabled());
|
||||
let current_fork_name = ForkName::Fulu;
|
||||
let slot = spec
|
||||
.fork_epoch(fork_name)
|
||||
.expect("fork must be scheduled")
|
||||
.start_slot(E::slots_per_epoch());
|
||||
|
||||
let rt = Arc::new(Runtime::new().unwrap());
|
||||
// get sender/receiver
|
||||
rt.block_on(async {
|
||||
let (mut sender, mut receiver) = common::build_node_pair(
|
||||
Arc::downgrade(&rt),
|
||||
current_fork_name,
|
||||
fork_name,
|
||||
spec.clone(),
|
||||
Protocol::Tcp,
|
||||
false,
|
||||
@@ -1146,36 +1174,49 @@ fn test_tcp_columns_by_range_chunked_rpc() {
|
||||
|
||||
// DataColumnsByRange Request
|
||||
let rpc_request = RequestType::DataColumnsByRange(DataColumnsByRangeRequest {
|
||||
start_slot: 320,
|
||||
start_slot: slot.as_u64(),
|
||||
count: 32,
|
||||
columns: (0..E::number_of_columns() as u64).collect(),
|
||||
});
|
||||
|
||||
// DataColumnsByRange Response
|
||||
let data_column = Arc::new(DataColumnSidecar {
|
||||
index: 1,
|
||||
signed_block_header: SignedBeaconBlockHeader {
|
||||
message: BeaconBlockHeader {
|
||||
slot: 320u64.into(),
|
||||
proposer_index: 1,
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body_root: Hash256::zero(),
|
||||
let data_column = if fork_name.gloas_enabled() {
|
||||
Arc::new(DataColumnSidecar::Gloas(DataColumnSidecarGloas {
|
||||
index: 1,
|
||||
slot,
|
||||
beacon_block_root: Hash256::zero(),
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
}))
|
||||
} else {
|
||||
Arc::new(DataColumnSidecar::Fulu(DataColumnSidecarFulu {
|
||||
index: 1,
|
||||
signed_block_header: SignedBeaconBlockHeader {
|
||||
message: BeaconBlockHeader {
|
||||
slot,
|
||||
proposer_index: 1,
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body_root: Hash256::zero(),
|
||||
},
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
signature: Signature::empty(),
|
||||
},
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
kzg_commitments_inclusion_proof: vec![
|
||||
Hash256::zero();
|
||||
E::kzg_commitments_inclusion_proof_depth()
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
|
||||
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
|
||||
kzg_commitments_inclusion_proof: vec![
|
||||
Hash256::zero();
|
||||
E::kzg_commitments_inclusion_proof_depth()
|
||||
]
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
});
|
||||
}))
|
||||
};
|
||||
|
||||
let rpc_response = Response::DataColumnsByRange(Some(data_column.clone()));
|
||||
|
||||
@@ -1218,34 +1259,27 @@ fn test_tcp_columns_by_range_chunked_rpc() {
|
||||
// build the receiver future
|
||||
let receiver_future = async {
|
||||
loop {
|
||||
match receiver.next_event().await {
|
||||
NetworkEvent::RequestReceived {
|
||||
if let NetworkEvent::RequestReceived {
|
||||
peer_id,
|
||||
inbound_request_id,
|
||||
request_type,
|
||||
} = receiver.next_event().await
|
||||
&& request_type == rpc_request
|
||||
{
|
||||
// send the response
|
||||
info!("Receiver got request");
|
||||
|
||||
for _ in 0..messages_to_send {
|
||||
receiver.send_response(peer_id, inbound_request_id, rpc_response.clone());
|
||||
info!("Sending message");
|
||||
}
|
||||
// send the stream termination
|
||||
receiver.send_response(
|
||||
peer_id,
|
||||
inbound_request_id,
|
||||
request_type,
|
||||
} => {
|
||||
if request_type == rpc_request {
|
||||
// send the response
|
||||
info!("Receiver got request");
|
||||
|
||||
for _ in 0..messages_to_send {
|
||||
receiver.send_response(
|
||||
peer_id,
|
||||
inbound_request_id,
|
||||
rpc_response.clone(),
|
||||
);
|
||||
info!("Sending message");
|
||||
}
|
||||
// send the stream termination
|
||||
receiver.send_response(
|
||||
peer_id,
|
||||
inbound_request_id,
|
||||
Response::DataColumnsByRange(None),
|
||||
);
|
||||
info!("Send stream term");
|
||||
}
|
||||
}
|
||||
_ => {} // Ignore other events
|
||||
Response::DataColumnsByRange(None),
|
||||
);
|
||||
info!("Send stream term");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1260,6 +1294,18 @@ fn test_tcp_columns_by_range_chunked_rpc() {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_tcp_columns_by_range_chunked_rpc_fulu() {
|
||||
test_tcp_columns_by_range_chunked_rpc_for_fork(ForkName::Fulu);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_tcp_columns_by_range_chunked_rpc_gloas() {
|
||||
test_tcp_columns_by_range_chunked_rpc_for_fork(ForkName::Gloas);
|
||||
}
|
||||
|
||||
// Tests a streamed, chunked BlocksByRoot RPC Message terminates when all expected reponses have been received
|
||||
#[test]
|
||||
fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
|
||||
|
||||
Reference in New Issue
Block a user