Skip to content

feat: cherry-pick: configurable batch block header retrieval via RPCClientConfig#1606

Merged
joanestebanr merged 2 commits intodevelopfrom
cherry-pick/1601-batch-block-header-retrieval
Apr 29, 2026
Merged

feat: cherry-pick: configurable batch block header retrieval via RPCClientConfig#1606
joanestebanr merged 2 commits intodevelopfrom
cherry-pick/1601-batch-block-header-retrieval

Conversation

@joanestebanr
Copy link
Copy Markdown
Collaborator

🔄 Changes Summary

Cherry-pick of #1601 (originally merged into release/0.10) into develop.

  • Moves BlockHeadersResult, ErrNotFound and IsErrNotFound from etherman to the types package
  • Adds RetrieveBlockHeaders(ctx, blockNumbers, maxConcurrency) to the CustomEthereumClienter interface, implemented by DefaultEthClient
  • Adds BatchBlockHeaderRetrieval bool (default true) to RPCClientConfig — operators can disable batch RPC requests for nodes that do not support them
  • Simplifies multidownloader call sites: the three etherman.RetrieveBlockHeaders(ctx, log, ethClient, rpcClient, ...) calls collapse to dh.ethClient.RetrieveBlockHeaders(ctx, ...)
  • Documents RPCClientConfig in docs/common_config.md

⚠️ Breaking Changes

N/A

📋 Config Updates

  • 🧾 New optional field in [L1NetworkConfig.RPC] and [Common.L2RPC]:
BatchBlockHeaderRetrieval = true  # default, disable for nodes without batch support

✅ Testing

📝 Notes

  • etherman.BlockHeadersResult and etherman.NewBlockHeadersResult are kept as type aliases for backward compatibility
  • etherman.ErrNotFound and etherman.IsErrNotFound are kept as wrappers delegating to types

🤖 Generated with Claude Code

…1601)

## 🔄 Changes Summary
- Moves `BlockHeadersResult`, `ErrNotFound` and `IsErrNotFound` from
`etherman` to the `types` package
- Adds `RetrieveBlockHeaders(ctx, blockNumbers, maxConcurrency)` to the
`CustomEthereumClienter` interface, implemented by `DefaultEthClient`
- Adds `BatchBlockHeaderRetrieval bool` (default `true`) to
`RPCClientConfig` — operators can disable batch RPC requests for nodes
that do not support them
- Simplifies `multidownloader` call sites: the three
`etherman.RetrieveBlockHeaders(ctx, log, ethClient, rpcClient, ...)`
calls collapse to `dh.ethClient.RetrieveBlockHeaders(ctx, ...)`
- Documents `RPCClientConfig` in `docs/common_config.md`

## ⚠️ Breaking Changes
N/A

## 📋 Config Updates
- 🧾 New optional field in `[L1NetworkConfig.RPC]` and `[Common.L2RPC]`:
```toml
BatchBlockHeaderRetrieval = true  # default, disable for nodes without batch support
```

## ✅ Testing
- 🤖 **Automatic**: existing unit tests updated
(`TestEVMMultidownloader_MoveUnsafeToSafeIfPossible`,
`TestEVMMultidownloader_StepSafe`); `TestLoadDefaultConfig` asserts the
new default
- 🖱️ **Manual**: build passes (`go build ./...`), unit tests pass (`go
test ./types/... ./etherman/... ./multidownloader/... ./config/...`)

## 📝 Notes
- `etherman.BlockHeadersResult` and `etherman.NewBlockHeadersResult` are
kept as type aliases for backward compatibility with existing callers
- `etherman.ErrNotFound` and `etherman.IsErrNotFound` are kept as
wrappers delegating to `types`
- The standalone `etherman.RetrieveBlockHeaders`,
`RetrieveBlockHeadersBatch`, `RetrieveBlockHeadersLegacy` functions
remain for direct use in tests and other callers outside the
multidownloader

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude Bot commented Apr 29, 2026

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


PR Review Complete ✅

I've completed a comprehensive review of PR #1606. This is a well-structured cherry-pick that adds configurable batch block header retrieval functionality.


🚀 What's New

  • New BatchBlockHeaderRetrieval config flag (default: true) in RPCClientConfig allows operators to disable batch RPC requests for nodes that don't support them
  • Refactored architecture: Moved BlockHeadersResult, ErrNotFound, and IsErrNotFound from etherman to the types package for better code organization
  • New interface method: Added RetrieveBlockHeaders(ctx, blockNumbers, maxConcurrency) to CustomEthereumClienter, implemented by DefaultEthClient
  • Simplified API: Consolidated three separate etherman.RetrieveBlockHeaders call sites in multidownloader into direct calls to ethClient.RetrieveBlockHeaders
  • Documentation: Added comprehensive documentation for RPCClientConfig in docs/common_config.md

🐛 Bug Fixes

None.

📋 Config Updates

New optional field in [L1NetworkConfig.RPC] and [Common.L2RPC]:

BatchBlockHeaderRetrieval = true  # default; set to false for nodes without batch support

⚠️ Breaking Changes

None. Backward compatibility is maintained via type aliases (etherman.BlockHeadersResult) and wrapper functions (etherman.ErrNotFound, etherman.IsErrNotFound).


📊 Review Findings

🟢 Strengths

  1. Excellent backward compatibility approach - Type aliases and wrapper functions ensure existing code continues to work
  2. Comprehensive test coverage - 261 lines of tests for BlockHeadersResult, plus updates to existing tests
  3. Good separation of concerns - Moving types to the types package improves architecture
  4. Proper configuration defaults - BatchBlockHeaderRetrieval = true is sensible and tested
  5. Clear documentation - The new docs/common_config.md section clearly explains the new config option
  6. Robust error handling - BlockHeadersResult properly distinguishes between partial success, full success, and various error types

🟡 Suggestions (Code Quality)

1. Potential nil pointer dereference in IsErrNotFound

File: types/errors.go:23

The IsErrNotFound function could be more defensive:

// If error contains "not found" (case sensitive) is an ErrNotFound
if strings.Contains(err.Error(), "not found") {
    return true
}

If err.Error() panics (though unlikely with standard errors), this could cause issues. Consider wrapping in a recover or checking the error type more carefully. However, this is a very minor concern as Go's error interface guarantees Error() returns a string.

Priority: 🟢 Optional (very low risk in practice)

2. Comment typo in batch_requests.go:170

File: etherman/batch_requests.go:170

// retrieveBlockHeadersInBatchParallel split request into chuncks and execute it in parallel

Should be "chunks" not "chuncks". Also appears in variable names throughout the file (chunck, chuncks).

Priority: 🟢 Optional (style/consistency)

3. Consider making batchRequestLimitHTTP configurable

File: etherman/batch_requests.go:52

const batchRequestLimitHTTP = 1000

This hardcoded limit (1000) is based on Alchemy's documented limits. Different RPC providers may have different limits. Consider making this configurable via RPCClientConfig in a future enhancement.

Priority: 🟢 Optional (future enhancement)

🟢 Security & Performance

  • No security issues identified
  • Concurrency properly handled - Uses sync.Mutex and errgroup correctly in multidownloader
  • Context cancellation respected - All RPC calls properly pass through context
  • Batch size limits enforced - Prevents overwhelming RPC nodes with oversized batch requests
  • Error handling is comprehensive - Distinguishes between catastrophic errors and per-block failures

🟢 Test Coverage

  • 261 lines of comprehensive tests for BlockHeadersResult in types/block_headers_result_test.go
  • 110 lines of tests added to etherman/default_eth_client_test.go
  • Updated existing tests in multidownloader, claimsync, and batch_requests
  • Config default verified in TestLoadDefaultConfig

🟢 Code Style Compliance

  • Follows Go naming conventions - CamelCase for exports, camelCase for private
  • Proper error wrapping - Uses fmt.Errorf with %w consistently
  • Doc comments present - All exported functions have proper doc comments
  • Import organization - Properly grouped (stdlib, external, internal)
  • Uses require in tests - Follows repo guidelines

🟢 Architecture & Design

  • Interface-based design - RetrieveBlockHeaders added to CustomEthereumClienter interface
  • Dependency injection - Config-driven behavior (batch vs. legacy)
  • Separation of concerns - Types in types package, implementation in etherman
  • Graceful degradation - Falls back to legacy mode when batch is disabled or unavailable

🔍 Detailed Analysis

Configuration Changes (etherman/config/network.go)

The new BatchBlockHeaderRetrieval field is well-integrated:

  • Default value of true maintains optimal performance for supported nodes
  • Clear documentation explains when to disable it
  • Properly validated and passed through to DefaultEthClient

Type Migration (types/ package)

Moving BlockHeadersResult to the types package is architecturally sound:

  • Reduces coupling between etherman and multidownloader
  • Makes the type reusable across the codebase
  • Backward compatibility maintained via type aliases in etherman/batch_requests.go:54-59

Implementation (etherman/default_eth_client.go)

The RetrieveBlockHeaders method (lines 171-181) properly delegates to either:

  • RetrieveBlockHeadersBatch when batch mode is enabled
  • RetrieveBlockHeadersLegacy when batch mode is disabled

Good defensive programming at lines 78-81 disables batch mode when rpcClient is nil.

Multidownloader Integration

Three call sites updated consistently:

  • evm_multidownloader.go:627 (StepUnsafe)
  • evm_multidownloader.go:702 (StepSafe)
  • evm_multidownloader.go:1051 (detectReorgs)

All properly handle BlockHeadersResult with partial success checking.


✅ Recommendations

  1. Approve and merge - This PR is production-ready
  2. Monitor in production - Track whether any operators need to disable BatchBlockHeaderRetrieval
  3. Consider future enhancement - Make batchRequestLimitHTTP configurable if different RPC providers have different limits
  4. Fix typo (optional) - Correct "chunck" → "chunk" throughout batch_requests.go for consistency

📝 CI Status

  • ✅ Lint: Passed
  • ✅ PR Semantic Check: Passed
  • ⏳ Unit Tests: In progress
  • ⏳ E2E Tests: In progress
  • ⏳ CodeQL: In progress
  • ❌ Go Vulnerability Check: Failed (likely unrelated to this PR - appears to be a pre-existing issue)

Overall Assessment: This is a high-quality PR that improves configurability and code architecture while maintaining backward compatibility. The implementation is robust, well-tested, and follows best practices. Recommend approval.

@joanestebanr joanestebanr changed the title feat: configurable batch block header retrieval via RPCClientConfig feat: cherry-pick: configurable batch block header retrieval via RPCClientConfig Apr 29, 2026
@joanestebanr joanestebanr self-assigned this Apr 29, 2026
@sonarqubecloud
Copy link
Copy Markdown

@joanestebanr joanestebanr merged commit d7da57b into develop Apr 29, 2026
24 of 25 checks passed
@joanestebanr joanestebanr deleted the cherry-pick/1601-batch-block-header-retrieval branch April 29, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants