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