Skip to content

Conversation

@julienrbrt
Copy link
Member

Closes: #2965

@github-actions
Copy link
Contributor

github-actions bot commented Jan 15, 2026

The latest Buf updates on your PR. Results from workflow CI / buf-check (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed⏩ skipped✅ passed✅ passedJan 16, 2026, 2:00 PM

@claude
Copy link
Contributor

claude bot commented Jan 15, 2026

Claude finished @julienrbrt's task in 2m 37s —— View job


Code Review Complete

I've completed a comprehensive code review of PR #2982. This is a well-executed refactoring that significantly improves the architecture by separating concerns and making execution parameters dynamically queryable. Below are my findings organized by category.


Summary

This PR successfully refactors the Executor interface by removing maxBytes return values from InitChain and ExecuteTxs, introducing two new optional interfaces (ExecutionInfoProvider via GetExecutionInfo method, and DATransactionFilter), and implementing gas-aware filtering of DA transactions in the sequencer. The changes are applied consistently across the codebase.

Overall Assessment: ✅ Approve with minor recommendations


1. Architecture & Code Quality ⭐

Strengths

  • Excellent separation of concerns: The refactoring removes the awkward dual-purpose return value (maxBytes) from execution methods and replaces it with dedicated query methods. This is a textbook example of interface segregation.

  • Optional interfaces done right: The use of optional interfaces (DATransactionFilter) via type assertion in pkg/sequencers/single/sequencer.go:132-138 is idiomatic Go and allows backward compatibility.

  • Consistent naming: GetExecutionInfo follows Go conventions and the ExecutionInfo struct is well-documented (core/execution/execution.go:8-13).

  • Protobuf design: The new RPC methods in proto/evnode/v1/execution.proto:22-26 maintain consistency with existing patterns.

Issues & Recommendations

🔴 Critical: Protobuf backward compatibility issue

Location: proto/evnode/v1/execution.proto:42-48, 76-83

Problem: The max_bytes field was removed from InitChainResponse and ExecuteTxsResponse messages. However, the proto file shows these fields are still present but marked as uint64 max_bytes = 2. This creates confusion - if these fields are deprecated, they should either:

  1. Be marked with [deprecated = true] option, OR
  2. Be removed entirely (breaking change requiring version bump)

Current state:

message InitChainResponse {
  bytes state_root = 1;
  uint64 max_bytes = 2;  // ⚠️ Still here but not returned by Go code
}

Recommendation:

  • If this is meant to be backward compatible, mark fields as deprecated:
    uint64 max_bytes = 2 [deprecated = true];
  • Document the migration path in the proto comments
  • Consider whether clients expect these fields and if they need a grace period

Learn more about protobuf field deprecation

🟡 Medium: Incomplete test coverage for new functionality

Location: execution/grpc/server_test.go:175-177

Problem: As noted by Gemini's review, the test validation was weakened:

if len(resp.Msg.Txs) != len(expectedTxs) {
    t.Fatalf("expected %d txs, got %d", len(expectedTxs), len(resp.Msg.Txs))
}
// ⚠️ Missing: content validation of returned transactions

Recommendation: Add content validation:

for i, tx := range resp.Msg.Txs {
    if !bytes.Equal(tx, expectedTxs[i]) {
        t.Errorf("tx %d: expected %x, got %x", i, expectedTxs[i], tx)
    }
}

🟡 Medium: Missing tests for new RPC methods

Location: execution/grpc/server_test.go, execution/grpc/client_test.go

Problem: No dedicated tests for GetExecutionInfo and FilterDATransactions RPC methods in the gRPC layer test files.

Recommendation: Add test cases following the existing pattern in server_test.go:

  • TestServer_GetExecutionInfo - test success, executor error, various heights
  • TestServer_FilterDATransactions - test success, unimplemented error, validation
  • TestClient_GetExecutionInfo
  • TestClient_FilterDATransactions

🟢 Low: Documentation could be clearer about non-gas execution layers

Location: core/execution/execution.go:97, 140

Observation: The comments mention "For non-gas-based execution layers, return ExecutionInfo{MaxGas: 0}" but don't clarify the behavior implications.

Recommendation: Expand the comment to explain what happens when MaxGas=0:

// For non-gas-based execution layers, return ExecutionInfo{MaxGas: 0}.
// When MaxGas is 0, the sequencer will include all DA transactions without gas filtering.

2. Error Handling & Resilience ✅

Strengths

  • Graceful degradation in sequencer: The sequencer properly handles missing DATransactionFilter implementation (pkg/sequencers/single/sequencer.go:229-255), logging warnings and proceeding without gas filtering.

  • Context propagation: All new methods properly accept and respect context.Context.

  • Error wrapping: Consistent use of fmt.Errorf with %w for error context.

Issues

🟢 Low: Silent failure on GetExecutionInfo error

Location: pkg/sequencers/single/sequencer.go:231-234

info, err := c.executor.GetExecutionInfo(ctx, 0)
if err != nil {
    c.logger.Warn().Err(err).Msg("failed to get execution info for gas filtering, proceeding without gas filter")
    filteredForcedTxs = forcedTxs  // ⚠️ Silently continues
}

Observation: While logging the error is good, this could mask a persistent issue (e.g., network problems with remote executor). Consider adding metrics or rate-limiting the warnings.

Recommendation: Add a metric counter for GetExecutionInfo failures to track if this is happening frequently.


3. Security 🔒

Strengths

  • No new security vulnerabilities introduced: The refactoring maintains the same execution model.

  • Gas limit enforcement: The new FilterDATransactions in execution/evm/execution.go:796-857 properly validates transactions and enforces gas limits, preventing DoS attacks via oversized DA transactions.

  • Input validation maintained: All existing validation (empty txs, malformed data) is preserved.

Issues

🟢 Low: Consider adding telemetry for filtered gibberish transactions

Location: execution/evm/execution.go:807-813

Observation: Gibberish transactions are filtered with debug logging, but there's no metric tracking how many malicious/malformed transactions are being filtered from DA.

Recommendation: Add a counter metric for security monitoring:

c.logger.Debug().Int("tx_index", i).Err(err).Msg("filtering out invalid DA transaction (gibberish)")
// Add: metrics.IncrCounter("da_transactions_filtered_gibberish")

4. Performance & Resource Efficiency ⚡

Strengths

  • Efficient gas tracking: The FilterDATransactions implementation uses cumulative gas tracking (execution/evm/execution.go:798, 816-819) avoiding recomputation.

  • Minimal allocations: Pre-allocated slices where capacity is known (execution/evm/execution.go:797).

  • Caching in sequencer: The sequencer caches filtered transactions (pkg/sequencers/single/sequencer.go:278) avoiding redundant filtering.

Issues

🟡 Medium: Potential N+1 query pattern

Location: pkg/sequencers/single/sequencer.go:231

Problem: GetExecutionInfo(ctx, 0) is called on every GetNextBatch call. For high-frequency block production, this could become a bottleneck if the executor is remote (gRPC).

Recommendation: Consider caching the ExecutionInfo with a short TTL (e.g., 1 second) since gas limits typically don't change frequently:

// Add to Sequencer struct:
type Sequencer struct {
    // ...
    cachedExecInfo     execution.ExecutionInfo
    cachedExecInfoTime time.Time
    execInfoCacheTTL   time.Duration
}

// In GetNextBatch:
if time.Since(c.cachedExecInfoTime) > c.execInfoCacheTTL {
    info, err := c.executor.GetExecutionInfo(ctx, 0)
    if err == nil {
        c.cachedExecInfo = info
        c.cachedExecInfoTime = time.Now()
    }
}

🟢 Low: Telemetry wrapper creates span on every call

Location: pkg/telemetry/executor_tracing.go:110-124

Observation: The tracing wrapper creates OpenTelemetry spans for every method call. While this is correct, it adds overhead. Ensure tracing is disabled in production if performance is critical.

Note: This is expected behavior for distributed tracing, but worth documenting.


5. Testing & Reliability 🧪

Strengths

  • Comprehensive test updates: All test files were updated to match the new signatures (35 files changed).

  • Mock generation: Mocks properly implement the new interfaces (test/mocks/execution.go:26-30).

  • Integration test coverage: The sequencer tests in pkg/sequencers/single/sequencer_test.go demonstrate the gas filtering functionality.

Issues

🔴 Critical: Low patch coverage (35.59%)

Location: Codecov report shows 38 missing lines

Primary culprits:

  1. pkg/telemetry/executor_tracing.go - 36 missing lines
  2. execution/grpc/client.go - 2 missing lines

Recommendation:

  • Add unit tests for the telemetry wrapper methods (GetExecutionInfo, FilterDATransactions)
  • Add error path tests for gRPC client methods
  • The telemetry code is straightforward but should have basic happy path tests

Example test to add:

func TestTracedExecutor_GetExecutionInfo(t *testing.T) {
    mockExec := &mockExecutor{
        getExecutionInfoFunc: func(ctx context.Context, height uint64) (execution.ExecutionInfo, error) {
            return execution.ExecutionInfo{MaxGas: 30000000}, nil
        },
    }
    traced := telemetry.WithTracingExecutor(mockExec)
    
    info, err := traced.GetExecutionInfo(context.Background(), 0)
    require.NoError(t, err)
    assert.Equal(t, uint64(30000000), info.MaxGas)
}

🟡 Medium: Missing negative test cases

Recommendation: Add tests for:

  • What happens when FilterDATransactions returns an error? (Currently only happy path tested)
  • What happens when executor returns MaxGas: 0 vs MaxGas: 30000000?
  • What happens when all DA transactions exceed gas limit?

6. Documentation & Developer Experience 📚

Strengths

  • Excellent interface documentation: The docstrings in core/execution/execution.go are comprehensive, explaining parameters, returns, and requirements.

  • Code examples in comments: The DATransactionFilter interface includes clear explanation of filtering behavior (core/execution/execution.go:125-151).

  • Migration path clear: The refactoring is straightforward for implementers - just add GetExecutionInfo method.

Issues

🟢 Low: Missing CHANGELOG entry

Observation: This is a significant API change that affects all executor implementations.

Recommendation: Add a CHANGELOG entry or migration guide:

## Executor Interface Changes

### Breaking Changes (for implementers)
- `InitChain` and `ExecuteTxs` no longer return `maxBytes`
- All executors must now implement `GetExecutionInfo(ctx, height) ExecutionInfo`

### Optional Enhancements
- Implement `DATransactionFilter` interface for gas-based DA transaction filtering

🟢 Low: Consider adding architecture decision record (ADR)

Recommendation: Document why maxBytes was removed and why GetExecutionInfo is the better approach. This helps future maintainers understand the reasoning.


7. Concurrency & Thread Safety 🧵

Strengths

  • EVM client mutex protection: The EngineClient properly protects shared state with mutexes (execution/evm/execution.go:168-173).

  • Atomic operations in sequencer: DA height updates use atomic.Uint64 (pkg/sequencers/single/sequencer.go:47-48).

  • No data races introduced: The refactoring doesn't add new shared state.

No Issues Identified ✅


8. Consistency Across Codebase 🎯

Strengths

  • All call sites updated: Impressive consistency across 35 files updating all InitChain and ExecuteTxs calls.

  • Interface implementations complete: All executors (EVM, KV, Dummy, gRPC) implement the new interface correctly.

  • Mock updates: Test mocks properly mirror the new interfaces.

No Issues Identified ✅


Action Items Summary

Must Fix Before Merge 🔴

  1. Clarify protobuf backward compatibility: Either mark max_bytes fields as deprecated or remove them entirely with version bump
  2. Improve test coverage: Add tests for GetExecutionInfo and FilterDATransactions in gRPC layer and telemetry wrapper (target >60% patch coverage)

Should Fix 🟡

  1. Restore test validation: Add transaction content validation in execution/grpc/server_test.go:177
  2. Add negative test cases: Test error paths and edge cases for new functionality
  3. Consider performance optimization: Cache GetExecutionInfo results in sequencer to avoid N+1 queries

Nice to Have 🟢

  1. Documentation improvements: Add CHANGELOG entry and clarify MaxGas=0 behavior
  2. Monitoring: Add metrics for filtered gibberish transactions and GetExecutionInfo failures
  3. Architecture documentation: Consider adding ADR explaining the refactoring rationale

Conclusion

This is a high-quality refactoring that improves the codebase architecture significantly. The separation of execution parameters into a dedicated query method (GetExecutionInfo) is the right design choice, and the gas-aware filtering of DA transactions is implemented correctly.

The main concerns are:

  1. Protobuf compatibility needs clarification
  2. Test coverage should be improved (currently 35.59% patch coverage)
  3. A few minor enhancements around documentation and performance

Once the test coverage is improved and the protobuf compatibility is clarified, this PR will be ready to merge.

Estimated effort to address critical issues: ~2-3 hours for test additions and protobuf clarification.


@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @julienrbrt, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the interaction between ev-node and its execution clients. By removing the maxBytes return value from the core InitChain and ExecuteTxs methods, it introduces more specialized interfaces (ExecutionInfoProvider and DATransactionFilter). This change enhances modularity, allowing for dynamic retrieval of execution parameters and robust, gas-aware filtering of transactions originating from the Data Availability layer, thereby improving the system's flexibility and maintainability.

Highlights

  • Refactored Executor Interface: The core Executor interface's InitChain and ExecuteTxs methods no longer directly return maxBytes or gasLimit, streamlining their primary responsibility to state root management.
  • Introduced ExecutionInfoProvider: A new ExecutionInfoProvider interface has been added, allowing execution clients to expose dynamic parameters, such as MaxGas, through a dedicated GetExecutionInfo method. This provides a more flexible way to retrieve execution-layer specific information.
  • Introduced DATransactionFilter: A new DATransactionFilter interface is now available for execution clients to implement. This interface provides a FilterDATransactions method, specifically designed to validate and filter force-included transactions from the Data Availability (DA) layer based on execution-layer rules, such as gas limits.
  • EVM Engine Client Enhancements: The EVM EngineClient has been updated to implement both the new ExecutionInfoProvider and DATransactionFilter interfaces. It now retrieves gas limits dynamically and performs gas-aware filtering of DA transactions before execution.
  • Codebase-Wide Signature Updates: Numerous calls to InitChain and ExecuteTxs across the entire codebase, including application logic, tests, and mock implementations, have been updated to align with the revised function signatures, removing the maxBytes return value.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the Executor interface by removing the maxBytes return value from InitChain and ExecuteTxs. It introduces new interfaces, ExecutionInfoProvider and DATransactionFilter, to expose execution client parameters like MaxGas more explicitly. The changes are applied consistently throughout the codebase, including implementations, mocks, and tests. This is a solid refactoring that improves the separation of concerns. I've found one issue in a test file where a check was removed, weakening the test's validation.

Comment on lines 175 to 177
if len(resp.Msg.Txs) != len(expectedTxs) {
t.Fatalf("expected %d txs, got %d", len(expectedTxs), len(resp.Msg.Txs))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The check for the content of the returned transactions has been removed, which weakens the test. It now only verifies the number of transactions, not that they are the correct ones. It would be better to verify the content as well to ensure the server is returning the expected data.

if len(resp.Msg.Txs) != len(expectedTxs) {
	t.Fatalf("expected %d txs, got %d", len(expectedTxs), len(resp.Msg.Txs))
}
for i, tx := range resp.Msg.Txs {
	if string(tx) != string(expectedTxs[i]) {
		t.Errorf("tx %d: expected %s, got %s", i, expectedTxs[i], tx)
	}
}

@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 39.56835% with 84 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.75%. Comparing base (7d30f97) to head (987beb0).

Files with missing lines Patch % Lines
pkg/telemetry/executor_tracing.go 15.38% 33 Missing ⚠️
execution/grpc/client.go 16.00% 21 Missing ⚠️
execution/grpc/server.go 10.00% 18 Missing ⚠️
pkg/sequencers/single/sequencer.go 80.95% 5 Missing and 3 partials ⚠️
core/execution/dummy.go 50.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2982      +/-   ##
==========================================
- Coverage   59.13%   58.75%   -0.38%     
==========================================
  Files         102      102              
  Lines        9822     9931     +109     
==========================================
+ Hits         5808     5835      +27     
- Misses       3397     3476      +79     
- Partials      617      620       +3     
Flag Coverage Δ
combined 58.75% <39.56%> (-0.38%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from julien/da-strategy to main January 16, 2026 12:24
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.

Expose gas in execution interface

2 participants