@@ -35,6 +35,7 @@ import (
35
35
"github.com/ethereum/go-ethereum/core/state"
36
36
"github.com/ethereum/go-ethereum/core/types"
37
37
"github.com/ethereum/go-ethereum/internal/ethapi"
38
+ "github.com/ethereum/go-ethereum/log"
38
39
"github.com/ethereum/go-ethereum/rlp"
39
40
"github.com/ethereum/go-ethereum/rpc"
40
41
"github.com/ethereum/go-ethereum/trie"
@@ -545,3 +546,64 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
545
546
}
546
547
return dirty , nil
547
548
}
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
+ }
0 commit comments