1// Copyright 2015 The go-ethereum Authors
2// This file is part of the go-ethereum library.
3//
4// The go-ethereum library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// The go-ethereum library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public License
15// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
17package eth
18
19import (
20	"compress/gzip"
21	"context"
22	"errors"
23	"fmt"
24	"io"
25	"math/big"
26	"os"
27	"runtime"
28	"strings"
29	"time"
30
31	"github.com/ethereum/go-ethereum/common"
32	"github.com/ethereum/go-ethereum/common/hexutil"
33	"github.com/ethereum/go-ethereum/core"
34	"github.com/ethereum/go-ethereum/core/rawdb"
35	"github.com/ethereum/go-ethereum/core/state"
36	"github.com/ethereum/go-ethereum/core/types"
37	"github.com/ethereum/go-ethereum/internal/ethapi"
38	"github.com/ethereum/go-ethereum/params"
39	"github.com/ethereum/go-ethereum/rlp"
40	"github.com/ethereum/go-ethereum/rpc"
41	"github.com/ethereum/go-ethereum/trie"
42)
43
44// PublicEthereumAPI provides an API to access Ethereum full node-related
45// information.
46type PublicEthereumAPI struct {
47	e *Ethereum
48}
49
50// NewPublicEthereumAPI creates a new Ethereum protocol API for full nodes.
51func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI {
52	return &PublicEthereumAPI{e}
53}
54
55// Etherbase is the address that mining rewards will be send to
56func (api *PublicEthereumAPI) Etherbase() (common.Address, error) {
57	return api.e.Etherbase()
58}
59
60// Coinbase is the address that mining rewards will be send to (alias for Etherbase)
61func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
62	return api.Etherbase()
63}
64
65// Hashrate returns the POW hashrate
66func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
67	return hexutil.Uint64(api.e.Miner().HashRate())
68}
69
70// PublicMinerAPI provides an API to control the miner.
71// It offers only methods that operate on data that pose no security risk when it is publicly accessible.
72type PublicMinerAPI struct {
73	e *Ethereum
74}
75
76// NewPublicMinerAPI create a new PublicMinerAPI instance.
77func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI {
78	return &PublicMinerAPI{e}
79}
80
81// Mining returns an indication if this node is currently mining.
82func (api *PublicMinerAPI) Mining() bool {
83	return api.e.IsMining()
84}
85
86// PrivateMinerAPI provides private RPC methods to control the miner.
87// These methods can be abused by external users and must be considered insecure for use by untrusted users.
88type PrivateMinerAPI struct {
89	e *Ethereum
90}
91
92// NewPrivateMinerAPI create a new RPC service which controls the miner of this node.
93func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI {
94	return &PrivateMinerAPI{e: e}
95}
96
97// Start starts the miner with the given number of threads. If threads is nil,
98// the number of workers started is equal to the number of logical CPUs that are
99// usable by this process. If mining is already running, this method adjust the
100// number of threads allowed to use and updates the minimum price required by the
101// transaction pool.
102func (api *PrivateMinerAPI) Start(threads *int) error {
103	if threads == nil {
104		return api.e.StartMining(runtime.NumCPU())
105	}
106	return api.e.StartMining(*threads)
107}
108
109// Stop terminates the miner, both at the consensus engine level as well as at
110// the block creation level.
111func (api *PrivateMinerAPI) Stop() {
112	api.e.StopMining()
113}
114
115// SetExtra sets the extra data string that is included when this miner mines a block.
116func (api *PrivateMinerAPI) SetExtra(extra string) (bool, error) {
117	if err := api.e.Miner().SetExtra([]byte(extra)); err != nil {
118		return false, err
119	}
120	return true, nil
121}
122
123// SetGasPrice sets the minimum accepted gas price for the miner.
124func (api *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
125	api.e.lock.Lock()
126	api.e.gasPrice = (*big.Int)(&gasPrice)
127	api.e.lock.Unlock()
128
129	api.e.txPool.SetGasPrice((*big.Int)(&gasPrice))
130	return true
131}
132
133// SetEtherbase sets the etherbase of the miner
134func (api *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool {
135	api.e.SetEtherbase(etherbase)
136	return true
137}
138
139// SetRecommitInterval updates the interval for miner sealing work recommitting.
140func (api *PrivateMinerAPI) SetRecommitInterval(interval int) {
141	api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond)
142}
143
144// GetHashrate returns the current hashrate of the miner.
145func (api *PrivateMinerAPI) GetHashrate() uint64 {
146	return api.e.miner.HashRate()
147}
148
149// PrivateAdminAPI is the collection of Ethereum full node-related APIs
150// exposed over the private admin endpoint.
151type PrivateAdminAPI struct {
152	eth *Ethereum
153}
154
155// NewPrivateAdminAPI creates a new API definition for the full node private
156// admin methods of the Ethereum service.
157func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI {
158	return &PrivateAdminAPI{eth: eth}
159}
160
161// ExportChain exports the current blockchain into a local file.
162func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
163	// Make sure we can create the file to export into
164	out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
165	if err != nil {
166		return false, err
167	}
168	defer out.Close()
169
170	var writer io.Writer = out
171	if strings.HasSuffix(file, ".gz") {
172		writer = gzip.NewWriter(writer)
173		defer writer.(*gzip.Writer).Close()
174	}
175
176	// Export the blockchain
177	if err := api.eth.BlockChain().Export(writer); err != nil {
178		return false, err
179	}
180	return true, nil
181}
182
183func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
184	for _, b := range bs {
185		if !chain.HasBlock(b.Hash(), b.NumberU64()) {
186			return false
187		}
188	}
189
190	return true
191}
192
193// ImportChain imports a blockchain from a local file.
194func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
195	// Make sure the can access the file to import
196	in, err := os.Open(file)
197	if err != nil {
198		return false, err
199	}
200	defer in.Close()
201
202	var reader io.Reader = in
203	if strings.HasSuffix(file, ".gz") {
204		if reader, err = gzip.NewReader(reader); err != nil {
205			return false, err
206		}
207	}
208
209	// Run actual the import in pre-configured batches
210	stream := rlp.NewStream(reader, 0)
211
212	blocks, index := make([]*types.Block, 0, 2500), 0
213	for batch := 0; ; batch++ {
214		// Load a batch of blocks from the input file
215		for len(blocks) < cap(blocks) {
216			block := new(types.Block)
217			if err := stream.Decode(block); err == io.EOF {
218				break
219			} else if err != nil {
220				return false, fmt.Errorf("block %d: failed to parse: %v", index, err)
221			}
222			blocks = append(blocks, block)
223			index++
224		}
225		if len(blocks) == 0 {
226			break
227		}
228
229		if hasAllBlocks(api.eth.BlockChain(), blocks) {
230			blocks = blocks[:0]
231			continue
232		}
233		// Import the batch and reset the buffer
234		if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil {
235			return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err)
236		}
237		blocks = blocks[:0]
238	}
239	return true, nil
240}
241
242// PublicDebugAPI is the collection of Ethereum full node APIs exposed
243// over the public debugging endpoint.
244type PublicDebugAPI struct {
245	eth *Ethereum
246}
247
248// NewPublicDebugAPI creates a new API definition for the full node-
249// related public debug methods of the Ethereum service.
250func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
251	return &PublicDebugAPI{eth: eth}
252}
253
254// DumpBlock retrieves the entire state of the database at a given block.
255func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
256	if blockNr == rpc.PendingBlockNumber {
257		// If we're dumping the pending state, we need to request
258		// both the pending block as well as the pending state from
259		// the miner and operate on those
260		_, stateDb := api.eth.miner.Pending()
261		return stateDb.RawDump(), nil
262	}
263	var block *types.Block
264	if blockNr == rpc.LatestBlockNumber {
265		block = api.eth.blockchain.CurrentBlock()
266	} else {
267		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
268	}
269	if block == nil {
270		return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
271	}
272	stateDb, err := api.eth.BlockChain().StateAt(block.Root())
273	if err != nil {
274		return state.Dump{}, err
275	}
276	return stateDb.RawDump(), nil
277}
278
279// PrivateDebugAPI is the collection of Ethereum full node APIs exposed over
280// the private debugging endpoint.
281type PrivateDebugAPI struct {
282	config *params.ChainConfig
283	eth    *Ethereum
284}
285
286// NewPrivateDebugAPI creates a new API definition for the full node-related
287// private debug methods of the Ethereum service.
288func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
289	return &PrivateDebugAPI{config: config, eth: eth}
290}
291
292// Preimage is a debug API function that returns the preimage for a sha3 hash, if known.
293func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
294	if preimage := rawdb.ReadPreimage(api.eth.ChainDb(), hash); preimage != nil {
295		return preimage, nil
296	}
297	return nil, errors.New("unknown preimage")
298}
299
300// BadBlockArgs represents the entries in the list returned when bad blocks are queried.
301type BadBlockArgs struct {
302	Hash  common.Hash            `json:"hash"`
303	Block map[string]interface{} `json:"block"`
304	RLP   string                 `json:"rlp"`
305}
306
307// GetBadBlocks returns a list of the last 'bad blocks' that the client has seen on the network
308// and returns them as a JSON list of block-hashes
309func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) {
310	blocks := api.eth.BlockChain().BadBlocks()
311	results := make([]*BadBlockArgs, len(blocks))
312
313	var err error
314	for i, block := range blocks {
315		results[i] = &BadBlockArgs{
316			Hash: block.Hash(),
317		}
318		if rlpBytes, err := rlp.EncodeToBytes(block); err != nil {
319			results[i].RLP = err.Error() // Hacky, but hey, it works
320		} else {
321			results[i].RLP = fmt.Sprintf("0x%x", rlpBytes)
322		}
323		if results[i].Block, err = ethapi.RPCMarshalBlock(block, true, true); err != nil {
324			results[i].Block = map[string]interface{}{"error": err.Error()}
325		}
326	}
327	return results, nil
328}
329
330// StorageRangeResult is the result of a debug_storageRangeAt API call.
331type StorageRangeResult struct {
332	Storage storageMap   `json:"storage"`
333	NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie.
334}
335
336type storageMap map[common.Hash]storageEntry
337
338type storageEntry struct {
339	Key   *common.Hash `json:"key"`
340	Value common.Hash  `json:"value"`
341}
342
343// StorageRangeAt returns the storage at the given block height and transaction index.
344func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) {
345	_, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0)
346	if err != nil {
347		return StorageRangeResult{}, err
348	}
349	st := statedb.StorageTrie(contractAddress)
350	if st == nil {
351		return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress)
352	}
353	return storageRangeAt(st, keyStart, maxResult)
354}
355
356func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeResult, error) {
357	it := trie.NewIterator(st.NodeIterator(start))
358	result := StorageRangeResult{Storage: storageMap{}}
359	for i := 0; i < maxResult && it.Next(); i++ {
360		_, content, _, err := rlp.Split(it.Value)
361		if err != nil {
362			return StorageRangeResult{}, err
363		}
364		e := storageEntry{Value: common.BytesToHash(content)}
365		if preimage := st.GetKey(it.Key); preimage != nil {
366			preimage := common.BytesToHash(preimage)
367			e.Key = &preimage
368		}
369		result.Storage[common.BytesToHash(it.Key)] = e
370	}
371	// Add the 'next key' so clients can continue downloading.
372	if it.Next() {
373		next := common.BytesToHash(it.Key)
374		result.NextKey = &next
375	}
376	return result, nil
377}
378
379// GetModifiedAccountsByNumber returns all accounts that have changed between the
380// two blocks specified. A change is defined as a difference in nonce, balance,
381// code hash, or storage hash.
382//
383// With one parameter, returns the list of accounts modified in the specified block.
384func (api *PrivateDebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64) ([]common.Address, error) {
385	var startBlock, endBlock *types.Block
386
387	startBlock = api.eth.blockchain.GetBlockByNumber(startNum)
388	if startBlock == nil {
389		return nil, fmt.Errorf("start block %x not found", startNum)
390	}
391
392	if endNum == nil {
393		endBlock = startBlock
394		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash())
395		if startBlock == nil {
396			return nil, fmt.Errorf("block %x has no parent", endBlock.Number())
397		}
398	} else {
399		endBlock = api.eth.blockchain.GetBlockByNumber(*endNum)
400		if endBlock == nil {
401			return nil, fmt.Errorf("end block %d not found", *endNum)
402		}
403	}
404	return api.getModifiedAccounts(startBlock, endBlock)
405}
406
407// GetModifiedAccountsByHash returns all accounts that have changed between the
408// two blocks specified. A change is defined as a difference in nonce, balance,
409// code hash, or storage hash.
410//
411// With one parameter, returns the list of accounts modified in the specified block.
412func (api *PrivateDebugAPI) GetModifiedAccountsByHash(startHash common.Hash, endHash *common.Hash) ([]common.Address, error) {
413	var startBlock, endBlock *types.Block
414	startBlock = api.eth.blockchain.GetBlockByHash(startHash)
415	if startBlock == nil {
416		return nil, fmt.Errorf("start block %x not found", startHash)
417	}
418
419	if endHash == nil {
420		endBlock = startBlock
421		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash())
422		if startBlock == nil {
423			return nil, fmt.Errorf("block %x has no parent", endBlock.Number())
424		}
425	} else {
426		endBlock = api.eth.blockchain.GetBlockByHash(*endHash)
427		if endBlock == nil {
428			return nil, fmt.Errorf("end block %x not found", *endHash)
429		}
430	}
431	return api.getModifiedAccounts(startBlock, endBlock)
432}
433
434func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) {
435	if startBlock.Number().Uint64() >= endBlock.Number().Uint64() {
436		return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64())
437	}
438
439	oldTrie, err := trie.NewSecure(startBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
440	if err != nil {
441		return nil, err
442	}
443	newTrie, err := trie.NewSecure(endBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0)
444	if err != nil {
445		return nil, err
446	}
447
448	diff, _ := trie.NewDifferenceIterator(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{}))
449	iter := trie.NewIterator(diff)
450
451	var dirty []common.Address
452	for iter.Next() {
453		key := newTrie.GetKey(iter.Key)
454		if key == nil {
455			return nil, fmt.Errorf("no preimage found for hash %x", iter.Key)
456		}
457		dirty = append(dirty, common.BytesToAddress(key))
458	}
459	return dirty, nil
460}
461