From 488948c7cd1d566a0938393c520664378d5ed554 Mon Sep 17 00:00:00 2001 From: BT Enterprise Date: Sat, 30 Mar 2019 12:43:10 +0900 Subject: [PATCH] eth/api: add debug_listAccounts API --- core/state/statedb.go | 5 +++++ eth/api.go | 45 +++++++++++++++++++++++++++++++++++++ internal/web3ext/web3ext.go | 8 ++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index db2e0d5e06..7e679a01f2 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -609,6 +609,11 @@ func (self *StateDB) GetRefund() uint64 { return self.refund } +// GetTrie returns the current value of the trie. +func (self *StateDB) GetTrie() Trie { + return self.trie +} + // Finalise finalises the state by removing the self destructed objects // and clears the journal as well as the refunds. func (s *StateDB) Finalise(deleteEmptyObjects bool) { diff --git a/eth/api.go b/eth/api.go index bdbbd1ba38..8916856fa5 100644 --- a/eth/api.go +++ b/eth/api.go @@ -34,6 +34,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -284,6 +285,50 @@ func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error return stateDb.RawDump(), nil } +// ListAccounts retrieves accounts of the database at a given block. +func (api *PublicDebugAPI) ListAccounts(count uint64, offset *common.Address, blockNr *rpc.BlockNumber) ([]common.Address, error) { + var block *types.Block = nil + var tr state.Trie + + if blockNr == nil || *blockNr == rpc.LatestBlockNumber { + block = api.eth.blockchain.CurrentBlock() + } else if *blockNr != rpc.PendingBlockNumber { + block = api.eth.blockchain.GetBlockByNumber(uint64(*blockNr)) + } + if block != nil { + stateDb, err := api.eth.BlockChain().StateAt(block.Root()) + if err != nil { + return nil, err + } + tr, err = stateDb.Database().OpenTrie(block.Root()) + if err != nil { + return nil, err + } + } else if *blockNr != rpc.PendingBlockNumber { + return nil, fmt.Errorf("block #%d not found", *blockNr) + } else { + // Get the pending state + _, stateDb := api.eth.miner.Pending() + tr = stateDb.GetTrie() + } + + var accounts []common.Address + var it *trie.Iterator + + if offset != nil && *offset != (common.Address{}) { + it = trie.NewIterator(tr.NodeIterator(crypto.Keccak256(offset[:]))) + it.Next() + } else { + it = trie.NewIterator(tr.NodeIterator(nil)) + } + + for ; count > 0 && it.Next(); count-- { + addr := tr.GetKey(it.Key) + accounts = append(accounts, common.BytesToAddress(addr)) + } + return accounts, nil +} + // PrivateDebugAPI is the collection of Ethereum full node APIs exposed over // the private debugging endpoint. type PrivateDebugAPI struct { diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index e1577fe2f8..8ef083f64f 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -234,7 +234,7 @@ web3._extend({ new web3._extend.Method({ name: 'testSignCliqueBlock', call: 'debug_testSignCliqueBlock', - params: 2, + params: 2, inputFormatters: [web3._extend.formatters.inputAddressFormatter, null], }), new web3._extend.Method({ @@ -252,6 +252,12 @@ web3._extend({ call: 'debug_dumpBlock', params: 1 }), + new web3._extend.Method({ + name: 'listAccounts', + call: 'debug_listAccounts', + params: 3, + inputFormatter: [null, null, web3._extend.formatters.inputDefaultBlockNumberFormatter], + }), new web3._extend.Method({ name: 'chaindbProperty', call: 'debug_chaindbProperty',