Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions crates/beacon_state/tile/src/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,6 @@ impl BeaconStateTile {
// column validation/availability), not here; see the TODO at its
// column-request path.
EngineResp::GetBlobs(_) => {}
// Payload-body reconstruction is unneeded: the store persists and
// serves full SignedBeaconBlocks, so there is nothing to rebuild
// from EL bodies.
EngineResp::GetPayloadBodies(_) => {}
}
}

Expand Down
12 changes: 5 additions & 7 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ pub use crate::{
BeaconApiResponse, BeaconStateEvent, BlockLookup, BlockSource, BlockStage, ClusterIn,
ClusterMsgIn, ClusterMsgOut, ColumnOrigin, Consumer as TConsumer, DataColumnsEvent,
ELSyncStatus, EngineFcuReq, EngineFcuResp, EngineGetBlobsReq, EngineGetBlobsResp,
EngineGetPayloadBodiesByHashReq, EngineGetPayloadBodiesByRangeReq,
EngineGetPayloadBodiesResp, EngineGetPayloadReq, EngineGetPayloadResp, EngineHealthEvent,
EngineNewPayloadEnvelopeReq, EngineNewPayloadReq, EngineNewPayloadResp,
EnginePreparePayloadReq, EngineReq, EngineResp, Error as TCacheError, GossipMsgIn,
GossipMsgOut, HeadChange, HeadRoots, IpBytes, LOCAL_GOSSIP_STREAM_ID,
LocalAttestationFailure, LocalAttestationResult, MAX_BLOBS_PER_BLOCK,
MAX_PAYLOAD_BODIES_PER_REQ, MULTISTREAM_V1, MultiProducer as TMultiProducer, NewGossipMsg,
EngineGetPayloadReq, EngineGetPayloadResp, EngineHealthEvent, EngineNewPayloadEnvelopeReq,
EngineNewPayloadReq, EngineNewPayloadResp, EnginePreparePayloadReq, EngineReq, EngineResp,
Error as TCacheError, GossipMsgIn, GossipMsgOut, HeadChange, HeadRoots, IpBytes,
LOCAL_GOSSIP_STREAM_ID, LocalAttestationFailure, LocalAttestationResult,
MAX_BLOBS_PER_BLOCK, MULTISTREAM_V1, MultiProducer as TMultiProducer, NewGossipMsg,
P2pConnectionStats, P2pSend, P2pStreamId, PREFILL_SLOTS, PayloadResolution,
PayloadValidationStatus, PeerControl, PeerEvent, PeerScores, PeerStats, PeerStatus,
PeerTopicScores, PendingSubReservation, Prefill, Producer as TProducer, REJECT_RESPONSE,
Expand Down
13 changes: 6 additions & 7 deletions crates/common/src/spine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ pub use messages::{
AgentString, BeaconApiRequest, BeaconApiResponse, BeaconStateEvent, BlockLookup, BlockSource,
BlockStage, ClusterIn, ClusterMsgIn, ClusterMsgOut, ColumnOrigin, DataColumnsEvent,
ELSyncStatus, EngineFcuReq, EngineFcuResp, EngineGetBlobsReq, EngineGetBlobsResp,
EngineGetPayloadBodiesByHashReq, EngineGetPayloadBodiesByRangeReq, EngineGetPayloadBodiesResp,
EngineGetPayloadReq, EngineGetPayloadResp, EngineHealthEvent, EngineNewPayloadEnvelopeReq,
EngineNewPayloadReq, EngineNewPayloadResp, EnginePreparePayloadReq, EngineReq, EngineResp,
GossipMsgIn, GossipMsgOut, HeadChange, HeadRoots, IpBytes, LocalAttestationFailure,
LocalAttestationResult, MAX_BLOBS_PER_BLOCK, MAX_PAYLOAD_BODIES_PER_REQ, NewGossipMsg,
P2pConnectionStats, P2pSend, PREFILL_SLOTS, PayloadResolution, PayloadValidationStatus,
PeerControl, PeerEvent, PeerScores, PeerStats, PeerStatus, PeerTopicScores, Prefill,
ReplayBlock, RpcInbound, RpcOutbound, RpcRequest, RpcRequestInbound, RpcRequestOutbound,
RpcResponse, RpcResponseInbound, RpcResponseOutbound, RpcSeverity, SelfBuiltGossip,
ServedBlock, SszCache, SyncNeed, SyncUpdate, SyncingStrategy, WithdrawalInline,
LocalAttestationResult, MAX_BLOBS_PER_BLOCK, NewGossipMsg, P2pConnectionStats, P2pSend,
PREFILL_SLOTS, PayloadResolution, PayloadValidationStatus, PeerControl, PeerEvent, PeerScores,
PeerStats, PeerStatus, PeerTopicScores, Prefill, ReplayBlock, RpcInbound, RpcOutbound,
RpcRequest, RpcRequestInbound, RpcRequestOutbound, RpcResponse, RpcResponseInbound,
RpcResponseOutbound, RpcSeverity, SelfBuiltGossip, ServedBlock, SszCache, SyncNeed, SyncUpdate,
SyncingStrategy, WithdrawalInline,
};
pub use stream_id::{LOCAL_GOSSIP_STREAM_ID, P2pStreamId};
pub use stream_protocol::{
Expand Down
38 changes: 0 additions & 38 deletions crates/common/src/spine/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,9 +1082,6 @@ pub enum SyncingStrategy {
/// evolves).
pub const MAX_BLOBS_PER_BLOCK: usize = 21;

/// Maximum number of block hashes in a single `getPayloadBodiesByHash` request.
pub const MAX_PAYLOAD_BODIES_PER_REQ: usize = 128;

/// Execution-payload validation result returned by the EL.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
Expand Down Expand Up @@ -1254,38 +1251,6 @@ impl EngineGetBlobsResp {
}
}

/// `engine_getPayloadBodiesByHashV1` request.
/// `hashes[..hash_count]` are the execution block hashes to fetch bodies for.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct EngineGetPayloadBodiesByHashReq {
pub id: u64,
pub hash_count: u8,
pub hashes: [[u8; 32]; MAX_PAYLOAD_BODIES_PER_REQ],
}

/// `engine_getPayloadBodiesByRangeV1` request. Fully inline.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct EngineGetPayloadBodiesByRangeReq {
pub id: u64,
pub start: u64,
pub count: u64,
}

/// Response to either `getPayloadBodiesByHash` or `getPayloadBodiesByRange`.
/// When `ok` is true, `data` is a TCache slot with binary-encoded bodies:
/// `[u32 count] ([u8 present] [u32 tx_count] ([u32 tx_len][tx bytes])* [u32
/// withdrawal_count] ([u32 index][u32 validator_index][20B address][u64
/// amount])*)*` `present == 0` means the entry is null (block missing).
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct EngineGetPayloadBodiesResp {
pub id: u64,
pub ok: bool,
pub data: TCacheRead,
}

/// Multiplexed engine request. A single spine queue carries FCU,
/// new-payload, and raw passthrough requests, preserving strict FIFO ordering.
#[derive(Clone, Copy, Debug)]
Expand All @@ -1298,8 +1263,6 @@ pub enum EngineReq {
PreparePayload(EnginePreparePayloadReq),
GetPayload(EngineGetPayloadReq),
GetBlobs(EngineGetBlobsReq),
GetPayloadBodiesByHash(EngineGetPayloadBodiesByHashReq),
GetPayloadBodiesByRange(EngineGetPayloadBodiesByRangeReq),
}

/// Multiplexed engine response.
Expand All @@ -1311,7 +1274,6 @@ pub enum EngineResp {
NewPayload(EngineNewPayloadResp),
GetPayload(EngineGetPayloadResp),
GetBlobs(EngineGetBlobsResp),
GetPayloadBodies(EngineGetPayloadBodiesResp),
}

/// Sync status of the attached execution layer.
Expand Down
4 changes: 1 addition & 3 deletions crates/config/src/engine_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ fn default_max_connections() -> usize {
32
}

// Clears every engine-api per-method minimum-wait floor (the highest is
// getPayloadBodiesBy* at 10 s) with margin: this deadline breaks wedged
// connections, it is not a latency target.
// The deadline breaks wedged connections; it is not a latency target.
fn default_request_timeout_secs() -> u64 {
12
}
Expand Down
4 changes: 0 additions & 4 deletions crates/engine_api/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ impl EngineApi {
ReqKind::NewPayload(block_root) => out.new_payload(block_root, response),
ReqKind::GetPayloadFetch(spine_id) => out.get_payload(spine_id, response),
ReqKind::GetBlobs { block_root, slot } => out.get_blobs(block_root, slot, response),
ReqKind::GetPayloadBodiesByHash(spine_id) |
ReqKind::GetPayloadBodiesByRange(spine_id) => {
out.payload_bodies(spine_id, response)
}
});
}

Expand Down
24 changes: 0 additions & 24 deletions crates/engine_api/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ const OUR_CAPABILITIES: &[&str] = &[
"engine_getPayloadV3",
"engine_getPayloadV4",
"engine_getBlobsV2",
"engine_getPayloadBodiesByHashV1",
"engine_getPayloadBodiesByRangeV1",
"engine_getClientVersionV1",
];

Expand All @@ -39,8 +37,6 @@ pub enum ReqKind {
NewPayload(B256), // block root
GetPayloadFetch(u64),
GetBlobs { block_root: B256, slot: u64 },
GetPayloadBodiesByHash(u64),
GetPayloadBodiesByRange(u64),
}

pub struct EngineClient {
Expand Down Expand Up @@ -254,26 +250,6 @@ pub fn get_blobs(c: &mut EngineClient, params: simd_json::OwnedValue, block_root
c.pending_requests.insert(id, ReqKind::GetBlobs { block_root, slot });
}

pub fn get_payload_bodies_by_hash(
c: &mut EngineClient,
params: simd_json::OwnedValue,
req_id: u64,
) {
let (id, body) = make_rpc_body(&mut c.id, "engine_getPayloadBodiesByHashV1", params);
enqueue(c, id, &body);
c.pending_requests.insert(id, ReqKind::GetPayloadBodiesByHash(req_id));
}

pub fn get_payload_bodies_by_range(
c: &mut EngineClient,
params: simd_json::OwnedValue,
req_id: u64,
) {
let (id, body) = make_rpc_body(&mut c.id, "engine_getPayloadBodiesByRangeV1", params);
enqueue(c, id, &body);
c.pending_requests.insert(id, ReqKind::GetPayloadBodiesByRange(req_id));
}

pub fn get_sync_status(c: &mut EngineClient) {
let (id, body) = make_rpc_body(&mut c.id, "eth_syncing", simd_json::json!([]));
enqueue(c, id, &body);
Expand Down
47 changes: 3 additions & 44 deletions crates/engine_api/src/req_handlers.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
use flux::spine::FluxSpine;
use silver_common::{
BlockSource, EngineFcuReq, EngineFcuResp, EngineGetBlobsReq, EngineGetBlobsResp,
EngineGetPayloadBodiesByHashReq, EngineGetPayloadBodiesByRangeReq, EngineGetPayloadBodiesResp,
EngineGetPayloadReq, EngineGetPayloadResp, EngineNewPayloadEnvelopeReq, EngineNewPayloadReq,
EngineNewPayloadResp, EnginePreparePayloadReq, EngineReq, EngineResp, PayloadValidationStatus,
SilverSpine, TCacheRead, TProducer, TRandomAccess,
};

use crate::{
EngineClient, EngineError,
client::{
get_blobs, get_payload, get_payload_bodies_by_hash, get_payload_bodies_by_range, send_fcu,
send_new_payload, send_new_payload_envelope,
},
client::{get_blobs, get_payload, send_fcu, send_new_payload, send_new_payload_envelope},
resp_handlers::write_tcache,
types::{ForkchoiceState, PayloadAttributesV3, Withdrawal},
};
Expand All @@ -36,14 +32,12 @@ pub(crate) fn handle_request(
EngineReq::PreparePayload(r) => handle_prepare_payload(client, *r),
EngineReq::GetPayload(r) => handle_get_payload(client, *r),
EngineReq::GetBlobs(r) => handle_get_blobs(client, r),
EngineReq::GetPayloadBodiesByHash(r) => handle_get_payload_bodies_by_hash(client, r),
EngineReq::GetPayloadBodiesByRange(r) => handle_get_payload_bodies_by_range(client, r),
}
}

/// Unsafe no-EL testing mode: answer each request with a synthetic VALID
/// response without contacting an execution client. Built payloads and payload
/// bodies can't be fabricated, so those return `ok: false`; blob fetches answer
/// response without contacting an execution client. Built payloads can't be
/// fabricated, so those return `ok: false`; blob fetches answer
/// as a healthy EL that simply holds none of the requested blobs.
#[inline]
pub(crate) fn handle_request_no_el(
Expand Down Expand Up @@ -93,20 +87,6 @@ pub(crate) fn handle_request_no_el(
}),
None => EngineResp::GetBlobs(EngineGetBlobsResp::failed(r.block_root, r.slot)),
},
EngineReq::GetPayloadBodiesByHash(r) => {
EngineResp::GetPayloadBodies(EngineGetPayloadBodiesResp {
id: r.id,
ok: false,
data: unsafe { std::mem::zeroed() },
})
}
EngineReq::GetPayloadBodiesByRange(r) => {
EngineResp::GetPayloadBodies(EngineGetPayloadBodiesResp {
id: r.id,
ok: false,
data: unsafe { std::mem::zeroed() },
})
}
};
producers.engine_resps.produce(&resp.into());
}
Expand Down Expand Up @@ -211,27 +191,6 @@ fn handle_get_blobs(client: &mut EngineClient, r: &EngineGetBlobsReq) {
get_blobs(client, simd_json::json!([hashes]), r.block_root, r.slot);
}

#[inline]
fn handle_get_payload_bodies_by_hash(
client: &mut EngineClient,
r: &EngineGetPayloadBodiesByHashReq,
) {
let n = r.hash_count as usize;
let hashes: Vec<String> =
r.hashes[..n].iter().map(|h| format!("0x{}", hex::encode(h))).collect();
get_payload_bodies_by_hash(client, simd_json::json!([hashes]), r.id);
}

#[inline]
fn handle_get_payload_bodies_by_range(
client: &mut EngineClient,
r: &EngineGetPayloadBodiesByRangeReq,
) {
let start_hex = format!("0x{:x}", r.start);
let count_hex = format!("0x{:x}", r.count);
get_payload_bodies_by_range(client, simd_json::json!([start_hex, count_hex]), r.id);
}

#[inline]
fn handle_prepare_payload(client: &mut EngineClient, r: EnginePreparePayloadReq) {
tracing::info!(head = %hex::encode(&r.head_block_hash[..4]), id = r.id, "preparePayload ← spine");
Expand Down
48 changes: 4 additions & 44 deletions crates/engine_api/src/resp_handlers.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use flux::spine::SpineAdapter;
use serde::Deserialize;
use silver_common::{
ELSyncStatus, EngineFcuResp, EngineGetBlobsResp, EngineGetPayloadBodiesResp,
EngineGetPayloadResp, EngineHealthEvent, EngineNewPayloadResp, EngineResp,
PayloadValidationStatus, SilverSpine, TCacheProducer, TCacheRead, TProducer, merkle::B256,
ELSyncStatus, EngineFcuResp, EngineGetBlobsResp, EngineGetPayloadResp, EngineHealthEvent,
EngineNewPayloadResp, EngineResp, PayloadValidationStatus, SilverSpine, TCacheProducer,
TCacheRead, TProducer, merkle::B256,
};
use simd_json::prelude::{ValueAsArray, ValueAsScalar, ValueObjectAccess};

use crate::{
EngineError,
types::{
ForkchoiceUpdatedResult, PayloadStatus, json_get_blobs_to_tcache,
json_get_payload_bodies_to_tcache, json_get_payload_to_tcache,
json_get_payload_to_tcache,
},
};

Expand Down Expand Up @@ -65,12 +65,6 @@ pub(crate) fn handle_capabilities_response(
if !has("engine_newPayloadV4") {
tracing::warn!("EL does not support engine_newPayloadV4");
}
if !has("engine_getPayloadBodiesByHashV1") {
tracing::warn!("EL does not support engine_getPayloadBodiesByHashV1");
}
if !has("engine_getPayloadBodiesByRangeV1") {
tracing::warn!("EL does not support engine_getPayloadBodiesByRangeV1");
}
let method = if has("engine_getPayloadV4") { "engine_getPayloadV4" } else { FALLBACK };
tracing::info!("capabilities negotiated, using {method}");
method
Expand Down Expand Up @@ -321,35 +315,6 @@ impl<'a> Responses<'a> {
};
self.adapter.produce(EngineResp::GetBlobs(resp));
}

#[inline]
pub(crate) fn payload_bodies(
&mut self,
spine_id: u64,
response: Result<&mut [u8], EngineError>,
) {
let resp = match response {
Ok(raw) => match self.encode(raw, json_get_payload_bodies_to_tcache) {
Ok(Some(((), data))) => {
tracing::info!(id = spine_id, "getPayloadBodies ok");
EngineGetPayloadBodiesResp { id: spine_id, ok: true, data }
}
Ok(None) => {
tracing::warn!("getPayloadBodies TCache full");
get_payload_bodies_error(spine_id)
}
Err(e) => {
tracing::warn!("getPayloadBodies parse error: {e}");
get_payload_bodies_error(spine_id)
}
},
Err(e) => {
tracing::warn!("getPayloadBodies error: {e}");
get_payload_bodies_error(spine_id)
}
};
self.adapter.produce(EngineResp::GetPayloadBodies(resp));
}
}

#[inline]
Expand Down Expand Up @@ -390,11 +355,6 @@ fn get_payload_error(id: u64) -> EngineGetPayloadResp {
EngineGetPayloadResp { id, ok: false, data: unsafe { std::mem::zeroed() } }
}

#[inline]
fn get_payload_bodies_error(id: u64) -> EngineGetPayloadBodiesResp {
EngineGetPayloadBodiesResp { id, ok: false, data: unsafe { std::mem::zeroed() } }
}

#[inline]
fn fcu_error(block_root: [u8; 32]) -> EngineFcuResp {
EngineFcuResp {
Expand Down
Loading
Loading