forked from cerc-io/plugeth
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/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@ -545,3 +546,64 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
|
|||||||
}
|
}
|
||||||
return dirty, nil
|
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',
|
call: 'debug_freezeClient',
|
||||||
params: 1,
|
params: 1,
|
||||||
}),
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getAccessibleState',
|
||||||
|
call: 'debug_getAccessibleState',
|
||||||
|
params: 2,
|
||||||
|
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
properties: []
|
properties: []
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user