Skip to content

Commit 72ed186

Browse files
Arachnidkaralabe
authored andcommitted
eth, internal: Implement getModifiedAccountsBy(Hash|Number) using trie diffs (#15512)
* eth, internal: Implement using trie diffs * eth, internal: Changes in response to review * eth: More fixes to getModifiedAccountsBy* * eth: minor polishes on error capitalization
1 parent 7b95cca commit 72ed186

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

eth/api.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,86 @@ func storageRangeAt(st state.Trie, start []byte, maxResult int) StorageRangeResu
636636
}
637637
return result
638638
}
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+
}

internal/web3ext/web3ext.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,18 @@ web3._extend({
354354
call: 'debug_storageRangeAt',
355355
params: 5,
356356
}),
357+
new web3._extend.Method({
358+
name: 'getModifiedAccountsByNumber',
359+
call: 'debug_getModifiedAccountsByNumber',
360+
params: 2,
361+
inputFormatter: [null, null],
362+
}),
363+
new web3._extend.Method({
364+
name: 'getModifiedAccountsByHash',
365+
call: 'debug_getModifiedAccountsByHash',
366+
params: 2,
367+
inputFormatter:[null, null],
368+
}),
357369
],
358370
properties: []
359371
});

0 commit comments

Comments
 (0)