Skip to content

feat: autoclaim L1 -> L2#1644

Open
arnaubennassar wants to merge 20 commits into
developfrom
feat/autoclaim-plan
Open

feat: autoclaim L1 -> L2#1644
arnaubennassar wants to merge 20 commits into
developfrom
feat/autoclaim-plan

Conversation

@arnaubennassar

@arnaubennassar arnaubennassar commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

🔄 Changes Summary

  • Adds an opt-in autoclaim Aggkit component for L1 -> L2 bridge claims. It discovers eligible exits from l1bridgesync, persists request/cursor/attempt state, prepares claim proofs with l1infotreesync plus a per-claimer l2gersync, submits claimAsset / claimMessage transactions through EthTxManager, and tracks requests through confirmation or failure.
  • Adds per-destination claimers with named policies: allow-all, api-approve, no-message, and basic-filter.
  • Adds optional Auto Claim REST endpoints under /autoclaim/v1 for request listing, inspection, manual approval, and manual rejection, with generated Swagger docs.
  • Wires Auto Claim into startup through the new autoclaim component, config loading/validation/defaults, docs, mocks, and the OP e2e environment.
  • Hardens the bridge-service L2 deposit L1 info tree lookup used by /l1-info-tree-index: if a verified batch LER is missing from the local L2 exit tree, the lookup now avoids mixing L2 bridge-sync block numbers with L1 verified-batch block numbers and falls back to a bounded linear scan.

⚠️ Breaking Changes

  • 🛠️ Config: No breaking migration. Auto Claim adds a new optional [AutoClaim] config section and remains disabled by default.
  • 🔌 API/CLI: Adds a new optional autoclaim component selector and optional /autoclaim/v1 API. Existing bridge service API paths are unchanged.
  • 🗑️ Deprecated Features: None.

📋 Config Updates

  • 🧾 Diff/Config snippet: Adds defaults for the new disabled-by-default Auto Claim section:
[AutoClaim]
Enabled = false
StoragePath = "{{PathRWData}}/autoclaim.sqlite"
Claimers = []

[AutoClaim.API]
Enabled = false
Host = "0.0.0.0"
Port = 5579

[AutoClaim.L1ToL2Watchdog]
Enabled = true
StartBlock = 0
PollInterval = "3s"
RetryAfterErrorPeriod = "1s"
MaxRetryAttemptsAfterError = -1
EtrogL1UpgradeBlock = 0

[AutoClaim.L2ToLxWatchdog]
Enabled = false
  • Enabling Auto Claim requires both selecting the autoclaim component and setting [AutoClaim].Enabled = true.
  • Each enabled [[AutoClaim.Claimers]] entry configures one EVM destination network with its own RPC URL, bridge address, policy, gas settings, retry settings, and EthTxManager storage/signing config.
  • Auto Claim owns AutoClaim.StoragePath; each claimer also has an independent EthTxManager.StoragePath and isolated per-claimer l2gersync / L2 reorg detector databases under the Auto Claim storage directory.
  • L2 -> Lx Auto Claim remains unsupported and must stay disabled.

✅ Testing

  • 🤖 Automatic: Added unit coverage across autoclaim/api, claimer, claimtx, config, policy, proof, runtime, sender, simulator, storage, types, and watchdog.
  • 🤖 Automatic: Added Go e2e coverage for TestAutoClaimL1ToL2AllowAll, TestAutoClaimL1ToL2APIApprove, and TestAutoClaimL1ToL2BasicFilter.
  • 🤖 Automatic: Current PR checks show lint, test-unit, Go e2e, Docker image build, CodeQL, SonarCloud, and the configured multi/single-chain e2e workflows passing. Run govulncheck is currently failing.
  • 🖱️ Manual: No separate manual testing was run while refreshing this PR description.

🐞 Issues

🔗 Related PRs

  • None listed.

📝 Notes

  • Auto Claim currently supports L1 -> L2 only. L2 -> Lx discovery is reserved for future work.
  • Request IDs are derived from origin_network:destination_network:deposit_count; origin_network is the bridged token's origin network, not necessarily the chain where the bridge was initiated.
  • GER readiness is checked during proof preparation by each claimer's own l2gersync, which supports both legacy and sovereign L2 GER manager behavior.
  • The optional api-approve policy requires the Auto Claim API so operators can approve or reject requests in manual-approval-required status.
  • This branch currently skips five known flaky remove-GER e2e entrypoint tests: TestRemoveGER_NoProblematicClaims, TestRemoveGER_CategoryA, TestRemoveGER_CategoryB1, TestRemoveGER_CategoryB2, and TestGenerateInvalidGER. This is being worked on feat: migrate e2e tests from bats to go #1643
  • Bridge-service changes are a scoped regression fix for L2-origin bridge proof lookup. The previous fallback could call GetFirstVerifiedBatchesAfterBlock with GetLastRoot().BlockNum, which is an L2 bridge-sync block number even though the L1 info tree query expects an L1 block number. The new path only falls back on db.ErrNotFound, keeps the original L1 verified-batch bounds, and skips missing LERs with a linear scan when binary search cannot safely continue.

@arnaubennassar arnaubennassar marked this pull request as draft June 8, 2026 09:06
Comment thread autoclaim/storage/storage.go Fixed
@arnaubennassar arnaubennassar changed the title Feat/autoclaim plan feat: autoclaim plan Jun 9, 2026
@arnaubennassar arnaubennassar self-assigned this Jun 9, 2026
# Conflicts:
#	multidownloader/evm_multidownloader_reorg.go
#	multidownloader/evm_multidownloader_reorg_test.go
Comment thread autoclaim/storage/storage.go Fixed
@arnaubennassar arnaubennassar changed the title feat: autoclaim plan feat: autoclaim L1 -> L2 Jun 11, 2026
arnaubennassar and others added 12 commits June 11, 2026 10:57
…tic logs

- config/config_test.go: move testify/urfave imports to end of non-stdlib
  group to satisfy gci two-group ordering (fixes CI lint failure)
- config/default.go: set AutoClaim.L1ToL2Watchdog Enabled = true to match
  the assertion in TestLoadDefaultConfig (fixes unit test failure)
- autoclaim/proof/preparer.go: add debug logs in selectL1InfoTreeIndex to
  surface whether the proof is blocked by l1InfoTree lag or gerSyncer lag
- autoclaim/claimer/claimer.go: log info when proof not ready so E2E logs
  clearly show the pending state on each poll cycle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rackedBlocks wipe

reorgDetector.Start calls loadTrackedHeaders which replaces the in-memory
trackedBlocks map entirely from DB. If l2gersync.New (which calls Subscribe
internally) ran first, the subscription entry it added would be wiped by the
subsequent loadTrackedHeaders call, causing every AddBlockToTrack to return
"subscriber not subscribed" forever.

The per-claimer l2gersync was stuck in a retry loop at the first GER injection
block (block 24), never processing the GER that covered the bridge deposit, so
GetFirstGERAfterL1InfoTreeIndex always returned ErrNotFound and the claim proof
was never prepared.

Fix: call reorgDetector.Start synchronously before l2gersync.New so that
loadTrackedHeaders completes before Subscribe adds the entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The 3 SQL injection hotspots in autoclaim/storage/storage.go were marked
SAFE on SonarCloud (all use parameterized ? placeholders, not user input).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add tests across 11 files covering uncovered nil-arg error paths, option
closures, getter/accessor methods, disabled-state branches, and constructor
validation to push SonarCloud new_coverage above the 80% quality gate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…overage

Adds 7 targeted tests across sender and api packages to cover
previously unreachable lines: default time.Now closure bodies,
IsClaimed error propagation, pollResult Result() failure path,
zero WaitPeriod fallback to s.pollPeriod, zero-MaxRetries target
fallback to request.MaxRetries, and claimTxHash with nil Tx entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@agglayer agglayer deleted a comment from claude Bot Jun 12, 2026
@arnaubennassar arnaubennassar marked this pull request as ready for review June 12, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

L1 -> L2 Autoclaim

2 participants