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:
Martin Holst Swende 2021-10-05 08:13:00 +02:00 committed by GitHub
parent 0dbb3b1601
commit 307156cc46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 0 deletions

@ -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: []
});