Repository navigation
op-node: derive CGTv2 upgrades from escrow receipts - #567
Conversation
bdd5575 to
3b76ae9
Compare
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.
3b76ae9 to
2cb9b60
Compare
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.
2cb9b60 to
27c9e21
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
| if types.DeriveSha(receipts, trie.NewStackTrie(nil)) != header.ReceiptHash { | ||
| return nil, nil, nil, NewCriticalError(fmt.Errorf("CGTv2 receipts do not match origin %s", origin)) | ||
| } |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
|
If we want to shrink this PR, these two ways might work:
|
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.
|
@karlb Implemented both suggestions from your comment in 7ca6226: reuse authenticated Local validation passed: |
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, andmise x -- just --unstable lint-gopasses 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.