@@ -636,3 +636,86 @@ func storageRangeAt(st state.Trie, start []byte, maxResult int) StorageRangeResu
636
636
}
637
637
return result
638
638
}
639
+
640
+ // GetModifiedAccountsByumber returns all accounts that have changed between the
641
+ // two blocks specified. A change is defined as a difference in nonce, balance,
642
+ // code hash, or storage hash.
643
+ //
644
+ // With one parameter, returns the list of accounts modified in the specified block.
645
+ func (api * PrivateDebugAPI ) GetModifiedAccountsByNumber (startNum uint64 , endNum * uint64 ) ([]common.Address , error ) {
646
+ var startBlock , endBlock * types.Block
647
+
648
+ startBlock = api .eth .blockchain .GetBlockByNumber (startNum )
649
+ if startBlock == nil {
650
+ return nil , fmt .Errorf ("start block %x not found" , startNum )
651
+ }
652
+
653
+ if endNum == nil {
654
+ endBlock = startBlock
655
+ startBlock = api .eth .blockchain .GetBlockByHash (startBlock .ParentHash ())
656
+ if startBlock == nil {
657
+ return nil , fmt .Errorf ("block %x has no parent" , endBlock .Number ())
658
+ }
659
+ } else {
660
+ endBlock = api .eth .blockchain .GetBlockByNumber (* endNum )
661
+ if endBlock == nil {
662
+ return nil , fmt .Errorf ("end block %d not found" , * endNum )
663
+ }
664
+ }
665
+ return api .getModifiedAccounts (startBlock , endBlock )
666
+ }
667
+
668
+ // GetModifiedAccountsByHash returns all accounts that have changed between the
669
+ // two blocks specified. A change is defined as a difference in nonce, balance,
670
+ // code hash, or storage hash.
671
+ //
672
+ // With one parameter, returns the list of accounts modified in the specified block.
673
+ func (api * PrivateDebugAPI ) GetModifiedAccountsByHash (startHash common.Hash , endHash * common.Hash ) ([]common.Address , error ) {
674
+ var startBlock , endBlock * types.Block
675
+ startBlock = api .eth .blockchain .GetBlockByHash (startHash )
676
+ if startBlock == nil {
677
+ return nil , fmt .Errorf ("start block %x not found" , startHash )
678
+ }
679
+
680
+ if endHash == nil {
681
+ endBlock = startBlock
682
+ startBlock = api .eth .blockchain .GetBlockByHash (startBlock .ParentHash ())
683
+ if startBlock == nil {
684
+ return nil , fmt .Errorf ("block %x has no parent" , endBlock .Number ())
685
+ }
686
+ } else {
687
+ endBlock = api .eth .blockchain .GetBlockByHash (* endHash )
688
+ if endBlock == nil {
689
+ return nil , fmt .Errorf ("end block %x not found" , * endHash )
690
+ }
691
+ }
692
+ return api .getModifiedAccounts (startBlock , endBlock )
693
+ }
694
+
695
+ func (api * PrivateDebugAPI ) getModifiedAccounts (startBlock , endBlock * types.Block ) ([]common.Address , error ) {
696
+ if startBlock .Number ().Uint64 () >= endBlock .Number ().Uint64 () {
697
+ return nil , fmt .Errorf ("start block height (%d) must be less than end block height (%d)" , startBlock .Number ().Uint64 (), endBlock .Number ().Uint64 ())
698
+ }
699
+
700
+ oldTrie , err := trie .NewSecure (startBlock .Root (), api .eth .chainDb , 0 )
701
+ if err != nil {
702
+ return nil , err
703
+ }
704
+ newTrie , err := trie .NewSecure (endBlock .Root (), api .eth .chainDb , 0 )
705
+ if err != nil {
706
+ return nil , err
707
+ }
708
+
709
+ diff , _ := trie .NewDifferenceIterator (oldTrie .NodeIterator ([]byte {}), newTrie .NodeIterator ([]byte {}))
710
+ iter := trie .NewIterator (diff )
711
+
712
+ var dirty []common.Address
713
+ for iter .Next () {
714
+ key := newTrie .GetKey (iter .Key )
715
+ if key == nil {
716
+ return nil , fmt .Errorf ("no preimage found for hash %x" , iter .Key )
717
+ }
718
+ dirty = append (dirty , common .BytesToAddress (key ))
719
+ }
720
+ return dirty , nil
721
+ }
0 commit comments