Skip to content

Commit c2c106f

Browse files
authored
feat(l1) Check withdrawals is not missing or null on v2 engine payloads. (#1606)
**Description** The difference between a v1 vs a v2 engine payload is the fact that v2 has a withdrawal field, this PR adds a check on V2 fork & engine endpoints to check this field is not missing. Closes #1605
1 parent c5dee10 commit c2c106f

File tree

4 files changed

+14
-4
lines changed

4 files changed

+14
-4
lines changed

.github/workflows/ci_l1.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ jobs:
179179
test_pattern: "engine-api/RPC|Re-Org Back to Canonical Chain From Syncing Chain|Re-org to Previously Validated Sidechain Payload|Re-Org Back into Canonical Chain, Depth=5|Safe Re-Org|Transaction Re-Org|Inconsistent|Suggested Fee|PrevRandao|Fork ID|Unknown|Invalid PayloadAttributes|Bad Hash|Unique Payload ID|Re-Execute Payload|In-Order|Multiple New Payloads|Valid NewPayload|NewPayload with|Invalid NewPayload|Payload Build|Invalid NewPayload, Transaction|ParentHash equals|Build Payload|Invalid Missing Ancestor ReOrg"
180180
- name: "Engine withdrawal tests"
181181
simulation: ethereum/engine
182-
test_pattern: "engine-withdrawals/engine-withdrawals test loader|GetPayloadV2 Block Value|Sync after 2 blocks - Withdrawals on Genesis|Max Initcode Size|Pre-Merge Fork Number > 0"
182+
test_pattern: "engine-withdrawals/engine-withdrawals test loader|GetPayloadV2 Block Value|Sync after 2 blocks - Withdrawals on Genesis|Max Initcode Size|Pre-Merge Fork Number > 0|Empty Withdrawals|Corrupted Block Hash Payload"
183183
- name: "Sync"
184184
simulation: ethereum/sync
185185
test_pattern: ""

crates/networking/rpc/engine/fork_choice.rs

+5
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ fn validate_v2(
214214
context: &RpcApiContext,
215215
) -> Result<(), RpcErr> {
216216
let chain_config = context.storage.get_chain_config()?;
217+
if attributes.withdrawals.is_none() {
218+
return Err(RpcErr::WrongParam(
219+
"forkChoiceV2 withdrawals is null".to_string(),
220+
));
221+
}
217222
if attributes.parent_beacon_block_root.is_some() {
218223
return Err(RpcErr::InvalidPayloadAttributes(
219224
"forkChoiceV2 with Beacon Root".to_string(),

crates/networking/rpc/engine/payload.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ impl RpcHandler for NewPayloadV2Request {
3939
}
4040

4141
fn handle(&self, context: RpcApiContext) -> Result<Value, RpcErr> {
42-
handle_new_payload_v1_v2(&self.payload, Fork::Shanghai, context)
42+
if self.payload.withdrawals.is_none() {
43+
Err(RpcErr::WrongParam(
44+
"forkChoiceV2 withdrawals is null".to_string(),
45+
))
46+
} else {
47+
handle_new_payload_v1_v2(&self.payload, Fork::Shanghai, context)
48+
}
4349
}
4450
}
4551

crates/networking/rpc/types/payload.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct ExecutionPayload {
3535
pub block_hash: H256,
3636
transactions: Vec<EncodedTransaction>,
3737
#[serde(skip_serializing_if = "Option::is_none", default)]
38-
withdrawals: Option<Vec<Withdrawal>>,
38+
pub withdrawals: Option<Vec<Withdrawal>>,
3939
// ExecutionPayloadV3 fields. Optional since we support V2 too
4040
#[serde(
4141
skip_serializing_if = "Option::is_none",
@@ -104,7 +104,6 @@ impl ExecutionPayload {
104104
ommers: vec![],
105105
withdrawals: self.withdrawals,
106106
};
107-
108107
let header = BlockHeader {
109108
parent_hash: self.parent_hash,
110109
ommers_hash: *DEFAULT_OMMERS_HASH,

0 commit comments

Comments
 (0)