git.pirl.io/community/pirl@v0.0.0-20201111064343-9d3d31ff74be/cmd/pirl/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  	"git.pirl.io/community/pirl/cmd/utils"
    30  	"git.pirl.io/community/pirl/common"
    31  	"git.pirl.io/community/pirl/common/hexutil"
    32  	"git.pirl.io/community/pirl/common/math"
    33  	"git.pirl.io/community/pirl/consensus"
    34  	"git.pirl.io/community/pirl/consensus/ethash"
    35  	"git.pirl.io/community/pirl/consensus/misc"
    36  	"git.pirl.io/community/pirl/core"
    37  	"git.pirl.io/community/pirl/core/rawdb"
    38  	"git.pirl.io/community/pirl/core/state"
    39  	"git.pirl.io/community/pirl/core/types"
    40  	"git.pirl.io/community/pirl/core/vm"
    41  	"git.pirl.io/community/pirl/crypto"
    42  	"git.pirl.io/community/pirl/ethdb"
    43  	"git.pirl.io/community/pirl/log"
    44  	"git.pirl.io/community/pirl/node"
    45  	"git.pirl.io/community/pirl/params"
    46  	"git.pirl.io/community/pirl/rlp"
    47  	"git.pirl.io/community/pirl/rpc"
    48  	"git.pirl.io/community/pirl/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  	GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error)
    84  	GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error)
    85  	GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error)
    86  	GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error)
    87  }
    88  
    89  type RetestethDebugAPI interface {
    90  	AccountRange(ctx context.Context,
    91  		blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
    92  		addressHash *math.HexOrDecimal256, maxResults uint64,
    93  	) (AccountRangeResult, error)
    94  	StorageRangeAt(ctx context.Context,
    95  		blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
    96  		address common.Address,
    97  		begin *math.HexOrDecimal256, maxResults uint64,
    98  	) (StorageRangeResult, error)
    99  }
   100  
   101  type RetestWeb3API interface {
   102  	ClientVersion(ctx context.Context) (string, error)
   103  }
   104  
   105  type RetestethAPI struct {
   106  	ethDb         ethdb.Database
   107  	db            state.Database
   108  	chainConfig   *params.ChainConfig
   109  	author        common.Address
   110  	extraData     []byte
   111  	genesisHash   common.Hash
   112  	engine        *NoRewardEngine
   113  	blockchain    *core.BlockChain
   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:      true,
   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.txMap = make(map[common.Address]map[uint64]*types.Transaction)
   415  	api.txSenders = make(map[common.Address]struct{})
   416  	api.blockInterval = 0
   417  	return true, nil
   418  }
   419  
   420  func (api *RetestethAPI) SendRawTransaction(ctx context.Context, rawTx hexutil.Bytes) (common.Hash, error) {
   421  	tx := new(types.Transaction)
   422  	if err := rlp.DecodeBytes(rawTx, tx); err != nil {
   423  		// Return nil is not by mistake - some tests include sending transaction where gasLimit overflows uint64
   424  		return common.Hash{}, nil
   425  	}
   426  	signer := types.MakeSigner(api.chainConfig, big.NewInt(int64(api.currentNumber())))
   427  	sender, err := types.Sender(signer, tx)
   428  	if err != nil {
   429  		return common.Hash{}, err
   430  	}
   431  	if nonceMap, ok := api.txMap[sender]; ok {
   432  		nonceMap[tx.Nonce()] = tx
   433  	} else {
   434  		nonceMap = make(map[uint64]*types.Transaction)
   435  		nonceMap[tx.Nonce()] = tx
   436  		api.txMap[sender] = nonceMap
   437  	}
   438  	api.txSenders[sender] = struct{}{}
   439  	return tx.Hash(), nil
   440  }
   441  
   442  func (api *RetestethAPI) MineBlocks(ctx context.Context, number uint64) (bool, error) {
   443  	for i := 0; i < int(number); i++ {
   444  		if err := api.mineBlock(); err != nil {
   445  			return false, err
   446  		}
   447  	}
   448  	fmt.Printf("Mined %d blocks\n", number)
   449  	return true, nil
   450  }
   451  
   452  func (api *RetestethAPI) currentNumber() uint64 {
   453  	if current := api.blockchain.CurrentBlock(); current != nil {
   454  		return current.NumberU64()
   455  	}
   456  	return 0
   457  }
   458  
   459  func (api *RetestethAPI) mineBlock() error {
   460  	number := api.currentNumber()
   461  	parentHash := rawdb.ReadCanonicalHash(api.ethDb, number)
   462  	parent := rawdb.ReadBlock(api.ethDb, parentHash, number)
   463  	var timestamp uint64
   464  	if api.blockInterval == 0 {
   465  		timestamp = uint64(time.Now().Unix())
   466  	} else {
   467  		timestamp = parent.Time() + api.blockInterval
   468  	}
   469  	gasLimit := core.CalcGasLimit(parent, 9223372036854775807, 9223372036854775807)
   470  	header := &types.Header{
   471  		ParentHash: parent.Hash(),
   472  		Number:     big.NewInt(int64(number + 1)),
   473  		GasLimit:   gasLimit,
   474  		Extra:      api.extraData,
   475  		Time:       timestamp,
   476  	}
   477  	header.Coinbase = api.author
   478  	if api.engine != nil {
   479  		api.engine.Prepare(api.blockchain, header)
   480  	}
   481  	// If we are care about TheDAO hard-fork check whether to override the extra-data or not
   482  	if daoBlock := api.chainConfig.DAOForkBlock; daoBlock != nil {
   483  		// Check whether the block is among the fork extra-override range
   484  		limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
   485  		if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
   486  			// Depending whether we support or oppose the fork, override differently
   487  			if api.chainConfig.DAOForkSupport {
   488  				header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
   489  			} else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
   490  				header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data
   491  			}
   492  		}
   493  	}
   494  	statedb, err := api.blockchain.StateAt(parent.Root())
   495  	if err != nil {
   496  		return err
   497  	}
   498  	if api.chainConfig.DAOForkSupport && api.chainConfig.DAOForkBlock != nil && api.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 {
   499  		misc.ApplyDAOHardFork(statedb)
   500  	}
   501  	gasPool := new(core.GasPool).AddGas(header.GasLimit)
   502  	txCount := 0
   503  	var txs []*types.Transaction
   504  	var receipts []*types.Receipt
   505  	var blockFull = gasPool.Gas() < params.TxGas
   506  	for address := range api.txSenders {
   507  		if blockFull {
   508  			break
   509  		}
   510  		m := api.txMap[address]
   511  		for nonce := statedb.GetNonce(address); ; nonce++ {
   512  			if tx, ok := m[nonce]; ok {
   513  				// Try to apply transactions to the state
   514  				statedb.Prepare(tx.Hash(), common.Hash{}, txCount)
   515  				snap := statedb.Snapshot()
   516  
   517  				receipt, err := core.ApplyTransaction(
   518  					api.chainConfig,
   519  					api.blockchain,
   520  					&api.author,
   521  					gasPool,
   522  					statedb,
   523  					header, tx, &header.GasUsed, *api.blockchain.GetVMConfig(),
   524  				)
   525  				if err != nil {
   526  					statedb.RevertToSnapshot(snap)
   527  					break
   528  				}
   529  				txs = append(txs, tx)
   530  				receipts = append(receipts, receipt)
   531  				delete(m, nonce)
   532  				if len(m) == 0 {
   533  					// Last tx for the sender
   534  					delete(api.txMap, address)
   535  					delete(api.txSenders, address)
   536  				}
   537  				txCount++
   538  				if gasPool.Gas() < params.TxGas {
   539  					blockFull = true
   540  					break
   541  				}
   542  			} else {
   543  				break // Gap in the nonces
   544  			}
   545  		}
   546  	}
   547  	block, err := api.engine.FinalizeAndAssemble(api.blockchain, header, statedb, txs, []*types.Header{}, receipts)
   548  	if err != nil {
   549  		return err
   550  	}
   551  	return api.importBlock(block)
   552  }
   553  
   554  func (api *RetestethAPI) importBlock(block *types.Block) error {
   555  	if _, err := api.blockchain.InsertChain([]*types.Block{block}); err != nil {
   556  		return err
   557  	}
   558  	fmt.Printf("Imported block %d,  head is %d\n", block.NumberU64(), api.currentNumber())
   559  	return nil
   560  }
   561  
   562  func (api *RetestethAPI) ModifyTimestamp(ctx context.Context, interval uint64) (bool, error) {
   563  	api.blockInterval = interval
   564  	return true, nil
   565  }
   566  
   567  func (api *RetestethAPI) ImportRawBlock(ctx context.Context, rawBlock hexutil.Bytes) (common.Hash, error) {
   568  	block := new(types.Block)
   569  	if err := rlp.DecodeBytes(rawBlock, block); err != nil {
   570  		return common.Hash{}, err
   571  	}
   572  	fmt.Printf("Importing block %d with parent hash: %x, genesisHash: %x\n", block.NumberU64(), block.ParentHash(), api.genesisHash)
   573  	if err := api.importBlock(block); err != nil {
   574  		return common.Hash{}, err
   575  	}
   576  	return block.Hash(), nil
   577  }
   578  
   579  func (api *RetestethAPI) RewindToBlock(ctx context.Context, newHead uint64) (bool, error) {
   580  	if err := api.blockchain.SetHead(newHead); err != nil {
   581  		return false, err
   582  	}
   583  	// When we rewind, the transaction pool should be cleaned out.
   584  	api.txMap = make(map[common.Address]map[uint64]*types.Transaction)
   585  	api.txSenders = make(map[common.Address]struct{})
   586  	return true, nil
   587  }
   588  
   589  var emptyListHash common.Hash = common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
   590  
   591  func (api *RetestethAPI) GetLogHash(ctx context.Context, txHash common.Hash) (common.Hash, error) {
   592  	receipt, _, _, _ := rawdb.ReadReceipt(api.ethDb, txHash, api.chainConfig)
   593  	if receipt == nil {
   594  		return emptyListHash, nil
   595  	} else {
   596  		if logListRlp, err := rlp.EncodeToBytes(receipt.Logs); err != nil {
   597  			return common.Hash{}, err
   598  		} else {
   599  			return common.BytesToHash(crypto.Keccak256(logListRlp)), nil
   600  		}
   601  	}
   602  }
   603  
   604  func (api *RetestethAPI) BlockNumber(ctx context.Context) (uint64, error) {
   605  	return api.currentNumber(), nil
   606  }
   607  
   608  func (api *RetestethAPI) GetBlockByNumber(ctx context.Context, blockNr math.HexOrDecimal64, fullTx bool) (map[string]interface{}, error) {
   609  	block := api.blockchain.GetBlockByNumber(uint64(blockNr))
   610  	if block != nil {
   611  		response, err := RPCMarshalBlock(block, true, fullTx)
   612  		if err != nil {
   613  			return nil, err
   614  		}
   615  		response["author"] = response["miner"]
   616  		response["totalDifficulty"] = (*hexutil.Big)(api.blockchain.GetTd(block.Hash(), uint64(blockNr)))
   617  		return response, err
   618  	}
   619  	return nil, fmt.Errorf("block %d not found", blockNr)
   620  }
   621  
   622  func (api *RetestethAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
   623  	block := api.blockchain.GetBlockByHash(blockHash)
   624  	if block != nil {
   625  		response, err := RPCMarshalBlock(block, true, fullTx)
   626  		if err != nil {
   627  			return nil, err
   628  		}
   629  		response["author"] = response["miner"]
   630  		response["totalDifficulty"] = (*hexutil.Big)(api.blockchain.GetTd(block.Hash(), block.Number().Uint64()))
   631  		return response, err
   632  	}
   633  	return nil, fmt.Errorf("block 0x%x not found", blockHash)
   634  }
   635  
   636  func (api *RetestethAPI) AccountRange(ctx context.Context,
   637  	blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
   638  	addressHash *math.HexOrDecimal256, maxResults uint64,
   639  ) (AccountRangeResult, error) {
   640  	var (
   641  		header *types.Header
   642  		block  *types.Block
   643  	)
   644  	if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 {
   645  		blockHash := common.BigToHash((*big.Int)(blockHashOrNumber))
   646  		header = api.blockchain.GetHeaderByHash(blockHash)
   647  		block = api.blockchain.GetBlockByHash(blockHash)
   648  		//fmt.Printf("Account range: %x, txIndex %d, start: %x, maxResults: %d\n", blockHash, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults)
   649  	} else {
   650  		blockNumber := (*big.Int)(blockHashOrNumber).Uint64()
   651  		header = api.blockchain.GetHeaderByNumber(blockNumber)
   652  		block = api.blockchain.GetBlockByNumber(blockNumber)
   653  		//fmt.Printf("Account range: %d, txIndex %d, start: %x, maxResults: %d\n", blockNumber, txIndex, common.BigToHash((*big.Int)(addressHash)), maxResults)
   654  	}
   655  	parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash)
   656  	var root common.Hash
   657  	var statedb *state.StateDB
   658  	var err error
   659  	if parentHeader == nil || int(txIndex) >= len(block.Transactions()) {
   660  		root = header.Root
   661  		statedb, err = api.blockchain.StateAt(root)
   662  		if err != nil {
   663  			return AccountRangeResult{}, err
   664  		}
   665  	} else {
   666  		root = parentHeader.Root
   667  		statedb, err = api.blockchain.StateAt(root)
   668  		if err != nil {
   669  			return AccountRangeResult{}, err
   670  		}
   671  		// Recompute transactions up to the target index.
   672  		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
   673  		for idx, tx := range block.Transactions() {
   674  			// Assemble the transaction call message and return if the requested offset
   675  			msg, _ := tx.AsMessage(signer)
   676  			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
   677  			// Not yet the searched for transaction, execute on top of the current state
   678  			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
   679  			if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   680  				return AccountRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   681  			}
   682  			// Ensure any modifications are committed to the state
   683  			// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   684  			root = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number()))
   685  			if idx == int(txIndex) {
   686  				// This is to make sure root can be opened by OpenTrie
   687  				root, err = statedb.Commit(api.chainConfig.IsEIP158(block.Number()))
   688  				if err != nil {
   689  					return AccountRangeResult{}, err
   690  				}
   691  				break
   692  			}
   693  		}
   694  	}
   695  	accountTrie, err := statedb.Database().OpenTrie(root)
   696  	if err != nil {
   697  		return AccountRangeResult{}, err
   698  	}
   699  	it := trie.NewIterator(accountTrie.NodeIterator(common.BigToHash((*big.Int)(addressHash)).Bytes()))
   700  	result := AccountRangeResult{AddressMap: make(map[common.Hash]common.Address)}
   701  	for i := 0; i < int(maxResults) && it.Next(); i++ {
   702  		if preimage := accountTrie.GetKey(it.Key); preimage != nil {
   703  			result.AddressMap[common.BytesToHash(it.Key)] = common.BytesToAddress(preimage)
   704  		}
   705  	}
   706  	//fmt.Printf("Number of entries returned: %d\n", len(result.AddressMap))
   707  	// Add the 'next key' so clients can continue downloading.
   708  	if it.Next() {
   709  		next := common.BytesToHash(it.Key)
   710  		result.NextKey = next
   711  	}
   712  	return result, nil
   713  }
   714  
   715  func (api *RetestethAPI) GetBalance(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (*math.HexOrDecimal256, error) {
   716  	//fmt.Printf("GetBalance %x, block %d\n", address, blockNr)
   717  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   718  	statedb, err := api.blockchain.StateAt(header.Root)
   719  	if err != nil {
   720  		return nil, err
   721  	}
   722  	return (*math.HexOrDecimal256)(statedb.GetBalance(address)), nil
   723  }
   724  
   725  func (api *RetestethAPI) GetCode(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (hexutil.Bytes, error) {
   726  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   727  	statedb, err := api.blockchain.StateAt(header.Root)
   728  	if err != nil {
   729  		return nil, err
   730  	}
   731  	return statedb.GetCode(address), nil
   732  }
   733  
   734  func (api *RetestethAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr math.HexOrDecimal64) (uint64, error) {
   735  	header := api.blockchain.GetHeaderByNumber(uint64(blockNr))
   736  	statedb, err := api.blockchain.StateAt(header.Root)
   737  	if err != nil {
   738  		return 0, err
   739  	}
   740  	return statedb.GetNonce(address), nil
   741  }
   742  
   743  func (api *RetestethAPI) StorageRangeAt(ctx context.Context,
   744  	blockHashOrNumber *math.HexOrDecimal256, txIndex uint64,
   745  	address common.Address,
   746  	begin *math.HexOrDecimal256, maxResults uint64,
   747  ) (StorageRangeResult, error) {
   748  	var (
   749  		header *types.Header
   750  		block  *types.Block
   751  	)
   752  	if (*big.Int)(blockHashOrNumber).Cmp(big.NewInt(math.MaxInt64)) > 0 {
   753  		blockHash := common.BigToHash((*big.Int)(blockHashOrNumber))
   754  		header = api.blockchain.GetHeaderByHash(blockHash)
   755  		block = api.blockchain.GetBlockByHash(blockHash)
   756  		//fmt.Printf("Storage range: %x, txIndex %d, addr: %x, start: %x, maxResults: %d\n",
   757  		//	blockHash, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults)
   758  	} else {
   759  		blockNumber := (*big.Int)(blockHashOrNumber).Uint64()
   760  		header = api.blockchain.GetHeaderByNumber(blockNumber)
   761  		block = api.blockchain.GetBlockByNumber(blockNumber)
   762  		//fmt.Printf("Storage range: %d, txIndex %d, addr: %x, start: %x, maxResults: %d\n",
   763  		//	blockNumber, txIndex, address, common.BigToHash((*big.Int)(begin)), maxResults)
   764  	}
   765  	parentHeader := api.blockchain.GetHeaderByHash(header.ParentHash)
   766  	var root common.Hash
   767  	var statedb *state.StateDB
   768  	var err error
   769  	if parentHeader == nil || int(txIndex) >= len(block.Transactions()) {
   770  		root = header.Root
   771  		statedb, err = api.blockchain.StateAt(root)
   772  		if err != nil {
   773  			return StorageRangeResult{}, err
   774  		}
   775  	} else {
   776  		root = parentHeader.Root
   777  		statedb, err = api.blockchain.StateAt(root)
   778  		if err != nil {
   779  			return StorageRangeResult{}, err
   780  		}
   781  		// Recompute transactions up to the target index.
   782  		signer := types.MakeSigner(api.blockchain.Config(), block.Number())
   783  		for idx, tx := range block.Transactions() {
   784  			// Assemble the transaction call message and return if the requested offset
   785  			msg, _ := tx.AsMessage(signer)
   786  			context := core.NewEVMContext(msg, block.Header(), api.blockchain, nil)
   787  			// Not yet the searched for transaction, execute on top of the current state
   788  			vmenv := vm.NewEVM(context, statedb, api.blockchain.Config(), vm.Config{})
   789  			if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
   790  				return StorageRangeResult{}, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
   791  			}
   792  			// Ensure any modifications are committed to the state
   793  			// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
   794  			_ = statedb.IntermediateRoot(vmenv.ChainConfig().IsEIP158(block.Number()))
   795  			if idx == int(txIndex) {
   796  				// This is to make sure root can be opened by OpenTrie
   797  				_, err = statedb.Commit(vmenv.ChainConfig().IsEIP158(block.Number()))
   798  				if err != nil {
   799  					return StorageRangeResult{}, err
   800  				}
   801  			}
   802  		}
   803  	}
   804  	storageTrie := statedb.StorageTrie(address)
   805  	it := trie.NewIterator(storageTrie.NodeIterator(common.BigToHash((*big.Int)(begin)).Bytes()))
   806  	result := StorageRangeResult{Storage: make(map[common.Hash]SRItem)}
   807  	for i := 0; /*i < int(maxResults) && */ it.Next(); i++ {
   808  		if preimage := storageTrie.GetKey(it.Key); preimage != nil {
   809  			key := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(preimage))
   810  			v, _, err := rlp.SplitString(it.Value)
   811  			if err != nil {
   812  				return StorageRangeResult{}, err
   813  			}
   814  			value := (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(v))
   815  			ks, _ := key.MarshalText()
   816  			vs, _ := value.MarshalText()
   817  			if len(ks)%2 != 0 {
   818  				ks = append(append(append([]byte{}, ks[:2]...), byte('0')), ks[2:]...)
   819  			}
   820  			if len(vs)%2 != 0 {
   821  				vs = append(append(append([]byte{}, vs[:2]...), byte('0')), vs[2:]...)
   822  			}
   823  			result.Storage[common.BytesToHash(it.Key)] = SRItem{
   824  				Key:   string(ks),
   825  				Value: string(vs),
   826  			}
   827  		}
   828  	}
   829  	if it.Next() {
   830  		result.Complete = false
   831  	} else {
   832  		result.Complete = true
   833  	}
   834  	return result, nil
   835  }
   836  
   837  func (api *RetestethAPI) ClientVersion(ctx context.Context) (string, error) {
   838  	return "Geth-" + params.VersionWithCommit(gitCommit, gitDate), nil
   839  }
   840  
   841  // splitAndTrim splits input separated by a comma
   842  // and trims excessive white space from the substrings.
   843  func splitAndTrim(input string) []string {
   844  	result := strings.Split(input, ",")
   845  	for i, r := range result {
   846  		result[i] = strings.TrimSpace(r)
   847  	}
   848  	return result
   849  }
   850  
   851  func retesteth(ctx *cli.Context) error {
   852  	log.Info("Welcome to retesteth!")
   853  	// register signer API with server
   854  	var (
   855  		extapiURL string
   856  	)
   857  	apiImpl := &RetestethAPI{}
   858  	var testApi RetestethTestAPI = apiImpl
   859  	var ethApi RetestethEthAPI = apiImpl
   860  	var debugApi RetestethDebugAPI = apiImpl
   861  	var web3Api RetestWeb3API = apiImpl
   862  	rpcAPI := []rpc.API{
   863  		{
   864  			Namespace: "test",
   865  			Public:    true,
   866  			Service:   testApi,
   867  			Version:   "1.0",
   868  		},
   869  		{
   870  			Namespace: "eth",
   871  			Public:    true,
   872  			Service:   ethApi,
   873  			Version:   "1.0",
   874  		},
   875  		{
   876  			Namespace: "debug",
   877  			Public:    true,
   878  			Service:   debugApi,
   879  			Version:   "1.0",
   880  		},
   881  		{
   882  			Namespace: "web3",
   883  			Public:    true,
   884  			Service:   web3Api,
   885  			Version:   "1.0",
   886  		},
   887  	}
   888  	vhosts := splitAndTrim(ctx.GlobalString(utils.RPCVirtualHostsFlag.Name))
   889  	cors := splitAndTrim(ctx.GlobalString(utils.RPCCORSDomainFlag.Name))
   890  
   891  	// start http server
   892  	httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name))
   893  	listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, rpc.DefaultHTTPTimeouts)
   894  	if err != nil {
   895  		utils.Fatalf("Could not start RPC api: %v", err)
   896  	}
   897  	extapiURL = fmt.Sprintf("http://%s", httpEndpoint)
   898  	log.Info("HTTP endpoint opened", "url", extapiURL)
   899  
   900  	defer func() {
   901  		listener.Close()
   902  		log.Info("HTTP endpoint closed", "url", httpEndpoint)
   903  	}()
   904  
   905  	abortChan := make(chan os.Signal, 11)
   906  	signal.Notify(abortChan, os.Interrupt)
   907  
   908  	sig := <-abortChan
   909  	log.Info("Exiting...", "signal", sig)
   910  	return nil
   911  }