resolve merge conflicts

This commit is contained in:
Eitan Seri-Levi
2026-04-30 01:51:26 +02:00
544 changed files with 48684 additions and 18351 deletions

View File

@@ -15,6 +15,7 @@ use std::io::{Read, Write};
use std::marker::PhantomData;
use std::sync::Arc;
use tokio_util::codec::{Decoder, Encoder};
use types::SignedExecutionPayloadEnvelope;
use types::{
BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnsByRootIdentifier, EthSpec, ForkContext,
ForkName, Hash256, LightClientBootstrap, LightClientFinalityUpdate,
@@ -76,6 +77,8 @@ impl<E: EthSpec> SSZSnappyInboundCodec<E> {
},
RpcSuccessResponse::BlocksByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlocksByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::PayloadEnvelopesByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::PayloadEnvelopesByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlobsByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlobsByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::DataColumnsByRoot(res) => res.as_ssz_bytes(),
@@ -356,6 +359,8 @@ impl<E: EthSpec> Encoder<RequestType<E>> for SSZSnappyOutboundCodec<E> {
BlocksByRootRequest::V1(req) => req.block_roots.as_ssz_bytes(),
BlocksByRootRequest::V2(req) => req.block_roots.as_ssz_bytes(),
},
RequestType::PayloadEnvelopesByRange(req) => req.as_ssz_bytes(),
RequestType::PayloadEnvelopesByRoot(req) => req.beacon_block_roots.as_ssz_bytes(),
RequestType::BlobsByRange(req) => req.as_ssz_bytes(),
RequestType::BlobsByRoot(req) => req.blob_ids.as_ssz_bytes(),
RequestType::DataColumnsByRange(req) => req.as_ssz_bytes(),
@@ -457,6 +462,9 @@ fn handle_error<T>(
Ok(None)
}
}
// All snappy errors from the snap crate bubble up as `Other` kind errors
// that imply invalid response
ErrorKind::Other => Err(RPCError::InvalidData(err.to_string())),
_ => Err(RPCError::from(err)),
}
}
@@ -545,6 +553,19 @@ fn handle_rpc_request<E: EthSpec>(
)?,
}),
))),
SupportedProtocol::PayloadEnvelopesByRangeV1 => {
Ok(Some(RequestType::PayloadEnvelopesByRange(
PayloadEnvelopesByRangeRequest::from_ssz_bytes(decoded_buffer)?,
)))
}
SupportedProtocol::PayloadEnvelopesByRootV1 => Ok(Some(
RequestType::PayloadEnvelopesByRoot(PayloadEnvelopesByRootRequest {
beacon_block_roots: RuntimeVariableList::from_ssz_bytes(
decoded_buffer,
spec.max_request_payloads(),
)?,
}),
)),
SupportedProtocol::BlobsByRangeV1 => Ok(Some(RequestType::BlobsByRange(
BlobsByRangeRequest::from_ssz_bytes(decoded_buffer)?,
))),
@@ -647,6 +668,48 @@ fn handle_rpc_response<E: EthSpec>(
SupportedProtocol::BlocksByRootV1 => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new(
SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?),
)))),
SupportedProtocol::PayloadEnvelopesByRangeV1 => match fork_name {
Some(fork_name) => {
if fork_name.gloas_enabled() {
Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRange(Arc::new(
SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?,
))))
} else {
Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
"Invalid fork name for payload envelopes by range".to_string(),
))
}
}
None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
SupportedProtocol::PayloadEnvelopesByRootV1 => match fork_name {
Some(fork_name) => {
if fork_name.gloas_enabled() {
Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRoot(Arc::new(
SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?,
))))
} else {
Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
"Invalid fork name for payload envelopes by root".to_string(),
))
}
}
None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
SupportedProtocol::BlobsByRangeV1 => match fork_name {
Some(fork_name) => {
if fork_name.deneb_enabled() {
@@ -693,7 +756,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 +777,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(
@@ -923,8 +986,10 @@ mod tests {
use types::{
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader,
DataColumnsByRootIdentifier, EmptyBlock, Epoch, FullPayload, KzgCommitment, KzgProof,
SignedBeaconBlockHeader, Slot, blob_sidecar::BlobIdentifier, data_column_sidecar::Cell,
SignedBeaconBlockHeader, Slot,
data::{BlobIdentifier, Cell},
};
use types::{BlobSidecar, DataColumnSidecarFulu};
type Spec = types::MainnetEthSpec;
@@ -988,7 +1053,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(),
@@ -1004,7 +1069,7 @@ mod tests {
signature: Signature::empty(),
},
kzg_commitments_inclusion_proof: Default::default(),
};
});
Arc::new(data_column_sidecar)
}
@@ -1035,9 +1100,11 @@ mod tests {
let mut block: BeaconBlockBellatrix<_, FullPayload<Spec>> =
BeaconBlockBellatrix::empty(spec);
// 11,000 × 1KB ≈ 11MB, just above the 10MB max_payload_size.
// Previously used 100,000 txs (~100MB) which made this test take >60s.
let tx = VariableList::try_from(vec![0; 1024]).unwrap();
let txs =
VariableList::try_from(std::iter::repeat_n(tx, 100000).collect::<Vec<_>>()).unwrap();
VariableList::try_from(std::iter::repeat_n(tx, 11000).collect::<Vec<_>>()).unwrap();
block.body.execution_payload.execution_payload.transactions = txs;
@@ -1267,6 +1334,12 @@ mod tests {
RequestType::BlobsByRange(blbrange) => {
assert_eq!(decoded, RequestType::BlobsByRange(blbrange))
}
RequestType::PayloadEnvelopesByRange(perange) => {
assert_eq!(decoded, RequestType::PayloadEnvelopesByRange(perange))
}
RequestType::PayloadEnvelopesByRoot(peroot) => {
assert_eq!(decoded, RequestType::PayloadEnvelopesByRoot(peroot))
}
RequestType::BlobsByRoot(bbroot) => {
assert_eq!(decoded, RequestType::BlobsByRoot(bbroot))
}
@@ -2355,4 +2428,43 @@ mod tests {
RPCError::InvalidData(_)
));
}
/// Test invalid snappy response.
#[test]
fn test_invalid_snappy_response() {
let spec = spec_with_all_forks_enabled();
let fork_ctx = Arc::new(fork_context(ForkName::latest(), &spec));
let max_packet_size = spec.max_payload_size as usize; // 10 MiB.
let protocol = ProtocolId::new(SupportedProtocol::BlocksByRangeV2, Encoding::SSZSnappy);
let mut codec = SSZSnappyOutboundCodec::<Spec>::new(
protocol.clone(),
max_packet_size,
fork_ctx.clone(),
);
let mut payload = BytesMut::new();
payload.extend_from_slice(&[0u8]);
let deneb_epoch = spec.deneb_fork_epoch.unwrap();
payload.extend_from_slice(&fork_ctx.context_bytes(deneb_epoch));
// Claim the MAXIMUM allowed size (10 MiB)
let claimed_size = max_packet_size;
let mut uvi_codec: Uvi<usize> = Uvi::default();
uvi_codec.encode(claimed_size, &mut payload).unwrap();
payload.extend_from_slice(&[0xBB; 16]); // Junk snappy.
let result = codec.decode(&mut payload);
assert!(result.is_err(), "Expected decode to fail");
// IoError = reached snappy decode (allocation happened).
let err = result.unwrap_err();
assert!(
matches!(err, RPCError::InvalidData(_)),
"Should return invalid data variant {}",
err
);
}
}