-
Notifications
You must be signed in to change notification settings - Fork 72
feat(derivation): SPEC-005 L2 state tiering and rollback #948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
curryxbo
wants to merge
19
commits into
main
Choose a base branch
from
feat/state-tiering-and-rollback
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
8e559f6
feat(derivation): add batch verification and L1 reorg detection
0c48f5c
fix(derivation): address code review feedback
f9a2578
fix(derivation): address round-2 review feedback
675e8fb
fix(derivation): prevent derivation height advancing when L1 block re…
fb3e1ce
fix(derivation): address round-3 review — halt on mismatch, optimize …
3c960cf
feat(derivation): add halted gauge metric for production alerting
ca81ed7
fix(derivation): guard against nil lastHeader panic on empty batch, f…
182b8d1
fix(derivation): add nil check for lastHeader on re-derive path, docu…
46edfa1
docs(derivation): add language tags to fenced code blocks (MD040)
a45705c
refactor(derivation): split new logic into verify.go and reorg.go
4380f96
Merge branch 'origin/main' into feat/derivation-batch-verification-re…
b178497
Merge branch 'main' into feat/derivation-batch-verification-reorg-det…
curryxbo 3e49457
refactor(node): remove validator/challenge bypass per SPEC-005
4822571
feat(derivation): SPEC-005 P2 — state model + head anchors + dual-cha…
2ed4e8c
feat(derivation): SPEC-005 P3 — path B / rollback executor / admin RP…
3848b87
docs(derivation): drop DERIVATION_REFACTOR.md — superseded by morph-s…
a2a4390
Merge branch 'main' into feat/state-tiering-and-rollback
curryxbo 308dfcb
feat(derivation): SPEC-005 §3.1 dual-channel main loop + safe/finaliz…
4158e4e
Revert "feat(derivation): SPEC-005 §3.1 dual-channel main loop + safe…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package derivation | ||
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "fmt" | ||
|
|
||
| "github.com/morph-l2/go-ethereum/common" | ||
| ) | ||
|
|
||
| // SPEC-005 §3.6 / §5.1 admin RPC: operator-triggered rollback entry point. | ||
| // | ||
| // Exposes the ability to roll the local L2 chain back to a target (number, | ||
| // hash) pair. Per tech-design §3.3, the rollback **must** match by hash — | ||
| // rolling back to a number alone is unsafe because it can silently land | ||
| // on a different fork after a reorg. | ||
| // | ||
| // Authentication and the concrete wire-up (registering this with the | ||
| // node's existing admin RPC server) are blocked on SPEC-005 §8 #2: | ||
| // - dev-mode only (current default below) | ||
| // - operator-only via a node-local UNIX socket | ||
| // - signed multisig request | ||
| // All three options keep the same public method signature. | ||
|
|
||
| // AdminAPI groups operator-only RPC entry points exposed by the | ||
| // derivation pipeline. | ||
| // | ||
| // TODO(spec-005-admin-rpc): wire this into morph/node/cmd/node/main.go | ||
| // once SPEC-005 §8 #2 (auth) is decided. Until then, AdminAPI is | ||
| // constructible but unregistered; tests can still exercise it directly. | ||
| type AdminAPI struct { | ||
| d *Derivation | ||
| } | ||
|
|
||
| // NewAdminAPI returns the operator-only API surface bound to the given | ||
| // Derivation instance. | ||
| func NewAdminAPI(d *Derivation) *AdminAPI { | ||
| return &AdminAPI{d: d} | ||
| } | ||
|
|
||
| // SetL2Head requests a rollback of the local L2 chain to the supplied | ||
| // (number, hash). The implementation must verify that hash matches the | ||
| // local block at the given number before delegating to the rollback | ||
| // executor (SPEC-005 §5.1 / §5.2). | ||
| // | ||
| // Returns an error if: | ||
| // - the (number, hash) does not match the local canonical chain; | ||
| // - the target is below finalized_head (SPEC-005 §3.6: halted); | ||
| // - the rollback executor itself fails (the node enters halted). | ||
| func (a *AdminAPI) SetL2Head(ctx context.Context, number uint64, hash common.Hash) error { | ||
| if a == nil || a.d == nil { | ||
| return errors.New("admin API not bound to a derivation instance") | ||
| } | ||
|
|
||
| if err := a.d.checkRollbackBoundary(number); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // TODO(spec-005-admin-rpc): | ||
| // 1. Authenticate the request (SPEC-005 §8 #2). | ||
| // 2. Verify hash matches local block at `number` via l2Client. | ||
| // 3. Acquire sequencerMutex.AcquireRollback() / defer release. | ||
| // 4. Call into rollbackLocalChain(number) — currently returns | ||
| // "not implemented" because the underlying go-ethereum | ||
| // hash-matched SetHead interface (SPEC-005 §8 #4) is not finalised. | ||
| return fmt.Errorf("admin SetL2Head not yet implemented (number=%d, hash=%s)", number, hash.Hex()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iterate L1 blocks via prefix scan and panic on
Haserrors.Two related concerns in
DeleteDerivationL1BlocksFrom:if err != nil || !has { break }swallows DB errors fromHasand treats them as "not found", silently terminating deletion. This breaks consistency with the rest ofStore(and the established codebase pattern), which panics on non-NotFounderrors.heightupward. A previous interruptedrecordL1Blocks(e.g. mid-range header fetch failure) can leave a hole; deletion will stop at the first gap, leaving stale block records at higher heights. When a reorg rewindslatestDerivationL1Heightbelow those stale heights, they never get overwritten and can mislead futuredetectReorgcomparisons if the chain re-advances.Prefer iterating the derivation-L1-block key prefix with
db.NewIterator(derivationL1BlockPrefix, …)(or pass in an explicit upper bound fromReadLatestDerivationL1Height) and treat anyHas/iterator error as fatal.🛡️ Sketch of safer implementation
func (s *Store) DeleteDerivationL1BlocksFrom(height uint64) { - batch := s.db.NewBatch() - for h := height; ; h++ { - key := DerivationL1BlockKey(h) - has, err := s.db.Has(key) - if err != nil || !has { - break - } - if err := batch.Delete(key); err != nil { - panic(fmt.Sprintf("failed to delete DerivationL1Block at %d, err: %v", h, err)) - } - } - if err := batch.Write(); err != nil { - panic(fmt.Sprintf("failed to write batch delete for DerivationL1Blocks, err: %v", err)) - } + batch := s.db.NewBatch() + it := s.db.NewIterator(derivationL1BlockPrefix, encodeBlockNumber(height)) + defer it.Release() + for it.Next() { + if err := batch.Delete(it.Key()); err != nil { + panic(fmt.Sprintf("failed to delete DerivationL1Block, err: %v", err)) + } + } + if err := it.Error(); err != nil { + panic(fmt.Sprintf("iterator error deleting DerivationL1Blocks, err: %v", err)) + } + if err := batch.Write(); err != nil { + panic(fmt.Sprintf("failed to write batch delete for DerivationL1Blocks, err: %v", err)) + } }(Adjust
encodeBlockNumber/ iterator helper to whatever exists innode/db/keys.go.)Based on learnings: "DB write methods … use a panic-on-error pattern instead of returning errors. This panic behavior is intentional and consistent across the codebase".
🤖 Prompt for AI Agents