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