eth/api: add rpc method to obtain which states are accessible (#23646)
This PR adds a method to the debug namespace, to iterate over the blocks and check where we have the roots on disk.
This commit is contained in:
parent
0dbb3b1601
commit
307156cc46
62
eth/api.go
62
eth/api.go
@ -35,6 +35,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
@ -545,3 +546,64 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
|
||||
}
|
||||
return dirty, nil
|
||||
}
|
||||
|
||||
// GetAccessibleState returns the first number where the node has accessible
|
||||
// state on disk. Note this being the post-state of that block and the pre-state
|
||||
// of the next block.
|
||||
// The (from, to) parameters are the sequence of blocks to search, which can go
|
||||
// either forwards or backwards
|
||||
func (api *PrivateDebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) {
|
||||
db := api.eth.ChainDb()
|
||||
var pivot uint64
|
||||
if p := rawdb.ReadLastPivotNumber(db); p != nil {
|
||||
pivot = *p
|
||||
log.Info("Found fast-sync pivot marker", "number", pivot)
|
||||
}
|
||||
var resolveNum = func(num rpc.BlockNumber) (uint64, error) {
|
||||
// We don't have state for pending (-2), so treat it as latest
|
||||
if num.Int64() < 0 {
|
||||
block := api.eth.blockchain.CurrentBlock()
|
||||
if block == nil {
|
||||
return 0, fmt.Errorf("current block missing")
|
||||
}
|
||||
return block.NumberU64(), nil
|
||||
}
|
||||
return uint64(num.Int64()), nil
|
||||
}
|
||||
var (
|
||||
start uint64
|
||||
end uint64
|
||||
delta = int64(1)
|
||||
lastLog time.Time
|
||||
err error
|
||||
)
|
||||
if start, err = resolveNum(from); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if end, err = resolveNum(to); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if start == end {
|
||||
return 0, fmt.Errorf("from and to needs to be different")
|
||||
}
|
||||
if start > end {
|
||||
delta = -1
|
||||
}
|
||||
for i := int64(start); i != int64(end); i += delta {
|
||||
if time.Since(lastLog) > 8*time.Second {
|
||||
log.Info("Finding roots", "from", start, "to", end, "at", i)
|
||||
lastLog = time.Now()
|
||||
}
|
||||
if i < int64(pivot) {
|
||||
continue
|
||||
}
|
||||
h := api.eth.BlockChain().GetHeaderByNumber(uint64(i))
|
||||
if h == nil {
|
||||
return 0, fmt.Errorf("missing header %d", i)
|
||||
}
|
||||
if ok, _ := api.eth.ChainDb().Has(h.Root[:]); ok {
|
||||
return uint64(i), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("No state found")
|
||||
}
|
||||
|
@ -465,6 +465,12 @@ web3._extend({
|
||||
call: 'debug_freezeClient',
|
||||
params: 1,
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'getAccessibleState',
|
||||
call: 'debug_getAccessibleState',
|
||||
params: 2,
|
||||
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
|
||||
}),
|
||||
],
|
||||
properties: []
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user