Skip to content

Conversation

@curryxbo
Copy link
Contributor

@curryxbo curryxbo commented Dec 11, 2025

1. Purpose or design rationale of this PR

...

2. PR title

Your PR title must follow conventional commits (as we are doing squash merge for each PR), so it must start with one of the following types:

  • build: Changes that affect the build system or external dependencies (example scopes: yarn, eslint, typescript)
  • ci: Changes to our CI configuration files and scripts (example scopes: vercel, github, cypress)
  • docs: Documentation-only changes
  • feat: A new feature
  • fix: A bug fix
  • perf: A code change that improves performance
  • refactor: A code change that doesn't fix a bug, or add a feature, or improves performance
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • test: Adding missing tests or correcting existing tests

3. Deployment tag versioning

Has the version in params/version.go been updated?

  • This PR doesn't involve a new deployment, git tag, docker image tag, and it doesn't affect traces
  • Yes

4. Breaking change label

Does this PR have the breaking-change label?

  • This PR is not a breaking change
  • Yes

Summary by CodeRabbit

  • New Features

    • L2 block assembly now supports optional custom timestamp parameters for enhanced control over block timestamps.
  • Changes

    • Standardized internal timestamp representation from time objects to Unix timestamps (uint64) for consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

@curryxbo curryxbo requested a review from a team as a code owner December 11, 2025 08:15
@curryxbo curryxbo requested review from r3aker86 and removed request for a team December 11, 2025 08:15
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

Changes convert block timestamp handling from time.Time to uint64 Unix seconds across the L2 catalyst API and miner. An optional timestamp field is added to the L2 block assembly parameters, allowing timestamps to be provided during block assembly and threaded through engine and miner interfaces.

Changes

Cohort / File(s) Summary
Catalyst L2 API types
eth/catalyst/api_types.go, eth/catalyst/gen_l2blockparams.go
Added optional Timestamp *uint64 field to AssembleL2BlockParams struct and its JSON marshaling/unmarshaling support. Auto-generated code updated to handle the new field in MarshalJSON and UnmarshalJSON.
Catalyst L2 API implementation
eth/catalyst/l2_api.go, eth/catalyst/l2_api_test.go
Modified AssembleL2Block to compute timestamp as uint64(time.Now().Unix()) with override from params.Timestamp, passing uint64 to BuildBlock instead of time.Now(). Updated four test cases to pass uint64 timestamps.
Engine client
ethclient/authclient/engine.go
Updated AssembleL2Block method signature to accept timeStamp *uint64 parameter and pass it to engine call. Added error handling for transaction marshaling with indexed error messages.
Miner
miner/miner.go
Changed BuildBlock method signature from timestamp time.Time to timestamp uint64, updating internal call site to pass timestamp directly without Unix() conversion.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Type signature changes across multiple layers: Verify timestamp conversions are consistent from catalyst API through engine client to miner.
  • Auto-generated code: Confirm eth/catalyst/gen_l2blockparams.go correctly reflects the struct field changes.
  • Logic modification in l2_api.go: Review the timestamp computation logic (default vs. override from params) to ensure correct behavior.
  • Test updates: Ensure all test cases properly reflect the new uint64 timestamp parameter.

Possibly related PRs

Suggested reviewers

  • Web3Jumb0

Poem

🐰 A timestamp now dances in uint64's clothing,
No more time.Time's passing, just seconds unswathing,
Through catalyst, engine, and miner it goes,
An optional gift that the assembler now knows,
Each block built with precision, no temporal throes! 📦✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'WIP:Update AssembleL2Block params' is vague and does not clearly convey the primary change. It uses a generic term 'Update' without specifying what is being changed or why, and lacks concrete detail about the timestamp parameter modifications. Revise the title to be more specific about the change, such as 'feat: Add optional timestamp parameter to AssembleL2Block' or 'refactor: Use uint64 timestamp instead of time.Time in BuildBlock'. Ensure it follows the Conventional Commits format noted in the PR requirements.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mpt-switch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
eth/catalyst/gen_l2blockparams.go (1)

15-24: Generated JSON uses plain numeric timestamp; fix via override, not manual edits

The generated helper structs here use Timestamp *uint64 and assign it directly, so timestamp is encoded as a JSON number. Given the // DO NOT EDIT header and the hexutil override defined for this type, the real fix should be in assembleL2BlockParamsMarshaling (see eth/catalyst/api_types.go), followed by re-running go generate, rather than editing this file directly.

Also applies to: 35-49

🧹 Nitpick comments (1)
eth/catalyst/l2_api.go (1)

84-90: Timestamp default/override wiring looks correct

Defaulting timestamp to uint64(time.Now().Unix()) and conditionally overriding with params.Timestamp before calling BuildBlock is sound and matches the new uint64 API. If you ever need stricter control, you could clamp the final timestamp here to be at least the parent header timestamp (e.g., max(parent.Time+1, timestamp)) instead of relying solely on downstream checks, but that’s optional for this change.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49fa27b and 796834a.

📒 Files selected for processing (6)
  • eth/catalyst/api_types.go (1 hunks)
  • eth/catalyst/gen_l2blockparams.go (3 hunks)
  • eth/catalyst/l2_api.go (1 hunks)
  • eth/catalyst/l2_api_test.go (3 hunks)
  • ethclient/authclient/engine.go (2 hunks)
  • miner/miner.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
eth/catalyst/l2_api_test.go (1)
common/mclock/mclock.go (1)
  • Now (34-36)
miner/miner.go (2)
core/types/transaction.go (1)
  • Transactions (615-615)
miner/worker.go (1)
  • NewBlockResult (73-77)
eth/catalyst/gen_l2blockparams.go (2)
eth/catalyst/api_types.go (1)
  • AssembleL2BlockParams (41-45)
common/hexutil/json.go (1)
  • Uint64 (339-339)
ethclient/authclient/engine.go (2)
eth/catalyst/api_types.go (1)
  • ExecutableL2Data (91-113)
eth/catalyst/gen_l2_ed.go (2)
  • ExecutableL2Data (18-33)
  • ExecutableL2Data (59-74)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (5)
eth/catalyst/l2_api_test.go (3)

111-117: Adaptation to uint64 timestamp in tests is correct

Passing uint64(time.Now().Unix()) into BuildBlock matches the new signature and preserves prior semantics.


171-176: NewL2Block test updated consistently

This BuildBlock call is updated to the uint64 timestamp form and remains consistent with the other tests and the miner API.


224-229: NewSafeL2Block test timestamp change is aligned with API

Using uint64(time.Now().Unix()) here correctly follows the new BuildBlock signature without altering the test’s intent.

ethclient/authclient/engine.go (1)

15-31: Client-side AssembleL2Block wiring and tx marshaling look solid

Marshaling each types.Transaction with indexed error reporting and threading the optional timeStamp pointer through to AssembleL2BlockParams.Timestamp cleanly match the updated engine API. This method remains straightforward and consistent with the rest of the auth client.

miner/miner.go (1)

170-177: BuildBlock API change to uint64 timestamp is correctly implemented across all call sites

The change to BuildBlock accepting uint64 timestamp instead of time.Time is consistent with how getPending uses uint64(time.Now().Unix()), simplifying the API to match the header's native time representation. All call sites in the codebase correctly pass uint64 timestamps: the catalyst API forwards a properly constructed uint64 value, and test code correctly converts time.Now().Unix() to uint64.

Comment on lines 41 to 45
type AssembleL2BlockParams struct {
Number uint64 `json:"number" gencodec:"required"`
Transactions [][]byte `json:"transactions"`
Timestamp *uint64 `json:"timestamp"`
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

gencodec go-ethereum pointer hexutil override examples

💡 Result:

Summary + minimal example — show how to use gencodec field overrides to make pointer fields marshal/unmarshal with go-ethereum's hexutil types.

Key points

  • gencodec supports a "field override" struct: put the alternate (marshal/unmarshal) types there; generated code converts between original and override types. [1]
  • Use hexutil types (hexutil.Bytes, hexutil.Big, hexutil.Uint64, etc.) in the override to get 0x-prefixed hex JSON encoding. [2]
  • Generated code will use pointer override types for required pointer fields (example of generated code using hexutil shown below). [3]

Minimal example

  1. Original type (in package types.go)
    package mypkg

import "math/big"

type MyStruct struct {
Data []byte json:"data" gencodec:"required"
Amount *big.Int json:"amount" gencodec:"required"
Nonce uint64 json:"nonce" gencodec:"required"
}

  1. Override type + go:generate (in same package)
    //go:generate gencodec -type MyStruct -field-override mystruct_marshaling -out mystruct_json.go
    type mystruct_marshaling struct {
    Data hexutil.Bytes // overrides []byte -> hexutil.Bytes
    Amount *hexutil.Big // overrides *big.Int -> *hexutil.Big
    Nonce hexutil.Uint64 json:"nonce" // overrides uint64 -> hexutil.Uint64
    }

  2. Run generator
    go generate ./...

What gencodec generates (conceptual)

  • MarshalJSON will build an enc struct with the override types and assign:
    enc.Data = hexutil.Bytes(m.Data)
    enc.Amount = (*hexutil.Big)(m.Amount) // (conversion code is generated)
    enc.Nonce = hexutil.Uint64(m.Nonce)
    then json.Marshal(&enc)
  • UnmarshalJSON will decode into pointer override fields (so missing required pointer fields are detected) and convert back into original types. See generated example using hexutil in real projects. [3]

References

  • gencodec documentation (field-override behavior, examples). [1]
  • go-ethereum hexutil types and behavior (hex marshaling types: Bytes, Big, Uint64). [2]
  • Example generated code using hexutil (shows pointer override conversions in generated Marshal/Unmarshal). [3]

🏁 Script executed:

# Search for examples of pointer fields with hexutil in overrides in the repo
rg 'type.*Marshaling\s*struct' -A 10 | head -100

Repository: morph-l2/go-ethereum

Length of output: 5492


🏁 Script executed:

# Look for BaseFee patterns in the codebase to see how pointer big.Int fields are overridden
rg 'BaseFee.*\*big.Int' -B 2 -A 5

Repository: morph-l2/go-ethereum

Length of output: 15345


🏁 Script executed:

# Find the gen_l2blockparams.go file to see the current generated code
fd 'gen_l2blockparams.go' -x cat {}

Repository: morph-l2/go-ethereum

Length of output: 1650


🏁 Script executed:

sed -n '35,60p' eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 1127


🏁 Script executed:

# Also check the override struct to see all override definitions
fd 'api_types.go' -x cat {} | head -100

Repository: morph-l2/go-ethereum

Length of output: 4240


🏁 Script executed:

head -80 eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 3321


🏁 Script executed:

# Find the second struct around lines 48-52
sed -n '40,80p' eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 1745


🏁 Script executed:

sed -n '40,80p' eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 1745


🏁 Script executed:

# Look for all override structs
rg 'type.*Marshaling struct' -A 8 eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 1440


🏁 Script executed:

# Get the full content of api_types.go to see both structs
cat eth/catalyst/api_types.go

Repository: morph-l2/go-ethereum

Length of output: 5814


Fix pointer/override type mismatch for AssembleL2BlockParams.Timestamp

AssembleL2BlockParams declares Timestamp *uint64 but the override type is non-pointer hexutil.Uint64. gencodec requires matching pointer signatures; this mismatch causes the override to be ignored and timestamp to encode as a plain JSON number instead of a hex quantity like number and other numeric Engine API fields.

Change the override to pointer-typed:

 type assembleL2BlockParamsMarshaling struct {
 	Number       hexutil.Uint64
 	Transactions []hexutil.Bytes
-	Timestamp    hexutil.Uint64
+	Timestamp    *hexutil.Uint64
 }

Then regenerate with go generate ./... so gen_l2blockparams.go properly encodes/decodes timestamp as a hex quantity.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In eth/catalyst/api_types.go around lines 41 to 45, the
AssembleL2BlockParams.Timestamp field is declared as *uint64 but the gencodec
override used elsewhere is a non-pointer hexutil.Uint64 which causes the
override to be ignored; update the override type to a pointer form (i.e.
*hexutil.Uint64) so it matches the *uint64 field, then run go generate ./... to
regenerate gen_l2blockparams.go so timestamp is encoded/decoded as a hex
quantity.

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