# Grandine Gloas / EIP-7732 conformance review

## Scope and pins

This was a static, public-source review only: no node, devnet, or network
protocol was run.  It covers the Gloas ePBS state transition, fork transition,
SSZ declarations, and the directly related fork-choice envelope/PTC paths.  It
does not report any Fulu-live-code finding (none of the findings below is such a
finding).

| Repository / ref requested | Pinned revision used |
|---|---|
| Grandine `develop` | [`52cd677117b5d93bf477fe4843148070b0303444`](https://api.github.com/repos/grandinetech/grandine/commits/develop) |
| consensus-specs `master` | [`8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2`](https://api.github.com/repos/ethereum/consensus-specs/commits/master) |
| Nimbus `stable` | [`0abc0dd0fc0750a8875c49089d074f7d7197b62c`](https://api.github.com/repos/status-im/nimbus-eth2/commits/stable) |

The reviewed EIPs are [EIP-7732](https://eips.ethereum.org/EIPS/eip-7732)
(ePBS) and [EIP-8282](https://eips.ethereum.org/EIPS/eip-8282) (builder
requests), in the pinned Gloas spec above.  The master fork spec includes
[consensus-specs PR 5736](https://github.com/ethereum/consensus-specs/pull/5736),
which changed only fork-time builder onboarding relative to v1.7.0-beta.4.
Grandine targets **master/PR-5736 semantics**, not beta.4: its onboarding keeps
non-builder deposits queued, distinguishes existing validators and pending valid
validator deposits, accepts a valid builder registration using a validator
pubkey, and only then adds/tops up a builder
([fork.rs#L984-L1101](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/fork.rs#L984-L1101)).
That matches the master algorithm
([fork.md#L59-L121](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md#L59-L121)).

**Spec-version-lag candidate — disproved.** A fork state with a valid builder
deposit sharing a pubkey with a validator (or an earlier valid pending validator
top-up) is the discriminating condition.  Grandine retains/handles it under the
master rule rather than applying beta.4’s simpler pass, so no different state
root follows.  Nimbus stable independently implements the same master-style
pending-validator preservation and builder onboarding
([beaconstate.nim#L2308-L2405](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beaconstate.nim#L2308-L2405)).
Confidence high; disproof was line-by-line comparison of the fork algorithm and
both clients. Severity: cosmetic (no lag at this pin).

## Candidate

### G-1 — fork-boundary clock can make Gloas deadlines 250 ms early (known)

1. **Spec.** Fork choice defines the payload and PTC deadlines as slot-component
   durations: `return get_slot_component_duration_ms(PAYLOAD_DUE_BPS)` and
   `return get_slot_component_duration_ms(PAYLOAD_ATTESTATION_DUE_BPS)`
   ([fork-choice.md#L780-L791](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork-choice.md#L780-L791)); those deadlines feed block-timeliness recording
   ([fork-choice.md#L986-L1000](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork-choice.md#L986-L1000)).
2. **Grandine.** The next-tick search advances `next_tick` first, switches
   `tick_duration` based on that next tick’s phase, then adds it to elapsed time:
   `next_tick = next_tick.next...`; `if next_phase != current_phase { ... }`;
   `now_to_next_tick = now_to_next_tick.saturating_add(tick_duration)`
   ([clock/src/lib.rs#L502-L526](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/clock/src/lib.rs#L502-L526)).  The stream itself uses the current tick’s duration after emitting it
   ([clock/src/lib.rs#L398-L417](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/clock/src/lib.rs#L398-L417)), exposing the inconsistent transition ordering.
3. **Trigger/result.** Start or re-find the tick stream during the final
   pre-Gloas slot, after its 11th of 12 one-second ticks.  On crossing to a
   16-tick Gloas slot, the search charges the final pre-fork interval at 750 ms
   instead of one second.  Thus it can schedule the first Gloas tick and builder
   deadlines 250 ms early; messages/envelopes in that interval receive a
   different local timing/gossip treatment and can change the fork-choice
   timeliness input.  The submitted issue gives the concrete slot-64,
   767.5-second example and expected 768-second boundary.
4. **Nimbus comparison.** Nimbus computes Gloas payload and PTC deadlines from
   the configured basis-points offset
   ([beacon_time.nim#L135-L140](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beacon_time.nim#L135-L140),
   [#L182-L188](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/beacon_time.nim#L182-L188)) and waits on those deadlines
   ([beacon_validators.nim#L1087-L1099](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/validators/beacon_validators.nim#L1087-L1099)); it agrees with the spec’s deadline model, not Grandine’s boundary calculation.
5. **Confidence/disproof.** High.  I traced both branches and the 12-to-16 tick
   change (the latter is explicit at
   [clock/src/lib.rs#L355-L368](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/clock/src/lib.rs#L355-L368)).
   I also tried to disprove it by checking the emitted-stream update order; that
   loop uses the correct current-tick duration but does not repair the initial
   search. **Known:** open [Grandine PR #989](https://github.com/grandinetech/grandine/pull/989), “Fix clock deadlines at the Gloas fork boundary,” describes the same 250-ms case and proposes the ordering fix.
6. **Severity.** Fork-choice divergence (known; not a new report).

No other candidate met the requested threshold: the state-transition and
encoding differences investigated below either agree with the pinned master
spec or are already fixed/known.  In particular, the previously indexed
attestation-balance issue is closed/merged as
[Grandine PR #747](https://github.com/grandinetech/grandine/pull/747), and was
not re-reported.

## Rules checked and found conformant at the pin

| Rule / boundary checked | Grandine evidence | Result |
|---|---|---|
| Self-build: zero amount and infinity signature; builder active/version/signature; cover-bid floor | [block_processing.rs#L605-L665](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L605-L665), [predicates.rs#L466-L482](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/predicates.rs#L466-L482), and the BLS `empty()` encoding is `0xc0` followed by zeroes ([signature_bytes.rs#L66-L77](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/bls/bls-core/src/traits/signature_bytes.rs#L66-L77)). | Matches spec bid checks ([beacon-chain.md#L2159-L2197](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L2159-L2197)) and Nimbus ([state_transition_block.nim#L1252-L1301](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1252-L1301)). |
| Bid slot/genesis boundary, blob count, parent block/root, non-identical hash, RANDAO | [block_processing.rs#L668-L725](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L668-L725) | Correct; including `state.slot > GENESIS_SLOT`. |
| Payment insertion index, zero initial weight, quorum, epoch rollover | [block_processing.rs#L849-L884](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L849-L884), [epoch_processing.rs#L209-L238](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/epoch_processing.rs#L209-L238) | Matches master ([beacon-chain.md#L2199-L2215](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L2199-L2215), [#L1716-L1731](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1716-L1731)); Nimbus agrees ([state_transition_epoch.nim#L1394-L1415](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_epoch.nim#L1394-L1415)). |
| Empty-parent early return; nonempty parent request root/counts; required request order | [block_processing.rs#L728-L819](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L728-L819) | Correct against master ([beacon-chain.md#L1783-L1853](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1783-L1853)); Nimbus agrees ([state_transition_block.nim#L1373-L1411](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L1373-L1411)). |
| Withdrawals’ empty-parent early return, builder-before-partial-before-sweep order, builder sweep index | [block_processing.rs#L488-L579](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L488-L579) | Correct against ([beacon-chain.md#L2042-L2092](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L2042-L2092)). |
| Block payload-attestation parent root/previous slot/aggregate signature and limit | [block_processing.rs#L904-L960](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L904-L960), [#L1241-L1281](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/block_processing.rs#L1241-L1281) | Matches ([beacon-chain.md#L2485-L2499](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L2485-L2499)); Nimbus agrees ([state_transition_block.nim#L706-L728](https://raw.githubusercontent.com/status-im/nimbus-eth2/0abc0dd0fc0750a8875c49089d074f7d7197b62c/beacon_chain/spec/state_transition_block.nim#L706-L728)). |
| PTC: committee-order candidates, duplicate-capable weighted 16-bit selection, epoch window shift/refill | [accessors.rs#L1114-L1169](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/helper_functions/src/accessors.rs#L1114-L1169), [epoch_processing.rs#L189-L207](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/epoch_processing.rs#L189-L207) | Matches compute/window spec ([beacon-chain.md#L1195-L1229](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1195-L1229), [#L1263-L1282](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1263-L1282), [#L1734-L1748](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L1734-L1748)). |
| Envelope roots, bid commitments, parent hash/timestamp/withdrawals, signature, versioned hashes/EL notify | [store.rs#L4040-L4256](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/fork_choice_store/src/store.rs#L4040-L4256) | Matches ([fork-choice.md#L680-L726](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork-choice.md#L680-L726)). |
| Gloas defaults / SSZ order | State’s 46-field order is declared at [beacon_state.rs#L20-L140](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/types/src/gloas/beacon_state.rs#L20-L140); all consensus-facing Gloas containers, including body, builder, bid, envelope, requests, and PTC attestations, are in declaration order at [containers.rs#L38-L580](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/types/src/gloas/containers.rs#L38-L580). | Matches the state order ([beacon-chain.md#L900-L934](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L900-L934)) and `ExecutionRequests` order ([#L968-L982](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md#L968-L982)). |
| Constants | [consts.rs#L81-L106](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/types/src/gloas/consts.rs#L81-L106), [preset.rs#L427-L434](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/types/src/preset.rs#L427-L434) | Correct: self-build `u64::MAX`, builder flag `0x0100_0000_0000`, prefix `0xB0`, domains `0x0B`–`0x0E`, and `PTC_SIZE=512`. |

## Known-check and public-test-result check

I searched Grandine open and closed issues/PRs for `EIP-7732`, `gloas`,
`epbs`, `process_execution_payload_bid`, `process_parent_execution_payload`,
`can_builder_cover_bid`, `process_ptc_window`,
`onboard_builders_from_pending_deposits`, `payload attestation`, and
`execution payload envelope`, using the GitHub issues API (for example,
[exact bid-rule query](https://api.github.com/search/issues?q=repo%3Agrandinetech%2Fgrandine%20%22process_execution_payload_bid%22%20is%3Aissue),
[Gloas/EIP query](https://api.github.com/search/issues?q=repo%3Agrandinetech%2Fgrandine%20%28EIP-7732%20OR%20gloas%20OR%20epbs%29%20is%3Aissue),
and [PR query](https://api.github.com/search/issues?q=repo%3Agrandinetech%2Fgrandine%20%28EIP-7732%20OR%20gloas%20OR%20epbs%29%20is%3Apr)).
The exact bid/parent/cover/PTC/onboarding terms returned no issue.  G-1 is
known via open PR #989; #747 is closed/merged.  The broader timing-related
configuration observation is also already open as
[issue #912](https://github.com/grandinetech/grandine/issues/912), so it is not
promoted to a new spec-conformance candidate.

For public Glamsterdam validation, this review found source references to
consensus-spec-tests and Hive but no authoritative, pinned public Hive/results
page establishing a Grandine failure for any rule above.  Accordingly, no
passing or failing devnet result is claimed.  Grandine’s own source has Gloas
spec-test hooks for pending payments/PTC
([epoch_processing.rs#L485-L510](https://raw.githubusercontent.com/grandinetech/grandine/52cd677117b5d93bf477fe4843148070b0303444/transition_functions/src/gloas/epoch_processing.rs#L485-L510)); they were not executed.

## URLs read

Primary sources were the three pinned commit APIs, their raw source links cited
above, the pinned Gloas [`beacon-chain.md`](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/beacon-chain.md),
[`fork.md`](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork.md),
[`builder.md`](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/builder.md),
and [`fork-choice.md`](https://raw.githubusercontent.com/ethereum/consensus-specs/8a80ffa82bd49aac0dd6db17f9e8150aa257fbc2/specs/gloas/fork-choice.md), plus EIPs 7732/8282, PR 5736, and Grandine PRs/issues 989, 912, and 747 cited above.
