Skip to content

op-node: derive CGTv2 upgrades from escrow receipts - #567

Merged
seolaoh merged 5 commits into
celo-rebase-19from
seolaoh/cgtv2-l1-activation
Nov 4, 2026
Merged

seolaoh merged 5 commits into
celo-rebase-19from
seolaoh/cgtv2-l1-activation

Conversation

@seolaoh

@seolaoh seolaoh commented Oct 23, 2026 •

Copy link
Copy Markdown

Derive CGTv2 activation from the authenticated EscrowSeeded(address,uint256) receipt emitted by the fixed L1 bridge, without an activation timestamp, separate storage snapshot or feature bootstrap tracker. This supplies the direct upgrade deposits from #570 to the shared executor in celo-org/celo-kona#241. Kona independently reconstructs the same deposits in celo-org/celo-kona#364. Tracked in celo-org/celo-blockchain-planning#1466.

Activation ordering: all Portal deposits from the activation L1 origin, including deposits emitted after EscrowSeeded, execute against the pre-migration L2 state. The CGTv2 group is appended after all of that origin's deposits. This ordering is intentional even for zero-value deposits that make calls whose result depends on the migration state.

Sequencing and safe derivation use the same receipt-root-authenticated event and construct identical static upgrades plus dynamic reserve funding. Activation batches must be empty after span decomposition, with no SDM/PostExec exception. The one-time gas allowance comes from the selected network bundle and is removed when recovering SystemConfig for subsequent blocks.

Production bundle files and final bridge addresses remain unresolved and fail explicitly. The synthetic fixtures cover byte parity with Rust; production-configured devnet parity and final gas calibration remain required.

Local validation: go test ./op-node/... ./op-service/sources/... passes in 33 packages, and mise x -- just --unstable lint-go passes with zero issues and a clean module-tidy diff. Final Go/derivation review found no material issues, including receipt authentication, singular/span activation rules, channel invalidation and gas recovery.

The CI follow-up retains only the runtime-embedded fixture JSON in the Docker build context and fixes the planning-issue TODO references. A scratch Docker build reproduces the missing-file failure before the exception and exports byte-identical JSON after it; strict TODO format validation passes.

@seolaoh seolaoh changed the title op-node: derive CGTv2 activation from the L1 feature event op-node: derive CGTv2 upgrades from escrow receipts Oct 28, 2026
@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-l1-activation branch from bdd5575 to 3b76ae9 Compare October 28, 2026 16:29
Select fixed network profiles and reviewed NUT bundles. Construct the
15 direct upgrade deposits plus reserve funding from fixed total supply
minus the migrated amount, with checked one-time gas allowances.

Keep production placeholders separate from the synthetic chain-1337
bundle. Freeze shared byte/hash vectors and include the embedded runtime
fixture in Docker builds.
@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-l1-activation branch from 3b76ae9 to 2cb9b60 Compare November 2, 2026 13:03
Authenticate each new origin header and its receipt root, then read the
configured bridge's EscrowSeeded event for the configured Portal. Rebuild
deposit log metadata from canonical traversal rather than RPC metadata.

Append upgrades after every Portal deposit in the origin. Wire raw header
access through the driver and attributes builder, and restore the normal
gas limit after activation. No storage-proof bootstrap or migration cache
is needed. Cover header binding, malformed receipts, retries, reorgs and
cross-client origin vectors.
Disable the transaction pool for the activation block and reject user
transactions during safe batch derivation after span decomposition.
Retain candidates across RPC retries and clear them on reset or flush.

Wire the activation detector into the production pipeline and guard the
attributes queue. Cover singular/span boundaries, sequencing and safe
payload validation.
@seolaoh
seolaoh force-pushed the seolaoh/cgtv2-l1-activation branch from 2cb9b60 to 27c9e21 Compare November 2, 2026 13:52
@seolaoh
seolaoh marked this pull request as ready for review November 2, 2026 13:53
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T11:00:42.194060Z 7ca6226 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Comment thread op-node/rollup/derive/cgt_v2.go Outdated
Comment on lines +70 to +72
if types.DeriveSha(receipts, trie.NewStackTrie(nil)) != header.ReceiptHash {
return nil, nil, nil, NewCriticalError(fmt.Errorf("CGTv2 receipts do not match origin %s", origin))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: FetchReceipts already authenticates these receipts (validateReceipts), so this check repeats it. Fine to keep as defence in depth, but it runs every epoch and brings extra plumbing (CgtV2InputSource, variadic parameters, driver type assertion). Dropping it would simplify things.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Implemented in 7ca6226. The escrow scan now uses the authenticated FetchReceipts result directly. Removed CgtV2InputSource, the extra header/root check, variadic parameters and driver wiring. The upstream parent-hash check and DeriveDeposits remain, along with the canonical Status/PostState checks.

Comment thread op-node/rollup/derive/batch_mux.go Resolved
Comment thread op-node/rollup/derive/batches.go Resolved
@karlb

karlb commented Nov 3, 2026

Copy link
Copy Markdown

If we want to shrink this PR, these two ways might work:

  1. Use the FetchReceipts output directly. It already checks the receipts root and each log's BlockHash/Index. Keep the upstream info.ParentHash() check and DeriveDeposits, and add only the escrow scan plus the Status/PostState check. That drops CgtV2InputSource, cgtV2Header, originDeposits, the variadic parameters and the driver changes.

  2. Apply the deposits-only rule in AttributesQueue.createNextAttributes: if the attributes contain the CGT group and the batch has transactions, flush the channel and return NotEnoughData. That drops the BatchMux changes, CgtV2ActivationBlock (which currently derives each epoch twice) and the cgtActivation parameter.

Reuse FetchReceipts authentication instead of requiring a second header
source. Keep canonical receipt field checks.

Reject activation batches with user transactions in AttributesQueue
after attributes are built, preserving RPC retries and accepted span
prefixes. Remove the BatchMux detector and extra driver/pipeline wiring.

seolaoh commented Nov 4, 2026

Copy link
Copy Markdown
Author

@karlb Implemented both suggestions from your comment in 7ca6226: reuse authenticated FetchReceipts output and enforce deposits-only activation batches in AttributesQueue. This removes the extra header source, driver/pipeline wiring and CGTv2-specific BatchMux detection. The remaining BatchMux.FlushChannel method handles the legacy queue without calling its unsupported flush operation.

Local validation passed: go test ./op-node/... ./op-service/sources/... (33 packages), just --unstable lint-go with zero issues and a clean module-tidy diff, and Go/Rust fixture parity. The final cleanup was followed by another focused derivation test run.

@seolaoh
seolaoh merged commit 81198dd into celo-rebase-19 Nov 4, 2026
31 checks passed
@seolaoh
seolaoh deleted the seolaoh/cgtv2-l1-activation branch November 4, 2026 12:38
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