# Besu Glamsterdam public-page conformance review

Review date: 2026-10-27. Scope was public source pages only; no node or network was queried. I found no defensible, line-level Besu consensus/security candidate in the requested surfaces. One important coverage limitation is recorded below.

## Pins and scope

* Besu `main`: `aa06c4f8dfc461e483d46c6a1ac72b5bfef8d945`, from https://api.github.com/repos/besu-eth/besu/commits/main.
* execution-specs `forks/bogota`: `7f2f4c9bf6d73b09ecb8b24eb14d08bf0cf0247b`, from https://api.github.com/repos/ethereum/execution-specs/commits/forks/bogota.
* execution-apis: the requested `master` ref does not exist (GitHub API returned “No commit found for SHA: master”), so the API source was read at its public `master` raw URL as requested; it currently resolves to the Amsterdam document used below. This is a source-ref discrepancy, not a fabricated pin.
* Geth `master`: `8817f99f92852f8ac53e596de6202dd9e3494065`, from https://api.github.com/repos/ethereum/go-ethereum/commits/master.

The Glamsterdam meta EIP is EIP-7773 (still Review/Draft rather than Final). Its current inclusion list includes EIP-7843, EIP-7928, EIP-7997, and EIP-8282 among the execution changes. See https://eips.ethereum.org/EIPS/eip-7773. Current EIP pages describe 7843 (SLOTNUM), 7928 (BAL), 7997 (Deterministic Factory Contract), and 8282 (Builder Execution Requests); the relevant pages are https://eips.ethereum.org/EIPS/eip-7843, https://eips.ethereum.org/EIPS/eip-7928, https://eips.ethereum.org/EIPS/eip-7997, and https://eips.ethereum.org/EIPS/eip-8282. The EIP pages are the current draft specification text for these proposals; EIP-7773 explicitly says the scope can change while the meta EIP is not final.

## Rules checked and results

| Rule | Besu source at pin | Result |
|---|---|---|
| Builder request contracts are fixed at 0x...D8282 and 0x...E8282; types 0x03/0x04 | `ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestContractAddresses.java#L31-L37`; `MainnetRequestsProcessor.java#L27-L49` | Correct |
| Builder calls are empty-data system calls and failure/no-code invalidates | `MainnetRequestsProcessor.java#L31-L49`; `SystemCallRequestProcessor.java#L49-L60`; `SystemCallProcessor.java#L69-L106` | Correct |
| System-call gas is 30,000,000, with Amsterdam state-gas reservoir support | `SystemCallProcessor.java#L45-L57`; `SystemCallProcessor.java#L210-L254` | Correct for the reviewed implementation |
| Requests are ascending by type and empty request data is omitted from canonical encoding | `RequestProcessorCoordinator.java#L39-L49`; `ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Request.java#L62-L75` | Correct; coordinator is a sorted map and canonicalization filters empty data |
| Requests hash is the SHA-256-of-item-SHA-256 construction | `Request.java#L52-L60` plus Besu request-header validation path | No discrepancy found in inspected path; direct hash helper was not exposed in the selected tree slice |
| `newPayloadV5` requires BAL and slot number, hashes raw BAL into header | `EngineNewPayloadV5.java#L61-L73`, `#L75-L93` | Correct |
| Invalid BAL encoding is INVALID payload, while missing BAL is invalid params | `EngineNewPayloadV5.java#L108-L138` | Correct |
| `getPayloadV6` returns ExecutionPayloadV4 and execution requests | `EngineGetPayloadV6.java#L44-L67` | Correct |
| `forkchoiceUpdatedV4` has third `custodyColumns`, exactly 16 bytes, and errors are isolated | `EngineForkchoiceUpdatedV4.java#L87-L119`, `#L122-L143` | Correct |
| V4 payload attributes require slot number and target gas limit; slot is passed to builder | `EngineForkchoiceUpdatedV4.java#L151-L183` | Correct |
| EIP-7997 factory: no fork-boundary existence check/state mutation | No matching factory/state-transition implementation path was found in the pinned Besu source tree | Not verifiable as an implemented surface; no line-level candidate asserted |

The execution-specs anchors for the comparison are: request types `src/ethereum/forks/amsterdam/requests.py#L93-L105`; request hash `#L307-L326`; fixed addresses and system gas `src/ethereum/forks/amsterdam/fork.py#L103-L125` and `#L699-L721`; request ordering, non-empty-only collection, and builder calls `fork.py#L855-L921`; header `requests_hash`, `block_access_list_hash`, and `slot_number` `src/ethereum/forks/amsterdam/blocks.py#L241-L268`.

The Amsterdam Engine API text says `newPayloadV5` must return unsupported-fork for timestamps outside Amsterdam, invalid params for missing BAL, and INVALID for bad BAL encoding: https://raw.githubusercontent.com/ethereum/execution-apis/master/src/engine/amsterdam.md#L100-L127. It defines the V4 payload fields at `#L49-L91`, `getPayloadV6` at `#L128-L152`, and the third `custodyColumns` parameter plus the independent-update rule at `#L203-L242`.

## Candidate findings

None. In particular, Besu’s builder request code calls the same checked system-call operation as the execution spec, and `SystemCallProcessor` explicitly rejects both missing code and non-success completion. Its sorted processor map plus `Request.asCanonicalList` agrees with the spec’s ascending type order and non-empty-data rule. The Engine API field and validation paths above agree with the Amsterdam API text. I did not promote the EIP-7997 coverage gap to a candidate because the requested six-part candidate format requires a concrete client file and trigger; neither can be honestly supplied for an absent implementation.

For completeness, the Geth cross-check agrees on the Engine API edge cases: `eth/catalyst/api.go#L221-L243` checks V4 slot number, Amsterdam fork gating, and updates custody only after parameter checks; `#L865-L887` checks V5 slot number, BAL presence, and distinguishes malformed payload validation from parameter errors. Source: https://raw.githubusercontent.com/ethereum/go-ethereum/8817f99f92852f8ac53e596de6202dd9e3494065/eth/catalyst/api.go.

Disproof attempts: I compared each requested rule against the EELS fork code and Engine API prose, checked boundary conditions (empty request output, absent code, failed system call, missing versus malformed BAL, zero-valued/any uint64 slot, wrong-length custody bitmap), and inspected the pinned Besu tree for the EIP-7997 factory address and fork-boundary state transition. These checks produced no confirmed difference. No live-mainnet withholding rule was triggered because the reviewed Amsterdam paths are pre-mainnet Glamsterdam code.

## Known-check

Queries were made against Besu issues and pull requests, open and closed, using `EIP-8282`, `EIP-7997`, `newPayloadV5`, `forkchoiceUpdatedV4`, and `Amsterdam`. Relevant implementation/history pages found were closed PR #10743 (EIP-8282), closed PR #10929 (builder predeploy addresses), and open issue #11726 (Amsterdam network support): https://github.com/besu-eth/besu/pull/10743, https://github.com/besu-eth/besu/pull/10929, https://github.com/besu-eth/besu/issues/11726. Since there is no candidate, none is marked “known”; these are context/results, not known duplicates.

The execution-specs Test Release Tracker query returned open issue #3217 and closed Glamsterdam tracker issues #3311, #3452, #3479, and #3518. No Besu-specific defect corresponding to a candidate was identified: https://github.com/ethereum/execution-specs/issues/3217.

The public Hive listing was read at https://hive.ethpandaops.io/glamsterdam/listing.jsonl. Besu entries include `consume-enginex` 83,189/83,258 passing (69 failing), `consume-engine` 44,216/44,225 passing (9 failing), and `execute` 173/173 passing for the listed develop builds. These aggregate results neither identify a requested-rule failure nor justify a candidate without the per-test evidence, so they are recorded but not treated as proof of conformance.

## URLs read

EIP-7773 and EIPs 7843/7928/7997/8282 (links above); pinned Besu, execution-specs, and Geth raw/API URLs above; execution-apis Amsterdam raw document above; Besu issue/PR search results and execution-specs tracker above; Hive listing above.
