| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | package eth | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	"compress/gzip" | 
					
						
							| 
									
										
										
										
											2017-03-22 18:20:33 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2016-12-17 15:39:55 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common/hexutil" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/miner" | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2017-04-05 17:49:54 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rpc" | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/trie" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | // PublicEthereumAPI provides an API to access Ethereum full node-related | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // information. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | type PublicEthereumAPI struct { | 
					
						
							|  |  |  | 	e *Ethereum | 
					
						
							| 
									
										
										
										
											2016-01-27 18:01:30 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 05:31:31 -04:00
										 |  |  | // NewPublicEthereumAPI creates a new Ethereum protocol API for full nodes. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI { | 
					
						
							|  |  |  | 	return &PublicEthereumAPI{e} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Etherbase is the address that mining rewards will be send to | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicEthereumAPI) Etherbase() (common.Address, error) { | 
					
						
							|  |  |  | 	return api.e.Etherbase() | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-12 19:32:04 +02:00
										 |  |  | // Coinbase is the address that mining rewards will be send to (alias for Etherbase) | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicEthereumAPI) Coinbase() (common.Address, error) { | 
					
						
							|  |  |  | 	return api.Etherbase() | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Hashrate returns the POW hashrate | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 { | 
					
						
							|  |  |  | 	return hexutil.Uint64(api.e.Miner().HashRate()) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | // PublicMinerAPI provides an API to control the miner. | 
					
						
							|  |  |  | // It offers only methods that operate on data that pose no security risk when it is publicly accessible. | 
					
						
							|  |  |  | type PublicMinerAPI struct { | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | 	e     *Ethereum | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | 	agent *miner.RemoteAgent | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPublicMinerAPI create a new PublicMinerAPI instance. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI { | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	agent := miner.NewRemoteAgent(e.BlockChain(), e.Engine()) | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | 	e.Miner().Register(agent) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &PublicMinerAPI{e, agent} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Mining returns an indication if this node is currently mining. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicMinerAPI) Mining() bool { | 
					
						
							|  |  |  | 	return api.e.IsMining() | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was | 
					
						
							|  |  |  | // accepted. Note, this is not an indication if the provided work was valid! | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest common.Hash) bool { | 
					
						
							|  |  |  | 	return api.agent.SubmitWork(nonce, digest, solution) | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetWork returns a work package for external miner. The work package consists of 3 strings | 
					
						
							|  |  |  | // result[0], 32 bytes hex encoded current block header pow-hash | 
					
						
							|  |  |  | // result[1], 32 bytes hex encoded seed hash used for DAG | 
					
						
							|  |  |  | // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicMinerAPI) GetWork() ([3]string, error) { | 
					
						
							|  |  |  | 	if !api.e.IsMining() { | 
					
						
							| 
									
										
										
										
											2017-04-10 11:43:01 +03:00
										 |  |  | 		if err := api.e.StartMining(false); err != nil { | 
					
						
							| 
									
										
										
										
											2017-03-02 15:06:16 +02:00
										 |  |  | 			return [3]string{}, err | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	work, err := api.agent.GetWork() | 
					
						
							| 
									
										
										
										
											2017-03-02 15:06:16 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return work, fmt.Errorf("mining not ready: %v", err) | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-02 15:06:16 +02:00
										 |  |  | 	return work, nil | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined | 
					
						
							|  |  |  | // hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which | 
					
						
							|  |  |  | // must be unique between nodes. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool { | 
					
						
							|  |  |  | 	api.agent.SubmitHashrate(id, uint64(hashrate)) | 
					
						
							| 
									
										
										
										
											2016-02-09 16:03:04 +02:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // PrivateMinerAPI provides private RPC methods to control the miner. | 
					
						
							|  |  |  | // These methods can be abused by external users and must be considered insecure for use by untrusted users. | 
					
						
							|  |  |  | type PrivateMinerAPI struct { | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | 	e *Ethereum | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPrivateMinerAPI create a new RPC service which controls the miner of this node. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI { | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	return &PrivateMinerAPI{e: e} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | // Start the miner with the given number of threads. If threads is nil the number | 
					
						
							|  |  |  | // of workers started is equal to the number of logical CPUs that are usable by | 
					
						
							|  |  |  | // this process. If mining is already running, this method adjust the number of | 
					
						
							|  |  |  | // threads allowed to use. | 
					
						
							|  |  |  | func (api *PrivateMinerAPI) Start(threads *int) error { | 
					
						
							|  |  |  | 	// Set the number of threads if the seal engine supports it | 
					
						
							| 
									
										
										
										
											2017-04-07 17:22:06 +03:00
										 |  |  | 	if threads == nil { | 
					
						
							|  |  |  | 		threads = new(int) | 
					
						
							|  |  |  | 	} else if *threads == 0 { | 
					
						
							|  |  |  | 		*threads = -1 // Disable the miner from within | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	type threaded interface { | 
					
						
							|  |  |  | 		SetThreads(threads int) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if th, ok := api.e.engine.(threaded); ok { | 
					
						
							|  |  |  | 		log.Info("Updated mining threads", "threads", *threads) | 
					
						
							|  |  |  | 		th.SetThreads(*threads) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	// Start the miner and return | 
					
						
							|  |  |  | 	if !api.e.IsMining() { | 
					
						
							| 
									
										
										
										
											2017-05-16 22:07:27 +03:00
										 |  |  | 		// Propagate the initial price point to the transaction pool | 
					
						
							| 
									
										
										
										
											2017-05-29 10:21:34 +03:00
										 |  |  | 		api.e.lock.RLock() | 
					
						
							|  |  |  | 		price := api.e.gasPrice | 
					
						
							|  |  |  | 		api.e.lock.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		api.e.txPool.SetGasPrice(price) | 
					
						
							| 
									
										
										
										
											2017-04-10 11:43:01 +03:00
										 |  |  | 		return api.e.StartMining(true) | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Stop the miner | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PrivateMinerAPI) Stop() bool { | 
					
						
							| 
									
										
										
										
											2017-04-07 17:22:06 +03:00
										 |  |  | 	type threaded interface { | 
					
						
							|  |  |  | 		SetThreads(threads int) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if th, ok := api.e.engine.(threaded); ok { | 
					
						
							|  |  |  | 		th.SetThreads(-1) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	api.e.StopMining() | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetExtra sets the extra data string that is included when this miner mines a block. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PrivateMinerAPI) SetExtra(extra string) (bool, error) { | 
					
						
							|  |  |  | 	if err := api.e.Miner().SetExtra([]byte(extra)); err != nil { | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetGasPrice sets the minimum accepted gas price for the miner. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { | 
					
						
							| 
									
										
										
										
											2017-05-29 10:21:34 +03:00
										 |  |  | 	api.e.lock.Lock() | 
					
						
							|  |  |  | 	api.e.gasPrice = (*big.Int)(&gasPrice) | 
					
						
							|  |  |  | 	api.e.lock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-16 22:07:27 +03:00
										 |  |  | 	api.e.txPool.SetGasPrice((*big.Int)(&gasPrice)) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetEtherbase sets the etherbase of the miner | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool { | 
					
						
							|  |  |  | 	api.e.SetEtherbase(etherbase) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-06 17:20:25 +02:00
										 |  |  | // GetHashrate returns the current hashrate of the miner. | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | func (api *PrivateMinerAPI) GetHashrate() uint64 { | 
					
						
							|  |  |  | 	return uint64(api.e.miner.HashRate()) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 05:31:31 -04:00
										 |  |  | // PrivateAdminAPI is the collection of Ethereum full node-related APIs | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // exposed over the private admin endpoint. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | type PrivateAdminAPI struct { | 
					
						
							|  |  |  | 	eth *Ethereum | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // NewPrivateAdminAPI creates a new API definition for the full node private | 
					
						
							|  |  |  | // admin methods of the Ethereum service. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI { | 
					
						
							|  |  |  | 	return &PrivateAdminAPI{eth: eth} | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ExportChain exports the current blockchain into a local file. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) { | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	// Make sure we can create the file to export into | 
					
						
							|  |  |  | 	out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer out.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	var writer io.Writer = out | 
					
						
							|  |  |  | 	if strings.HasSuffix(file, ".gz") { | 
					
						
							|  |  |  | 		writer = gzip.NewWriter(writer) | 
					
						
							|  |  |  | 		defer writer.(*gzip.Writer).Close() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	// Export the blockchain | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	if err := api.eth.BlockChain().Export(writer); err != nil { | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool { | 
					
						
							|  |  |  | 	for _, b := range bs { | 
					
						
							| 
									
										
										
										
											2017-09-09 18:03:07 +02:00
										 |  |  | 		if !chain.HasBlock(b.Hash(), b.NumberU64()) { | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | // ImportChain imports a blockchain from a local file. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) { | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	// Make sure the can access the file to import | 
					
						
							|  |  |  | 	in, err := os.Open(file) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer in.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	var reader io.Reader = in | 
					
						
							|  |  |  | 	if strings.HasSuffix(file, ".gz") { | 
					
						
							|  |  |  | 		if reader, err = gzip.NewReader(reader); err != nil { | 
					
						
							|  |  |  | 			return false, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	// Run actual the import in pre-configured batches | 
					
						
							| 
									
										
										
										
											2016-12-12 15:08:23 +00:00
										 |  |  | 	stream := rlp.NewStream(reader, 0) | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	blocks, index := make([]*types.Block, 0, 2500), 0 | 
					
						
							|  |  |  | 	for batch := 0; ; batch++ { | 
					
						
							|  |  |  | 		// Load a batch of blocks from the input file | 
					
						
							|  |  |  | 		for len(blocks) < cap(blocks) { | 
					
						
							|  |  |  | 			block := new(types.Block) | 
					
						
							|  |  |  | 			if err := stream.Decode(block); err == io.EOF { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} else if err != nil { | 
					
						
							|  |  |  | 				return false, fmt.Errorf("block %d: failed to parse: %v", index, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			blocks = append(blocks, block) | 
					
						
							|  |  |  | 			index++ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(blocks) == 0 { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if hasAllBlocks(api.eth.BlockChain(), blocks) { | 
					
						
							|  |  |  | 			blocks = blocks[:0] | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 		// Import the batch and reset the buffer | 
					
						
							|  |  |  | 		if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil { | 
					
						
							|  |  |  | 			return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		blocks = blocks[:0] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 05:31:31 -04:00
										 |  |  | // PublicDebugAPI is the collection of Ethereum full node APIs exposed | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // over the public debugging endpoint. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | type PublicDebugAPI struct { | 
					
						
							|  |  |  | 	eth *Ethereum | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | // NewPublicDebugAPI creates a new API definition for the full node- | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // related public debug methods of the Ethereum service. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI { | 
					
						
							|  |  |  | 	return &PublicDebugAPI{eth: eth} | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // DumpBlock retrieves the entire state of the database at a given block. | 
					
						
							| 
									
										
										
										
											2017-04-05 17:49:54 +02:00
										 |  |  | func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) { | 
					
						
							|  |  |  | 	if blockNr == rpc.PendingBlockNumber { | 
					
						
							|  |  |  | 		// If we're dumping the pending state, we need to request | 
					
						
							|  |  |  | 		// both the pending block as well as the pending state from | 
					
						
							|  |  |  | 		// the miner and operate on those | 
					
						
							|  |  |  | 		_, stateDb := api.eth.miner.Pending() | 
					
						
							|  |  |  | 		return stateDb.RawDump(), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var block *types.Block | 
					
						
							|  |  |  | 	if blockNr == rpc.LatestBlockNumber { | 
					
						
							|  |  |  | 		block = api.eth.blockchain.CurrentBlock() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	if block == nil { | 
					
						
							| 
									
										
										
										
											2017-04-05 17:49:54 +02:00
										 |  |  | 		return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-27 13:13:13 +03:00
										 |  |  | 	stateDb, err := api.eth.BlockChain().StateAt(block.Root()) | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		return state.Dump{}, err | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return stateDb.RawDump(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 05:31:31 -04:00
										 |  |  | // PrivateDebugAPI is the collection of Ethereum full node APIs exposed over | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // the private debugging endpoint. | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | type PrivateDebugAPI struct { | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | 	config *params.ChainConfig | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | 	eth    *Ethereum | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | // NewPrivateDebugAPI creates a new API definition for the full node-related | 
					
						
							| 
									
										
										
										
											2015-12-16 04:26:23 +01:00
										 |  |  | // private debug methods of the Ethereum service. | 
					
						
							| 
									
										
										
										
											2016-10-20 13:36:29 +02:00
										 |  |  | func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI { | 
					
						
							| 
									
										
										
										
											2016-06-30 13:03:26 +03:00
										 |  |  | 	return &PrivateDebugAPI{config: config, eth: eth} | 
					
						
							| 
									
										
										
										
											2016-02-20 14:36:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-17 11:19:50 +00:00
										 |  |  | // Preimage is a debug API function that returns the preimage for a sha3 hash, if known. | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) { | 
					
						
							|  |  |  | 	db := core.PreimageTable(api.eth.ChainDb()) | 
					
						
							|  |  |  | 	return db.Get(hash.Bytes()) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-13 21:44:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network | 
					
						
							|  |  |  | // and returns them as a JSON list of block-hashes | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]core.BadBlockArgs, error) { | 
					
						
							|  |  |  | 	return api.eth.BlockChain().BadBlocks() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // StorageRangeResult is the result of a debug_storageRangeAt API call. | 
					
						
							|  |  |  | type StorageRangeResult struct { | 
					
						
							|  |  |  | 	Storage storageMap   `json:"storage"` | 
					
						
							|  |  |  | 	NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie. | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type storageMap map[common.Hash]storageEntry | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type storageEntry struct { | 
					
						
							|  |  |  | 	Key   *common.Hash `json:"key"` | 
					
						
							|  |  |  | 	Value common.Hash  `json:"value"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StorageRangeAt returns the storage at the given block height and transaction index. | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) { | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	_, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0) | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return StorageRangeResult{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st := statedb.StorageTrie(contractAddress) | 
					
						
							|  |  |  | 	if st == nil { | 
					
						
							|  |  |  | 		return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-12-06 07:42:16 -08:00
										 |  |  | 	return storageRangeAt(st, keyStart, maxResult) | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 07:42:16 -08:00
										 |  |  | func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeResult, error) { | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 	it := trie.NewIterator(st.NodeIterator(start)) | 
					
						
							|  |  |  | 	result := StorageRangeResult{Storage: storageMap{}} | 
					
						
							|  |  |  | 	for i := 0; i < maxResult && it.Next(); i++ { | 
					
						
							| 
									
										
										
										
											2017-12-06 07:42:16 -08:00
										 |  |  | 		_, content, _, err := rlp.Split(it.Value) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return StorageRangeResult{}, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		e := storageEntry{Value: common.BytesToHash(content)} | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | 		if preimage := st.GetKey(it.Key); preimage != nil { | 
					
						
							|  |  |  | 			preimage := common.BytesToHash(preimage) | 
					
						
							|  |  |  | 			e.Key = &preimage | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		result.Storage[common.BytesToHash(it.Key)] = e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Add the 'next key' so clients can continue downloading. | 
					
						
							|  |  |  | 	if it.Next() { | 
					
						
							|  |  |  | 		next := common.BytesToHash(it.Key) | 
					
						
							|  |  |  | 		result.NextKey = &next | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-12-06 07:42:16 -08:00
										 |  |  | 	return result, nil | 
					
						
							| 
									
										
										
										
											2017-04-19 12:09:04 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-20 16:18:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetModifiedAccountsByumber returns all accounts that have changed between the | 
					
						
							|  |  |  | // two blocks specified. A change is defined as a difference in nonce, balance, | 
					
						
							|  |  |  | // code hash, or storage hash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // With one parameter, returns the list of accounts modified in the specified block. | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) GetModifiedAccountsByNumber(startNum uint64, endNum *uint64) ([]common.Address, error) { | 
					
						
							|  |  |  | 	var startBlock, endBlock *types.Block | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	startBlock = api.eth.blockchain.GetBlockByNumber(startNum) | 
					
						
							|  |  |  | 	if startBlock == nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("start block %x not found", startNum) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if endNum == nil { | 
					
						
							|  |  |  | 		endBlock = startBlock | 
					
						
							|  |  |  | 		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) | 
					
						
							|  |  |  | 		if startBlock == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		endBlock = api.eth.blockchain.GetBlockByNumber(*endNum) | 
					
						
							|  |  |  | 		if endBlock == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("end block %d not found", *endNum) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return api.getModifiedAccounts(startBlock, endBlock) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetModifiedAccountsByHash returns all accounts that have changed between the | 
					
						
							|  |  |  | // two blocks specified. A change is defined as a difference in nonce, balance, | 
					
						
							|  |  |  | // code hash, or storage hash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // With one parameter, returns the list of accounts modified in the specified block. | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) GetModifiedAccountsByHash(startHash common.Hash, endHash *common.Hash) ([]common.Address, error) { | 
					
						
							|  |  |  | 	var startBlock, endBlock *types.Block | 
					
						
							|  |  |  | 	startBlock = api.eth.blockchain.GetBlockByHash(startHash) | 
					
						
							|  |  |  | 	if startBlock == nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("start block %x not found", startHash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if endHash == nil { | 
					
						
							|  |  |  | 		endBlock = startBlock | 
					
						
							|  |  |  | 		startBlock = api.eth.blockchain.GetBlockByHash(startBlock.ParentHash()) | 
					
						
							|  |  |  | 		if startBlock == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("block %x has no parent", endBlock.Number()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		endBlock = api.eth.blockchain.GetBlockByHash(*endHash) | 
					
						
							|  |  |  | 		if endBlock == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("end block %x not found", *endHash) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return api.getModifiedAccounts(startBlock, endBlock) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]common.Address, error) { | 
					
						
							|  |  |  | 	if startBlock.Number().Uint64() >= endBlock.Number().Uint64() { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("start block height (%d) must be less than end block height (%d)", startBlock.Number().Uint64(), endBlock.Number().Uint64()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	oldTrie, err := trie.NewSecure(startBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0) | 
					
						
							| 
									
										
										
										
											2017-11-20 16:18:50 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	newTrie, err := trie.NewSecure(endBlock.Root(), trie.NewDatabase(api.eth.chainDb), 0) | 
					
						
							| 
									
										
										
										
											2017-11-20 16:18:50 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	diff, _ := trie.NewDifferenceIterator(oldTrie.NodeIterator([]byte{}), newTrie.NodeIterator([]byte{})) | 
					
						
							|  |  |  | 	iter := trie.NewIterator(diff) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var dirty []common.Address | 
					
						
							|  |  |  | 	for iter.Next() { | 
					
						
							|  |  |  | 		key := newTrie.GetKey(iter.Key) | 
					
						
							|  |  |  | 		if key == nil { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("no preimage found for hash %x", iter.Key) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		dirty = append(dirty, common.BytesToAddress(key)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return dirty, nil | 
					
						
							|  |  |  | } |