Skip to content

Conversation

@julienrbrt
Copy link
Member

Overview

ref: #2906

Add based block time based on epoch da time.

DO NOT MERGE YET, based on #2908 to avoid conflicts later.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

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

BuildFormatLintBreakingUpdated (UTC)
✅ passed⏩ skipped✅ passed✅ passedDec 5, 2025, 1:19 PM

@claude
Copy link
Contributor

claude bot commented Dec 5, 2025

Claude finished @julienrbrt's task —— View job


Code Review Complete

I've reviewed the PR changes that add based block time based on epoch DA time. Here's my comprehensive feedback:


Summary

This PR implements timestamp tracking for based sequencer batches by propagating DA block timestamps through the forced inclusion retrieval system. The changes are focused and well-tested.


✅ Positive Observations

  1. Clean Architecture: The timestamp propagation follows a logical flow: ForcedInclusionRetrieverBasedSequencer.fetchNextDAEpoch()GetNextBatch() response
  2. Comprehensive Test Coverage: The PR adds 223 lines of tests covering various edge cases including multi-height epochs, partial batches, and error scenarios
  3. Idiomatic Go: Code follows Go conventions with proper error handling and context usage
  4. Backward Compatibility: Changes are additive and don't break existing interfaces

🔍 Issues & Recommendations

1. Zero-Value Timestamp Semantics (Minor)

Location: sequencers/based/sequencer.go:96

When no new DA epoch is fetched, t remains time.Time{} (zero value). This could be confusing for consumers who can't distinguish between:

  • "No timestamp available"
  • "Timestamp is actually Unix epoch zero"

Recommendation: Consider using *time.Time or documenting this behavior explicitly. For example:

// t will be time.Time{} if we're serving from cached transactions
// and the DA timestamp was already retrieved in a previous call
t := time.Time{}

2. Test Timestamp Assertion Inconsistency (Minor)

Location: block/internal/da/forced_inclusion_retriever_test.go:338

assert.Equal(t, event.Timestamp, time.Time{})

This test asserts that the timestamp remains zero when result.Timestamp is not set. However, the test data in line 279-283 doesn't specify a timestamp in the mock result, so this is testing implementation detail rather than business logic.

Recommendation: Either explicitly set a timestamp in the test data or add a comment explaining why zero is expected here.

3. Missing Error Handling Test (Medium)

Location: sequencers/based/sequencer.go:99-106

The fetchNextDAEpoch can return three different states:

  • Success with timestamp
  • Error with ErrForceInclusionNotConfigured
  • Error with ErrHeightFromFuture

However, there's no test in sequencers/based/ that verifies GetNextBatch correctly handles these error cases.

Recommendation: Add integration tests for GetNextBatch error scenarios to ensure error propagation works correctly.

4. Timestamp Comparison Logic (Minor Security/Correctness)

Location: block/internal/da/forced_inclusion_retriever.go:163-165

if result.Timestamp.After(event.Timestamp) {
    event.Timestamp = result.Timestamp
}

This logic takes the latest timestamp across all blobs in an epoch. However:

  • What happens if result.Timestamp is zero? The comparison might not behave as expected
  • Should this be the latest timestamp or perhaps the earliest (epoch start)?

Recommendation: Add validation to ensure result.Timestamp is non-zero before comparison, and document why we choose the latest timestamp rather than earliest.

5. UTC Conversion Timing (Minor)

Location: sequencers/based/sequencer.go:201

return forcedTxsEvent.Timestamp.UTC(), forcedTxsEvent.EndDaHeight, nil

The UTC conversion happens at return time, but the timestamp comparison in processForcedInclusionBlobs happens before UTC conversion. This could theoretically cause issues if timestamps have different time zones.

Recommendation: Normalize to UTC earlier in the pipeline, ideally when receiving the timestamp from the DA layer.

6. Missing Documentation (Minor)

Location: block/internal/da/forced_inclusion_retriever.go:28

The Timestamp field is added to ForcedInclusionEvent without godoc comments explaining:

  • What this timestamp represents (DA block time? Earliest? Latest?)
  • What happens if no blobs are found (will it be zero?)
  • UTC vs local time expectations

Recommendation: Add field documentation:

type ForcedInclusionEvent struct {
    // Timestamp is the latest DA block timestamp from the epoch range.
    // Will be time.Time{} if no blobs were found in the epoch.
    Timestamp     time.Time
    // ...
}

🔒 Security & Resilience

No security issues identified

  • No credential handling
  • No user input validation needed (internal API)
  • Proper error wrapping maintains context

Resilience looks good

  • Errors are properly propagated
  • Context handling is consistent
  • Checkpoint mechanism ensures recovery

⚡ Performance

No performance concerns

  • Timestamp operations are O(1)
  • No additional DA calls introduced
  • Memory overhead is negligible (single time.Time per event)

📝 Testing

Strong: 223 new lines of test coverage including:

  • Batched retrieval with partial batches
  • Error handling in batch operations
  • Multi-height epoch scenarios

Gap: Missing sequencer-level tests for GetNextBatch error scenarios as noted in issue #3.


🎯 Final Assessment

This is a well-implemented PR that solves the timestamp tracking requirement cleanly. The issues raised are minor and mostly about defensive programming and documentation. The code is production-ready but would benefit from the improvements suggested above.

Recommendation: ✅ Approve with minor suggestions - The PR can be merged as-is, but consider addressing the documentation and test coverage gaps in a follow-up.


@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 enhances the based sequencer by integrating the Data Availability (DA) layer's block timestamp directly into the batch creation process. This change ensures that each generated batch is associated with a precise and verifiable timestamp from the DA layer, improving the determinism and reliability of the sequencer's operation. Additionally, new tests have been introduced to thoroughly validate the DA client's data retrieval capabilities, including batching mechanisms.

Highlights

  • DA Block Timestamp Integration: The Data Availability (DA) layer's block timestamp is now retrieved and propagated through the fetchNextDAEpoch function to the GetNextBatch method in the based sequencer.
  • Deterministic Batch Timing: The GetNextBatchResponse now includes the actual DA block timestamp, replacing a placeholder, which ensures deterministic timing for sequencer batches.
  • Forced Inclusion Event Enhancement: The ForcedInclusionEvent struct has been updated to include a Timestamp field, which is populated and updated during the processing of forced inclusion blobs.
  • Expanded DA Client Testing: New unit tests have been added for the DA client's retrieval methods, specifically RetrieveHeaders, RetrieveData, and Retrieve with batching, covering various scenarios including partial batches and error handling.
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.

@julienrbrt julienrbrt mentioned this pull request Dec 5, 2025
8 tasks
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

The pull request introduces changes to incorporate the Data Availability (DA) block timestamp into the batching process for the BasedSequencer. This addresses a previous TODO to use the DA block timestamp for determinism. The ForcedInclusionEvent struct now includes a Timestamp field, which is populated during the retrieval of forced inclusion blobs. The BasedSequencer's fetchNextDAEpoch method has been updated to return this timestamp, which is then used in the GetNextBatchResponse. New test cases have been added to client_test.go to cover batch retrieval scenarios, and existing tests in forced_inclusion_retriever_test.go have been updated to assert on the new timestamp field. The changes are well-implemented and improve the determinism of the sequencer.

assert.Equal(t, coreda.StatusError, result.Code)
assert.Assert(t, result.Message != "")
// Error message should mention the batch range
assert.Assert(t, len(result.Message) > 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This assertion is a bit weak. It only checks that the error message is not empty. It would be more robust to assert on the specific content of the error message, or at least a substring, to ensure the expected error is being returned. For example, checking if it contains "network error in batch 2" or "failed to get blobs".

Suggested change
assert.Assert(t, len(result.Message) > 0)
assert.ErrorContains(t, errors.New(result.Message), "network error in batch 2")

return &coresequencer.GetNextBatchResponse{
Batch: batch,
Timestamp: time.Time{}, // TODO(@julienrbrt): we need to use DA block timestamp for determinism
Timestamp: t,
Copy link
Member Author

Choose a reason for hiding this comment

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

We currently want strictly increasing time and not the same time. So maybe we can have a jitter based on the tx index (so if it doesn't fit all in the same block the time is the same for everyone)

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you think @alpe?

@julienrbrt julienrbrt removed the blocked label Dec 5, 2025
@julienrbrt julienrbrt marked this pull request as draft December 5, 2025 13:22
@codecov
Copy link

codecov bot commented Dec 5, 2025

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 65.82%. Comparing base (c761301) to head (7ed1ee3).
⚠️ Report is 3 commits behind head on julien/persist-base.

Files with missing lines Patch % Lines
sequencers/based/sequencer.go 88.88% 1 Missing ⚠️
Additional details and impacted files
@@                   Coverage Diff                   @@
##           julien/persist-base    #2911      +/-   ##
=======================================================
+ Coverage                65.75%   65.82%   +0.06%     
=======================================================
  Files                       87       87              
  Lines                     7995     7999       +4     
=======================================================
+ Hits                      5257     5265       +8     
+ Misses                    2164     2160       -4     
  Partials                   574      574              
Flag Coverage Δ
combined 65.82% <90.90%> (+0.06%) ⬆️

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.

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