Skip to content

fix(l1): bound EIP-7702 authorization y_parity to a single byte#6753

Open
ElFantasma wants to merge 1 commit into
mainfrom
fix/eip7702-y-parity-bound
Open

fix(l1): bound EIP-7702 authorization y_parity to a single byte#6753
ElFantasma wants to merge 1 commit into
mainfrom
fix/eip7702-y-parity-bound

Conversation

@ElFantasma
Copy link
Copy Markdown
Contributor

Summary

EIP-7702 bounds an authorization tuple's y_parity to < 2**8 (it must fit in a single byte); geth models it as a uint8 and rejects an out-of-range value at RLP decode, which makes the whole transaction — and any block containing it — invalid.

ethrex typed y_parity as U256 and decoded it with no bound, so a value like 256 decoded successfully. At execution eip7702_recover_address returns Ok(None) for any non-0/1 y_parity and the authorization tuple is silently skipped (the transaction stays valid). The result: a type-4 transaction with y_parity >= 2**8 is accepted and executed by ethrex but rejected at decode by other clients → an L1 block carrying it splits ethrex from the network.

Note the bound is purely a field-size rule: y_parity values in 2..=255 are in range, fail signature recovery, and are skipped (tuple ignored, tx valid) — matching geth. Only >= 2**8 diverges, and only that is changed here.

Fix

Type the field as u8 (crates/common/types/tx_fields.rs), making the < 2**8 bound a type invariant:

  • RLP decode into a u8 now rejects >= 256 automatically, matching geth's uint8.
  • From<AuthorizationTupleEntry> for AuthorizationTuple becomes TryFrom, so the JSON-RPC input path (eth_sendTransaction) also rejects out-of-range y_parity instead of silently truncating. Callers (the tx deserializer, GenericTransaction conversion, and vm_from_generic) thread the fallible conversion.
  • eip7702_recover_address simplifies to a u8 comparison and drops a now-redundant try_into.

The 2..=255→skip behavior is unchanged.

Test

Adds authorization_tuple_rejects_y_parity_at_or_above_256, which hand-builds the RLP of an authorization tuple with y_parity = 256 (type-agnostic) and asserts decode rejects it — the chokepoint a type-4 transaction's authorization_list decodes through. Confirmed red on the pre-fix code (decoded y_parity: 256) and green after.

@ElFantasma ElFantasma requested review from a team as code owners May 29, 2026 20:48
@github-actions
Copy link
Copy Markdown

⚠️ Known Issues — intentionally skipped tests

Source: docs/known_issues.md

Known Issues

Tests intentionally excluded from CI. Source of truth for the Known
Issues
section the L1 workflow appends to each ef-tests job summary
and posts as a sticky PR comment.

EF Tests — Stateless coverage narrowed to EIP-8025 optional-proofs

make -C tooling/ef_tests/blockchain test calls test-stateless-zkevm
instead of test-stateless. The zkevm@v0.3.3 fixtures are filled against
bal@v5.6.1, out of sync with current bal spec; the broad target trips ~549
fixtures. Re-broaden once the zkevm bundle is regenerated.

Why and resolution path

PR #6527 broadened
test-stateless to extract the entire for_amsterdam/ tree from the
zkevm bundle and run all of it under --features stateless; combined with
this branch's bal-devnet-7 semantics that scope produces ~549
GasUsedMismatch / ReceiptsRootMismatch /
BlockAccessListHashMismatch failures.

test-stateless-zkevm filters cargo to the eip8025_optional_proofs
suite, which still validates the stateless harness without the bal-version
mismatch.

Re-broaden by switching test: back to test-stateless in
tooling/ef_tests/blockchain/Makefile once the zkevm bundle is regenerated
against the current bal spec.

@github-actions github-actions Bot added the L1 Ethereum client label May 29, 2026
@github-actions
Copy link
Copy Markdown

🤖 Kimi Code Review

This PR correctly fixes a consensus-critical EIP-7702 compliance issue by enforcing the y_parity < 2**8 bound at the type level. The changes are sound and idiomatic.

Summary of changes:

  1. Changed AuthorizationTuple.y_parity from U256 to u8 in tx_fields.rs
  2. Converted From to TryFrom for AuthorizationTupleEntryAuthorizationTuple conversion with proper validation
  3. Updated all call sites to handle the fallible conversion
  4. Added regression test for RLP decoding rejection of out-of-range values

Review feedback:

crates/common/types/tx_fields.rs:44-47
Good: The comment clearly explains the EIP-7702 rationale. Removing the #[rkyv(with = ...)] attribute is correct since u8 doesn't require custom serialization.

crates/common/types/transaction.rs:1907-1910
Good: The TryFrom implementation correctly validates the bound and provides a descriptive error message. Note that you're converting from U256 (entry) to u8 (internal), which is the correct direction for validation.

crates/common/types/transaction.rs:2450-2454
Good: Proper use of collect::<Result<Vec<_>, _>>() to short-circuit on first error and propagate via serde::de::Error::custom.

crates/vm/levm/src/utils.rs:218
Good: The simplified comparison auth_tuple.y_parity != 1 && auth_tuple.y_parity != 0 is correct and more efficient than the previous U256 comparisons.

crates/vm/levm/src/utils.rs:227
Good: Eliminating the fallible TryInto conversion is safe now that the type is u8, removing a potential panic path.

crates/common/types/tx_fields.rs:88-121 (test)
Good: The test correctly constructs RLP with an out-of-range value (256) and verifies decoding fails. This prevents consensus splits where ethrex would accept transactions that geth rejects.

Minor observations:

  • Error type consistency: In crates/vm/backends/levm/mod.rs:2794, you map the specific "authorization tuple y_parity exceeds 2**8" error to a generic InternalError::TypeConversion. This is acceptable for internal VM boundaries, though you might consider preserving the message for debugging if this error path is observable.

  • Serde field: In transaction.rs, AuthorizationTupleEntry presumably retains y_parity: U256 (implied by the conversion code). This is correct for JSON-RPC compatibility where clients might send malformed large integers that need validation during deserialization.

Verdict: Approving. This is a clean, security-focused fix that prevents a consensus split by enforcing EIP-7702 constraints at the type system and deserialization boundaries.


Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt

@github-actions
Copy link
Copy Markdown

🤖 Codex Code Review

  1. crates/common/types/tx_fields.rs:46 changes AuthorizationTuple::y_parity from U256 to u8, but a few existing test helpers still construct it with U256. That leaves the tree uncompilable once those test targets are built: test/tests/blockchain/eip7702_revert_authority_tests.rs, test/tests/blockchain/eip7702_zero_transfer_tests.rs, and test/tests/levm/eip8037_tests.rs. Those initializers need to be updated to u8 values.

Aside from that, the change itself looks correct and consensus-hardening: decoding AuthorizationTuple.y_parity as u8 in crates/common/types/tx_fields.rs closes the out-of-range RLP acceptance gap, and the new TryFrom validation in crates/common/types/transaction.rs correctly propagates the bound to JSON/generic transaction paths.

I couldn’t run the full test suite in this environment because the sandbox blocks rustup/cargo writes and network fetches, so the review is based on source inspection.


Automated review by OpenAI Codex · gpt-5.4 · custom prompt

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR fixes a consensus split risk in EIP-7702 (type-4) transaction processing: y_parity in AuthorizationTuple was typed as U256 and decoded without an upper-bound check, so an authorization tuple with y_parity >= 256 was silently accepted by ethrex but rejected at RLP decode by geth and other clients. The fix narrows the type to u8, making the < 2**8 bound a compile-time invariant enforced by the RLP decoder.

  • tx_fields.rs: AuthorizationTuple.y_parity changed from U256 to u8; RLP encode/decode and the new regression test all use the narrowed type.
  • transaction.rs: From<AuthorizationTupleEntry> upgraded to TryFrom, propagating an error when y_parity doesn't fit in a u8; both the direct deserialization path and the GenericTransaction conversion path now fail-fast.
  • levm/mod.rs / levm/utils.rs: vm_from_generic threads the fallible conversion, and eip7702_recover_address drops the now-unnecessary try_into boilerplate.

Confidence Score: 4/5

Safe to merge; the change is well-scoped, closes a real consensus-split bug, and all affected call sites have been updated consistently.

The structural change is correct and the regression test directly exercises the chokepoint. The only remaining rough edge is the TryFrom::Error = String on the JSON-RPC conversion path, which causes callers to discard the diagnostic message — a style concern that does not affect correctness.

No files require special attention; transaction.rs has the minor untyped-error pattern noted above, but it does not affect the correctness of the fix.

Important Files Changed

Filename Overview
crates/common/types/tx_fields.rs Core structural fix: y_parity narrowed from U256 to u8; RLP decode now rejects >= 256 automatically. Regression test correctly verifies the rejection.
crates/common/types/transaction.rs From upgraded to TryFrom with String error type; all three call sites (serde deserialization, GenericTransaction conversion, vm_from_generic) correctly propagate the failure. The untyped String error is a minor style point.
crates/vm/backends/levm/mod.rs vm_from_generic now collects authorization list with try_from; TypeConversion error correctly surfaced if an out-of-range entry slips through earlier validation.
crates/vm/levm/src/utils.rs eip7702_recover_address simplified: infallible u8 assignment replaces the former TryInto. The 2..=255 → Ok(None) guard is unchanged and still correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Incoming type-4 tx bytes] --> B[RLPDecode AuthorizationTuple]
    B -->|y_parity gt 255| C[RLPDecodeError - rejects block]
    B -->|y_parity 0-255| D[AuthorizationTuple - y_parity as u8]
    D --> E[eip7702_recover_address]
    E -->|y_parity 2-255| F[Ok None - tuple skipped, tx valid]
    E -->|y_parity 0 or 1| G[ECDSA recovery - Ok Some address]

    H[JSON-RPC eth_sendTransaction] --> I[Deserialize GenericTransaction - AuthorizationTupleEntry y_parity as U256]
    I --> J[TryFrom into AuthorizationTuple]
    J -->|y_parity gt 255| K[Error propagated to caller]
    J -->|y_parity 0-255| D
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
crates/common/types/transaction.rs:1901-1912
**Untyped `String` error makes the `TryFrom` contract opaque**

`TryFrom<AuthorizationTupleEntry>` declares `type Error = String`, which callers must either discard (`map_err(|_| …)`) or forward as a raw string. `vm_from_generic` already discards the message with `|_|`, so the descriptive string is lost at the only call site that propagates an `InternalError`. Consider promoting this to a dedicated variant (e.g., `GenericTransactionError::InvalidYParity`) or at least a `Box<dyn std::error::Error>`, so callers can preserve structure without losing the diagnostic.

Reviews (1): Last reviewed commit: "fix(l1): bound EIP-7702 authorization y_..." | Re-trigger Greptile

Comment on lines +1901 to 1912
impl TryFrom<AuthorizationTupleEntry> for AuthorizationTuple {
type Error = String;

// EIP-7702 bounds y_parity to < 2**8; reject anything that doesn't fit a u8.
fn try_from(entry: AuthorizationTupleEntry) -> Result<AuthorizationTuple, Self::Error> {
Ok(AuthorizationTuple {
chain_id: entry.chain_id,
address: entry.address,
nonce: entry.nonce,
y_parity: entry.y_parity,
y_parity: TryInto::<u8>::try_into(entry.y_parity)
.map_err(|_| "authorization tuple y_parity exceeds 2**8".to_string())?,
r_signature: entry.r,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Untyped String error makes the TryFrom contract opaque

TryFrom<AuthorizationTupleEntry> declares type Error = String, which callers must either discard (map_err(|_| …)) or forward as a raw string. vm_from_generic already discards the message with |_|, so the descriptive string is lost at the only call site that propagates an InternalError. Consider promoting this to a dedicated variant (e.g., GenericTransactionError::InvalidYParity) or at least a Box<dyn std::error::Error>, so callers can preserve structure without losing the diagnostic.

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/common/types/transaction.rs
Line: 1901-1912

Comment:
**Untyped `String` error makes the `TryFrom` contract opaque**

`TryFrom<AuthorizationTupleEntry>` declares `type Error = String`, which callers must either discard (`map_err(|_| …)`) or forward as a raw string. `vm_from_generic` already discards the message with `|_|`, so the descriptive string is lost at the only call site that propagates an `InternalError`. Consider promoting this to a dedicated variant (e.g., `GenericTransactionError::InvalidYParity`) or at least a `Box<dyn std::error::Error>`, so callers can preserve structure without losing the diagnostic.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@github-actions
Copy link
Copy Markdown

Lines of code report

Total lines added: 25
Total lines removed: 1
Total lines changed: 26

Detailed view
+-------------------------------------------+-------+------+
| File                                      | Lines | Diff |
+-------------------------------------------+-------+------+
| ethrex/crates/common/types/transaction.rs | 3407  | +4   |
+-------------------------------------------+-------+------+
| ethrex/crates/common/types/tx_fields.rs   | 101   | +20  |
+-------------------------------------------+-------+------+
| ethrex/crates/vm/backends/levm/mod.rs     | 2397  | +1   |
+-------------------------------------------+-------+------+
| ethrex/crates/vm/levm/src/utils.rs        | 627   | -1   |
+-------------------------------------------+-------+------+

@github-actions
Copy link
Copy Markdown

🤖 Claude Code Review

Now I have enough context to write the full review.


Code Review: PR #6753fix(l1): bound EIP-7702 authorization y_parity to a single byte

Overview

This PR fixes a consensus-split vulnerability: ethrex was decoding type-4 (EIP-7702) transactions whose y_parity field encodes >= 256 without error, while all other clients (geth models it as uint8) reject them at the RLP decode boundary. A block carrying such a transaction would be accepted by ethrex and rejected by every other client, causing a chain split.

The fix is correct in principle: changing the field type from U256 to u8 makes the < 2**8 invariant a type invariant, so the RLP decoder rejects out-of-range values automatically. The regression test is well-structured and directly validates the choke point.


Correctness — Core Fix

The L1 path is sound:

  • tx_fields.rsy_parity: u8 causes Decoder::decode_field("y_parity") to use the u8 RLP impl, which rejects a multi-byte encoding. Verified by inspection of impl RLPDecode for AuthorizationTuple (lines 68–90).
  • utils.rs — the comparison simplification (!= 1 && != 0 over != U256::one() && != U256::zero()) and the removal of the now-redundant try_into are both correct.
  • transaction.rs — the TryFrom<AuthorizationTupleEntry> and the From<&AuthorizationTuple> for AuthorizationTupleEntry (inverse, y_parity: U256::from(value.y_parity)) form a correct round-trip for the JSON-RPC path.
  • vm_from_generic in levm/mod.rs — correctly handles the now-fallible conversion for the VM construction path.

Issues Found

1. L2 JSON deserialization regression (medium)

crates/l2/networking/rpc/l2/transaction.rs line 24:

pub authorization_list: Option<AuthorizationList>,

AuthorizationList = Vec<AuthorizationTuple>. When this field is deserialized from JSON the derived Deserialize impl for AuthorizationTuple is used directly, and y_parity: u8 expects a JSON integer.

However, crates/l2/networking/rpc/clients.rs lines 127–131 serialize authorization tuples via AuthorizationTupleEntry (which has y_parity: U256) before sending:

let authorization_list = authorization_list.map(|list| {
    list.iter().map(AuthorizationTupleEntry::from).collect::<Vec<_>>()
});

Since ethereum-types = { version = "0.15.1", features = ["serialize"] } serializes U256 as a hex string (e.g. "0x1"), the L2 client sends "y_parity": "0x1". The L2 server now tries to parse that hex string into u8, which fails — serde's u8 deserializer rejects strings.

Before this PR: AuthorizationTuple.y_parity: U256 deserialized from "0x1" correctly.
After this PR: same JSON fails to deserialize.

The fix is to add a custom deserializer to the field in tx_fields.rs:

#[serde(deserialize_with = "crate::serde_utils::u8::deser_hex_or_dec")]
pub y_parity: u8,

or change the L2 struct to use AuthorizationTupleEntry for deserialization instead of AuthorizationTuple directly, mirroring the L1 path.


2. rkyv binary format change (low — worth documenting)

AuthorizationTuple derives Archive/RSerialize/RDeserialize and is transitively included in EIP7702Transaction, which is rkyv-serialized in crates/l2/storage/src/store_db/sql.rs (line 381) for prover inputs.

The old format encoded y_parity as a custom U256Wrapper (32 bytes on the wire); the new format encodes it as a native u8 (1 byte). Any persisted prover-input blobs containing an EIP-7702 transaction will fail to deserialize after this upgrade. If the L2 storage is treated as ephemeral (regenerated per-block), this is harmless. If blobs survive a node restart, a migration note should be added.


3. Error message is slightly imprecise (cosmetic)

transaction.rs line 1911:

.map_err(|_| "authorization tuple y_parity exceeds 2**8".to_string())?

256 equals 2**8, it doesn't exceed it. The check rejects values >= 256. Prefer: "y_parity must be < 2**8 (got a value that does not fit in a byte)" or simply "y_parity out of range".


4. vm_from_generic silently discards the error string (cosmetic)

levm/mod.rs lines 2794–2795:

.map_err(|_| InternalError::TypeConversion)?

The String error from the TryFrom impl is thrown away. This can't be triggered in practice (the transaction was already validated upstream), but if it ever is hit during debugging the loss of context is frustrating. .map_err(|e| { tracing::warn!(...); InternalError::TypeConversion }) or at minimum keeping the message if InternalError supports it would help.


5. Test boundary coverage (minor)

The test exercises only y_parity = 256 (first out-of-range value). Adding cases for 255 (last valid byte, should decode OK) and at least 0/1 (valid signature parities, should decode OK) would give a more complete regression suite and document the intended boundary explicitly.


What Looks Good

  • The RLP decode path is the correct single choke-point to guard: everything that brings an EIP-7702 transaction in from the network or from a block body passes through AuthorizationTuple::decode. Putting the bound there rather than at each callsite is the right design.
  • The From<AuthorizationTupleEntry> → TryFrom change is correctly threaded through all three callsites with appropriate error types.
  • The eip7702_recover_address simplification is clean and the removal of the now-unreachable try_into is correct.
  • The regression test is self-contained, type-agnostic (builds the RLP directly so the test doesn't depend on the field type), and includes a descriptive failure message.
  • The PR description clearly explains the before/after behavior for y_parity values in the range 2..=255 (still skipped, tx valid — matches geth) vs >= 256 (now rejected at decode).

Summary

The L1 fix is correct and necessary. The primary concern is Item 1 (L2 ethrex_sendTransaction deserialization regression) — it's a concrete functional break caused by the serde format change between U256 and u8 on a path that wasn't updated to use AuthorizationTupleEntry. The rkyv format concern (Item 2) is worth a comment at minimum. The rest are cosmetic.


Automated review by Claude (Anthropic) · sonnet · custom prompt

@github-actions
Copy link
Copy Markdown

Benchmark Results Comparison

No significant difference was registered for any benchmark run.

Detailed Results

Benchmark Results: BubbleSort

Command Mean [s] Min [s] Max [s] Relative
main_revm_BubbleSort 3.327 ± 0.033 3.283 3.404 1.13 ± 0.01
main_levm_BubbleSort 2.944 ± 0.019 2.914 2.967 1.00
pr_revm_BubbleSort 3.263 ± 0.017 3.242 3.297 1.11 ± 0.01
pr_levm_BubbleSort 2.948 ± 0.026 2.917 2.994 1.00 ± 0.01

Benchmark Results: ERC20Approval

Command Mean [s] Min [s] Max [s] Relative
main_revm_ERC20Approval 1.073 ± 0.029 1.044 1.127 1.00 ± 0.05
main_levm_ERC20Approval 1.112 ± 0.033 1.083 1.188 1.04 ± 0.05
pr_revm_ERC20Approval 1.071 ± 0.046 1.043 1.200 1.00
pr_levm_ERC20Approval 1.104 ± 0.013 1.088 1.124 1.03 ± 0.05

Benchmark Results: ERC20Mint

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Mint 144.8 ± 1.2 143.6 147.7 1.01 ± 0.01
main_levm_ERC20Mint 162.7 ± 3.0 160.3 169.9 1.14 ± 0.02
pr_revm_ERC20Mint 143.1 ± 0.9 141.8 144.6 1.00
pr_levm_ERC20Mint 162.5 ± 1.0 161.1 164.2 1.14 ± 0.01

Benchmark Results: ERC20Transfer

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ERC20Transfer 254.5 ± 4.6 249.2 260.9 1.01 ± 0.03
main_levm_ERC20Transfer 274.7 ± 5.3 270.0 288.0 1.09 ± 0.03
pr_revm_ERC20Transfer 252.2 ± 4.8 248.9 263.8 1.00
pr_levm_ERC20Transfer 275.0 ± 2.7 271.0 279.1 1.09 ± 0.02

Benchmark Results: Factorial

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Factorial 234.5 ± 5.5 228.6 243.7 1.00
main_levm_Factorial 269.4 ± 3.5 264.7 273.9 1.15 ± 0.03
pr_revm_Factorial 234.9 ± 6.0 229.0 246.5 1.00 ± 0.03
pr_levm_Factorial 271.2 ± 4.2 266.8 282.1 1.16 ± 0.03

Benchmark Results: FactorialRecursive

Command Mean [s] Min [s] Max [s] Relative
main_revm_FactorialRecursive 1.635 ± 0.095 1.409 1.739 1.04 ± 0.06
main_levm_FactorialRecursive 1.578 ± 0.008 1.564 1.588 1.00
pr_revm_FactorialRecursive 1.667 ± 0.042 1.617 1.754 1.06 ± 0.03
pr_levm_FactorialRecursive 1.585 ± 0.016 1.568 1.618 1.00 ± 0.01

Benchmark Results: Fibonacci

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Fibonacci 230.5 ± 8.7 221.4 245.3 1.00
main_levm_Fibonacci 253.3 ± 8.0 245.8 270.5 1.10 ± 0.05
pr_revm_Fibonacci 232.7 ± 8.7 223.7 245.4 1.01 ± 0.05
pr_levm_Fibonacci 249.7 ± 5.2 245.1 258.0 1.08 ± 0.05

Benchmark Results: FibonacciRecursive

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_FibonacciRecursive 866.4 ± 16.6 832.5 890.2 1.18 ± 0.02
main_levm_FibonacciRecursive 737.5 ± 7.6 728.6 754.3 1.00 ± 0.01
pr_revm_FibonacciRecursive 870.3 ± 14.4 855.1 900.7 1.18 ± 0.02
pr_levm_FibonacciRecursive 736.6 ± 4.1 729.3 742.0 1.00

Benchmark Results: ManyHashes

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_ManyHashes 9.1 ± 0.1 9.0 9.2 1.00
main_levm_ManyHashes 10.6 ± 0.1 10.5 10.8 1.16 ± 0.01
pr_revm_ManyHashes 9.2 ± 0.1 9.1 9.5 1.01 ± 0.02
pr_levm_ManyHashes 10.6 ± 0.1 10.5 10.7 1.17 ± 0.01

Benchmark Results: MstoreBench

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_MstoreBench 294.3 ± 5.3 287.0 300.8 1.26 ± 0.02
main_levm_MstoreBench 233.0 ± 0.9 232.1 234.6 1.00
pr_revm_MstoreBench 297.8 ± 6.1 286.8 308.7 1.28 ± 0.03
pr_levm_MstoreBench 236.5 ± 4.6 232.3 247.4 1.02 ± 0.02

Benchmark Results: Push

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_Push 327.7 ± 5.7 321.4 340.6 1.11 ± 0.02
main_levm_Push 294.7 ± 2.0 292.8 297.8 1.00
pr_revm_Push 328.7 ± 5.8 321.5 337.8 1.12 ± 0.02
pr_levm_Push 299.9 ± 9.6 293.3 321.9 1.02 ± 0.03

Benchmark Results: SstoreBench_no_opt

Command Mean [ms] Min [ms] Max [ms] Relative
main_revm_SstoreBench_no_opt 180.6 ± 2.2 178.7 185.8 1.58 ± 0.02
main_levm_SstoreBench_no_opt 114.6 ± 0.4 114.2 115.3 1.00
pr_revm_SstoreBench_no_opt 180.5 ± 1.4 179.2 183.7 1.58 ± 0.01
pr_levm_SstoreBench_no_opt 114.9 ± 0.4 114.1 115.3 1.00 ± 0.00

@ElFantasma
Copy link
Copy Markdown
Contributor Author

Ran the EIP-7702 Hive EELS suite against this branch (image built from the branch):

ethereum/eels/consume-rlp.*7702.* → 1210 passed / 0 failed (Prague + Osaka, tests/prague/eip7702_set_code_tx/...).

This is the RLP block-import path that this fix touches. Notable coverage in the run:

  • Invalid-authorization-tuple skip semantics — test_valid_tx_invalid_auth_signature, test_set_code_all_invalid_authorization_tuples, test_set_code_multiple_valid_authorization_tuples_first_invalid_same_signer, test_account_warming[...single_invalid_authorization...]. These passing confirms the change does not regress the "skip the invalid tuple, keep the tx" behavior for in-range, non-0/1 y_parity (the 2..=255 case we intentionally leave alone).
  • test_signature_s_out_of_range — the field-range analogue of this fix for the s field — passes.
  • Broad 7702 conformance (delegation, gas, nonce validity, chain-id, precompiles) intact.

Note: v5.3.0 doesn't appear to ship a fixture named specifically for y_parity >= 2**8 rejection, so the exact out-of-bounds decode rejection is covered by the unit test added here; Hive confirms surrounding conformance and no regression.

Also running consume-engine (newPayload path); will follow up with that result.

@ElFantasma
Copy link
Copy Markdown
Contributor Author

Follow-up: ethereum/eels/consume-engine.*7702.*1210 passed / 0 failed (engine newPayload path). Both consensus entry points (RLP import + newPayload) are green for the EIP-7702 fixtures with this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

L1 Ethereum client

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant