Skip to content

feat: split bridgesyncer into bridgesyncer + claimsyncer#1539

Open
joanestebanr wants to merge 28 commits intodevelopfrom
feat/claim_syncs_required_by_aggsender-pm285
Open

feat: split bridgesyncer into bridgesyncer + claimsyncer#1539
joanestebanr wants to merge 28 commits intodevelopfrom
feat/claim_syncs_required_by_aggsender-pm285

Conversation

@joanestebanr
Copy link
Collaborator

@joanestebanr joanestebanr commented Mar 11, 2026

🔄 Changes Summary

This PR extracts claim event synchronization out of bridgesync into a new, dedicated claimsync package. The change enables claim indexing to run as an independent component with its own database, lifecycle, and RPC interface. Both the AggSender and the AggSender Validator are updated to use the new claim syncer.

The key feature is that decoupling claimsync allow to use a full-node RPC instead of archive RPC for aggsender-proposer and aggsender-validator.

  • Don't sync L1 claims
  • For new deployments starts to synchronize just the block required: This synchornization use a debug end-point for the legacy claim events, but new deployments emit detailedClaimEvent that avoid this requiremente

⚠️ Breaking Changes

🚨 This PR force to resync all claims! It's going to be deletagate to another PR to prevent it and move the data to new database

📋 Config Updates

This PR introduces the new configuration for claimsyncer for L1 and L2

[ClaimL1Sync]
DBPath = "{{PathRWData}}/claiml1sync.sqlite"
DBQueryTimeout = "{{BridgeL1Sync.DBQueryTimeout}}"
BlockFinality = "{{BridgeL1Sync.BlockFinality}}"
InitialBlockNum = {{BridgeL1Sync.InitialBlockNum}}
AutoStart = "auto"
BridgeAddr = "{{BridgeL1Sync.BridgeAddr}}"
SyncBlockChunkSize = {{BridgeL1Sync.SyncBlockChunkSize}}
RetryAfterErrorPeriod = "{{BridgeL1Sync.RetryAfterErrorPeriod}}"
MaxRetryAttemptsAfterError = {{BridgeL1Sync.MaxRetryAttemptsAfterError}}
WaitForNewBlocksPeriod = "{{BridgeL1Sync.WaitForNewBlocksPeriod}}"
RequireStorageContentCompatibility = {{BridgeL1Sync.RequireStorageContentCompatibility}}

[ClaimL2Sync]
DBPath = "{{PathRWData}}/claiml2sync.sqlite"
DBQueryTimeout = "{{BridgeL2Sync.DBQueryTimeout}}"
BlockFinality = "{{BridgeL2Sync.BlockFinality}}"
InitialBlockNum = {{BridgeL2Sync.InitialBlockNum}}
AutoStart = "auto"
BridgeAddr = "{{BridgeL2Sync.BridgeAddr}}"
SyncBlockChunkSize = {{BridgeL2Sync.SyncBlockChunkSize}}
RetryAfterErrorPeriod = "{{BridgeL2Sync.RetryAfterErrorPeriod}}"
MaxRetryAttemptsAfterError = {{BridgeL2Sync.MaxRetryAttemptsAfterError}}
WaitForNewBlocksPeriod = "{{BridgeL2Sync.WaitForNewBlocksPeriod}}"
RequireStorageContentCompatibility = {{BridgeL2Sync.RequireStorageContentCompatibility}}

✅ Testing

  • 🤖 Automatic: e2e-kurtosis, and e2e-go

🐞 Issues

  • Closes #[issue-number]

🔗 Related PRs

  • [Optional: Enumerate related pull requests]

📝 Notes

  • [Optional: design decisions, tradeoffs, or TODOs]

- Add new claimsync package with its own storage (SQLite), processor,
  embedded mode, and ClaimsReader interface
- Remove duplicated claim event handlers from bridgesync/downloader.go;
  bridgesync now delegates to claimsync via ClaimsSyncProcessor interface
- Add ProcessBlockWithTx(insertBlock bool) to allow shared tx reuse
  between bridgesync and claimsync (atomic writes)
- Add ReorgWithTx to ClaimsSyncProcessor so bridgesync can call claimsync
  reorg within its own transaction
- Add ClaimsReader interface grouping read-only claim queries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@joanestebanr joanestebanr self-assigned this Mar 11, 2026
joanestebanr and others added 7 commits March 16, 2026 14:28
- Move Claim/Unclaim types from bridgesync to claimsync/types package
- Add ClaimSyncRPC server exposing l2claimsync_* JSON-RPC methods
- Add paged storage implementation for claimsync
- Add claimsync config and claim_data types
- Update aggsender interfaces to use claimsync.Claim instead of bridgesync.Claim
- Add GetNextBlockNumber and GeneratePreBuildParams to AggsenderBuilderFlow/FlowBaser interfaces
- Extend GetLastProcessedBlock signature to return (uint64, bool, error)
- Add op-pp local config and e2e bridge tests
- Regenerate all affected mocks

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

- Move TrueFalseAutoMode to config/types as a struct with Mode string and
  Resolved *bool (not read from config); add type alias + var re-exports in bridgesync
- claimsync RPC: GetRPCServices() sets service name (l1claimsync/l2claimsync)
  based on syncerID stored in ClaimSync struct
- claimsync config: add AutoStart TrueFalseAutoMode field; resolved against
  BRIDGE/L1BRIDGESYNC or BRIDGE/L2BRIDGESYNC components at startup
- sync/EVMDriver: add SyncNextBlock(ctx, blockNum) to bootstrap the first block;
  returns ErrAlreadyBootstrapped if a block already exists (ignorable)
- claimsync: Start() passes InitialBlockNum to Sync() when AutoStart=true;
  syncNextBlockInfinite() retries bootstrap until success or ctx cancellation
- sync: add README.md documenting how to implement a new syncer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@joanestebanr joanestebanr changed the title feat: add claimsync package and integrate with bridgesync feat: split bridgesyncer into bridgesyncer + claimsyncer Mar 18, 2026
@agglayer agglayer deleted a comment from claude bot Mar 18, 2026
joanestebanr and others added 17 commits March 18, 2026 10:37
…cerSetter

- Remove GetNextBlockNumber from AggsenderBuilderFlow and AggsenderFlowBaser interfaces and their implementations
- Introduce InitialBlockClaimSyncerSetter interface and implementation to encapsulate the logic of setting the initial claim syncer block
- AggsenderValidator uses the new interface with a RetryHandler for retry/sleep management
- Rename claimsync/claim_data.go to claimsync/claimdata.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@joanestebanr joanestebanr requested a review from Copilot March 20, 2026 15:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extracts claim event synchronization into a dedicated claimsync package and updates existing syncers and aggsender components to use the new claim syncer, enabling independent claim indexing and improved RPC requirements (full-node vs archive).

Changes:

  • Added standalone + embedded claim syncer APIs, storage/migrations, and RPC services.
  • Extended sync driver/downloader interfaces to support bootstrap syncing and “no blocks processed yet” semantics.
  • Updated aggsender/bridge service flows and interfaces to source claims from claimsync instead of bridgesync.

Reviewed changes

Copilot reviewed 128 out of 140 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
sync/evmdriver.go Adds bootstrap sync and supports “no processed block” flow.
sync/evmdownloader.go Extends downloader API to support bounded downloads and empty-first-block reporting.
sync/evmdownloader_test.go Updates tests and adds coverage for new downloader behaviors.
scripts/local_config_fep Makes config artifact name overridable with a default.
scripts/l2claimsync_get_claims.sh Adds helper script for ClaimSync RPC getClaims.
scripts/l1claimsync_set_starting_block.sh Adds helper script for ClaimSync RPC setNextRequiredBlock.
scripts/aggsender_request_status.sh Adds helper script for Aggsender status RPC.
scripts/aggsender_request_last_cert.sh Adds helper script for Aggsender last cert RPC.
multidownloader/sync/evmdriver.go Updates multidownloader driver sync signature and logging/error labels.
multidownloader/sync/evmdriver_test.go Adds test coverage for firstBlockNumber parameter validation.
multidownloader/sync/evmdownloader.go Renames log/error prefixes and reduces log verbosity.
multidownloader/evm_multidownloader.go Changes info logs to debug and fixes finalized flag handling for missing DB header.
multidownloader/evm_multidownloader_test.go Updates exploratory test to pass explicit fromBlock pointer.
multidownloader/e2e_test.go Updates e2e to pass explicit fromBlock pointer.
l2gersync/processor.go Changes GetLastProcessedBlock to return (num, found, err).
l2gersync/processor_test.go Updates tests for new GetLastProcessedBlock signature.
l2gersync/l2_ger_syncer.go Passes initial block into driver sync and stores config in syncer.
l2gersync/evm_downloader_sovereign.go Updates downloader interface signature and improves error logging context.
l2gersync/evm_downloader_sovereign_test.go Updates download call signature.
l2gersync/evm_downloader_legacy.go Updates downloader interface signature.
l1infotreesync/processor.go Changes GetLastProcessedBlock to return (num, found, err).
l1infotreesync/l1infotreesync.go Threads initial block into driver sync and adapts to new processor API.
l1infotreesync/mock_driver_interface.go Updates driver mock Sync signature.
grpc/server.go Adds TODO note about setting claimsyncer starting block.
config/types/true_false_auto.go Introduces tri-state config type (true/false/auto) with resolution support.
config/types/true_false_auto_test.go Adds unit tests for tri-state config parsing/validation/resolve.
config/default.go Adds default ClaimL1Sync/ClaimL2Sync sections and EmbeddedClaimSync toggle.
config/config.go Adds ClaimL1Sync/ClaimL2Sync config fields.
common/components.go Adds L2CLAIMSYNC component; removes PROVER constant from validation list.
claimsync/config.go Adds embedded/standalone claimsync configuration definitions and validation.
claimsync/config_test.go Adds validation tests for claimsync configs.
claimsync/processor.go Adds standalone claimsync processor (DB + embedded processor).
claimsync/embedded.go Adds embedded claimsync integration for bridgesync transaction reuse.
claimsync/claimdata.go Adds local aliases for claimsync types/constants.
claimsync/helpers_test.go Fixes package name to claimsync.
claimsync/claimcalldata_test.go Updates package and callsites; adds alias/constant tests.
claimsync/claimsync_test.go Adds integration test for deferred-start behavior via SetNextRequiredBlock.
claimsync/claimsync_rpc.go Adds ClaimSync RPC service endpoints (status/getClaims/getClaimsByGlobalIndex/setNextRequiredBlock).
claimsync/claimsync_rpc_test.go Adds unit tests for ClaimSync RPC endpoints.
claimsync/agglayer_bridge_l2_reader.go Moves AgglayerBridgeL2Reader into claimsync package/types.
claimsync/agglayer_bridge_l2_reader_test.go Updates tests to use claimsync types.
claimsync/types/claim_syncer.go Defines ClaimSyncer interface for claimsync component.
claimsync/types/claim_storager.go Defines storage interface for claims DB operations.
claimsync/types/claim_reader.go Defines read-only claims interface.
claimsync/types/claim_querier.go Defines boundary block query interface.
claimsync/types/processor.go Defines embedded processor interface for transactional embedding.
claimsync/types/syncer_id.go Adds claim syncer IDs and DB schema version constant.
claimsync/storage/migrations/migrations.go Adds claimsync migration registry and embedded SQL.
claimsync/storage/migrations/claimsync0001.sql Adds initial claimsync schema.
claimsync/types/mocks/mock_embedded_processor.go Adds autogenerated mocks for embedded processor interface.
claimsync/types/mocks/mock_claim_querier.go Adds autogenerated mocks for claim querier interface.
bridgesync/config.go Replaces custom tri-state with shared TrueFalseAutoMode and adds resolved logging.
bridgesync/types/types.go Removes Unclaim type (moved to claimsync types).
bridgesync/bridgesync.go Removes claim APIs from bridgesync and threads initial block into sync driver.
bridgesync/bridgesync_test.go Updates tests for new APIs and removed claim methods.
bridgesync/e2e_test.go Adapts helpers to new GetLastProcessedBlock signature and constructor params.
bridgesync/mock_bridge_querier.go Updates BridgeQuerier mock to use claimsync claim types.
bridgeservice/bridge_interfaces.go Splits claim operations into a dedicated Claimer interface.
bridgeservice/utils.go Updates claim response conversion to accept claimsync claim type.
bridgeservice/bridge.go Wires claimL1/claimL2 into handlers and updates GetLastProcessedBlock signature usage.
aggsender/types/status.go Adds explicit status transitions with logging.
aggsender/types/interfaces.go Updates interfaces to use claimsync types and adds InitialBlockClaimSyncerSetter.
aggsender/types/optimistic_interface.go Switches optimistic signer to consume claimsync claims.
aggsender/types/certificate_build_params.go Switches certificate build params claims/unclaims to claimsync types.
aggsender/types/certificate_build_params_test.go Updates tests for claimsync types.
aggsender/trigger/trigger_by_bridge.go Handles “no processed block” in ForceTriggerEvent.
aggsender/trigger/trigger_by_bridge_test.go Updates GetLastProcessedBlock mock signature.
aggsender/query/bridge_query.go Sources claims from claim syncer and reports min(bridge, claim) synced height.
aggsender/query/certificate_query.go Uses claim syncer for globalIndex→block resolution.
aggsender/query/initial_block_to_claimsync_setter.go Adds helper to set claim syncer next required block from latest settled cert.
aggsender/query/initial_block_to_claimsync_setter_test.go Adds tests covering success and error paths of initial-block setter.
aggsender/query/aggchain_proof_query.go Switches to claimsync unclaim types and claims input.
aggsender/query/aggchain_proof_query_test.go Updates tests for claimsync types.
aggsender/prover/proof_generation_tool.go Pulls claims via claim syncer and updates L2 reader to claimsync.
aggsender/prover/proof_generation_tool_test.go Updates tests to include claim syncer mock and new signatures.
aggsender/flows/builder_flow_factory.go Threads claim syncer through common flow components and uses claimsync reader.
aggsender/flows/builder_flow_factory_test.go Updates factory tests for new parameter.
aggsender/flows/verifier_flow_factory.go Threads claim syncer into verifier flows.
aggsender/flows/verifier_flow_factory_test.go Updates verifier flow factory test parameters.
aggsender/flows/flow_base.go Switches claims/unclaims types and uses new GetLastProcessedBlock signature.
aggsender/flows/max_l2blocknumber_limiter_test.go Updates claims test data types.
aggsender/converters/imported_bridge_exit_converter.go Converts from claimsync claim type instead of bridgesync claim.
aggsender/converters/imported_bridge_exit_converter_test.go Updates tests for claimsync claim type.
aggsender/optimistic/optimistichash/calculate_hash_commit_imported_bridges.go Switches optimistic hashing inputs to claimsync claim type.
aggsender/optimistic/optimistichash/calculate_hash_commit_imported_bridges_test.go Updates tests for claimsync claim type.
aggsender/optimistic/optimistic_sign.go Switches optimistic signing inputs to claimsync claim type.
aggsender/optimistic/optimistic_sign_test.go Updates tests for claimsync claim types.
aggsender/optimistic/mocks/mock_optimistic_signature_calculator.go Updates mock signature to use claimsync claim types.
aggsender/mocks/mock_optimistic_signer.go Updates mock signature to use claimsync claim types.
aggsender/mocks/mock_l2_bridge_syncer.go Updates GetLastProcessedBlock signature and removes claim mocks from L2 bridge syncer.
aggsender/mocks/mock_bridge_querier.go Updates bridge querier mock to use claimsync claim/unclaim types + new last processed signature.
aggsender/mocks/mock_aggsender_flow_baser.go Updates claim conversion mock signature to claimsync claim.
aggsender/mocks/mock_agglayer_bridge_l2_reader.go Updates reader mock to use claimsync Unclaim type.
aggsender/mocks/mock_initial_block_claim_syncer_setter.go Adds mock for initial block claim syncer setter.
aggsender/aggsender.go Wires claim syncer and sets claim sync starting block before flow init.
aggsender/aggsender_test.go Updates tests for claim syncer wiring and new signatures/types.
aggsender/aggsender_validator.go Wires claim syncer + initial-block setter into validator startup.
aggsender/aggsender_validator_test.go Adds tests for validator startup and delegation behavior.
.mockery.yaml Adds mockery generation config for claimsync interfaces.

@joanestebanr joanestebanr marked this pull request as ready for review March 20, 2026 15:43
@joanestebanr
Copy link
Collaborator Author

@claude

@claude
Copy link

claude bot commented Mar 20, 2026

Claude finished @joanestebanr's task in 2m 11s —— View job


Code Review Complete ✅


🚀 What's New

This PR extracts claim event synchronization from bridgesync into a new, dedicated claimsync package. The change enables claim indexing to run as an independent component with its own database, lifecycle, and RPC interface. This architectural improvement allows the aggsender to use full-node RPC instead of archive RPC, and provides better separation of concerns between bridge event and claim event synchronization.

🐛 Bug Fixes

None - this is a refactoring/architectural change.

📋 Config Updates

Introduces new configuration sections for ClaimL1Sync and ClaimL2Sync:

[ClaimL1Sync]
DBPath = "{{PathRWData}}/claiml1sync.sqlite"
AutoStart = "auto"  # New tri-state: true/false/auto
BridgeAddr = "{{BridgeL1Sync.BridgeAddr}}"
# ... other sync config fields

[ClaimL2Sync]
DBPath = "{{PathRWData}}/claiml2sync.sqlite"
AutoStart = "auto"
BridgeAddr = "{{BridgeL2Sync.BridgeAddr}}"
# ... other sync config fields

⚠️ Breaking Changes

  • Database resync required: All claims must be re-synced due to schema changes
  • bridgesync no longer provides claim-related methods (GetClaims, GetClaimsByGlobalIndex, etc.) - these are now in claimsync
  • Interfaces updated: GetLastProcessedBlock now returns (uint64, bool, error) instead of (uint64, error)

📊 Review Summary

Overall Assessment: This is a well-architected refactoring with good test coverage (80% on new code). The separation of concerns is clear and the code quality is high. However, there are some issues that should be addressed before merging.

🔴 Required Changes

1. Context Timeout Issue in processor.go:54

The dbCtx context with database timeout is created but not used for the InsertBlock call.

Location: claimsync/processor.go:54

// Current code uses ctx instead of dbCtx
if err := p.storage.InsertBlock(ctx, tx, block.Num, block.Hash); err != nil {

Issue: This bypasses the intended DB timeout/cancellation behavior and could lead to hangs.

Fix: Use dbCtx consistently for all DB operations within the transaction:

if err := p.storage.InsertBlock(dbCtx, tx, block.Num, block.Hash); err != nil {

Fix this →

2. Type Assertion Error Message Bug in embedded.go:116

When type assertion fails, %T is applied to event (zero value) instead of eventRaw, hiding the actual type.

Location: claimsync/embedded.go:116

return fmt.Errorf("claimsync ProcessBlock: unexpected event type %T in block %d", event, block.Num)

Issue: Will print <nil> instead of the actual offending type, making debugging difficult.

Fix:

return fmt.Errorf("claimsync ProcessBlock: unexpected event type %T in block %d", eventRaw, block.Num)

Fix this →

3. Potential Panic in syncer_id.go:22

Array indexing can panic with invalid/future enum values.

Location: claimsync/types/syncer_id.go:18-23

func (b ClaimSyncerID) String() string {
	if b < L1ClaimSyncer || b > L2ClaimSyncer {
		return fmt.Sprintf("UnknownClaimSyncerID(%d)", b)
	}
	return [...]string{"L1ClaimSyncer", "L2ClaimSyncer"}[b]
}

Issue: Bounds check protects against out-of-range, but this pattern is fragile if enums are reordered or if zero-value is misused.

Recommendation: Use a switch statement for safety and clarity:

func (b ClaimSyncerID) String() string {
	switch b {
	case L1ClaimSyncer:
		return "L1ClaimSyncer"
	case L2ClaimSyncer:
		return "L2ClaimSyncer"
	default:
		return fmt.Sprintf("UnknownClaimSyncerID(%d)", b)
	}
}

Fix this →

🟡 Suggested Improvements

4. Typo in Migration Comment

Location: claimsync/storage/migrations/migrations.go (comment)

Change bridegsyncbridgesync in the comment explaining the relationship between migrations.

Fix this →

5. Logging Format String Issue

Location: Multiple files use log.Info with format strings

Several locations use Info with printf-style format strings instead of Infof. Examples:

  • l2gersync/l2_ger_syncer.go (mentioned in copilot review)
  • Check for similar patterns in claimsync package

Recommendation: Audit logging calls to ensure format strings use the f variants (Infof, Debugf, etc.).

6. Mock Nil-Safety

Location: l1infotreesync/mock_driver_interface.go:90

The mock type assertion firstBlockNumber = args[1].(*uint64) will panic if nil is passed. Consider adding nil checks in mocks for pointer parameters, though this is auto-generated code (mockery).

Note: This is generated code, so fixing the mockery template would be the proper solution.

7. TODOs in Code

Found several TODOs that should be addressed or tracked:

  • claimsync/types/claim_data.go:203: "Why this struct is duplicated??"
  • claimsync/downloader.go:98: "Check syncfullclaims"
  • grpc/server.go: "Setting claimsyncer starting block"

Recommendation: Either resolve these or create tracking issues.

🟢 Positive Observations

  1. Clean Architecture: The separation between standalone and embedded modes is well-designed
  2. Good Test Coverage: 80% coverage on new code is excellent
  3. Interface Design: The ClaimSyncer interface is clean and well-documented
  4. Transaction Safety: Proper use of deferred rollback with shouldRollback flag
  5. Error Handling: Comprehensive error wrapping with context
  6. Database Migrations: Clean migration strategy with CASCADE deletes for referential integrity
  7. Type Safety: Good use of typed enums (ClaimSyncerID, ClaimType)
  8. Configuration: The new TrueFalseAutoMode type is a nice addition for tri-state config
  9. Logging: Generally good logging with structured fields and appropriate levels

🔍 Additional Observations

Performance Considerations

  • The sync driver properly handles block ranges and includes buffering (downloadBufferSize = 1000)
  • Database indexes are properly defined for claim queries (idx_claim_type_block)
  • Paged query support is included for large result sets

Security Considerations

  • SQL injection protection via parameterized queries (using meddler and prepared statements)
  • Proper input validation on configuration
  • Table name regex validation to prevent injection

Compatibility

  • Runtime data compatibility checking is properly implemented
  • Database versioning (CurrentDBVersion = 1) is in place for future schema changes

🎯 Recommendation

Approve with Required Changes: This is a solid architectural improvement. The three required issues (context usage, error message, potential panic) should be fixed before merge, but they're straightforward fixes. The suggested improvements can be addressed in follow-up PRs if time is a constraint.

The PR successfully achieves its goal of decoupling claim synchronization, enabling full-node RPC usage, and improving code organization.


@sonarqubecloud
Copy link

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.

2 participants