github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/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 Ethereum 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 Ethereum 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(), b.NumberU64()) {
   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 Ethereum 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, typ string) (state.Dump, error) {
   315  	var publicState, privateState *state.StateDB
   316  	var err error
   317  	if blockNr == rpc.PendingBlockNumber {
   318  		// If we're dumping the pending state, we need to request
   319  		// both the pending block as well as the pending state from
   320  		// the miner and operate on those
   321  		_, publicState, privateState = api.eth.miner.Pending()
   322  	} else {
   323  		var block *types.Block
   324  		if blockNr == rpc.LatestBlockNumber {
   325  			block = api.eth.blockchain.CurrentBlock()
   326  		} else {
   327  			block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
   328  		}
   329  		if block == nil {
   330  			return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
   331  		}
   332  		publicState, privateState, err = api.eth.BlockChain().StateAt(block.Root())
   333  		if err != nil {
   334  			return state.Dump{}, err
   335  		}
   336  	}
   337  
   338  	switch typ {
   339  	case "public":
   340  		return publicState.RawDump(), nil
   341  	case "private":
   342  		return privateState.RawDump(), nil
   343  	default:
   344  		return state.Dump{}, fmt.Errorf("unknown type: '%s'", typ)
   345  	}
   346  }
   347  
   348  // PrivateDebugAPI is the collection of Ethereum full node APIs exposed over
   349  // the private debugging endpoint.
   350  type PrivateDebugAPI struct {
   351  	config *params.ChainConfig
   352  	eth    *Ethereum
   353  }
   354  
   355  // NewPrivateDebugAPI creates a new API definition for the full node-related
   356  // private debug methods of the Ethereum service.
   357  func NewPrivateDebugAPI(config *params.ChainConfig, eth *Ethereum) *PrivateDebugAPI {
   358  	return &PrivateDebugAPI{config: config, eth: eth}
   359  }
   360  
   361  // BlockTraceResult is the returned value when replaying a block to check for
   362  // consensus results and full VM trace logs for all included transactions.
   363  type BlockTraceResult struct {
   364  	Validated  bool                  `json:"validated"`
   365  	StructLogs []ethapi.StructLogRes `json:"structLogs"`
   366  	Error      string                `json:"error"`
   367  }
   368  
   369  // TraceArgs holds extra parameters to trace functions
   370  type TraceArgs struct {
   371  	*vm.LogConfig
   372  	Tracer  *string
   373  	Timeout *string
   374  }
   375  
   376  // TraceBlock processes the given block'api RLP but does not import the block in to
   377  // the chain.
   378  func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.LogConfig) BlockTraceResult {
   379  	var block types.Block
   380  	err := rlp.Decode(bytes.NewReader(blockRlp), &block)
   381  	if err != nil {
   382  		return BlockTraceResult{Error: fmt.Sprintf("could not decode block: %v", err)}
   383  	}
   384  
   385  	validated, logs, err := api.traceBlock(&block, config)
   386  	return BlockTraceResult{
   387  		Validated:  validated,
   388  		StructLogs: ethapi.FormatLogs(logs),
   389  		Error:      formatError(err),
   390  	}
   391  }
   392  
   393  // TraceBlockFromFile loads the block'api RLP from the given file name and attempts to
   394  // process it but does not import the block in to the chain.
   395  func (api *PrivateDebugAPI) TraceBlockFromFile(file string, config *vm.LogConfig) BlockTraceResult {
   396  	blockRlp, err := ioutil.ReadFile(file)
   397  	if err != nil {
   398  		return BlockTraceResult{Error: fmt.Sprintf("could not read file: %v", err)}
   399  	}
   400  	return api.TraceBlock(blockRlp, config)
   401  }
   402  
   403  // TraceBlockByNumber processes the block by canonical block number.
   404  func (api *PrivateDebugAPI) TraceBlockByNumber(blockNr rpc.BlockNumber, config *vm.LogConfig) BlockTraceResult {
   405  	// Fetch the block that we aim to reprocess
   406  	var block *types.Block
   407  	switch blockNr {
   408  	case rpc.PendingBlockNumber:
   409  		// Pending block is only known by the miner
   410  		block = api.eth.miner.PendingBlock()
   411  	case rpc.LatestBlockNumber:
   412  		block = api.eth.blockchain.CurrentBlock()
   413  	default:
   414  		block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
   415  	}
   416  
   417  	if block == nil {
   418  		return BlockTraceResult{Error: fmt.Sprintf("block #%d not found", blockNr)}
   419  	}
   420  
   421  	validated, logs, err := api.traceBlock(block, config)
   422  	return BlockTraceResult{
   423  		Validated:  validated,
   424  		StructLogs: ethapi.FormatLogs(logs),
   425  		Error:      formatError(err),
   426  	}
   427  }
   428  
   429  // TraceBlockByHash processes the block by hash.
   430  func (api *PrivateDebugAPI) TraceBlockByHash(hash common.Hash, config *vm.LogConfig) BlockTraceResult {
   431  	// Fetch the block that we aim to reprocess
   432  	block := api.eth.BlockChain().GetBlockByHash(hash)
   433  	if block == nil {
   434  		return BlockTraceResult{Error: fmt.Sprintf("block #%x not found", hash)}
   435  	}
   436  
   437  	validated, logs, err := api.traceBlock(block, config)
   438  	return BlockTraceResult{
   439  		Validated:  validated,
   440  		StructLogs: ethapi.FormatLogs(logs),
   441  		Error:      formatError(err),
   442  	}
   443  }
   444  
   445  // traceBlock processes the given block but does not save the state.
   446  func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConfig) (bool, []vm.StructLog, error) {
   447  	// Validate and reprocess the block
   448  	var (
   449  		blockchain = api.eth.BlockChain()
   450  		validator  = blockchain.Validator()
   451  		processor  = blockchain.Processor()
   452  	)
   453  
   454  	structLogger := vm.NewStructLogger(logConfig)
   455  
   456  	config := vm.Config{
   457  		Debug:  true,
   458  		Tracer: structLogger,
   459  	}
   460  	if err := api.eth.engine.VerifyHeader(blockchain, block.Header(), true); err != nil {
   461  		return false, structLogger.StructLogs(), err
   462  	}
   463  	statedb, privateStateDb, err := blockchain.StateAt(blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1).Root())
   464  	if err != nil {
   465  		return false, structLogger.StructLogs(), err
   466  	}
   467  
   468  	receipts, _, _, usedGas, err := processor.Process(block, statedb, privateStateDb, config)
   469  	if err != nil {
   470  		return false, structLogger.StructLogs(), err
   471  	}
   472  	if err := validator.ValidateState(block, blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1), statedb, receipts, usedGas); err != nil {
   473  		return false, structLogger.StructLogs(), err
   474  	}
   475  	return true, structLogger.StructLogs(), nil
   476  }
   477  
   478  // formatError formats a Go error into either an empty string or the data content
   479  // of the error itself.
   480  func formatError(err error) string {
   481  	if err == nil {
   482  		return ""
   483  	}
   484  	return err.Error()
   485  }
   486  
   487  type timeoutError struct{}
   488  
   489  func (t *timeoutError) Error() string {
   490  	return "Execution time exceeded"
   491  }
   492  
   493  // TraceTransaction returns the structured logs created during the execution of EVM
   494  // and returns them as a JSON object.
   495  func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.Hash, config *TraceArgs) (interface{}, error) {
   496  	var tracer vm.Tracer
   497  	if config != nil && config.Tracer != nil {
   498  		timeout := defaultTraceTimeout
   499  		if config.Timeout != nil {
   500  			var err error
   501  			if timeout, err = time.ParseDuration(*config.Timeout); err != nil {
   502  				return nil, err
   503  			}
   504  		}
   505  
   506  		var err error
   507  		if tracer, err = ethapi.NewJavascriptTracer(*config.Tracer); err != nil {
   508  			return nil, err
   509  		}
   510  
   511  		// Handle timeouts and RPC cancellations
   512  		deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
   513  		go func() {
   514  			<-deadlineCtx.Done()
   515  			tracer.(*ethapi.JavascriptTracer).Stop(&timeoutError{})
   516  		}()
   517  		defer cancel()
   518  	} else if config == nil {
   519  		tracer = vm.NewStructLogger(nil)
   520  	} else {
   521  		tracer = vm.NewStructLogger(config.LogConfig)
   522  	}
   523  
   524  	// Retrieve the tx from the chain and the containing block
   525  	tx, blockHash, _, txIndex := core.GetTransaction(api.eth.ChainDb(), txHash)
   526  	if tx == nil {
   527  		return nil, fmt.Errorf("transaction %x not found", txHash)
   528  	}
   529  	msg, context, statedb, privateStateDb, err := api.computeTxEnv(blockHash, int(txIndex))
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  
   534  	// Run the transaction with tracing enabled.
   535  	vmenv := vm.NewEVM(context, statedb, privateStateDb, api.config, vm.Config{Debug: true, Tracer: tracer})
   536  	ret, gas, failed, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
   537  	if err != nil {
   538  		return nil, fmt.Errorf("tracing failed: %v", err)
   539  	}
   540  	switch tracer := tracer.(type) {
   541  	case *vm.StructLogger:
   542  		return &ethapi.ExecutionResult{
   543  			Gas:         gas,
   544  			Failed:      failed,
   545  			ReturnValue: fmt.Sprintf("%x", ret),
   546  			StructLogs:  ethapi.FormatLogs(tracer.StructLogs()),
   547  		}, nil
   548  	case *ethapi.JavascriptTracer:
   549  		return tracer.GetResult()
   550  	default:
   551  		panic(fmt.Sprintf("bad tracer type %T", tracer))
   552  	}
   553  }
   554  
   555  // computeTxEnv returns the execution environment of a certain transaction.
   556  func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int) (core.Message, vm.Context, *state.StateDB, *state.StateDB, error) {
   557  	// Create the parent state.
   558  	block := api.eth.BlockChain().GetBlockByHash(blockHash)
   559  	if block == nil {
   560  		return nil, vm.Context{}, nil, nil, fmt.Errorf("block %x not found", blockHash)
   561  	}
   562  	parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1)
   563  	if parent == nil {
   564  		return nil, vm.Context{}, nil, nil, fmt.Errorf("block parent %x not found", block.ParentHash())
   565  	}
   566  	statedb, privateStateDb, err := api.eth.BlockChain().StateAt(parent.Root())
   567  	if err != nil {
   568  		return nil, vm.Context{}, nil, nil, err
   569  	}
   570  	txs := block.Transactions()
   571  
   572  	// Recompute transactions up to the target index.
   573  	signer := types.MakeSigner(api.config, block.Number())
   574  	for idx, tx := range txs {
   575  		// Assemble the transaction call message
   576  		msg, _ := tx.AsMessage(signer)
   577  		context := core.NewEVMContext(msg, block.Header(), api.eth.BlockChain(), nil)
   578  		if idx == txIndex {
   579  			return msg, context, statedb, privateStateDb, nil
   580  		}
   581  
   582  		vmenv := vm.NewEVM(context, statedb, privateStateDb, api.config, vm.Config{})
   583  		gp := new(core.GasPool).AddGas(tx.Gas())
   584  		_, _, _, err := core.ApplyMessage(vmenv, msg, gp)
   585  		if err != nil {
   586  			return nil, vm.Context{}, nil, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
   587  		}
   588  		statedb.DeleteSuicides()
   589  	}
   590  	return nil, vm.Context{}, nil, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash)
   591  }
   592  
   593  // Preimage is a debug API function that returns the preimage for a sha3 hash, if known.
   594  func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
   595  	db := core.PreimageTable(api.eth.ChainDb())
   596  	return db.Get(hash.Bytes())
   597  }
   598  
   599  // GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network
   600  // and returns them as a JSON list of block-hashes
   601  func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]core.BadBlockArgs, error) {
   602  	return api.eth.BlockChain().BadBlocks()
   603  }
   604  
   605  // StorageRangeResult is the result of a debug_storageRangeAt API call.
   606  type StorageRangeResult struct {
   607  	Storage storageMap   `json:"storage"`
   608  	NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie.
   609  }
   610  
   611  type storageMap map[common.Hash]storageEntry
   612  
   613  type storageEntry struct {
   614  	Key   *common.Hash `json:"key"`
   615  	Value common.Hash  `json:"value"`
   616  }
   617  
   618  // StorageRangeAt returns the storage at the given block height and transaction index.
   619  func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) {
   620  	// XXX private state?
   621  	_, _, _, statedb, err := api.computeTxEnv(blockHash, txIndex)
   622  	if err != nil {
   623  		return StorageRangeResult{}, err
   624  	}
   625  	st := statedb.StorageTrie(contractAddress)
   626  	if st == nil {
   627  		return StorageRangeResult{}, fmt.Errorf("account %x doesn't exist", contractAddress)
   628  	}
   629  	return storageRangeAt(st, keyStart, maxResult), nil
   630  }
   631  
   632  func storageRangeAt(st state.Trie, start []byte, maxResult int) StorageRangeResult {
   633  	it := trie.NewIterator(st.NodeIterator(start))
   634  	result := StorageRangeResult{Storage: storageMap{}}
   635  	for i := 0; i < maxResult && it.Next(); i++ {
   636  		e := storageEntry{Value: common.BytesToHash(it.Value)}
   637  		if preimage := st.GetKey(it.Key); preimage != nil {
   638  			preimage := common.BytesToHash(preimage)
   639  			e.Key = &preimage
   640  		}
   641  		result.Storage[common.BytesToHash(it.Key)] = e
   642  	}
   643  	// Add the 'next key' so clients can continue downloading.
   644  	if it.Next() {
   645  		next := common.BytesToHash(it.Key)
   646  		result.NextKey = &next
   647  	}
   648  	return result
   649  }