Add non-ePBS Gloas support for bal-devnet-3#152
Open
qu0b wants to merge 20 commits intoethpandaops:masterfrom
Open
Add non-ePBS Gloas support for bal-devnet-3#152qu0b wants to merge 20 commits intoethpandaops:masterfrom
qu0b wants to merge 20 commits intoethpandaops:masterfrom
Conversation
- Replace go-eth2-client with qu0b fork (eip7928 branch) for non-ePBS Gloas SSZ types - Add Gloas/Fulu/Electra cases to block_utils.go - Supports EIP-7928 (BAL), EIP-7843 (SlotNumber), EIP-7954, EIP-8037
go-bitfield's Bitvector64.BitAt() requires exactly 8 bytes but with minimal preset (MAX_COMMITTEES_PER_SLOT=4), committeeBits is only 1 byte in SSZ. This caused all committee bit checks to return false, resulting in 0% attestation vote counts. Work around by checking the raw bytes directly instead of using BitAt().
Self-contained playbook that: - Installs Python/uv at runtime - Clones EELS (execution-specs) devnets/bal/3 branch - Runs execute remote against live RPC for all 7 bal-devnet-3 EIPs - Uses --sender-fund-refund-gas-limit=200000 for EIP-8037 state gas - Produces per-EIP JSON/HTML reports Also fixes typo in existing playbook (execution-spec → execution-specs).
1d5b002 to
4321d7d
Compare
Pinned to tests-bal@v5.7.0 (commit 524b446 on devnets/bal/4). Adds new EIP-7976 (calldata floor cost) and EIP-7981 (access list cost) test blocks; carries over 7708/7778/7843/7928/7954/8024/8037 from the bal-devnet-3 playbook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each task was overriding HOME=${EELS_DIR} BEFORE setting
PATH=$PATH:$HOME/.local/bin, so PATH ended up pointing to the empty
freshly-created EELS_DIR/.local/bin instead of the user's actual
~/.local/bin where pip-installed uv lives. Result: setup task failed
with exit 127 (uv not found) before any EIP test could run.
Swap the export order in all 10 task blocks (setup + 9 EIP tasks) so
PATH is computed against the original $HOME before HOME is overridden
for cache isolation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
run_shell builds command.Env from scratch with only user-supplied envVars, ASSERTOOR_SUMMARY, and ASSERTOOR_RESULT_DIR. Once command.Env is non-nil, exec.Command stops inheriting the parent process environment (Go's documented behavior), so the spawned shell starts with empty HOME, PATH, USER, etc. This breaks any playbook that relies on standard env. In our bal-devnet EELS playbooks, the script does `export PATH=\$PATH:\$HOME/.local/bin` to pick up pip --user installed binaries (uv) — with HOME="" and PATH="" this resolves to ":/.local/bin" and fails with `uv: command not found` (exit 127). The bal-devnet-3 playbook has the same latent bug. Fix: prepend os.Environ() to command.Env. User-supplied envVars are appended after and still override inherited values. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 1 was silently truncating after "Processing triggers" — pip install uv never ran, and task 2 failed with `bash: line 16: uv: command not found`. Root cause: assertoor pipes the command to bash via stdin, then closes stdin when done writing. apt-get / dpkg post-install scripts can read from stdin in interactive mode; once dpkg consumes the rest of the script bytes, bash sees EOF and exits without reaching `pip install uv`. Fix: set DEBIAN_FRONTEND=noninteractive and explicitly redirect stdin from /dev/null on every apt invocation. Same applies to dpkg --add-architecture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All 9 sequential EIP tests previously shared the same --rpc-seed-key (tasks.specTestsWallet.outputs.childWallet.privkey). When one EIP test's funding tx hung in mempool — e.g. the prior run hit a "Replacement transaction underpriced" error at nonce 0x62 (98) that blocked all 80 remaining tests in EIP-7708 — the shared wallet's nonce became corrupted and every subsequent EIP test inherited the same stuck nonce. Insert a generate_child_wallet task before each EIP run_shell with a unique walletSeed (spectests-bal4-eip7708, ...-eip7778, etc.). Each EIP test now uses its own freshly-funded child wallet derived from walletPrivkey, so nonce collisions across tests are impossible. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cherry-picks the Amsterdam funding-gas fix from upstream (spamoor #217 EIP-8037 gas accounting + #218 cpsbFloor on startup + assertoor ethpandaops#162 InitializeBlockStats) without pulling the whole upstream merge — that pulled go-eth2-client v0.1.0 from ethpandaops, whose Gloas SSZ schema for BLSToExecutionChanges differs from qu0b/go-eth2-client and breaks block decoding on bal-devnet-4. Keeps the existing `replace attestantio/go-eth2-client => qu0b/go-eth2-client` directive so block processing stays compatible with the chain we run.
Two corrections to bal-devnet-4-eels-tests.yaml: 1) Reorder check_consensus_slot_range BEFORE generate_child_wallet. Spamoor's WalletPool.FundingGasFor() reads cpsb from the latest observed block, which is 0 until processBlock receives a post-Gloas block. If we generate the funding tx in the [genesis, first-post-Gloas-block-observed] window on a chain with non-zero gloas_fork_epoch, the funding tx is sized at 21000 gas while geth's tx pool already requires 23333 (110% of intrinsic, post-EIP-8037). Result: 'intrinsic gas too low: gas 21000, minimum needed 23333' on geth. By the time check_consensus_slot_range returns, several post-Gloas blocks have been streamed and spamoor's IsAmsterdam is true, so funding is sized correctly. 2) Deselect test_slotnum_value from EIP-7843 run. The test asserts SSTORE(0, SLOTNUM) returns Environment(slot_number=N), where Environment(slot_number=) is a filler-time hint. In execute mode against a live chain, SLOTNUM returns the actual current beacon slot — so the 5 parameterised cases (slot_zero/one/4096/large/max_u64) fail on every client, not just nethermind. Test is structurally incompatible with execute mode and should be filler-only. test_slotnum_gas_cost still runs.
check_consensus_slot_range returns the moment the wallclock crosses the target epoch, but spamoor's processBlock needs an actual EL block (with BlockAccessListHash != nil) to flip isAmsterdam. Empirically the gap is ~5 sec; add 30s of margin to ensure ~5 post-Gloas EL blocks propagate.
Retarget the bal-devnet-4 EELS playbook from tests-bal@v5.7.0 to the new tests-snøbal-devnet-4@v1.0.0 release on ethereum/execution-specs (commit 28e6130 on devnets/snøbal/4). All 9 EIP test directories present at the new tag; spec/tests now use static cpsb=1174.
* go.mod: replace ethpandaops/spamoor with local /home/ubuntu/repos/spamoor (qu0b/fix/effective-cpsb-fork-race), which drops the racy 'observed pre-Amsterdam head → return 0' branch in WalletPool.effectiveCpsb. EIP-8037 fixes cost_per_state_byte at cpsbFloor=1174, so always returning cpsbFloor when no live cpsb is available is exact post-Amsterdam and only costs over-reservation on truly pre-Amsterdam chains (PR #218 already accepted that tradeoff for the no-head startup case). * pkg/txmgr/spamoor.go: drop the explicit InitializeBlockStats call. The current spamoor master auto-initializes block stats internally via initBlockStats; the public API my earlier surgical merge depended on no longer exists. The fix above removes the need for a synchronous startup refresh anyway — effectiveCpsb is now race-free. * playbooks/.../bal-devnet-4-eels-tests.yaml: revert the playbook reorder + 30s sleep workaround. With the spamoor fix, generate_child_wallet works correctly at any time relative to Gloas activation.
Local /home/ubuntu/repos path doesn't survive docker build context, so point at the published qu0b/spamoor fork at the same commit (72ac11889a85 on qu0b/fix/effective-cpsb-fork-race).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
qu0b/go-eth2-clienteip7928 branch which has proper Gloas types withExecutionPayloadin block body (not ePBS envelope)block_utils.goContext
The existing
gloas-supportbranch uses pk910's go-eth2-client fork which implements ePBS (EIP-7732) style Gloas. bal-devnet-3 uses non-ePBS Gloas where the execution payload is embedded in the beacon block body. This causedfailed to decode gloas signed block contents: incorrect offseton every block.This PR takes the simpler approach: start from master (no ePBS code) and just add the Gloas SSZ types via the replace directive.
Test plan
build-docker-imagelabel🤖 Generated with Claude Code