-
Notifications
You must be signed in to change notification settings - Fork 16
feature: block tag support(safe&finalize) #277
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -247,3 +247,22 @@ func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log { | |||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| return logs | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // SetSafe sets the safe block header. The safe block is derived from | ||||||||||||||||||||||||||||||||
| // L1 batch committed status. It represents the block that has been | ||||||||||||||||||||||||||||||||
| // submitted to L1 and is considered safe. | ||||||||||||||||||||||||||||||||
| func (bc *BlockChain) SetSafe(header *types.Header) { | ||||||||||||||||||||||||||||||||
| bc.currentSafeBlock.Store(header) | ||||||||||||||||||||||||||||||||
| log.Debug("Set safe block", "number", header.Number, "hash", header.Hash()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+254
to
+257
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add nil check to prevent potential panic. If 🛡️ Suggested fix func (bc *BlockChain) SetSafe(header *types.Header) {
+ if header == nil {
+ return
+ }
bc.currentSafeBlock.Store(header)
log.Debug("Set safe block", "number", header.Number, "hash", header.Hash())
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // SetFinalized sets the finalized block header. The finalized block is | ||||||||||||||||||||||||||||||||
| // derived from L1 batch finalized status. It represents the block that | ||||||||||||||||||||||||||||||||
| // has been finalized on L1 and is considered irreversible. | ||||||||||||||||||||||||||||||||
| // Also persists to rawdb for recovery on restart. | ||||||||||||||||||||||||||||||||
| func (bc *BlockChain) SetFinalized(header *types.Header) { | ||||||||||||||||||||||||||||||||
| bc.currentFinalizedBlock.Store(header) | ||||||||||||||||||||||||||||||||
| // Persist to rawdb for recovery on restart | ||||||||||||||||||||||||||||||||
| rawdb.WriteFinalizedBlockHash(bc.db, header.Hash()) | ||||||||||||||||||||||||||||||||
| log.Debug("Set finalized block", "number", header.Number, "hash", header.Hash()) | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
Comment on lines
+263
to
+268
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add nil check to prevent potential panic. Similar to 🛡️ Suggested fix func (bc *BlockChain) SetFinalized(header *types.Header) {
+ if header == nil {
+ return
+ }
bc.currentFinalizedBlock.Store(header)
// Persist to rawdb for recovery on restart
rawdb.WriteFinalizedBlockHash(bc.db, header.Hash())
log.Debug("Set finalized block", "number", header.Number, "hash", header.Hash())
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -176,16 +176,25 @@ func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _, _, stateDb := api.eth.miner.Pending() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return stateDb.RawDump(opts), nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var block *types.Block | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if blockNr == rpc.LatestBlockNumber { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block = api.eth.blockchain.CurrentBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var header *types.Header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch blockNr { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.LatestBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentBlock().Header() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.SafeBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentSafeBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.FinalizedBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentFinalizedBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if block == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = block.Header() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if block == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if header == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateDb, err := api.eth.BlockChain().StateAt(block.Root()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateDb, err := api.eth.BlockChain().StateAt(header.Root) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+179
to
+197
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error message shows raw negative block number for safe/finalized. When Proposed fix with descriptive error messages var header *types.Header
switch blockNr {
case rpc.LatestBlockNumber:
header = api.eth.blockchain.CurrentBlock().Header()
case rpc.SafeBlockNumber:
header = api.eth.blockchain.CurrentSafeBlock()
+ if header == nil {
+ return state.Dump{}, errors.New("safe block not available")
+ }
case rpc.FinalizedBlockNumber:
header = api.eth.blockchain.CurrentFinalizedBlock()
+ if header == nil {
+ return state.Dump{}, errors.New("finalized block not available")
+ }
default:
block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
if block == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
}
header = block.Header()
}
- if header == nil {
- return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
- }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.Dump{}, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -264,16 +273,25 @@ func (api *PublicDebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, sta | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the miner and operate on those | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _, _, stateDb = api.eth.miner.Pending() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var block *types.Block | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if number == rpc.LatestBlockNumber { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block = api.eth.blockchain.CurrentBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block = api.eth.blockchain.GetBlockByNumber(uint64(number)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var header *types.Header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| switch number { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.LatestBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentBlock().Header() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.SafeBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentSafeBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case rpc.FinalizedBlockNumber: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = api.eth.blockchain.CurrentFinalizedBlock() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| block := api.eth.blockchain.GetBlockByNumber(uint64(number)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if block == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.IteratorDump{}, fmt.Errorf("block #%d not found", number) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| header = block.Header() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if block == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if header == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.IteratorDump{}, fmt.Errorf("block #%d not found", number) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateDb, err = api.eth.BlockChain().StateAt(block.Root()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stateDb, err = api.eth.BlockChain().StateAt(header.Root) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+276
to
+294
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same error message issue in The error at Line 292 has the same issue as Proposed fix with descriptive error messages var header *types.Header
switch number {
case rpc.LatestBlockNumber:
header = api.eth.blockchain.CurrentBlock().Header()
case rpc.SafeBlockNumber:
header = api.eth.blockchain.CurrentSafeBlock()
+ if header == nil {
+ return state.IteratorDump{}, errors.New("safe block not available")
+ }
case rpc.FinalizedBlockNumber:
header = api.eth.blockchain.CurrentFinalizedBlock()
+ if header == nil {
+ return state.IteratorDump{}, errors.New("finalized block not available")
+ }
default:
block := api.eth.blockchain.GetBlockByNumber(uint64(number))
if block == nil {
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
}
header = block.Header()
}
- if header == nil {
- return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
- }📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return state.IteratorDump{}, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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.
🧩 Analysis chain
🏁 Script executed:
# First, check the structure of core/blockchain.go and locate setHeadBeyondRoot wc -l core/blockchain.goRepository: morph-l2/go-ethereum
Length of output: 87
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 224
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 746
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 718
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 2322
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 2462
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 1743
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 113
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 1768
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 46
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 585
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 1741
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 138
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 655
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 490
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 1209
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 359
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 46
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 484
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 771
🏁 Script executed:
Repository: morph-l2/go-ethereum
Length of output: 714
Clear safe/finalized blocks during chain rewind to prevent stale references.
When
setHeadBeyondRootrewinds the chain below the current finalized block, the finalized block header gets deleted from the database. However,loadLastState()attempts to reload it viaGetHeaderByHash(), which returnsnilif the header is no longer in the canonical chain. In this case,currentFinalizedBlockis not explicitly cleared and remains pointing to a stale block that is no longer part of the canonical chain. Add logic to clear or validatecurrentFinalizedBlockandcurrentSafeBlockwhenGetHeaderByHash()fails during chain rewind recovery.🤖 Prompt for AI Agents