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