feat(exit-certificate): alternative Step A (state dump + Transfer logs)#1687
feat(exit-certificate): alternative Step A (state dump + Transfer logs)#1687krlosMata wants to merge 3 commits into
Conversation
|
Claude finished @krlosMata's task in 1m 28s —— View job 🔍 Code Review Complete🚀 What's NewThis PR introduces an opt-in alternative to Step A for the exit-certificate tool (
This is an 🐛 Bug FixesNone. 📋 Config Updates
|
|
@codex review |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in alternative “Step A” (--step aalt) to the exit-certificate tool that discovers value-holding addresses via debug_accountRange state dump plus ERC-20 Transfer logs, wiring it into CLI/config/docs while keeping the existing trace-based Step A as default.
Changes:
- Introduces
RunStepAAltimplementation (state dump + Transfer-log holder discovery with auto fallback to receipt harvesting whendebug_accountRangeisn’t available). - Adds unit tests covering pagination, dialect probing, Transfer extraction, auto fallback, and source merging.
- Integrates the new step into the CLI runner/config/docs and adds a new output filename (
step-aalt-addresses.json) while still writing canonicalstep-a-addresses.json.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/exit_certificate/step_a_alt.go | Implements alternative Step A address discovery (state dump + Transfer logs + auto fallback). |
| tools/exit_certificate/step_a_alt_test.go | Adds unit tests for the alternative Step A logic and helpers. |
| tools/exit_certificate/run.go | Adds aalt step dispatch and single-step runner for alternative Step A. |
| tools/exit_certificate/README.md | Documents aalt step and options.addressDiscovery. |
| tools/exit_certificate/filenames.go | Adds step-aalt-addresses.json constant. |
| tools/exit_certificate/config.go | Adds addressDiscovery option with default and config merge support. |
| tools/exit_certificate/cmd/main.go | Updates CLI help text to mention aalt. |
| tools/exit_certificate/CLAUDE.md | Documents the new alternative Step A behavior and outputs. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c572925404
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Thanks for all the reviews — addressed the feedback in Code fixes
Coverage (SonarQube gate): added tests for the truncation/empty-dump guards, dialect param shapes, Not changed (with rationale):
Re-verified end-to-end against a live cdk-erigon node after the changes (LBT + alternative Step A: 321,581 addresses in ~2m43s). |
b546dad to
2433abe
Compare
…Transfer logs) Add an opt-in alternative to Step A (--step aalt) that discovers value-holding addresses without replaying the full transaction history via debug_traceTransaction. It combines a state-trie dump (debug_accountRange, auto-detecting the geth vs erigon dialect) for all ETH holders and contracts with a per-wrapped-token Transfer-log scan for token holders (including token-only EOAs that tracing structurally misses). Selectable via the addressDiscovery option (auto|stateDump|logs|both); auto falls back to receipt harvesting when debug_accountRange is unavailable. Writes the canonical step-a-addresses.json so Steps B-D consume it unchanged. On a 24M-block chain this ran in ~2m45s vs ~7h46m for the trace-based Step A, producing a superset of the relevant addresses. Co-authored-by: Cursor <cursoragent@cursor.com>
- State dump fails loudly on a truncated paginated dump (page cap hit with a non-empty next cursor) instead of silently returning a partial address set. - State dump rejects an empty accounts map (e.g. a stock geth node without address preimages), so auto falls back to receipt harvesting and stateDump/both fail loudly instead of omitting native holders/contracts. - Transfer-log holder scan now starts at block 0 (independent of l2StartBlock) so passive token-only holders that received before l2StartBlock are kept. - Reduce debug_accountRange page size from 5000 to 256: both geth and erigon cap responses at 256, and requesting more risks HTTP timeouts on a slow node. - Make the receipt-fallback warning explicit about missed internal value transfers; clarify pagination/page-size/zero-address comments. - Add tests for the truncation and empty-dump guards, dialect param shapes, stateDump/logs-only modes, genesis-scan, and accountRange error paths. - Document the preimage requirement and genesis scan in README/CLAUDE. Co-authored-by: Cursor <cursoragent@cursor.com>
7c91610 to
93d3f7f
Compare
…-locked from contracts Add two opt-in options for the alternative Step A / certificate build: - includeZeroAddress: keep the zero address (0x000…000) in the collected address set instead of dropping it, so its native/token balances are exited in the certificate. - nativeSCLockedFromContracts: compute the native-token SC-locked value in Step C from the actual ETH held by contract accounts (summed via eth_getBalance, excluding the L2 bridge) instead of LBT − EOA_accumulated. This is needed on chains with a native genesis premint, where LBT − EOA underflows and clamps to 0, silently dropping contract-held ETH. The contract-balance sum runs in Step C's runner (reading the already-saved contract addresses), so no heavy Step B re-run is required. Co-authored-by: Cursor <cursoragent@cursor.com>
|


What
Adds an opt-in alternative to Step A of the exit-certificate tool, run with
--step aalt.Instead of replaying the whole chain history with
debug_traceTransaction(the slowest part of the pipeline), it discovers value-holding addresses from the final state plus token logs:debug_accountRangeat the target block -> every ETH holder and contract (auto-detects geth vs erigon dialect).Transferevent logs per wrapped token -> every token holder, including token-only EOAs that tracing structurally misses.Strategy is selectable via the
addressDiscoveryoption (auto|stateDump|logs|both).autofalls back to receipt harvesting whendebug_accountRangeisn't available.It writes the same
step-a-addresses.json, so Steps B-D consume it unchanged. The existing trace-based Step A is untouched and remains the default.Why
The trace-based scan is
O(all transactions)and is also incomplete for token-only holders. The alternative isO(#accounts)and more complete.Result (real run, Bali, block 24,000,064)
The alternative covers 99.95% of the trace set and finds 5,987 extra real holders. The 166 it "misses" are empty accounts (zero balance/nonce/code at the target block, e.g. self-destructed) that can't hold value.
Test plan
go test ./tools/exit_certificate/...(newstep_a_alt_test.go: pagination, dialect, Transfer extraction, auto fallback, merge)golangci-lint run ./tools/exit_certificate/...cleanMade with Cursor