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