Skip to content

Update EIP-8024: Switch to branchless normalization and extend EXCHANGE#11306

Merged
eth-bot merged 4 commits into
ethereum:masterfrom
frangio:8024-branchless
Feb 25, 2026
Merged

Update EIP-8024: Switch to branchless normalization and extend EXCHANGE#11306
eth-bot merged 4 commits into
ethereum:masterfrom
frangio:8024-branchless

Conversation

@frangio
Copy link
Copy Markdown
Contributor

@frangio frangio commented Feb 11, 2026

Changes the encodings to slightly simpler ones that normalize the immediate to a contiguous range in a branchless way, and adds two more swappable pairs to EXCHANGE.

Suggested by @chfast in https://ethereum-magicians.org/t/eip-8024-backward-compatible-swapn-dupn-exchange/25486/7.

@github-actions github-actions Bot added c-update Modifies an existing proposal s-review This EIP is in Review t-core labels Feb 11, 2026
@eth-bot
Copy link
Copy Markdown
Collaborator

eth-bot commented Feb 11, 2026

✅ All reviewers have approved.

Copy link
Copy Markdown
Member

@chfast chfast left a comment

Choose a reason for hiding this comment

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

Big thanks for materializing this idea into the spec update.

Comment thread EIPS/eip-8024.md Outdated
return (x + 145) & 0xff

def decode_pair(x: int) -> tuple[int, int]:
assert 0 <= x <= 79 or 128 <= x <= 255
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why the range of valid byte values is different here?

Copy link
Copy Markdown
Contributor Author

@frangio frangio Feb 13, 2026

Choose a reason for hiding this comment

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

If we use the same domain as decode_single, we either have a discontinuity in the pairs that can be represented1, or there would be two ways to encode the same pair. So the range is reduced to keep this a bijection. We could try to map the extra available domain to some other continuous section but I figured the complexity wasn't worth it.

Footnotes

  1. You'd be able to swap 11,16 and 11,18 but not 11,17.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I found a way to extend EXCHANGE with two more pairs, making 14,15 and 14,16 swappable.

d4f4578

@frangio frangio changed the title Update EIP-8024: Switch to branchless normalization Update EIP-8024: Switch to branchless normalization and extend EXCHANGE Feb 13, 2026
Comment thread EIPS/eip-8024.md Outdated
rakita added a commit to bluealloy/revm that referenced this pull request Feb 24, 2026
Update decode_single/decode_pair to use branchless arithmetic per
ethereum/EIPs#11306: modular add for single values, XOR for pairs.
Extends EXCHANGE to support 2 additional swappable pairs (n up to 14).
@frangio frangio marked this pull request as ready for review February 25, 2026 13:08
@frangio frangio requested a review from eth-bot as a code owner February 25, 2026 13:08
Comment thread EIPS/eip-8024.md
3. If `79 < x < 128`, halt with exceptional failure.
3. If `81 < x < 128`, halt with exceptional failure.
4. Let `n, m = decode_pair(x)`.
5. If `m + 1 > len(stack)`, halt with exceptional failure.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks a lot @frangio :)

I have a question about the EXCHANGE depth check. If I understand correctly, the forbidden range implicitly ensures that decode_pair always produces n < m (with max n = 14, max m = 29). This invariant can be inferred from the encode_pair precondition, but not as a postcondition of decode_pair. Since the depth check only validates m, I believe it would be valuable for implementers to know that decode_pair also guarantees n < m, otherwise stack[top - n] could be an out-of-bounds access.

Would it make sense to either change the depth check to be defensive

Suggested change
5. If `m + 1 > len(stack)`, halt with exceptional failure.
5. If `max(n, m) + 1 > len(stack)`, halt with exceptional failure.

Or, since decode_pair should always produce n < m, maybe add an assert to make the invariant explicit like in encode_pair?

  def decode_pair(x: int) -> tuple[int, int]:
      # ...
      if q < r:
          n, m = q + 1, r + 1
      else:
          n, m = r + 1, 29 - q
      assert 1 <= n < m <= 29 and n + m <= 30
      return n, m

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh sorry, my mistake. I thought the diff showed you removing the assertion on the input x rather than modifying it. So asserting the result seems unnecessary.

Copy link
Copy Markdown
Contributor Author

@frangio frangio Feb 25, 2026

Choose a reason for hiding this comment

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

I still think there is an opportunity to make this clearer, though I prefer to keep the instruction spec as it is now. See #11351

By the way I realized with the new EXCHANGE it's much simpler to check whether a pair is swappable. Basically just n + m <= 30.

@eth-bot eth-bot enabled auto-merge (squash) February 25, 2026 13:39
Copy link
Copy Markdown
Collaborator

@eth-bot eth-bot left a comment

Choose a reason for hiding this comment

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

All Reviewers Have Approved; Performing Automatic Merge...

@eth-bot eth-bot merged commit d0b75a6 into ethereum:master Feb 25, 2026
18 checks passed
@frangio frangio deleted the 8024-branchless branch February 25, 2026 14:42
edg-l added a commit to lambdaclass/ethrex that referenced this pull request Mar 2, 2026
Align DUPN, SWAPN, and EXCHANGE decoding with the updated EIP-8024 spec
(ethereum/EIPs#11306). decode_single now uses (x + 145) % 256 instead of
branching, and decode_pair uses XOR 0x8F instead of conditional subtraction.
EXCHANGE valid range extended from 0x00-0x4F to 0x00-0x51, adding two new
swappable pairs (14,15) and (14,16).
edg-l added a commit to lambdaclass/ethrex that referenced this pull request Mar 3, 2026
Align DUPN, SWAPN, and EXCHANGE decoding with the updated EIP-8024 spec
(ethereum/EIPs#11306). decode_single now uses (x + 145) % 256 instead of
branching, and decode_pair uses XOR 0x8F instead of conditional subtraction.
EXCHANGE valid range extended from 0x00-0x4F to 0x00-0x51, adding two new
swappable pairs (14,15) and (14,16).
MariusVanDerWijden pushed a commit to ethereum/go-ethereum that referenced this pull request Mar 4, 2026
For bal-devnet-3 we need to update the EIP-8024 implementation to the
latest spec changes: ethereum/EIPs#11306

> Note: I deleted tests not specified in the EIP bc maintaining them
through EIP changes is too error prone.
rakita added a commit to bluealloy/revm that referenced this pull request Mar 13, 2026
* feat(interpreter): update EIP-8024 encoding to branchless normalization

Update decode_single/decode_pair to use branchless arithmetic per
ethereum/EIPs#11306: modular add for single values, XOR for pairs.
Extends EXCHANGE to support 2 additional swappable pairs (n up to 14).

* feat(primitives): rename EIP-7708 Selfdestruct event to Burn

Rename the EIP-7708 selfdestruct log event from
`Selfdestruct(address,uint256)` to `Burn(address,uint256)` per
EIP PR #11311. This updates the topic hash and makes the event
name more generic for any future ETH burn mechanism.

* feat(primitives): add EIP-7954 contract size limits for Amsterdam

Add spec-aware max_code_size (0x8000) and max_initcode_size (0x10000)
defaults for AMSTERDAM+, falling back to EIP-170/EIP-3860 for earlier specs.

* style: apply rustfmt formatting

* chore(scripts): temporarily skip devnet tests in run-tests.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c-update Modifies an existing proposal s-review This EIP is in Review t-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants