github.com/ethereum-optimism/optimism/l2geth@v0.0.0-20230612200230-50b04ade19e3/cmd/geth/retesteth.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"math/big"
    24  	"os"
    25  	"os/signal"
    26  	"strings"
    27  	"time"
    28  
    29  	"github.com/ethereum-optimism/optimism/l2geth/cmd/utils"
    30  	"github.com/ethereum-optimism/optimism/l2geth/common"
    31  	"github.com/ethereum-optimism/optimism/l2geth/common/hexutil"
    32  	"github.com/ethereum-optimism/optimism/l2geth/common/math"
    33  	"github.com/ethereum-optimism/optimism/l2geth/consensus"
    34  	"github.com/ethereum-optimism/optimism/l2geth/consensus/ethash"
    35  	"github.com/ethereum-optimism/optimism/l2geth/consensus/misc"
    36  	"github.com/ethereum-optimism/optimism/l2geth/core"
    37  	"github.com/ethereum-optimism/optimism/l2geth/core/rawdb"
    38  	"github.com/ethereum-optimism/optimism/l2geth/core/state"
    39  	"github.com/ethereum-optimism/optimism/l2geth/core/types"
    40  	"github.com/ethereum-optimism/optimism/l2geth/core/vm"
    41  	"github.com/ethereum-optimism/optimism/l2geth/crypto"
    42  	"github.com/ethereum-optimism/optimism/l2geth/ethdb"
    43  	"github.com/ethereum-optimism/optimism/l2geth/log"
    44  	"github.com/ethereum-optimism/optimism/l2geth/node"
    45  	"github.com/ethereum-optimism/optimism/l2geth/params"
    46  	"github.com/ethereum-optimism/optimism/l2geth/rlp"
    47  	"github.com/ethereum-optimism/optimism/l2geth/rpc"
    48  	"github.com/ethereum-optimism/optimism/l2geth/trie"
    49  
    50  	cli "gopkg.in/urfave/cli.v1"
    51  )
    52  
    53  var (
    54  	rpcPortFlag = cli.IntFlag{
    55  		Name:  "rpcport",
    56  		Usage: "HTTP-RPC server listening port",
    57  		Value: node.DefaultHTTPPort,
    58  	}
    59  	retestethCommand = cli.Command{
    60  		Action:      utils.MigrateFlags(retesteth),
    61  		Name:        "retesteth",
    62  		Usage:       "Launches geth in retesteth mode",
    63  		ArgsUsage:   "",
    64  		Flags:       []cli.Flag{rpcPortFlag},
    65  		Category:    "MISCELLANEOUS COMMANDS",
    66  		Description: `Launches geth in retesteth mode (no database, no network, only retesteth RPC interface)`,
    67  	}
    68  )
    69  
    70  type RetestethTestAPI interface {
    71  	SetChainParams(ctx context.Context, chainParams ChainParams) (bool, error)
    72  	MineBlocks(ctx context.Context, number uint64) (bool, error)
    73  	ModifyTimestamp(ctx context.Context, interval uint64) (bool, error)
    74  	ImportRawBlock(ctx context.Context, rawBlock hexutil.Bytes) (common.Hash, error)
    75  	RewindToBlock(ctx context.Context, number uint64) (bool, error)
    76  	GetLogHash(ctx context.Context, txHash common.Hash) (common.Hash, error)
    77  }
    78  
    79  type RetestethEthAPI interface {
    80  	SendRawTransaction(ctx context.Context, rawTx hexutil.Bytes) (common.Hash, error)
    81  	BlockNumber(ctx context.Context) (uint64, error)
    82  	GetBlockByNumber(ctx context.Context, blockNr math.HexOrDecimal64, fullTx bool) (map[string]interface{}, error)
    83  	GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error)
    84  	GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error)
    85  	GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error)
    86  }
    87  
    88  type RetestethDebugAPI interface {
    89  	AccountRange(ctx context.Context,
    90  		blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
    91  		addressHash *math.HexOrDecimal256, maxResults uint64,
    92  	) (AccountRangeResult, error)
    93  	StorageRangeAt(ctx context.Context,
    94  		blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
    95  		address common.Address,
    96  		begin *math.HexOrDecimal256, maxResults uint64,
    97  	) (StorageRangeResult, error)
    98  }
    99  
   100  type RetestWeb3API interface {
   101  	ClientVersion(ctx context.Context) (string, error)
   102  }
   103  
   104  type RetestethAPI struct {
   105  	ethDb         ethdb.Database
   106  	db            state.Database
   107  	chainConfig   *params.ChainConfig
   108  	author        common.Address
   109  	extraData     []byte
   110  	genesisHash   common.Hash
   111  	engine        *NoRewardEngine
   112  	blockchain    *core.BlockChain
   113  	blockNumber   uint64
   114  	txMap         map[common.Address]map[uint64]*types.Transaction // Sender -> Nonce -> Transaction
   115  	txSenders     map[common.Address]struct{}                      // Set of transaction senders
   116  	blockInterval uint64
   117  }
   118  
   119  type ChainParams struct {
   120  	SealEngine string                            `json:"sealEngine"`
   121  	Params     CParamsParams                     `json:"params"`
   122  	Genesis    CParamsGenesis                    `json:"genesis"`
   123  	Accounts   map[common.Address]CParamsAccount `json:"accounts"`
   124  }
   125  
   126  type CParamsParams struct {
   127  	AccountStartNonce          math.HexOrDecimal64   `json:"accountStartNonce"`
   128  	HomesteadForkBlock         *math.HexOrDecimal64  `json:"homesteadForkBlock"`
   129  	EIP150ForkBlock            *math.HexOrDecimal64  `json:"EIP150ForkBlock"`
   130  	EIP158ForkBlock            *math.HexOrDecimal64  `json:"EIP158ForkBlock"`
   131  	DaoHardforkBlock           *math.HexOrDecimal64  `json:"daoHardforkBlock"`
   132  	ByzantiumForkBlock         *math.HexOrDecimal64  `json:"byzantiumForkBlock"`
   133  	ConstantinopleForkBlock    *math.HexOrDecimal64  `json:"constantinopleForkBlock"`
   134  	ConstantinopleFixForkBlock *math.HexOrDecimal64  `json:"constantinopleFixForkBlock"`
   135  	IstanbulBlock              *math.HexOrDecimal64  `json:"istanbulForkBlock"`
   136  	ChainID                    *math.HexOrDecimal256 `json:"chainID"`
   137  	MaximumExtraDataSize       math.HexOrDecimal64   `json:"maximumExtraDataSize"`
   138  	TieBreakingGas             bool                  `json:"tieBreakingGas"`
   139  	MinGasLimit                math.HexOrDecimal64   `json:"minGasLimit"`
   140  	MaxGasLimit                math.HexOrDecimal64   `json:"maxGasLimit"`
   141  	GasLimitBoundDivisor       math.HexOrDecimal64   `json:"gasLimitBoundDivisor"`
   142  	MinimumDifficulty          math.HexOrDecimal256  `json:"minimumDifficulty"`
   143  	DifficultyBoundDivisor     math.HexOrDecimal256  `json:"difficultyBoundDivisor"`
   144  	DurationLimit              math.HexOrDecimal256  `json:"durationLimit"`
   145  	BlockReward                math.HexOrDecimal256  `json:"blockReward"`
   146  	NetworkID                  math.HexOrDecimal256  `json:"networkID"`
   147  }
   148  
   149  type CParamsGenesis struct {
   150  	Nonce      math.HexOrDecimal64   `json:"nonce"`
   151  	Difficulty *math.HexOrDecimal256 `json:"difficulty"`
   152  	MixHash    *math.HexOrDecimal256 `json:"mixHash"`
   153  	Author     common.Address        `json:"author"`
   154  	Timestamp  math.HexOrDecimal64   `json:"timestamp"`
   155  	ParentHash common.Hash           `json:"parentHash"`
   156  	ExtraData  hexutil.Bytes         `json:"extraData"`
   157  	GasLimit   math.HexOrDecimal64   `json:"gasLimit"`
   158  }
   159  
   160  type CParamsAccount struct {
   161  	Balance     *math.HexOrDecimal256 `json:"balance"`
   162  	Precompiled *CPAccountPrecompiled `json:"precompiled"`
   163  	Code        hexutil.Bytes         `json:"code"`
   164  	Storage     map[string]string     `json:"storage"`
   165  	Nonce       *math.HexOrDecimal64  `json:"nonce"`
   166  }
   167  
   168  type CPAccountPrecompiled struct {
   169  	Name          string                `json:"name"`
   170  	StartingBlock math.HexOrDecimal64   `json:"startingBlock"`
   171  	Linear        *CPAPrecompiledLinear `json:"linear"`
   172  }
   173  
   174  type CPAPrecompiledLinear struct {
   175  	Base uint64 `json:"base"`
   176  	Word uint64 `json:"word"`
   177  }
   178  
   179  type AccountRangeResult struct {
   180  	AddressMap map[common.Hash]common.Address `json:"addressMap"`
   181  	NextKey    common.Hash                    `json:"nextKey"`
   182  }
   183  
   184  type StorageRangeResult struct {
   185  	Complete bool                   `json:"complete"`
   186  	Storage  map[common.Hash]SRItem `json:"storage"`
   187  }
   188  
   189  type SRItem struct {
   190  	Key   string `json:"key"`
   191  	Value string `json:"value"`
   192  }
   193  
   194  type NoRewardEngine struct {
   195  	inner     consensus.Engine
   196  	rewardsOn bool
   197  }
   198  
   199  func (e *NoRewardEngine) Author(header *types.Header) (common.Address, error) {
   200  	return e.inner.Author(header)
   201  }
   202  
   203  func (e *NoRewardEngine) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   204  	return e.inner.VerifyHeader(chain, header, seal)
   205  }
   206  
   207  func (e *NoRewardEngine) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   208  	return e.inner.VerifyHeaders(chain, headers, seals)
   209  }
   210  
   211  func (e *NoRewardEngine) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   212  	return e.inner.VerifyUncles(chain, block)
   213  }
   214  
   215  func (e *NoRewardEngine) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   216  	return e.inner.VerifySeal(chain, header)
   217  }
   218  
   219  func (e *NoRewardEngine) Prepare(chain consensus.ChainReader, header *types.Header) error {
   220  	return e.inner.Prepare(chain, header)
   221  }
   222  
   223  func (e *NoRewardEngine) accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
   224  	// Simply touch miner and uncle coinbase accounts
   225  	reward := big.NewInt(0)
   226  	for _, uncle := range uncles {
   227  		state.AddBalance(uncle.Coinbase, reward)
   228  	}
   229  	state.AddBalance(header.Coinbase, reward)
   230  }
   231  
   232  func (e *NoRewardEngine) Finalize(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction,
   233  	uncles []*types.Header) {
   234  	if e.rewardsOn {
   235  		e.inner.Finalize(chain, header, statedb, txs, uncles)
   236  	} else {
   237  		e.accumulateRewards(chain.Config(), statedb, header, uncles)
   238  		header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   239  	}
   240  }
   241  
   242  func (e *NoRewardEngine) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, statedb *state.StateDB, txs []*types.Transaction,
   243  	uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
   244  	if e.rewardsOn {
   245  		return e.inner.FinalizeAndAssemble(chain, header, statedb, txs, uncles, receipts)
   246  	} else {
   247  		e.accumulateRewards(chain.Config(), statedb, header, uncles)
   248  		header.Root = statedb.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   249  
   250  		// Header seems complete, assemble into a block and return
   251  		return types.NewBlock(header, txs, uncles, receipts), nil
   252  	}
   253  }
   254  
   255  func (e *NoRewardEngine) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
   256  	return e.inner.Seal(chain, block, results, stop)
   257  }
   258  
   259  func (e *NoRewardEngine) SealHash(header *types.Header) common.Hash {
   260  	return e.inner.SealHash(header)
   261  }
   262  
   263  func (e *NoRewardEngine) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   264  	return e.inner.CalcDifficulty(chain, time, parent)
   265  }
   266  
   267  func (e *NoRewardEngine) APIs(chain consensus.ChainReader) []rpc.API {
   268  	return e.inner.APIs(chain)
   269  }
   270  
   271  func (e *NoRewardEngine) Close() error {
   272  	return e.inner.Close()
   273  }
   274  
   275  func (api *RetestethAPI) SetChainParams(ctx context.Context, chainParams ChainParams) (bool, error) {
   276  	// Clean up
   277  	if api.blockchain != nil {
   278  		api.blockchain.Stop()
   279  	}
   280  	if api.engine != nil {
   281  		api.engine.Close()
   282  	}
   283  	if api.ethDb != nil {
   284  		api.ethDb.Close()
   285  	}
   286  	ethDb := rawdb.NewMemoryDatabase()
   287  	accounts := make(core.GenesisAlloc)
   288  	for address, account := range chainParams.Accounts {
   289  		balance := big.NewInt(0)
   290  		if account.Balance != nil {
   291  			balance.Set((*big.Int)(account.Balance))
   292  		}
   293  		var nonce uint64
   294  		if account.Nonce != nil {
   295  			nonce = uint64(*account.Nonce)
   296  		}
   297  		if account.Precompiled == nil || account.Balance != nil {
   298  			storage := make(map[common.Hash]common.Hash)
   299  			for k, v := range account.Storage {
   300  				storage[common.HexToHash(k)] = common.HexToHash(v)
   301  			}
   302  			accounts[address] = core.GenesisAccount{
   303  				Balance: balance,
   304  				Code:    account.Code,
   305  				Nonce:   nonce,
   306  				Storage: storage,
   307  			}
   308  		}
   309  	}
   310  	chainId := big.NewInt(1)
   311  	if chainParams.Params.ChainID != nil {
   312  		chainId.Set((*big.Int)(chainParams.Params.ChainID))
   313  	}
   314  	var (
   315  		homesteadBlock      *big.Int
   316  		daoForkBlock        *big.Int
   317  		eip150Block         *big.Int
   318  		eip155Block         *big.Int
   319  		eip158Block         *big.Int
   320  		byzantiumBlock      *big.Int
   321  		constantinopleBlock *big.Int
   322  		petersburgBlock     *big.Int
   323  		istanbulBlock       *big.Int
   324  	)
   325  	if chainParams.Params.HomesteadForkBlock != nil {
   326  		homesteadBlock = big.NewInt(int64(*chainParams.Params.HomesteadForkBlock))
   327  	}
   328  	if chainParams.Params.DaoHardforkBlock != nil {
   329  		daoForkBlock = big.NewInt(int64(*chainParams.Params.DaoHardforkBlock))
   330  	}
   331  	if chainParams.Params.EIP150ForkBlock != nil {
   332  		eip150Block = big.NewInt(int64(*chainParams.Params.EIP150ForkBlock))
   333  	}
   334  	if chainParams.Params.EIP158ForkBlock != nil {
   335  		eip158Block = big.NewInt(int64(*chainParams.Params.EIP158ForkBlock))
   336  		eip155Block = eip158Block
   337  	}
   338  	if chainParams.Params.ByzantiumForkBlock != nil {
   339  		byzantiumBlock = big.NewInt(int64(*chainParams.Params.ByzantiumForkBlock))
   340  	}
   341  	if chainParams.Params.ConstantinopleForkBlock != nil {
   342  		constantinopleBlock = big.NewInt(int64(*chainParams.Params.ConstantinopleForkBlock))
   343  	}
   344  	if chainParams.Params.ConstantinopleFixForkBlock != nil {
   345  		petersburgBlock = big.NewInt(int64(*chainParams.Params.ConstantinopleFixForkBlock))
   346  	}
   347  	if constantinopleBlock != nil && petersburgBlock == nil {
   348  		petersburgBlock = big.NewInt(100000000000)
   349  	}
   350  	if chainParams.Params.IstanbulBlock != nil {
   351  		istanbulBlock = big.NewInt(int64(*chainParams.Params.IstanbulBlock))
   352  	}
   353  
   354  	genesis := &core.Genesis{
   355  		Config: &params.ChainConfig{
   356  			ChainID:             chainId,
   357  			HomesteadBlock:      homesteadBlock,
   358  			DAOForkBlock:        daoForkBlock,
   359  			DAOForkSupport:      false,
   360  			EIP150Block:         eip150Block,
   361  			EIP155Block:         eip155Block,
   362  			EIP158Block:         eip158Block,
   363  			ByzantiumBlock:      byzantiumBlock,
   364  			ConstantinopleBlock: constantinopleBlock,
   365  			PetersburgBlock:     petersburgBlock,
   366  			IstanbulBlock:       istanbulBlock,
   367  		},
   368  		Nonce:      uint64(chainParams.Genesis.Nonce),
   369  		Timestamp:  uint64(chainParams.Genesis.Timestamp),
   370  		ExtraData:  chainParams.Genesis.ExtraData,
   371  		GasLimit:   uint64(chainParams.Genesis.GasLimit),
   372  		Difficulty: big.NewInt(0).Set((*big.Int)(chainParams.Genesis.Difficulty)),
   373  		Mixhash:    common.BigToHash((*big.Int)(chainParams.Genesis.MixHash)),
   374  		Coinbase:   chainParams.Genesis.Author,
   375  		ParentHash: chainParams.Genesis.ParentHash,
   376  		Alloc:      accounts,
   377  	}
   378  	chainConfig, genesisHash, err := core.SetupGenesisBlock(ethDb, genesis)
   379  	if err != nil {
   380  		return false, err
   381  	}
   382  	fmt.Printf("Chain config: %v\n", chainConfig)
   383  
   384  	var inner consensus.Engine
   385  	switch chainParams.SealEngine {
   386  	case "NoProof", "NoReward":
   387  		inner = ethash.NewFaker()
   388  	case "Ethash":
   389  		inner = ethash.New(ethash.Config{
   390  			CacheDir:       "ethash",
   391  			CachesInMem:    2,
   392  			CachesOnDisk:   3,
   393  			DatasetsInMem:  1,
   394  			DatasetsOnDisk: 2,
   395  		}, nil, false)
   396  	default:
   397  		return false, fmt.Errorf("unrecognised seal engine: %s", chainParams.SealEngine)
   398  	}
   399  	engine := &NoRewardEngine{inner: inner, rewardsOn: chainParams.SealEngine != "NoReward"}
   400  
   401  	blockchain, err := core.NewBlockChain(ethDb, nil, chainConfig, engine, vm.Config{}, nil)
   402  	if err != nil {
   403  		return false, err
   404  	}
   405  
   406  	api.chainConfig = chainConfig
   407  	api.genesisHash = genesisHash
   408  	api.author = chainParams.Genesis.Author
   409  	api.extraData = chainParams.Genesis.ExtraData
   410  	api.ethDb = ethDb
   411  	api.engine = engine
   412  	api.blockchain = blockchain
   413  	api.db = state.NewDatabase(api.ethDb)
   414  	api.blockNumber = 0
   415  	api.txMap = make(map[common.Address]map[uint64]*types.Transaction)
   416  	api.txSenders = make(map[common.Address]struct{})
   417  	api.blockInterval = 0
   418  	return true, nil
   419  }
   420  
   421  func (api *RetestethAPI) SendRawTransaction(ctx context.Context, rawTx hexutil.Bytes) (common.Hash, error) {
   422  	tx := new(types.Transaction)
   423  	if err := rlp.DecodeBytes(rawTx, tx); err != nil {
   424  		// Return nil is not by mistake - some tests include sending transaction where gasLimit overflows uint64
   425  		return common.Hash{}, nil
   426  	}
   427  	signer := types.MakeSigner(api.chainConfig, big.NewInt(int64(api.blockNumber)))
   428  	sender, err := types.Sender(signer, tx)
   429  	if err != nil {
   430  		return common.Hash{}, err
   431  	}
   432  	if nonceMap, ok := api.txMap[sender]; ok {
   433  		nonceMap[tx.Nonce()] = tx
   434  	} else {
   435  		nonceMap = make(map[uint64]*types.Transaction)
   436  		nonceMap[tx.Nonce()] = tx
   437  		api.txMap[sender] = nonceMap
   438  	}
   439  	api.txSenders[sender] = struct{}{}
   440  	return tx.Hash(), nil
   441  }
   442  
   443  func (api *RetestethAPI) MineBlocks(ctx context.Context, number uint64) (bool, error) {
   444  	for i := 0; i < int(number); i++ {
   445  		if err := api.mineBlock(); err != nil {
   446  			return false, err
   447  		}
   448  	}
   449  	fmt.Printf("Mined %d blocks\n", number)
   450  	return true, nil
   451  }
   452  
   453  func (api *RetestethAPI) mineBlock() error {
   454  	parentHash := rawdb.ReadCanonicalHash(api.ethDb, api.blockNumber)
   455  	parent := rawdb.ReadBlock(api.ethDb, parentHash, api.blockNumber)
   456  	var timestamp uint64
   457  	if api.blockInterval == 0 {
   458  		timestamp = uint64(time.Now().Unix())
   459  	} else {
   460  		timestamp = parent.Time() + api.blockInterval
   461  	}
   462  	gasLimit := core.CalcGasLimit(parent, 9223372036854775807, 9223372036854775807)
   463  	header := &types.Header{
   464  		ParentHash: parent.Hash(),
   465  		Number:     big.NewInt(int64(api.blockNumber + 1)),
   466  		GasLimit:   gasLimit,
   467  		Extra:      api.extraData,
   468  		Time:       timestamp,
   469  	}
   470  	header.Coinbase = api.author
   471  	if api.engine != nil {
   472  		api.engine.Prepare(api.blockchain, header)
   473  	}
   474  	// If we are care about TheDAO hard-fork check whether to override the extra-data or not
   475  	if daoBlock := api.chainConfig.DAOForkBlock; daoBlock != nil {
   476  		// Check whether the block is among the fork extra-override range
   477  		limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
   478  		if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
   479  			// Depending whether we support or oppose the fork, override differently
   480  			if api.chainConfig.DAOForkSupport {
   481  				header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
   482  			} else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
   483  				header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data
   484  			}
   485  		}
   486  	}
   487  	statedb, err := api.blockchain.StateAt(parent.Root())
   488  	if err != nil {
   489  		return err
   490  	}
   491  	if api.chainConfig.DAOForkSupport && api.chainConfig.DAOForkBlock != nil && api.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 {
   492  		misc.ApplyDAOHardFork(statedb)
   493  	}
   494  	gasPool := new(core.GasPool).AddGas(header.GasLimit)
   495  	txCount := 0
   496  	var txs []*types.Transaction
   497  	var receipts []*types.Receipt
   498  	var blockFull = gasPool.Gas() < params.TxGas
   499  	for address := range api.txSenders {
   500  		if blockFull {
   501  			break
   502  		}
   503  		m := api.txMap[address]
   504  		for nonce := statedb.GetNonce(address); ; nonce++ {
   505  			if tx, ok := m[nonce]; ok {
   506  				// Try to apply transactions to the state
   507  				statedb.Prepare(tx.Hash(), common.Hash{}, txCount)
   508  				snap := statedb.Snapshot()
   509  
   510  				receipt, err := core.ApplyTransaction(
   511  					api.chainConfig,
   512  					api.blockchain,
   513  					&api.author,
   514  					gasPool,
   515  					statedb,
   516  					header, tx, &header.GasUsed, *api.blockchain.GetVMConfig(),
   517  				)
   518  				if err != nil {
   519  					statedb.RevertToSnapshot(snap)
   520  					break
   521  				}
   522  				txs = append(txs, tx)
   523  				receipts = append(receipts, receipt)
   524  				delete(m, nonce)
   525  				if len(m) == 0 {
   526  					// Last tx for the sender
   527  					delete(api.txMap, address)
   528  					delete(api.txSenders, address)
   529  				}
   530  				txCount++
   531  				if gasPool.Gas() < params.TxGas {
   532  					blockFull = true
   533  					break
   534  				}
   535  			} else {
   536  				break // Gap in the nonces
   537  			}
   538  		}
   539  	}
   540  	block, err := api.engine.FinalizeAndAssemble(api.blockchain, header, statedb, txs, []*types.Header{}, receipts)
   541  	if err != nil {
   542  		return err
   543  	}
   544  	return api.importBlock(block)
   545  }
   546  
   547  func (api *RetestethAPI) importBlock(block *types.Block) error {
   548  	if _, err := api.blockchain.InsertChain([]*types.Block{block}); err != nil {
   549  		return err
   550  	}
   551  	api.blockNumber = block.NumberU64()
   552  	fmt.Printf("Imported block %d\n", block.NumberU64())
   553  	return nil
   554  }
   555  
   556  func (api *RetestethAPI) ModifyTimestamp(ctx context.Context, interval uint64) (bool, error) {
   557  	api.blockInterval = interval
   558  	return true, nil
   559  }
   560  
   561  func (api *RetestethAPI) ImportRawBlock(ctx context.Context, rawBlock hexutil.Bytes) (common.Hash, error) {
   562  	block := new(types.Block)
   563  	if err := rlp.DecodeBytes(rawBlock, block); err != nil {
   564  		return common.Hash{}, err
   565  	}
   566  	fmt.Printf("Importing block %d with parent hash: %x, genesisHash: %x\n", block.NumberU64(), block.ParentHash(), api.genesisHash)
   567  	if err := api.importBlock(block); err != nil {
   568  		return common.Hash{}, err
   569  	}
   570  	return block.Hash(), nil
   571  }
   572  
   573  func (api *RetestethAPI) RewindToBlock(ctx context.Context, newHead uint64) (bool, error) {
   574  	if err := api.blockchain.SetHead(newHead); err != nil {
   575  		return false, err
   576  	}
   577  	api.blockNumber = newHead
   578  	return true, nil
   579  }
   580  
   581  var emptyListHash common.Hash = common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
   582  
   583  func (api *RetestethAPI) GetLogHash(ctx context.Context, txHash common.Hash) (common.Hash, error) {
   584  	receipt, _, _, _ := rawdb.ReadReceipt(api.ethDb, txHash, api.chainConfig)
   585  	if receipt == nil {
   586  		return emptyListHash, nil
   587  	} else {
   588  		if logListRlp, err := rlp.EncodeToBytes(receipt.Logs); err != nil {
   589  			return common.Hash{}, err
   590  		} else {
   591  			return common.BytesToHash(crypto.Keccak256(logListRlp)), nil
   592  		}
   593  	}
   594  }
   595  
   596  func (api *RetestethAPI) BlockNumber(ctx context.Context) (uint64, error) {
   597  	//fmt.Printf("BlockNumber, response: %d\n", api.blockNumber)
   598  	return api.blockNumber, nil
   599  }
   600  
   601  func (api *RetestethAPI) GetBlockByNumber(ctx context.Context, blockNr math.HexOrDecimal64, fullTx bool) (map[string]interface{}, error) {
   602  	block := api.blockchain.GetBlockByNumber(uint64(blockNr))
   603  	if block != nil {
   604  		response, err := RPCMarshalBlock(block, true, fullTx)
   605  		if err != nil {
   606  			return nil, err
   607  		}
   608  		response["author"] = response["miner"]
   609  		response["totalDifficulty"] = (*hexutil.Big)(api.blockchain.GetTd(block.Hash(), uint64(blockNr)))
   610  		return response, err
   611  	}
   612  	return nil, fmt.Errorf("block %d not found", blockNr)
   613  }
   614  
   615  func (api *RetestethAPI) AccountRange(ctx context.Context,
   616  	blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
   617  	addressHash *math.HexOrDecimal256, maxResults uint64,
   618  ) (AccountRangeResult, error) {
   619  	var (
   620  		header *types.Header
   621  		block  *types.Block
   622  	)
   623  	if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 {
   624  		blockHash := common.BigToHash((*big.Int)(blockHashOrNumber))
   625  		header = api.blockchain.GetHeaderByHash(blockHash)
   626  		block = api.blockchain.GetBlockByHash(blockHash)
   627  		//fmt.Printf("Account range: %x, txIndex %d, start: %x, maxResults: %d\n", blockHash, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults)
   628  	} else {
   629  		blockNumber := (*big.Int)(blockHashOrNumber).Uint64()
   630  		header = api.blockchain.GetHeaderByNumber(blockNumber)
   631  		block = api.blockchain.GetBlockByNumber(blockNumber)
   632  		//fmt.Printf("Account range: %d, txIndex %d, start: %x, maxResults: %d\n", blockNumber, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults)
   633  	}
   634  	parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash)
   635  	var root common.Hash
   636  	var statedb *state.StateDB
   637  	var err error
   638  	if parentHeader == nil || int(txIndex) >= len(block.Transactions()) {
   639  		root = header.Root
   640  		statedb, err = api.blockchain.StateAt(root)
   641  		if err != nil {
   642  			return AccountRangeResult{}, err
   643  		}
   644  	} else {
   645  		root = parentHeader.Root
   646  		statedb, err = api.blockchain.StateAt(root)
   647  		if err != nil {
   648  			return AccountRangeResult{}, err
   649  		}
   650  		// Recompute transactions up to the target index.
   651  		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
   652  		for idx, tx := range block.Transactions() {
   653  			// Assemble the transaction call message and return if the requested offset
   654  			msg, _ := tx.AsMessage(signer)
   655  			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
   656  			// Not yet the searched for transaction, execute on top of the current state
   657  			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
   658  			if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   659  				return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   660  			}
   661  			// Ensure any modifications are committed to the state
   662  			// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   663  			root = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number()))
   664  			if idx == int(txIndex) {
   665  				// This is to make sure root can be opened by OpenTrie
   666  				root, err = statedb.Commit(api.chainConfig.IsEIP158(block.Number()))
   667  				if err != nil {
   668  					return AccountRangeResult{}, err
   669  				}
   670  				break
   671  			}
   672  		}
   673  	}
   674  	accountTrie, err := statedb.Database().OpenTrie(root)
   675  	if err != nil {
   676  		return AccountRangeResult{}, err
   677  	}
   678  	it := trie.NewIterator(accountTrie.NodeIterator(common.BigToHash((*big.Int)(addressHash)).Bytes()))
   679  	result := AccountRangeResult{AddressMap: make(map[common.Hash]common.Address)}
   680  	for i := 0; i < int(maxResults) && it.Next(); i++ {
   681  		if preimage := accountTrie.GetKey(it.Key); preimage != nil {
   682  			result.AddressMap[common.BytesToHash(it.Key)] = common.BytesToAddress(preimage)
   683  		}
   684  	}
   685  	//fmt.Printf("Number of entries returned: %d\n", len(result.AddressMap))
   686  	// Add the 'next key' so clients can continue downloading.
   687  	if it.Next() {
   688  		next := common.BytesToHash(it.Key)
   689  		result.NextKey = next
   690  	}
   691  	return result, nil
   692  }
   693  
   694  func (api *RetestethAPI) GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error) {
   695  	//fmt.Printf("GetBalance %x, block %d\n", address, blockNr)
   696  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   697  	statedb, err := api.blockchain.StateAt(header.Root)
   698  	if err != nil {
   699  		return nil, err
   700  	}
   701  	return (*math.HexOrDecimal256)(statedb.GetBalance(address)), nil
   702  }
   703  
   704  func (api *RetestethAPI) GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error) {
   705  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   706  	statedb, err := api.blockchain.StateAt(header.Root)
   707  	if err != nil {
   708  		return nil, err
   709  	}
   710  	return statedb.GetCode(address), nil
   711  }
   712  
   713  func (api *RetestethAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error) {
   714  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   715  	statedb, err := api.blockchain.StateAt(header.Root)
   716  	if err != nil {
   717  		return 0, err
   718  	}
   719  	return statedb.GetNonce(address), nil
   720  }
   721  
   722  func (api *RetestethAPI) StorageRangeAt(ctx context.Context,
   723  	blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
   724  	address common.Address,
   725  	begin *math.HexOrDecimal256, maxResults uint64,
   726  ) (StorageRangeResult, error) {
   727  	var (
   728  		header *types.Header
   729  		block  *types.Block
   730  	)
   731  	if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 {
   732  		blockHash := common.BigToHash((*big.Int)(blockHashOrNumber))
   733  		header = api.blockchain.GetHeaderByHash(blockHash)
   734  		block = api.blockchain.GetBlockByHash(blockHash)
   735  		//fmt.Printf("Storage range: %x, txIndex %d, addr: %x, start: %x, maxResults: %d\n",
   736  		//	blockHash, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults)
   737  	} else {
   738  		blockNumber := (*big.Int)(blockHashOrNumber).Uint64()
   739  		header = api.blockchain.GetHeaderByNumber(blockNumber)
   740  		block = api.blockchain.GetBlockByNumber(blockNumber)
   741  		//fmt.Printf("Storage range: %d, txIndex %d, addr: %x, start: %x, maxResults: %d\n",
   742  		//	blockNumber, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults)
   743  	}
   744  	parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash)
   745  	var root common.Hash
   746  	var statedb *state.StateDB
   747  	var err error
   748  	if parentHeader == nil || int(txIndex) >= len(block.Transactions()) {
   749  		root = header.Root
   750  		statedb, err = api.blockchain.StateAt(root)
   751  		if err != nil {
   752  			return StorageRangeResult{}, err
   753  		}
   754  	} else {
   755  		root = parentHeader.Root
   756  		statedb, err = api.blockchain.StateAt(root)
   757  		if err != nil {
   758  			return StorageRangeResult{}, err
   759  		}
   760  		// Recompute transactions up to the target index.
   761  		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
   762  		for idx, tx := range block.Transactions() {
   763  			// Assemble the transaction call message and return if the requested offset
   764  			msg, _ := tx.AsMessage(signer)
   765  			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
   766  			// Not yet the searched for transaction, execute on top of the current state
   767  			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
   768  			if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   769  				return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   770  			}
   771  			// Ensure any modifications are committed to the state
   772  			// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   773  			_ = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number()))
   774  			if idx == int(txIndex) {
   775  				// This is to make sure root can be opened by OpenTrie
   776  				_, err = statedb.Commit(vmenv.ChainConfig().IsEIP158(block.Number()))
   777  				if err != nil {
   778  					return StorageRangeResult{}, err
   779  				}
   780  			}
   781  		}
   782  	}
   783  	storageTrie := statedb.StorageTrie(address)
   784  	it := trie.NewIterator(storageTrie.NodeIterator(common.BigToHash((*big.Int)(begin)).Bytes()))
   785  	result := StorageRangeResult{Storage: make(map[common.Hash]SRItem)}
   786  	for i := 0; /*i < int(maxResults) && */ it.Next(); i++ {
   787  		if preimage := storageTrie.GetKey(it.Key); preimage != nil {
   788  			key := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(preimage))
   789  			v, _, err := rlp.SplitString(it.Value)
   790  			if err != nil {
   791  				return StorageRangeResult{}, err
   792  			}
   793  			value := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(v))
   794  			ks, _ := key.MarshalText()
   795  			vs, _ := value.MarshalText()
   796  			if len(ks)%2 != 0 {
   797  				ks = append(append(append([]byte{}, ks[:2]...), byte('0')), ks[2:]...)
   798  			}
   799  			if len(vs)%2 != 0 {
   800  				vs = append(append(append([]byte{}, vs[:2]...), byte('0')), vs[2:]...)
   801  			}
   802  			result.Storage[common.BytesToHash(it.Key)] = SRItem{
   803  				Key:   string(ks),
   804  				Value: string(vs),
   805  			}
   806  		}
   807  	}
   808  	if it.Next() {
   809  		result.Complete = false
   810  	} else {
   811  		result.Complete = true
   812  	}
   813  	return result, nil
   814  }
   815  
   816  func (api *RetestethAPI) ClientVersion(ctx context.Context) (string, error) {
   817  	return "Geth-" + params.VersionWithCommit(gitCommit, gitDate), nil
   818  }
   819  
   820  // splitAndTrim splits input separated by a comma
   821  // and trims excessive white space from the substrings.
   822  func splitAndTrim(input string) []string {
   823  	result := strings.Split(input, ",")
   824  	for i, r := range result {
   825  		result[i] = strings.TrimSpace(r)
   826  	}
   827  	return result
   828  }
   829  
   830  func retesteth(ctx *cli.Context) error {
   831  	log.Info("Welcome to retesteth!")
   832  	// register signer API with server
   833  	var (
   834  		extapiURL string
   835  	)
   836  	apiImpl := &RetestethAPI{}
   837  	var testApi RetestethTestAPI = apiImpl
   838  	var ethApi RetestethEthAPI = apiImpl
   839  	var debugApi RetestethDebugAPI = apiImpl
   840  	var web3Api RetestWeb3API = apiImpl
   841  	rpcAPI := []rpc.API{
   842  		{
   843  			Namespace: "test",
   844  			Public:    true,
   845  			Service:   testApi,
   846  			Version:   "1.0",
   847  		},
   848  		{
   849  			Namespace: "eth",
   850  			Public:    true,
   851  			Service:   ethApi,
   852  			Version:   "1.0",
   853  		},
   854  		{
   855  			Namespace: "debug",
   856  			Public:    true,
   857  			Service:   debugApi,
   858  			Version:   "1.0",
   859  		},
   860  		{
   861  			Namespace: "web3",
   862  			Public:    true,
   863  			Service:   web3Api,
   864  			Version:   "1.0",
   865  		},
   866  	}
   867  	vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name))
   868  	cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name))
   869  
   870  	// start http server
   871  	httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name))
   872  	listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, rpc.DefaultHTTPTimeouts)
   873  	if err != nil {
   874  		utils.Fatalf("Could not start RPC api: %v", err)
   875  	}
   876  	extapiURL = fmt.Sprintf("http://%s", httpEndpoint)
   877  	log.Info("HTTP endpoint opened", "url", extapiURL)
   878  
   879  	defer func() {
   880  		listener.Close()
   881  		log.Info("HTTP endpoint closed", "url", httpEndpoint)
   882  	}()
   883  
   884  	abortChan := make(chan os.Signal, 11)
   885  	signal.Notify(abortChan, os.Interrupt)
   886  
   887  	sig := <-abortChan
   888  	log.Info("Exiting...", "signal", sig)
   889  	return nil
   890  }