github.com/halybang/go-ethereum@v1.0.5-0.20180325041310-3b262bc1367c/eth/api.go (about)

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