github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/eth/api.go (about)

     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  
    17  package eth
    18  
    19  import (
    20  	"bytes"
    21  	"compress/gzip"
    22  	"context"
    23  	"fmt"
    24  	"io"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"os"
    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/state"
    35  	"github.com/ethereum/go-ethereum/core/types"
    36  	"github.com/ethereum/go-ethereum/core/vm"
    37  	"github.com/ethereum/go-ethereum/internal/ethapi"
    38  	"github.com/ethereum/go-ethereum/log"
    39  	"github.com/ethereum/go-ethereum/miner"
    40  	"github.com/ethereum/go-ethereum/params"
    41  	"github.com/ethereum/go-ethereum/rlp"
    42  	"github.com/ethereum/go-ethereum/rpc"
    43  	"github.com/ethereum/go-ethereum/trie"
    44  )
    45  
    46  const defaultTraceTimeout = 5 * time.Second
    47  
    48  // PublicEthereumAPI provides an API to access Ethereum full node-related
    49  // information.
    50  type PublicEthereumAPI struct {
    51  	e *Ethereum
    52  }
    53  
    54  // NewPublicEthereumAPI creates a new Etheruem protocol API for full nodes.
    55  func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI {
    56  	return &PublicEthereumAPI{e}
    57  }
    58  
    59  // Etherbase is the address that mining rewards will be send to
    60  func (api *PublicEthereumAPI) Etherbase() (common.Address, error) {
    61  	return api.e.Etherbase()
    62  }
    63  
    64  // Coinbase is the address that mining rewards will be send to (alias for Etherbase)
    65  func (api *PublicEthereumAPI) Coinbase() (common.Address, error) {
    66  	return api.Etherbase()
    67  }
    68  
    69  // Hashrate returns the POW hashrate
    70  func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 {
    71  	return hexutil.Uint64(api.e.Miner().HashRate())
    72  }
    73  
    74  // PublicMinerAPI provides an API to control the miner.
    75  // It offers only methods that operate on data that pose no security risk when it is publicly accessible.
    76  type PublicMinerAPI struct {
    77  	e     *Ethereum
    78  	agent *miner.RemoteAgent
    79  }
    80  
    81  // NewPublicMinerAPI create a new PublicMinerAPI instance.
    82  func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI {
    83  	agent := miner.NewRemoteAgent(e.BlockChain(), e.Engine())
    84  	e.Miner().Register(agent)
    85  
    86  	return &PublicMinerAPI{e, agent}
    87  }
    88  
    89  // Mining returns an indication if this node is currently mining.
    90  func (api *PublicMinerAPI) Mining() bool {
    91  	return api.e.IsMining()
    92  }
    93  
    94  // SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was
    95  // accepted. Note, this is not an indication if the provided work was valid!
    96  func (api *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest common.Hash) bool {
    97  	return api.agent.SubmitWork(nonce, digest, solution)
    98  }
    99  
   100  // GetWork returns a work package for external miner. The work package consists of 3 strings
   101  // result[0], 32 bytes hex encoded current block header pow-hash
   102  // result[1], 32 bytes hex encoded seed hash used for DAG
   103  // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty
   104  func (api *PublicMinerAPI) GetWork() ([3]string, error) {
   105  	if !api.e.IsMining() {
   106  		if err := api.e.StartMining(false); err != nil {
   107  			return [3]string{}, err
   108  		}
   109  	}
   110  	work, err := api.agent.GetWork()
   111  	if err != nil {
   112  		return work, fmt.Errorf("mining not ready: %v", err)
   113  	}
   114  	return work, nil
   115  }
   116  
   117  // SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined
   118  // hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which
   119  // must be unique between nodes.
   120  func (api *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool {
   121  	api.agent.SubmitHashrate(id, uint64(hashrate))
   122  	return true
   123  }
   124  
   125  // PrivateMinerAPI provides private RPC methods to control the miner.
   126  // These methods can be abused by external users and must be considered insecure for use by untrusted users.
   127  type PrivateMinerAPI struct {
   128  	e *Ethereum
   129  }
   130  
   131  // NewPrivateMinerAPI create a new RPC service which controls the miner of this node.
   132  func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI {
   133  	return &PrivateMinerAPI{e: e}
   134  }
   135  
   136  // Start the miner with the given number of threads. If threads is nil the number
   137  // of workers started is equal to the number of logical CPUs that are usable by
   138  // this process. If mining is already running, this method adjust the number of
   139  // threads allowed to use.
   140  func (api *PrivateMinerAPI) Start(threads *int) error {
   141  	// Set the number of threads if the seal engine supports it
   142  	if threads == nil {
   143  		threads = new(int)
   144  	} else if *threads == 0 {
   145  		*threads = -1 // Disable the miner from within
   146  	}
   147  	type threaded interface {
   148  		SetThreads(threads int)
   149  	}
   150  	if th, ok := api.e.engine.(threaded); ok {
   151  		log.Info("Updated mining threads", "threads", *threads)
   152  		th.SetThreads(*threads)
   153  	}
   154  	// Start the miner and return
   155  	if !api.e.IsMining() {
   156  		// Propagate the initial price point to the transaction pool
   157  		api.e.lock.RLock()
   158  		price := api.e.gasPrice
   159  		api.e.lock.RUnlock()
   160  
   161  		api.e.txPool.SetGasPrice(price)
   162  		return api.e.StartMining(true)
   163  	}
   164  	return nil
   165  }
   166  
   167  // Stop the miner
   168  func (api *PrivateMinerAPI) Stop() bool {
   169  	type threaded interface {
   170  		SetThreads(threads int)
   171  	}
   172  	if th, ok := api.e.engine.(threaded); ok {
   173  		th.SetThreads(-1)
   174  	}
   175  	api.e.StopMining()
   176  	return true
   177  }
   178  
   179  // SetExtra sets the extra data string that is included when this miner mines a block.
   180  func (api *PrivateMinerAPI) SetExtra(extra string) (bool, error) {
   181  	if err := api.e.Miner().SetExtra([]byte(extra)); err != nil {
   182  		return false, err
   183  	}
   184  	return true, nil
   185  }
   186  
   187  // SetGasPrice sets the minimum accepted gas price for the miner.
   188  func (api *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
   189  	api.e.lock.Lock()
   190  	api.e.gasPrice = (*big.Int)(&gasPrice)
   191  	api.e.lock.Unlock()
   192  
   193  	api.e.txPool.SetGasPrice((*big.Int)(&gasPrice))
   194  	return true
   195  }
   196  
   197  // SetEtherbase sets the etherbase of the miner
   198  func (api *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool {
   199  	api.e.SetEtherbase(etherbase)
   200  	return true
   201  }
   202  
   203  // GetHashrate returns the current hashrate of the miner.
   204  func (api *PrivateMinerAPI) GetHashrate() uint64 {
   205  	return uint64(api.e.miner.HashRate())
   206  }
   207  
   208  // PrivateAdminAPI is the collection of Etheruem full node-related APIs
   209  // exposed over the private admin endpoint.
   210  type PrivateAdminAPI struct {
   211  	eth *Ethereum
   212  }
   213  
   214  // NewPrivateAdminAPI creates a new API definition for the full node private
   215  // admin methods of the Ethereum service.
   216  func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI {
   217  	return &PrivateAdminAPI{eth: eth}
   218  }
   219  
   220  // ExportChain exports the current blockchain into a local file.
   221  func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
   222  	// Make sure we can create the file to export into
   223  	out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
   224  	if err != nil {
   225  		return false, err
   226  	}
   227  	defer out.Close()
   228  
   229  	var writer io.Writer = out
   230  	if strings.HasSuffix(file, ".gz") {
   231  		writer = gzip.NewWriter(writer)
   232  		defer writer.(*gzip.Writer).Close()
   233  	}
   234  
   235  	// Export the blockchain
   236  	if err := api.eth.BlockChain().Export(writer); err != nil {
   237  		return false, err
   238  	}
   239  	return true, nil
   240  }
   241  
   242  func hasAllBlocks(chain *core.BlockChain, bs []*types.Block) bool {
   243  	for _, b := range bs {
   244  		if !chain.HasBlock(b.Hash()) {
   245  			return false
   246  		}
   247  	}
   248  
   249  	return true
   250  }
   251  
   252  // ImportChain imports a blockchain from a local file.
   253  func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
   254  	// Make sure the can access the file to import
   255  	in, err := os.Open(file)
   256  	if err != nil {
   257  		return false, err
   258  	}
   259  	defer in.Close()
   260  
   261  	var reader io.Reader = in
   262  	if strings.HasSuffix(file, ".gz") {
   263  		if reader, err = gzip.NewReader(reader); err != nil {
   264  			return false, err
   265  		}
   266  	}
   267  
   268  	// Run actual the import in pre-configured batches
   269  	stream := rlp.NewStream(reader, 0)
   270  
   271  	blocks, index := make([]*types.Block, 0, 2500), 0
   272  	for batch := 0; ; batch++ {
   273  		// Load a batch of blocks from the input file
   274  		for len(blocks) < cap(blocks) {
   275  			block := new(types.Block)
   276  			if err := stream.Decode(block); err == io.EOF {
   277  				break
   278  			} else if err != nil {
   279  				return false, fmt.Errorf("block %d: failed to parse: %v", index, err)
   280  			}
   281  			blocks = append(blocks, block)
   282  			index++
   283  		}
   284  		if len(blocks) == 0 {
   285  			break
   286  		}
   287  
   288  		if hasAllBlocks(api.eth.BlockChain(), blocks) {
   289  			blocks = blocks[:0]
   290  			continue
   291  		}
   292  		// Import the batch and reset the buffer
   293  		if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil {
   294  			return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err)
   295  		}
   296  		blocks = blocks[:0]
   297  	}
   298  	return true, nil
   299  }
   300  
   301  // PublicDebugAPI is the collection of Etheruem full node APIs exposed
   302  // over the public debugging endpoint.
   303  type PublicDebugAPI struct {
   304  	eth *Ethereum
   305  }
   306  
   307  // NewPublicDebugAPI creates a new API definition for the full node-
   308  // related public debug methods of the Ethereum service.
   309  func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
   310  	return &PublicDebugAPI{eth: eth}
   311  }
   312  
   313  // DumpBlock retrieves the entire state of the database at a given block.
   314  func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
   315  	if blockNr == rpc.PendingBlockNumber {
   316  		// If we're dumping the pending state, we need to request
   317  		// both the pending block as well as the pending state from
   318  		// the miner and operate on those
   319  		_, stateDb := api.eth.miner.Pending()
   320  		return stateDb.RawDump(), nil
   321  	}
   322  	var block *types.Block
   323  	if blockNr == rpc.LatestBlockNumber {
   324  		block = api.eth.blockchain.CurrentBlock()
   325  	} else {
   326  		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
   327  	}
   328  	if block == nil {
   329  		return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
   330  	}
   331  	stateDb, err := api.eth.BlockChain().StateAt(block.Root())
   332  	if err != nil {
   333  		return state.Dump{}, err
   334  	}
   335  	return stateDb.RawDump(), nil
   336  }
   337  
   338  // PrivateDebugAPI is the collection of Etheruem full node APIs exposed over
   339  // the private debugging endpoint.
   340  type PrivateDebugAPI struct {
   341  	config *params.ChainConfig
   342  	eth    *Ethereum
   343  }
   344  
   345  // NewPrivateDebugAPI creates a new API definition for the full node-related
   346  // private debug methods of the Ethereum service.
   347  func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
   348  	return &PrivateDebugAPI{config: config, eth: eth}
   349  }
   350  
   351  // BlockTraceResult is the returned value when replaying a block to check for
   352  // consensus results and full VM trace logs for all included transactions.
   353  type BlockTraceResult struct {
   354  	Validated  bool                  `json:"validated"`
   355  	StructLogs []ethapi.StructLogRes `json:"structLogs"`
   356  	Error      string                `json:"error"`
   357  }
   358  
   359  // TraceArgs holds extra parameters to trace functions
   360  type TraceArgs struct {
   361  	*vm.LogConfig
   362  	Tracer  *string
   363  	Timeout *string
   364  }
   365  
   366  // TraceBlock processes the given block'api RLP but does not import the block in to
   367  // the chain.
   368  func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.LogConfig) BlockTraceResult {
   369  	var block types.Block
   370  	err := rlp.Decode(bytes.NewReader(blockRlp), &block)
   371  	if err != nil {
   372  		return BlockTraceResult{Error: fmt.Sprintf("could not decode block: %v", err)}
   373  	}
   374  
   375  	validated, logs, err := api.traceBlock(&block, config)
   376  	return BlockTraceResult{
   377  		Validated:  validated,
   378  		StructLogs: ethapi.FormatLogs(logs),
   379  		Error:      formatError(err),
   380  	}
   381  }
   382  
   383  // TraceBlockFromFile loads the block'api RLP from the given file name and attempts to
   384  // process it but does not import the block in to the chain.
   385  func (api *PrivateDebugAPI) TraceBlockFromFile(file string, config *vm.LogConfig) BlockTraceResult {
   386  	blockRlp, err := ioutil.ReadFile(file)
   387  	if err != nil {
   388  		return BlockTraceResult{Error: fmt.Sprintf("could not read file: %v", err)}
   389  	}
   390  	return api.TraceBlock(blockRlp, config)
   391  }
   392  
   393  // TraceBlockByNumber processes the block by canonical block number.
   394  func (api *PrivateDebugAPI) TraceBlockByNumber(blockNr rpc.BlockNumber, config *vm.LogConfig) BlockTraceResult {
   395  	// Fetch the block that we aim to reprocess
   396  	var block *types.Block
   397  	switch blockNr {
   398  	case rpc.PendingBlockNumber:
   399  		// Pending block is only known by the miner
   400  		block = api.eth.miner.PendingBlock()
   401  	case rpc.LatestBlockNumber:
   402  		block = api.eth.blockchain.CurrentBlock()
   403  	default:
   404  		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
   405  	}
   406  
   407  	if block == nil {
   408  		return BlockTraceResult{Error: fmt.Sprintf("block #%d not found", blockNr)}
   409  	}
   410  
   411  	validated, logs, err := api.traceBlock(block, config)
   412  	return BlockTraceResult{
   413  		Validated:  validated,
   414  		StructLogs: ethapi.FormatLogs(logs),
   415  		Error:      formatError(err),
   416  	}
   417  }
   418  
   419  // TraceBlockByHash processes the block by hash.
   420  func (api *PrivateDebugAPI) TraceBlockByHash(hash common.Hash, config *vm.LogConfig) BlockTraceResult {
   421  	// Fetch the block that we aim to reprocess
   422  	block := api.eth.BlockChain().GetBlockByHash(hash)
   423  	if block == nil {
   424  		return BlockTraceResult{Error: fmt.Sprintf("block #%x not found", hash)}
   425  	}
   426  
   427  	validated, logs, err := api.traceBlock(block, config)
   428  	return BlockTraceResult{
   429  		Validated:  validated,
   430  		StructLogs: ethapi.FormatLogs(logs),
   431  		Error:      formatError(err),
   432  	}
   433  }
   434  
   435  // traceBlock processes the given block but does not save the state.
   436  func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConfig) (bool, []vm.StructLog, error) {
   437  	// Validate and reprocess the block
   438  	var (
   439  		blockchain = api.eth.BlockChain()
   440  		validator  = blockchain.Validator()
   441  		processor  = blockchain.Processor()
   442  	)
   443  
   444  	structLogger := vm.NewStructLogger(logConfig)
   445  
   446  	config := vm.Config{
   447  		Debug:  true,
   448  		Tracer: structLogger,
   449  	}
   450  	if err := api.eth.engine.VerifyHeader(blockchain, block.Header(), true); err != nil {
   451  		return false, structLogger.StructLogs(), err
   452  	}
   453  	statedb, err := blockchain.StateAt(blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1).Root())
   454  	if err != nil {
   455  		return false, structLogger.StructLogs(), err
   456  	}
   457  
   458  	receipts, _, usedGas, err := processor.Process(block, statedb, config)
   459  	if err != nil {
   460  		return false, structLogger.StructLogs(), err
   461  	}
   462  	if err := validator.ValidateState(block, blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1), statedb, receipts, usedGas); err != nil {
   463  		return false, structLogger.StructLogs(), err
   464  	}
   465  	return true, structLogger.StructLogs(), nil
   466  }
   467  
   468  // callmsg is the message type used for call transitions.
   469  type callmsg struct {
   470  	addr          common.Address
   471  	to            *common.Address
   472  	gas, gasPrice *big.Int
   473  	value         *big.Int
   474  	data          []byte
   475  }
   476  
   477  // accessor boilerplate to implement core.Message
   478  func (m callmsg) From() (common.Address, error)         { return m.addr, nil }
   479  func (m callmsg) FromFrontier() (common.Address, error) { return m.addr, nil }
   480  func (m callmsg) Nonce() uint64                         { return 0 }
   481  func (m callmsg) CheckNonce() bool                      { return false }
   482  func (m callmsg) To() *common.Address                   { return m.to }
   483  func (m callmsg) GasPrice() *big.Int                    { return m.gasPrice }
   484  func (m callmsg) Gas() *big.Int                         { return m.gas }
   485  func (m callmsg) Value() *big.Int                       { return m.value }
   486  func (m callmsg) Data() []byte                          { return m.data }
   487  
   488  // formatError formats a Go error into either an empty string or the data content
   489  // of the error itself.
   490  func formatError(err error) string {
   491  	if err == nil {
   492  		return ""
   493  	}
   494  	return err.Error()
   495  }
   496  
   497  type timeoutError struct{}
   498  
   499  func (t *timeoutError) Error() string {
   500  	return "Execution time exceeded"
   501  }
   502  
   503  // TraceTransaction returns the structured logs created during the execution of EVM
   504  // and returns them as a JSON object.
   505  func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.Hash, config *TraceArgs) (interface{}, error) {
   506  	var tracer vm.Tracer
   507  	if config != nil && config.Tracer != nil {
   508  		timeout := defaultTraceTimeout
   509  		if config.Timeout != nil {
   510  			var err error
   511  			if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
   512  				return nil, err
   513  			}
   514  		}
   515  
   516  		var err error
   517  		if tracer, err = ethapi.NewJavascriptTracer(*config.Tracer); err != nil {
   518  			return nil, err
   519  		}
   520  
   521  		// Handle timeouts and RPC cancellations
   522  		deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
   523  		go func() {
   524  			<-deadlineCtx.Done()
   525  			tracer.(*ethapi.JavascriptTracer).Stop(&timeoutError{})
   526  		}()
   527  		defer cancel()
   528  	} else if config == nil {
   529  		tracer = vm.NewStructLogger(nil)
   530  	} else {
   531  		tracer = vm.NewStructLogger(config.LogConfig)
   532  	}
   533  
   534  	// Retrieve the tx from the chain and the containing block
   535  	tx, blockHash, _, txIndex := core.GetTransaction(api.eth.ChainDb(), txHash)
   536  	if tx == nil {
   537  		return nil, fmt.Errorf("transaction %x not found", txHash)
   538  	}
   539  	msg, context, statedb, err := api.computeTxEnv(blockHash, int(txIndex))
   540  	if err != nil {
   541  		return nil, err
   542  	}
   543  
   544  	// Run the transaction with tracing enabled.
   545  	vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{Debug: true, Tracer: tracer})
   546  	ret, gas, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
   547  	if err != nil {
   548  		return nil, fmt.Errorf("tracing failed: %v", err)
   549  	}
   550  	switch tracer := tracer.(type) {
   551  	case *vm.StructLogger:
   552  		return &ethapi.ExecutionResult{
   553  			Gas:         gas,
   554  			ReturnValue: fmt.Sprintf("%x", ret),
   555  			StructLogs:  ethapi.FormatLogs(tracer.StructLogs()),
   556  		}, nil
   557  	case *ethapi.JavascriptTracer:
   558  		return tracer.GetResult()
   559  	default:
   560  		panic(fmt.Sprintf("bad tracer type %T", tracer))
   561  	}
   562  }
   563  
   564  // computeTxEnv returns the execution environment of a certain transaction.
   565  func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int) (core.Message, vm.Context, *state.StateDB, error) {
   566  	// Create the parent state.
   567  	block := api.eth.BlockChain().GetBlockByHash(blockHash)
   568  	if block == nil {
   569  		return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash)
   570  	}
   571  	parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1)
   572  	if parent == nil {
   573  		return nil, vm.Context{}, nil, fmt.Errorf("block parent %x not found", block.ParentHash())
   574  	}
   575  	statedb, err := api.eth.BlockChain().StateAt(parent.Root())
   576  	if err != nil {
   577  		return nil, vm.Context{}, nil, err
   578  	}
   579  	txs := block.Transactions()
   580  
   581  	// Recompute transactions up to the target index.
   582  	signer := types.MakeSigner(api.config, block.Number())
   583  	for idx, tx := range txs {
   584  		// Assemble the transaction call message
   585  		msg, _ := tx.AsMessage(signer)
   586  		context := core.NewEVMContext(msg, block.Header(), api.eth.BlockChain(), nil)
   587  		if idx == txIndex {
   588  			return msg, context, statedb, nil
   589  		}
   590  
   591  		vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
   592  		gp := new(core.GasPool).AddGas(tx.Gas())
   593  		_, _, err := core.ApplyMessage(vmenv, msg, gp)
   594  		if err != nil {
   595  			return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
   596  		}
   597  		statedb.DeleteSuicides()
   598  	}
   599  	return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
   600  }
   601  
   602  // Preimage is a debug API function that returns the preimage for a sha3 hash, if known.
   603  func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
   604  	db := core.PreimageTable(api.eth.ChainDb())
   605  	return db.Get(hash.Bytes())
   606  }
   607  
   608  // GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network
   609  // and returns them as a JSON list of block-hashes
   610  func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]core.BadBlockArgs, error) {
   611  	return api.eth.BlockChain().BadBlocks()
   612  }
   613  
   614  // StorageRangeResult is the result of a debug_storageRangeAt API call.
   615  type StorageRangeResult struct {
   616  	Storage storageMap   `json:"storage"`
   617  	NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie.
   618  }
   619  
   620  type storageMap map[common.Hash]storageEntry
   621  
   622  type storageEntry struct {
   623  	Key   *common.Hash `json:"key"`
   624  	Value common.Hash  `json:"value"`
   625  }
   626  
   627  // StorageRangeAt returns the storage at the given block height and transaction index.
   628  func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) {
   629  	_, _, statedb, err := api.computeTxEnv(blockHash, txIndex)
   630  	if err != nil {
   631  		return StorageRangeResult{}, err
   632  	}
   633  	st := statedb.StorageTrie(contractAddress)
   634  	if st == nil {
   635  		return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress)
   636  	}
   637  	return storageRangeAt(st, keyStart, maxResult), nil
   638  }
   639  
   640  func storageRangeAt(st *trie.SecureTrie, start []byte, maxResult int) StorageRangeResult {
   641  	it := trie.NewIterator(st.NodeIterator(start))
   642  	result := StorageRangeResult{Storage: storageMap{}}
   643  	for i := 0; i < maxResult && it.Next(); i++ {
   644  		e := storageEntry{Value: common.BytesToHash(it.Value)}
   645  		if preimage := st.GetKey(it.Key); preimage != nil {
   646  			preimage := common.BytesToHash(preimage)
   647  			e.Key = &preimage
   648  		}
   649  		result.Storage[common.BytesToHash(it.Key)] = e
   650  	}
   651  	// Add the 'next key' so clients can continue downloading.
   652  	if it.Next() {
   653  		next := common.BytesToHash(it.Key)
   654  		result.NextKey = &next
   655  	}
   656  	return result
   657  }