Skip to content

Commit 8189ad8

Browse files
holimanjagdeep sidhu
authored and
jagdeep sidhu
committed
eth/api: add rpc method to obtain which states are accessible (ethereum#23646)
This PR adds a method to the debug namespace, to iterate over the blocks and check where we have the roots on disk.
1 parent 481b770 commit 8189ad8

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

eth/api.go

+62
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/ethereum/go-ethereum/core/state"
3636
"github.com/ethereum/go-ethereum/core/types"
3737
"github.com/ethereum/go-ethereum/internal/ethapi"
38+
"github.com/ethereum/go-ethereum/log"
3839
"github.com/ethereum/go-ethereum/rlp"
3940
"github.com/ethereum/go-ethereum/rpc"
4041
"github.com/ethereum/go-ethereum/trie"
@@ -545,3 +546,64 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
545546
}
546547
return dirty, nil
547548
}
549+
550+
// GetAccessibleState returns the first number where the node has accessible
551+
// state on disk. Note this being the post-state of that block and the pre-state
552+
// of the next block.
553+
// The (from, to) parameters are the sequence of blocks to search, which can go
554+
// either forwards or backwards
555+
func (api *PrivateDebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) {
556+
db := api.eth.ChainDb()
557+
var pivot uint64
558+
if p := rawdb.ReadLastPivotNumber(db); p != nil {
559+
pivot = *p
560+
log.Info("Found fast-sync pivot marker", "number", pivot)
561+
}
562+
var resolveNum = func(num rpc.BlockNumber) (uint64, error) {
563+
// We don't have state for pending (-2), so treat it as latest
564+
if num.Int64() < 0 {
565+
block := api.eth.blockchain.CurrentBlock()
566+
if block == nil {
567+
return 0, fmt.Errorf("current block missing")
568+
}
569+
return block.NumberU64(), nil
570+
}
571+
return uint64(num.Int64()), nil
572+
}
573+
var (
574+
start uint64
575+
end uint64
576+
delta = int64(1)
577+
lastLog time.Time
578+
err error
579+
)
580+
if start, err = resolveNum(from); err != nil {
581+
return 0, err
582+
}
583+
if end, err = resolveNum(to); err != nil {
584+
return 0, err
585+
}
586+
if start == end {
587+
return 0, fmt.Errorf("from and to needs to be different")
588+
}
589+
if start > end {
590+
delta = -1
591+
}
592+
for i := int64(start); i != int64(end); i += delta {
593+
if time.Since(lastLog) > 8*time.Second {
594+
log.Info("Finding roots", "from", start, "to", end, "at", i)
595+
lastLog = time.Now()
596+
}
597+
if i < int64(pivot) {
598+
continue
599+
}
600+
h := api.eth.BlockChain().GetHeaderByNumber(uint64(i))
601+
if h == nil {
602+
return 0, fmt.Errorf("missing header %d", i)
603+
}
604+
if ok, _ := api.eth.ChainDb().Has(h.Root[:]); ok {
605+
return uint64(i), nil
606+
}
607+
}
608+
return 0, fmt.Errorf("No state found")
609+
}

internal/web3ext/web3ext.go

+6
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ web3._extend({
465465
call: 'debug_freezeClient',
466466
params: 1,
467467
}),
468+
new web3._extend.Method({
469+
name: 'getAccessibleState',
470+
call: 'debug_getAccessibleState',
471+
params: 2,
472+
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
473+
}),
468474
],
469475
properties: []
470476
});

0 commit comments

Comments
 (0)