github agglayer/aggkit v0.11.0-rc3

latest releases: v0.12.0-rc4, v0.12.0-rc3, v0.12.0-rc2...
pre-release3 months ago

๐Ÿš€ What's New

  • bridgetracker component + new aggkit-proxy service (#1740, #1758): A supervised bridge-status tracker that resolves a bridge's full lifecycle from its creation tx โ€” now covering all three directions (L1โ†’L2, L2โ†’L1, L2โ†’L2) โ€” exposed via REST + WebSocket endpoints on a new aggkit-proxy binary. Tracks through BridgeEvent emission, LER update, certificate inclusion/settlement, L1-settlement confirmation, GER injection and claim, backed by an in-memory registry and step engine, with Swagger/OpenAPI docs served at /tracker/v1/swagger and a new docs/bridgetracker.md.
    • โš ๏ธ Ships breaking config changes โ€” see Breaking Changes below.
  • Auto Claim: L2โ†’L1 and L2โ†’L2 support (#1705): Extends Auto Claim (L1โ†’L2 only since v0.11.0-rc1) to the other two bridge directions. A new L2ToLx bridge detector watches each source rollup's local exit root advancing and fetches new bridges from that rollup's own bridge service; GER-injection readiness for any L2-destination claimer is now gated by calling the destination network's own bridge service instead of running a per-claimer l2gersync (removed entirely โ€” no more per-claimer SQLite DB, reorg detector, or dedicated L2 RPC client). An L1-destination (NetworkID = 0) claimer is now a fully-supported configuration.
    • โš ๏ธ Ships breaking config, API and storage changes โ€” see Breaking Changes below.
  • New op-pp-2chains e2e environment (#1691): Two OP-PP L2 chains on a shared L1/agglayer instance, with a new TestBridgeL2ToL2 covering the full L2โ†’L2 flow end to end; the CI e2e matrix now runs both op-pp and op-pp-2chains.

โš ๏ธ Breaking Changes

  • ๐Ÿ› ๏ธ Config: [Tracker].BlockFinality (proxy config) splits into L1BlockFinality/L2BlockFinality; adds RegisterResolveTimeout (#1758).
  • ๐Ÿ› ๏ธ Config: bridgeservicefinder.Config's static bridge-service override map renames URLs โ†’ BridgeURLs, to make room for a new RPCURLs override map (#1740). Affects [AutoClaim.BridgeServiceFinder.URLs] โ†’ [AutoClaim.BridgeServiceFinder.BridgeURLs]; Viper silently ignores unknown keys, so a config left on the old key ends up with an empty override map.
  • ๐Ÿ› ๏ธ Config: bridgeservicefinder.DefaultHealthCheckPath default changes /health โ†’ /, matching where the bridge service actually registers its health handler (#1758).
  • ๐Ÿ› ๏ธ Config: [AutoClaim.L2ToLxBridgeDetector] is no longer a disabled placeholder โ€” it's a real, independently-enableable detector. A new [AutoClaim.BridgeServiceFinder] section is now required when it's enabled, or when any enabled claimer (either direction) has an L2 destination โ€” including a pure L1โ†’L2 setup with the detector disabled (#1705).
  • ๐Ÿ› ๏ธ Config: RetryAfterErrorPeriod/MaxRetryAttemptsAfterError removed from both [AutoClaim.L1ToL2BridgeDetector] and [AutoClaim.L2ToLxBridgeDetector] โ€” they were validated but never consumed (#1705).
  • ๐Ÿ› ๏ธ Config: Per-claimer [[AutoClaim.Claimers]].BlockFinality/.InitialBlockNum removed โ€” they configured the now-deleted per-claimer l2gersync (#1705).
  • โš™๏ธ Operational: L1โ†’L2 auto claiming now requires [AutoClaim.BridgeServiceFinder] (with RollupManagerAddr) and the destination network's own bridge service to be reachable, whenever the destination is an L2 โ€” previously it only needed the shared [L2GERSync]/[ReorgDetectorL2] settings (#1705).
  • ๐Ÿ”Œ API: New binary aggkit-proxy; new bridge-service endpoints GET /bridge/v1/root-by-ler (#1758) and GET /bridge/v1/claim-candidates (#1705).
  • ๐Ÿ”Œ API: GET /bridge/v1/injected-l1-info-leaf now returns 404 Not Found (previously 500 Internal Server Error) when no GER covers the requested L1 info tree index yet; the Go client surfaces this as client.ErrNotFound (#1705).
  • ๐Ÿ”Œ API: Auto Claim request IDs (GET /autoclaim/v1/bridges/{id}) change format from origin_network:destination_network:deposit_count to source_network:destination_network:deposit_count โ€” numerically identical for every pre-existing L1โ†’L2 request (#1705).
  • ๐Ÿ—„๏ธ Storage: autoclaim_request gains source_network, ler, verify_block_num columns and its uniqueness constraint moves to (source_network, destination_network, deposit_count); new autoclaim_ler_cursor table (migration autoclaim0002.sql, safe โ€” autoclaim0001 has not shipped in any tagged release) (#1705).
  • No breaking changes from #1769, #1761, #1732, #1760, #1691, #1743.

๐Ÿ“‹ Configuration Updates

  • ๐Ÿงพ Config Diff: v0.11.0-rc2...v0.11.0-rc3 โ€” see proxy/config/default.go, autoclaim/config/config.go, bridgeservicefinder/config.go.

New [Tracker] proxy-config section:

[Tracker]
RetentionPeriod = "10m"
RegisterResolveTimeout = "3s"
L1BlockFinality = "LatestBlock"
L2BlockFinality = "LatestBlock"
MaxTrackedBridges = 100000

Renamed bridge-service-finder override key:

 [AutoClaim.BridgeServiceFinder]
 RollupManagerAddr = "0x..."

-[AutoClaim.BridgeServiceFinder.URLs]
+[AutoClaim.BridgeServiceFinder.BridgeURLs]
 0 = "http://l1-bridge-service:5577"

New [AutoClaim.L2ToLxBridgeDetector] (real, and [AutoClaim.BridgeServiceFinder] now required alongside it):

[AutoClaim.L2ToLxBridgeDetector]
Enabled = true
StartL1Block = 0            # 0 = full history
PollInterval = "3s"

[AutoClaim.BridgeServiceFinder]
RollupManagerAddr = "0x..."  # required when L2ToLxBridgeDetector.Enabled = true, OR when any
                              # enabled claimer (either direction) has an L2 destination
PollInterval = "30s"

[AutoClaim.BridgeServiceFinder.BridgeURLs]
# Required to reach network 0 (L1), which is never enumerated on-chain:
0 = "http://static-override-l1:5577"

# Per-claimer BlockFinality/InitialBlockNum no longer exist โ€” an L2-destination
# claimer's readiness gate now comes from AutoClaim.BridgeServiceFinder + the
# destination's own bridge service instead.
[[AutoClaim.Claimers]]
Enabled = true
NetworkID = 0   # now a legal L1-destination claimer (requires L2ToLxBridgeDetector.Enabled)
...

Full reference: docs/autoclaim.md and docs/bridgetracker/README.md.

๐Ÿž Bug Fixes

  • #1769 โ€” force_ger_update sent a real forced update only once, ever. Every SendForcedGERUpdate call packs byte-for-byte identical calldata, and ethtxmanager.Add derives its monitored-tx id purely from (to, value, data) โ€” so every call after the first collided with ErrAlreadyExists and just re-observed that same (already-terminal) tx forever, instead of ever broadcasting a new one. In practice the GER never updated again after the first forced send, and every later trigger (including on every restart, since the boot scan always found the GER still genuinely stale) looked like a send but was really a stuck no-op. Fixed by removing the tx from the monitoring DB once it reaches a terminal status.
  • #1761 โ€” Auto Claim's proofReadyForRequest compared an L1 block number against Bridge.BlockNum, which for L2-origin requests is the source L2's own block number โ€” an incomparable-units bug that left the readiness gate permanently closed once the source L2's height exceeded L1's (common on fast-block devnets), stalling requests indefinitely (observed even after L1 was manually advanced 700+ blocks). Now compares against VerifyBlockNum for L2-origin requests, the same L1-block quantity the proof itself uses.
  • #1732 โ€” l2gersync never recovered automatically after an invalid GER was removed on-chain. The removal check was gated behind IsUpToDate and never converged, so the syncer retried forever (or crash-looped under a non-negative MaxRetryAttemptsAfterError). Now decoupled from IsUpToDate: each retry re-checks removal at latest and only skips the invalid insert once a genuine on-chain removal event is observed and the GER map entry is zeroed โ€” never fatal for this class of error. GET /bridge/v1/sync-status gains an additive l2_ger_info object for external visibility.
  • #1760 โ€” AggSender stopped creating certificates beyond the last claim/bridge block on chains whose finalized tag lags or never advances (some local devnets): the classic sync downloader only persisted progress past the reorg detector's finalized block when it either caught up or found an event, so with no new events it looped forever without reporting a block, pinning GetLastProcessedBlock to the last block that had one. Fixed by reporting the swept-to block as an (unfinalized) empty block once the chain head is reached, same as the existing "has events" path.

โœ… Testing & Validation

  • bridgetracker/aggkit-proxy (#1740, #1758): unit coverage across bridgetracker/..., bridgeservice/..., proxy/...; new e2e TestBridgeTrackerL1ToL2 in the op-pp-2chains CI matrix group.
  • Auto Claim L2โ†’L1/L2โ†’L2 (#1705): unit coverage across every touched/added package (60โ€“100% per package); dockerized e2e on op-pp (TestAutoClaimL2ToL1AllowAll, new L2โ†’L1 direction end to end) and op-pp-2chains (TestAutoClaimL2ToL2AllowAll, run twice consecutively).
  • force_ger_update (#1769): new regression test driving two full send cycles back-to-back asserting the second gets a fresh Add, plus a new integration test covering the flip side of the existing cold-start test โ€” booting with a genuinely fresh GER must not force a spurious send.
  • autoclaim L2-origin readiness (#1761): new unit tests plus in-enclave verification on a kurtosis-cdk 2-L2 devnet (previously-stuck L2-1โ†’L2-2 deposit now auto-claims in ~2m11s).
  • l2gersync recovery (#1732): unit coverage for the non-fatal retry path; the 5 previously-skipped remove-GER e2e tests re-enabled, split across three CI matrix groups on op-pp.
  • sync downloader fix (#1760): updated TestDownloadBeforeFinalized to assert progress is reported at the chain tip even with no events; reproduced the original stall against a local Kurtosis OP-PP environment.
  • op-pp-2chains env (#1691): new TestBridgeL2ToL2, both op-pp and op-pp-2chains CI matrix jobs green.

๐Ÿ”ง Maintenance & Dependencies

  • exit_certificate security report updated to v2.1 (#1743): Sigma Prime's audit report adds one new low-severity finding from their review of the state-dump completeness fix (#1729, already in v0.11.0-rc1).

๐Ÿ“ฆ Full Changelog

  • feat: add op-pp-2chains env and L2โ†’L2 bridge test by @arnaubennassar in #1691
  • feat: auto claim L2->L1 and L2->L2 support by @arnaubennassar in #1705
  • fix(l1infotreesync): recover from undetected L1 tip reorg instead of halting permanently by @joanestebanr in #1738 (content-identical to the cherry-pick already shipped in v0.11.0-rc2; appears here only because v0.11.0-rc3 is cut from develop rather than release/0.11)
  • chore(exit_certificate): update Sigma Prime security assessment report to v2.1 by @joanestebanr in #1743
  • feat(bridgetracker): add bridge tracking endpoints, L1->L2, and proxy service by @joanestebanr in #1740
  • fix(sync): Aggsender does not create certificates beyond the last claim block by @joanestebanr in #1760
  • fix(l2gersync): recover automatically when an invalid GER is removed on-chain by @arnaubennassar in #1732
  • feat(bridgetracker,proxy): add bridge status tracker with L2/Lx lifecycle tracking and REST/WS API by @joanestebanr in #1758
  • fix(autoclaim): use VerifyBlockNum instead of Bridge.BlockNum for L2-origin proof readiness by @arnaubennassar in #1761
  • fix(force_ger_update): forget completed tx so repeat sends are not deduped forever by @arnaubennassar in #1769

Full Changelog: v0.11.0-rc2...v0.11.0-rc3

Don't miss a new aggkit release

NewReleases is sending notifications on new releases.