Skip to content

Conversation

jonastheis
Copy link
Contributor

@jonastheis jonastheis commented Oct 24, 2024

Purpose or design rationale of this PR

This PR is part of the permissionless batches (aka enforced batches) feature. It implements the permissionless batch production, operator recovery and provides instructions how to run these in the readme.

permissionless batch production: rollup/cmd/permissionless_batches/app/app.go the main tool in conjunction with permissionless-batches/docker-compose.yml (usage will be explained in readme later) to create batches in a permissionless way and submit them to L1. It requires the recovery and potentially block production without signature in l2geth before.

operator recovery: rollup/cmd/rollup_relayer/app/app.go with cfg.RecoveryConfig.Enable == true. Will
restore all batches between the latest finalized batch in the DB and the latest finalized batch on L1 based on L1 data. It requires the recovery of l2geth before.

Other parts of this feature are implemented in following PRs:

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

Deployment tag versioning

Has tag in common/version.go been updated or have you added bump-version label to this PR?

  • No, this PR doesn't involve a new deployment, git tag, docker image tag
  • Yes

Breaking change label

Does this PR have the breaking-change label?

  • No, this PR is not a breaking change
  • Yes

Summary by CodeRabbit

  • New Features

    • Introduced a new Dockerfile and related configuration for permissionless batch relayer deployment.
    • Added CLI application supporting permissionless batch production with recovery capabilities.
    • Implemented full and minimal recovery mechanisms to restore rollup state from Layer 1 data.
    • Developed submission logic for finalizing permissionless batches on-chain, including zk-proof handling.
    • Added new database methods to support permissionless batch and chunk insertion and status updates.
    • Provided new scripts and Docker Compose setup for permissionless batch environment orchestration.
    • Enhanced batch production tooling with Makefile targets for streamlined development and monitoring.
  • Bug Fixes

    • Improved error propagation and handling in block fetching and watcher components.
    • Fixed method visibility and naming consistency for proposer and bundle updater components.
  • Documentation

    • Added comprehensive README detailing permissionless batch feature, batch production toolkit, and operator recovery.
    • Included configuration examples and usage instructions for permissionless batch workflows.
  • Chores

    • Updated version to v4.5.38.
    • Refined Docker build context exclusions with updated .dockerignore files across multiple services.

Copy link

coderabbitai bot commented Oct 24, 2024

Walkthrough

This change introduces the "permissionless batches" feature for the Scroll rollup system, adding new CLI tools, Docker configurations, orchestration scripts, configuration files, and extensive Go implementations for permissionless batch production, recovery, and submission. It also implements robust recovery controllers, new ORM methods, and updates to public interfaces for improved batch and bundle management.

Changes

File(s) Change Summary
build/dockerfiles/*.dockerignore Updated to ignore permissionless-batches/conf/ and, in some cases, contracts/ directories for multiple Docker builds.
build/dockerfiles/recovery_permissionless_batches.Dockerfile, .dockerignore Added new Dockerfile and dockerignore for building the rollup_relayer binary with staged builds and context exclusions.
rollup/cmd/permissionless_batches/app/app.go, main.go Added new CLI application entrypoint and logic for permissionless batch production and recovery.
rollup/internal/controller/permissionless_batches/minimal_recovery.go, submitter.go Implemented controllers for minimal recovery and batch submission in permissionless mode.
rollup/internal/controller/relayer/full_recovery.go Added full recovery controller to restore state from L1 events and blobs.
rollup/internal/config/recovery.go, l1.go, config.go Introduced RecoveryConfig struct, added BeaconNodeEndpoint to L1 config, and extended main config struct.
rollup/internal/controller/watcher/bundle_proposer.go Renamed method updateDBBundleInfo to UpdateDBBundleInfo (exported).
rollup/internal/controller/watcher/chunk_proposer.go Renamed method proposeChunk to ProposeChunk (exported).
rollup/internal/controller/watcher/l2_watcher.go Made TryFetchRunningMissingBlocks and getAndStoreBlocks exported and error-returning.
rollup/internal/orm/batch.go Added InsertPermissionlessBatch and UpdateRollupStatusCommitAndFinalizeTxHash methods.
rollup/internal/orm/bundle.go Renamed getLatestBundle to GetLatestBundle, updated UpdateRollupStatus to accept optional transaction.
rollup/internal/orm/chunk.go Added InsertPermissionlessChunk for permissionless batch support.
rollup/cmd/rollup_relayer/app/app.go Added recovery mode branch for full state restoration.
rollup/internal/controller/relayer/l2_relayer.go Minor import order change.
rollup/abi/bridge_abi_test.go Removed unused imports and test function.
common/version/version.go Updated version tag to v4.5.38.
permissionless-batches/README.md Added comprehensive documentation for permissionless batches and recovery.
permissionless-batches/docker-compose.yml, Makefile Introduced Docker Compose and Makefile for orchestrating batch production, proving, and database.
permissionless-batches/conf/*/config.json Added new configuration files for coordinator, relayer, and proving service.
permissionless-batches/conf/coordinator/coordinator_run.sh, proving-service/prover_run.sh Added scripts to automate setup and launch of coordinator and prover services.
permissionless-batches/conf/genesis.json Added placeholder for genesis configuration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI (permissionless-batches)
    participant DB
    participant L2Watcher
    participant ChunkProposer
    participant BatchProposer
    participant BundleProposer
    participant Submitter
    participant L1

    User->>CLI (permissionless-batches): Run recovery or batch production
    CLI (permissionless-batches)->>DB: Connect and initialize
    CLI (permissionless-batches)->>L2Watcher: Initialize watcher
    CLI (permissionless-batches)->>ChunkProposer: Initialize
    CLI (permissionless-batches)->>BatchProposer: Initialize
    CLI (permissionless-batches)->>BundleProposer: Initialize
    CLI (permissionless-batches)->>DB: Check recovery needed
    alt Recovery Needed
        CLI (permissionless-batches)->>MinimalRecovery: Run recovery
        MinimalRecovery->>DB: Reset and restore state
        MinimalRecovery->>L2Watcher: Fetch missing blocks
        MinimalRecovery->>ChunkProposer: Propose chunks
        MinimalRecovery->>BatchProposer: Propose batch
        MinimalRecovery->>BundleProposer: Propose bundle
        MinimalRecovery->>DB: Update statuses
    else No Recovery Needed
        CLI (permissionless-batches)->>Submitter: Submit batch (with/without proof)
        Submitter->>DB: Fetch latest bundle/batch
        Submitter->>L1: Submit batch/proof
        Submitter->>DB: Update statuses
    end
    CLI (permissionless-batches)->>User: Log status and wait for confirmation/exit
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • georgehao
  • yiweichi

Poem

A patch of code, a field anew,
Where batches hop and proofs leap through.
Recovery’s path, now clear and bright,
Permissionless dreams take flight tonight!
With Docker, scripts, and configs spun,
The rabbit’s work is never done—
On Scroll’s green hills, the future’s begun! 🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jt/permissionless-batches-recovery

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@georgehao
Copy link
Member

can you add more description about this pr

@jonastheis
Copy link
Contributor Author

can you add more description about this pr

Will do so once it's in a better shape. This is still a draft PR and and such many things are still changing. Once ready, I'll provide a high-level description + how it relates to the changes made in this PR :)

@colinlyguo colinlyguo self-requested a review October 29, 2024 05:05
@jonastheis jonastheis added the bump-version Bump the version tag for deployment label Jul 10, 2025
Copy link

@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: 0

♻️ Duplicate comments (2)
permissionless-batches/conf/coordinator/config.json (2)

18-20: Hard-coded DSN uses sslmode=disable and lacks a password
Same concern raised in earlier reviews: the connection string disables encryption and exposes the super-user without credentials. In production this is a critical security gap.

-    "dsn": "postgres://db/scroll?sslmode=disable&user=postgres",
+    // Use TLS (`require`), move credentials to env-vars / secrets manager.
+    "dsn": "postgres://db/scroll?sslmode=require&user=${POSTGRES_USER}&password=${POSTGRES_PASSWORD}",

26-28: Long-lived secret committed to VCS – flagged by gitleaks
A 64-byte token is embedded directly in the file; this is effectively an API key. Rotate it immediately and load it from an environment variable instead.

-    "secret": "e788b62d39254928a821ac1c76b274a8c835aa1e20ecfb6f50eb10e87847de44",
+    // inject via `AUTH_SECRET` env var
+    "secret": "${AUTH_SECRET}",
🧹 Nitpick comments (2)
permissionless-batches/conf/coordinator/config.json (2)

19-20: Inconsistent naming style (maxOpenNum, maxIdleNum)
Keys elsewhere use snake_case; mixed casing hampers grepping & tooling. Consider max_open_conns / max_idle_conns.


11-12: Absolute assets_path reduces portability
Hard-coding /verifier/... ties the config to a specific container layout; prefer a path relative to an env var (e.g., ${ASSETS_PATH}) so the same config works across dev & prod images.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 086542e and b221d42.

📒 Files selected for processing (3)
  • common/version/version.go (1 hunks)
  • permissionless-batches/conf/coordinator/config.json (1 hunks)
  • rollup/internal/orm/chunk.go (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • common/version/version.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • rollup/internal/orm/chunk.go
🧰 Additional context used
🧠 Learnings (1)
permissionless-batches/conf/coordinator/config.json (1)
Learnt from: colinlyguo
PR: scroll-tech/scroll#1645
File: rollup/proposer-tool-config.json:34-40
Timestamp: 2025-04-15T08:52:44.176Z
Learning: In configuration files like `rollup/proposer-tool-config.json`, placeholders such as `<mainnet read db config>` are intentionally left as-is to be replaced by users with their own configuration values when deploying the tool.
🪛 Gitleaks (8.26.0)
permissionless-batches/conf/coordinator/config.json

26-26: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Copy link

@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: 4

♻️ Duplicate comments (4)
permissionless-batches/conf/proving-service/prover_run.sh (1)

35-43: Quote the nested command substitution to avoid word-splitting

Unquoted $(dirname "$url") can break when path components contain spaces (Shellcheck SC2046).

-  dest_subdir="$BASE_DOWNLOAD_DIR/$(basename $(dirname "$url"))"
+  dest_subdir="$BASE_DOWNLOAD_DIR/$(basename "$(dirname "$url")")"
permissionless-batches/conf/coordinator/coordinator_run.sh (1)

50-58: Quote the nested command substitution (SC2046)

Same word-splitting risk as in prover_run.sh.

-  dest_subdir="$OPENVM_DIR/$(basename $(dirname "$url"))"
+  dest_subdir="$OPENVM_DIR/$(basename "$(dirname "$url")")"
permissionless-batches/README.md (2)

65-66: Triple hyphen ---miner.gaslimit is a typo

Only two dashes are valid.

- - `---miner.gaslimit 1 --miner.gasprice 1 --miner.maxaccountsnum 100 --rpc.gascap 0 --gpo.ignoreprice 1` - gas limits for block production
+ - `--miner.gaslimit 1 --miner.gasprice 1 --miner.maxaccountsnum 100 --rpc.gascap 0 --gpo.ignoreprice 1` - gas limits for block production

40-48: Placeholder --scroll<-sepolia> renders an invalid CLI flag

Geth will treat the angle brackets literally and abort. Provide two explicit examples or use a clearly marked placeholder.

-./build/bin/geth --scroll<-sepolia> \
+## Mainnet
+./build/bin/geth --scroll \
+# or for Sepolia
+./build/bin/geth --scroll-sepolia \
🧹 Nitpick comments (6)
permissionless-batches/Makefile (2)

12-14: Reuse the PG_URL variable to avoid duplication and make maintenance easier

psql target hard-codes the connection string instead of re-using the PG_URL variable you already declared. Any future change (host, port, db name) now needs to be done in two places.

-	psql 'postgres://postgres@localhost:5432/scroll'
+	psql '$(PG_URL)'

1-4: Consider adding standard all, clean, test targets

Static-analysis flagged the absence of common phony targets. Even stub implementations help IDEs and CI tooling.

.PHONY: all clean test
all: batch_production_submission
clean:
	@docker compose down -v
test:
	@echo "no tests for Makefile"
permissionless-batches/conf/proving-service/prover_run.sh (2)

35-43: Comment and behaviour disagree – currently always re-downloads files

The loop downloads every asset unconditionally while the comment says “skips if file exists.” Add a simple existence check:

-  echo "Downloading $filepath..."
-  curl -o "$filepath" -L "$url"
+  if [ ! -f "$filepath" ]; then
+    echo "Downloading $filepath…"
+    curl -o "$filepath" -L "$url"
+  else
+    echo "Skipping $filepath (already present)"
+  fi

45-47: Symlink creation may fail on second run

ln -s without -f will error if $HOME/.openvm/params already exists. Add -sf (force) or check before linking.

permissionless-batches/docker-compose.yml (1)

46-52: Environment variable ${SCROLL_ZKVM_VERSION} must be exported before docker compose up

Compose will substitute at parse time. Consider adding a default or documenting that export SCROLL_ZKVM_VERSION=<version> is required before running any Makefile target.

permissionless-batches/README.md (1)

161-169: Specify language for fenced code blocks

Markdown-lint warns (MD040). Add json for clarity.

```json
  "recovery_config": {
    "enable": true
  }

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b221d42995f5801b094d24f1aec24aaa52fcc88e and f102d18d59c452ca1ee5338ae98a4711ef3f69f9.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `permissionless-batches/Makefile` (1 hunks)
* `permissionless-batches/README.md` (1 hunks)
* `permissionless-batches/conf/coordinator/coordinator_run.sh` (1 hunks)
* `permissionless-batches/conf/proving-service/config.json` (1 hunks)
* `permissionless-batches/conf/proving-service/prover_run.sh` (1 hunks)
* `permissionless-batches/docker-compose.yml` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* permissionless-batches/conf/proving-service/config.json

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>permissionless-batches/README.md (1)</summary>

Learnt from: colinlyguo
PR: #1645
File: rollup/proposer-tool-config.json:34-40
Timestamp: 2025-04-15T08:52:44.176Z
Learning: In configuration files like rollup/proposer-tool-config.json, placeholders such as <mainnet read db config> are intentionally left as-is to be replaced by users with their own configuration values when deploying the tool.


</details>

</details><details>
<summary>🪛 Shellcheck (0.10.0)</summary>

<details>
<summary>permissionless-batches/conf/proving-service/prover_run.sh</summary>

[warning] 37-37: Quote this to prevent word splitting.

(SC2046)

</details>
<details>
<summary>permissionless-batches/conf/coordinator/coordinator_run.sh</summary>

[warning] 52-52: Quote this to prevent word splitting.

(SC2046)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.37.1)</summary>

<details>
<summary>permissionless-batches/docker-compose.yml</summary>

[warning] 98-98: wrong indentation: expected 2 but found 4

(indentation)

---

[error] 98-98: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>
<details>
<summary>🪛 checkmake (0.2.2)</summary>

<details>
<summary>permissionless-batches/Makefile</summary>

[warning] 1-1: Missing required phony target "all"

(minphony)

---

[warning] 1-1: Missing required phony target "clean"

(minphony)

---

[warning] 1-1: Missing required phony target "test"

(minphony)

</details>

</details>
<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>permissionless-batches/README.md</summary>

[style] ~36-~36: To form a complete sentence, be sure to include a subject.
Context: ...` - batch where to start recovery from. Can be found on [Scrollscan Explorer](https...

(MISSING_IT_THERE)

---

[style] ~143-~143: To form a complete sentence, be sure to include a subject.
Context: ...` - batch where to start recovery from. Can be found on [Scrollscan Explorer](https...

(MISSING_IT_THERE)

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>permissionless-batches/README.md</summary>

117-117: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

---

161-161: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

169-169: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</details>

<details>
<summary>⏰ 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). (3)</summary>

* GitHub Check: tests
* GitHub Check: check
* GitHub Check: tests

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link

@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: 0

♻️ Duplicate comments (2)
rollup/internal/controller/permissionless_batches/minimal_recovery.go (2)

64-90: Error handling masks real database issues.

The current implementation treats all database errors as "recovery needed", which could hide connectivity problems and lead to unnecessary destructive recovery operations.


116-133: Potential infinite loop in chunk creation.

The chunk creation loop may run indefinitely if ProposeChunk() fails to advance EndBlockNumber, as identified in previous reviews.

🧹 Nitpick comments (1)
rollup/internal/controller/permissionless_batches/minimal_recovery.go (1)

258-258: Remove debug print statement.

The fmt.Println(daBatch, daBlobPayload) appears to be leftover debug code that should be removed before production deployment.

-	fmt.Println(daBatch, daBlobPayload)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f102d18 and f663968.

📒 Files selected for processing (5)
  • permissionless-batches/conf/relayer/config.json (1 hunks)
  • rollup/abi/bridge_abi_test.go (1 hunks)
  • rollup/internal/config/recovery.go (1 hunks)
  • rollup/internal/controller/permissionless_batches/minimal_recovery.go (1 hunks)
  • rollup/internal/orm/batch.go (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • rollup/abi/bridge_abi_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • permissionless-batches/conf/relayer/config.json
  • rollup/internal/config/recovery.go
  • rollup/internal/orm/batch.go
🧰 Additional context used
🧠 Learnings (1)
rollup/internal/controller/permissionless_batches/minimal_recovery.go (1)
Learnt from: colinlyguo
PR: scroll-tech/scroll#1530
File: rollup/internal/controller/watcher/batch_proposer.go:291-294
Timestamp: 2024-10-20T16:13:20.397Z
Learning: In `batch_proposer.go`, it's acceptable to call `utils.CalculateBatchMetrics` multiple times within the loop because the batch's chunks are increasing in the loop, and each calculation reflects the updated batch state.
🧬 Code Graph Analysis (1)
rollup/internal/controller/permissionless_batches/minimal_recovery.go (8)
rollup/internal/orm/chunk.go (3)
  • Chunk (23-67)
  • Chunk (75-77)
  • NewChunk (70-72)
rollup/internal/orm/batch.go (3)
  • Batch (25-75)
  • Batch (83-85)
  • NewBatch (78-80)
rollup/internal/controller/watcher/chunk_proposer.go (1)
  • ChunkProposer (22-52)
rollup/internal/controller/watcher/batch_proposer.go (1)
  • BatchProposer (24-54)
rollup/internal/controller/watcher/bundle_proposer.go (1)
  • BundleProposer (22-42)
rollup/internal/controller/watcher/l2_watcher.go (1)
  • L2WatcherClient (22-38)
rollup/internal/config/recovery.go (1)
  • RecoveryConfig (3-14)
common/types/db.go (2)
  • ProvingTaskVerified (152-152)
  • RollupFinalized (239-239)
⏰ 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). (2)
  • GitHub Check: tests
  • GitHub Check: check
🔇 Additional comments (6)
rollup/internal/controller/permissionless_batches/minimal_recovery.go (6)

26-31: Constants are well-defined and documented.

The fake indices serve as placeholders for recovery state tracking and are appropriately documented.


33-62: Struct design and constructor are well-implemented.

The MinimalRecovery struct contains all necessary dependencies and the constructor properly initializes all fields.


194-325: State restoration logic is comprehensive and well-implemented.

The method properly validates configuration, fetches L1 data, and uses database transactions for atomic operations. Error handling is thorough throughout.


327-411: Batch decoding implementation is robust.

The method properly handles codec versioning, validates batch hashes, and includes comprehensive error handling for blob fetching operations.


413-445: Block range validation is present but could be enhanced.

The method includes basic validation for block height limits. The implementation appears correct with proper error handling.


447-458: Database reset implementation follows best practices.

The method correctly uses migrate.ResetDB() for a clean database reset, which is the recommended approach over manual rollback/migrate cycles.

Copy link

@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 (5)
rollup/internal/controller/permissionless_batches/submitter.go (1)

228-234: Add safety check for empty chunks slice.

The code accesses chunks[len(chunks)-1] without verifying that chunks is not empty, which could cause a panic if GetChunksInRange returns an empty slice.

Add a guard before accessing the slice:

 chunks, err := s.chunkOrm.GetChunksInRange(s.ctx, batch.StartChunkIndex, batch.EndChunkIndex)
 if err != nil {
     return nil, nil, fmt.Errorf("failed to get chunks in range for batch %d: %w", batch.Index, err)
 }
+if len(chunks) == 0 {
+    return nil, nil, fmt.Errorf("no chunks found for batch %d", batch.Index)
+}
 if chunks[len(chunks)-1].Index != batch.EndChunkIndex {
rollup/internal/controller/relayer/full_recovery.go (4)

75-83: Add nil-safety check for empty database.

If the local DB does not yet contain any batch, GetLatestBatch will return a "record not found" error, and the code doesn't handle this case properly.

Add explicit handling for the case when no batches exist:

 latestDBBatch, err := f.batchORM.GetLatestBatch(f.ctx)
 if err != nil {
+    if errors.Is(err, gorm.ErrRecordNotFound) {
+        // Start from genesis batch (index -1)
+        latestDBBatch = &orm.Batch{Index: 0} // or appropriate genesis value
+    } else {
         return fmt.Errorf("failed to get latest batch from DB: %w", err)
+    }
 }

91-98: Fix undefined method call.

The method f.l1Reader.LatestFinalizedBatchIndex is undefined. This will cause a compilation error.

Use the correct method name:

-latestFinalizedBatchContract, err := f.l1Reader.LatestFinalizedBatchIndex(latestFinalizedL1Block)
+latestFinalizedBatchContract, err := f.l1Reader.GetLatestFinalizedBatchIndex(latestFinalizedL1Block)

Or check the l1.Reader interface for the correct method name.


160-164: Return error instead of silently stopping on type assertion failure.

When the type assertion fails, the code logs an error and returns false, which stops event processing silently. This could leave the recovery in an incomplete state.

Consider modifying the callback to return an error instead of a boolean, or at least provide more context about the failure:

 revertBatch, ok := event.(*l1.RevertBatchEventV7)
 if !ok {
-    log.Error(fmt.Sprintf("unexpected type of revert event: %T, expected RevertEventV7Type", event))
-    return false
+    return fmt.Errorf("unexpected type of revert event: %T, expected RevertEventV7Type", event)
 }

Note: This would require modifying the callback signature to support error returns.


266-274: Fix incorrect batch references in error messages.

The error messages reference firstBatch but should reference the current batch b being processed.

-return fmt.Errorf("failed to fetch commit tx data of batch %d, tx hash: %v, err: %w", firstBatch.commit.BatchIndex().Uint64(), firstBatch.commit.TxHash().Hex(), err)
+return fmt.Errorf("failed to fetch commit tx data of batch %d, tx hash: %v, err: %w", b.commit.BatchIndex().Uint64(), b.commit.TxHash().Hex(), err)
-return fmt.Errorf("unsupported codec version: %v, batch index: %v, tx hash: %s", args.Version, firstBatch.commit.BatchIndex().Uint64(), firstBatch.commit.TxHash().Hex())
+return fmt.Errorf("unsupported codec version: %v, batch index: %v, tx hash: %s", args.Version, b.commit.BatchIndex().Uint64(), b.commit.TxHash().Hex())
🧹 Nitpick comments (4)
rollup/internal/controller/permissionless_batches/submitter.go (2)

178-200: Consider improving error handling for proving status updates.

The proving status update logic is marked as "not necessary" and placed outside the main transaction. However, if these updates fail, the error is only logged without any retry mechanism or alerting. This could lead to inconsistent state in the database.

Consider one of these approaches:

  1. Include these updates in the main transaction if they are important for consistency
  2. Add a retry mechanism for failed proving status updates
  3. Use structured logging with appropriate log levels for monitoring
 if txErr != nil {
-    log.Error("Updating chunk and batch proving status when finalizing without proof failure", "bundleHash", bundle.Hash, "err", txErr)
+    log.Warn("Failed to update proving status when finalizing without proof - this may require manual intervention", "bundleHash", bundle.Hash, "err", txErr)
 }

46-51: Consider adding context cancellation handling.

The constructor creates a sender but doesn't handle potential context cancellation during initialization. While not critical, this could improve graceful shutdown behavior.

Consider adding context cancellation check:

 func NewSubmitter(ctx context.Context, db *gorm.DB, cfg *config.RelayerConfig, chainCfg *params.ChainConfig) (*Submitter, error) {
+    select {
+    case <-ctx.Done():
+        return nil, ctx.Err()
+    default:
+    }
+    
     registry := prometheus.DefaultRegisterer
     finalizeSender, err := sender.NewSender(ctx, cfg.SenderConfig, cfg.FinalizeSenderSignerConfig, "permissionless_batches_submitter", "finalize_sender", types.SenderTypeFinalizeBatch, db, registry)
rollup/internal/controller/relayer/full_recovery.go (2)

242-244: Consider more descriptive error message.

The error message "no finalized batches to process" might be misleading if this is a valid state during recovery.

Consider a more descriptive message:

-return fmt.Errorf("no finalized batches to process")
+return fmt.Errorf("no finalized batches found between DB latest batch and L1 latest batch - recovery may be up to date")

464-466: Use more descriptive panic message.

The panic message could be more descriptive about what went wrong and why this is unexpected.

-panic(fmt.Sprintf("commit and finalize batch index mismatch: %d != %d", commit.BatchIndex().Uint64(), finalize.BatchIndex().Uint64()))
+panic(fmt.Sprintf("invalid batch events: commit batch index %d is greater than finalize batch index %d", commit.BatchIndex().Uint64(), finalize.BatchIndex().Uint64()))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f663968 and b1ecaf0.

📒 Files selected for processing (3)
  • rollup/cmd/permissionless_batches/app/app.go (1 hunks)
  • rollup/internal/controller/permissionless_batches/submitter.go (1 hunks)
  • rollup/internal/controller/relayer/full_recovery.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • rollup/cmd/permissionless_batches/app/app.go
🧰 Additional context used
🧠 Learnings (2)
rollup/internal/controller/permissionless_batches/submitter.go (1)
Learnt from: colinlyguo
PR: scroll-tech/scroll#1530
File: rollup/internal/controller/watcher/batch_proposer.go:291-294
Timestamp: 2024-10-20T16:13:20.397Z
Learning: In `batch_proposer.go`, it's acceptable to call `utils.CalculateBatchMetrics` multiple times within the loop because the batch's chunks are increasing in the loop, and each calculation reflects the updated batch state.
rollup/internal/controller/relayer/full_recovery.go (1)
Learnt from: colinlyguo
PR: scroll-tech/scroll#1530
File: rollup/internal/controller/watcher/batch_proposer.go:291-294
Timestamp: 2024-10-20T16:13:20.397Z
Learning: In `batch_proposer.go`, it's acceptable to call `utils.CalculateBatchMetrics` multiple times within the loop because the batch's chunks are increasing in the loop, and each calculation reflects the updated batch state.
⏰ 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). (3)
  • GitHub Check: tests
  • GitHub Check: tests
  • GitHub Check: check

@codecov-commenter
Copy link

codecov-commenter commented Jul 10, 2025

Codecov Report

Attention: Patch coverage is 1.11008% with 1069 lines in your changes missing coverage. Please review.

Project coverage is 37.59%. Comparing base (4233ad9) to head (6f36edc).

Files with missing lines Patch % Lines
...ollup/internal/controller/relayer/full_recovery.go 0.00% 344 Missing ⚠️
...troller/permissionless_batches/minimal_recovery.go 0.00% 326 Missing ⚠️
...nal/controller/permissionless_batches/submitter.go 0.00% 178 Missing ⚠️
rollup/cmd/permissionless_batches/app/app.go 0.00% 100 Missing ⚠️
rollup/internal/orm/batch.go 0.00% 49 Missing ⚠️
rollup/internal/orm/chunk.go 0.00% 39 Missing ⚠️
rollup/cmd/rollup_relayer/app/app.go 0.00% 23 Missing ⚠️
rollup/internal/controller/watcher/l2_watcher.go 33.33% 4 Missing ⚠️
rollup/internal/orm/bundle.go 55.55% 3 Missing and 1 partial ⚠️
rollup/cmd/permissionless_batches/main.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1555      +/-   ##
===========================================
- Coverage    39.69%   37.59%   -2.11%     
===========================================
  Files          237      242       +5     
  Lines        18935    19999    +1064     
===========================================
+ Hits          7516     7518       +2     
- Misses       10680    11741    +1061     
- Partials       739      740       +1     
Flag Coverage Δ
rollup 37.59% <1.11%> (-7.89%) ⬇️

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.

colinlyguo
colinlyguo previously approved these changes Jul 10, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Jul 16, 2025
georgehao
georgehao previously approved these changes Jul 16, 2025
Copy link

@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: 0

♻️ Duplicate comments (2)
permissionless-batches/README.md (2)

38-46: Placeholder --scroll<-sepolia> is still invalid CLI syntax

The angle-bracket notation will be passed verbatim to geth and cause the client to abort.
Recommend offering two explicit examples (mainnet vs sepolia) or a clear environment-variable placeholder instead of angle brackets, exactly as suggested in the earlier review.

-./build/bin/geth --scroll<-sepolia> \
+# Mainnet
+./build/bin/geth --scroll \
+  ...
+# Sepolia
+./build/bin/geth --scroll-sepolia \
+  ...

64-64: Triple hyphen ---miner.gaslimit will be rejected by geth

The flag must start with exactly two dashes.

- - `---miner.gaslimit 1 --miner.gasprice 1 --miner.maxaccountsnum 100 --rpc.gascap 0 --gpo.ignoreprice 1` - gas limits for block production
+ - `--miner.gaslimit 1 --miner.gasprice 1 --miner.maxaccountsnum 100 --rpc.gascap 0 --gpo.ignoreprice 1` - gas limits for block production
🧹 Nitpick comments (1)
permissionless-batches/README.md (1)

160-168: Add language hint to fenced JSON block for lint compliance

Markdown-lint flags this block; adding json after the opening back-ticks silences the warning and improves syntax highlighting.

-```
+```json
   "recovery_config": {
     "enable": true
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e5bda9 and 4e18153.

📒 Files selected for processing (1)
  • permissionless-batches/README.md (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: colinlyguo
PR: scroll-tech/scroll#1714
File: rollup/internal/controller/relayer/l2_relayer.go:1548-1555
Timestamp: 2025-07-29T16:38:24.647Z
Learning: In rollup/internal/controller/relayer/l2_relayer.go, the validateBatchFields function should error out when GetBatchByHash fails to find a parent batch. This is intentional behavior - missing parent batches represent genuine error conditions that should halt batch submission processing. Genesis batch handling occurs separately from normal batch validation flow.
📚 Learning: in rollup/internal/controller/relayer/l2_relayer.go, the validatebatchfields function should error o...
Learnt from: colinlyguo
PR: scroll-tech/scroll#1714
File: rollup/internal/controller/relayer/l2_relayer.go:1548-1555
Timestamp: 2025-07-29T16:38:24.647Z
Learning: In rollup/internal/controller/relayer/l2_relayer.go, the validateBatchFields function should error out when GetBatchByHash fails to find a parent batch. This is intentional behavior - missing parent batches represent genuine error conditions that should halt batch submission processing. Genesis batch handling occurs separately from normal batch validation flow.

Applied to files:

  • permissionless-batches/README.md
📚 Learning: in configuration files like `rollup/proposer-tool-config.json`, placeholders such as `
Learnt from: colinlyguo
PR: scroll-tech/scroll#1645
File: rollup/proposer-tool-config.json:34-40
Timestamp: 2025-04-15T08:52:44.176Z
Learning: In configuration files like `rollup/proposer-tool-config.json`, placeholders such as `<mainnet read db config>` are intentionally left as-is to be replaced by users with their own configuration values when deploying the tool.

Applied to files:

  • permissionless-batches/README.md
🪛 LanguageTool
permissionless-batches/README.md

[style] ~35-~35: To form a complete sentence, be sure to include a subject.
Context: ...` - batch where to start recovery from. Can be found on [Scrollscan Explorer](https...

(MISSING_IT_THERE)


[style] ~142-~142: To form a complete sentence, be sure to include a subject.
Context: ...` - batch where to start recovery from. Can be found on [Scrollscan Explorer](https...

(MISSING_IT_THERE)

🪛 markdownlint-cli2 (0.17.2)
permissionless-batches/README.md

116-116: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


160-160: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


168-168: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ 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). (3)
  • GitHub Check: tests
  • GitHub Check: check
  • GitHub Check: tests

@jonastheis jonastheis merged commit 6897cc5 into develop Aug 4, 2025
6 checks passed
@jonastheis jonastheis deleted the jt/permissionless-batches-recovery branch August 4, 2025 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bump-version Bump the version tag for deployment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants