diff options
59 files changed, 865 insertions, 590 deletions
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index da307663c..6b4943fc0 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -34,7 +34,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/eth/filters" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -69,7 +70,9 @@ func NewSimulatedBackend(alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBac database := ethdb.NewMemDatabase() genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} genesis.MustCommit(database) - blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vmConfig, nil) backend := &SimulatedBackend{ database: database, @@ -282,13 +285,15 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call dexon.CallMsg, // Execute the call. msg := callmsg{call} - evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil) + evmContext := core.NewVMContext(msg, block.Header(), b.blockchain, nil) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(evmContext, statedb, b.config, vmConfig) gaspool := new(core.GasPool).AddGas(math.MaxUint64) - return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() + return core.NewStateTransition(&pack, msg, gaspool).TransitionDb() } // SendTransaction updates the pending block to include the given transaction. diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 48782b496..8fee6761a 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -32,7 +32,7 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/core/vm/evm/runtime" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/log" @@ -73,15 +73,15 @@ func runCmd(ctx *cli.Context) error { glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) log.Root().SetHandler(glogger) - logconfig := &vm.LogConfig{ + logconfig := &evm.LogConfig{ DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), DisableStack: ctx.GlobalBool(DisableStackFlag.Name), Debug: ctx.GlobalBool(DebugFlag.Name), } var ( - tracer vm.Tracer - debugLogger *vm.StructLogger + tracer evm.Tracer + debugLogger *evm.StructLogger statedb *state.StateDB chainConfig *params.ChainConfig sender = common.BytesToAddress([]byte("sender")) @@ -89,12 +89,12 @@ func runCmd(ctx *cli.Context) error { genesisConfig *core.Genesis ) if ctx.GlobalBool(MachineFlag.Name) { - tracer = vm.NewJSONLogger(logconfig, os.Stdout) + tracer = evm.NewJSONLogger(logconfig, os.Stdout) } else if ctx.GlobalBool(DebugFlag.Name) { - debugLogger = vm.NewStructLogger(logconfig) + debugLogger = evm.NewStructLogger(logconfig) tracer = debugLogger } else { - debugLogger = vm.NewStructLogger(logconfig) + debugLogger = evm.NewStructLogger(logconfig) } if ctx.GlobalString(GenesisFlag.Name) != "" { gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) @@ -170,7 +170,7 @@ func runCmd(ctx *cli.Context) error { Time: new(big.Int).SetUint64(genesisConfig.Timestamp), Coinbase: genesisConfig.Coinbase, BlockNumber: new(big.Int).SetUint64(genesisConfig.Number), - EVMConfig: vm.Config{ + EVMConfig: evm.Config{ Tracer: tracer, Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), }, @@ -227,10 +227,10 @@ func runCmd(ctx *cli.Context) error { if ctx.GlobalBool(DebugFlag.Name) { if debugLogger != nil { fmt.Fprintln(os.Stderr, "#### TRACE ####") - vm.WriteTrace(os.Stderr, debugLogger.StructLogs()) + evm.WriteTrace(os.Stderr, debugLogger.StructLogs()) } fmt.Fprintln(os.Stderr, "#### LOGS ####") - vm.WriteLogs(os.Stderr, statedb.Logs()) + evm.WriteLogs(os.Stderr, statedb.Logs()) } if ctx.GlobalBool(StatDumpFlag.Name) { diff --git a/cmd/evm/staterunner.go b/cmd/evm/staterunner.go index ee96a539c..19c39bdb9 100644 --- a/cmd/evm/staterunner.go +++ b/cmd/evm/staterunner.go @@ -24,7 +24,7 @@ import ( "os" "github.com/dexon-foundation/dexon/core/state" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/log" "github.com/dexon-foundation/dexon/tests" @@ -58,24 +58,24 @@ func stateTestCmd(ctx *cli.Context) error { log.Root().SetHandler(glogger) // Configure the EVM logger - config := &vm.LogConfig{ + config := &evm.LogConfig{ DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), DisableStack: ctx.GlobalBool(DisableStackFlag.Name), } var ( - tracer vm.Tracer - debugger *vm.StructLogger + tracer evm.Tracer + debugger *evm.StructLogger ) switch { case ctx.GlobalBool(MachineFlag.Name): - tracer = vm.NewJSONLogger(config, os.Stderr) + tracer = evm.NewJSONLogger(config, os.Stderr) case ctx.GlobalBool(DebugFlag.Name): - debugger = vm.NewStructLogger(config) + debugger = evm.NewStructLogger(config) tracer = debugger default: - debugger = vm.NewStructLogger(config) + debugger = evm.NewStructLogger(config) } // Load the test content from the input file src, err := ioutil.ReadFile(ctx.Args().First()) @@ -87,7 +87,7 @@ func stateTestCmd(ctx *cli.Context) error { return err } // Iterate over all the tests, run them and aggregate the results - cfg := vm.Config{ + cfg := evm.Config{ Tracer: tracer, Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), } @@ -116,7 +116,7 @@ func stateTestCmd(ctx *cli.Context) error { if ctx.GlobalBool(DebugFlag.Name) { if debugger != nil { fmt.Fprintln(os.Stderr, "#### TRACE ####") - vm.WriteTrace(os.Stderr, debugger.StructLogs()) + evm.WriteTrace(os.Stderr, debugger.StructLogs()) } } } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 03540a33c..6f60603be 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -37,7 +37,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/dashboard" "github.com/dexon-foundation/dexon/dex" @@ -1253,7 +1254,6 @@ func SetDexConfig(ctx *cli.Context, stack *node.Node, cfg *dex.Config) { // TODO(fjl): force-enable this in --dev mode cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) } - if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) { cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name) } @@ -1516,7 +1516,8 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 } - vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} + vmcfg := [vm.NUMS]interface{}{} + vmcfg[vm.EVM] = evm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil) if err != nil { Fatalf("Can't create BlockChain: %v", err) diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 4ea86a77f..96b074511 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -25,7 +25,8 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -448,7 +449,10 @@ func TestClique(t *testing.T) { batches[len(batches)-1] = append(batches[len(batches)-1], block) } // Pass all the headers through clique and ensure tallying succeeds - chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := core.NewBlockChain(db, nil, &config, engine, vmConfig, nil) if err != nil { t.Errorf("test %d: failed to create test chain: %v", i, err) continue diff --git a/core/bench_test.go b/core/bench_test.go index 98d46176a..30200ae17 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -28,7 +28,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -175,7 +176,9 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { // Time the insertion of the new chain. // State and blocks are stored in the same DB. - chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer chainman.Stop() b.ReportAllocs() b.ResetTimer() @@ -287,7 +290,9 @@ func benchReadChain(b *testing.B, full bool, count uint64) { if err != nil { b.Fatalf("error opening database at %v: %v", dir, err) } - chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vmConfig, nil) if err != nil { b.Fatalf("error creating chain: %v", err) } diff --git a/core/block_validator_test.go b/core/block_validator_test.go index 5ae85c796..667959cd5 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -23,7 +23,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" ) @@ -42,7 +43,9 @@ func TestHeaderVerification(t *testing.T) { headers[i] = block.Header() } // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces - chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vmConfig, nil) defer chain.Stop() for i := 0; i < len(blocks); i++ { @@ -106,11 +109,15 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) { var results <-chan error if valid { - chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vmConfig, nil) _, results = chain.engine.VerifyHeaders(chain, headers, seals) chain.Stop() } else { - chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vmConfig, nil) _, results = chain.engine.VerifyHeaders(chain, headers, seals) chain.Stop() } @@ -173,7 +180,9 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) { defer runtime.GOMAXPROCS(old) // Start the verifications and immediately abort - chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vmConfig, nil) defer chain.Stop() abort, results := chain.engine.VerifyHeaders(chain, headers, seals) diff --git a/core/blockchain.go b/core/blockchain.go index 8037834c1..489959691 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -41,7 +41,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -139,7 +140,7 @@ type BlockChain struct { engine consensus.Engine processor Processor // block processor interface validator Validator // block and state validator interface - vmConfig vm.Config + vmConfig [vm.NUMS]interface{} badBlocks *lru.Cache // Bad block cache shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. @@ -154,7 +155,7 @@ type BlockChain struct { // NewBlockChain returns a fully initialised block chain using information // available in the database. It initialises the default Ethereum Validator and // Processor. -func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) { +func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig [vm.NUMS]interface{}, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) { if cacheConfig == nil { cacheConfig = &CacheConfig{ TrieCleanLimit: 256, @@ -272,8 +273,8 @@ func (bc *BlockChain) getProcInterrupt() bool { } // GetVMConfig returns the block chain VM config. -func (bc *BlockChain) GetVMConfig() *vm.Config { - return &bc.vmConfig +func (bc *BlockChain) GetVMConfig() [vm.NUMS]interface{} { + return bc.vmConfig } // loadLastState loads the last known chain state from the database. This method @@ -1931,7 +1932,7 @@ func (bc *BlockChain) GetGovStateByHash(hash common.Hash) (*types.GovState, erro if err != nil { return nil, err } - return state.GetGovState(statedb, header, vm.GovernanceContractAddress) + return state.GetGovState(statedb, header, evm.GovernanceContractAddress) } func (bc *BlockChain) GetGovStateByNumber(number uint64) (*types.GovState, error) { @@ -1953,7 +1954,7 @@ func (bc *BlockChain) GetGovStateByNumber(number uint64) (*types.GovState, error if err != nil { return nil, err } - return state.GetGovState(statedb, header, vm.GovernanceContractAddress) + return state.GetGovState(statedb, header, evm.GovernanceContractAddress) } // reorg takes two blocks, an old chain and a new chain and will reconstruct the diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 349bf698f..dedfacda8 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -34,7 +34,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/core/vm/tools" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" @@ -63,7 +64,9 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *B genesis := g.MustCommit(db) // Initialize a fresh chain with only a genesis block - blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vmConfig, nil) // Create and inject the requested chain if n == 0 { return db, blockchain, nil @@ -163,7 +166,9 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error { if err != nil { return err } - receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + receipts, _, usedGas, err := blockchain.Processor().Process(block, statedb, vmConfig) if err != nil { blockchain.reportBlock(block, receipts, err) return err @@ -534,7 +539,10 @@ func testReorgBadHashes(t *testing.T, full bool) { blockchain.Stop() // Create a new BlockChain and check that it rolled back the state. - ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vmConfig, nil) if err != nil { t.Fatalf("failed to create new chain manager: %v", err) } @@ -646,7 +654,9 @@ func TestFastVsFullChains(t *testing.T) { // Import the chain as an archive node for the comparison baseline archiveDb := ethdb.NewMemDatabase() gspec.MustCommit(archiveDb) - archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer archive.Stop() if n, err := archive.InsertChain(blocks); err != nil { @@ -655,7 +665,9 @@ func TestFastVsFullChains(t *testing.T) { // Fast import the chain as a non-archive node to test fastDb := ethdb.NewMemDatabase() gspec.MustCommit(fastDb) - fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer fast.Stop() headers := make([]*types.Header, len(blocks)) @@ -733,7 +745,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { archiveDb := ethdb.NewMemDatabase() gspec.MustCommit(archiveDb) - archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) if n, err := archive.InsertChain(blocks); err != nil { t.Fatalf("failed to process block %d: %v", n, err) } @@ -746,7 +760,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { // Import the chain as a non-archive node and ensure all pointers are updated fastDb := ethdb.NewMemDatabase() gspec.MustCommit(fastDb) - fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer fast.Stop() headers := make([]*types.Header, len(blocks)) @@ -767,7 +783,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) { lightDb := ethdb.NewMemDatabase() gspec.MustCommit(lightDb) - light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) if n, err := light.InsertHeaderChain(headers, 1); err != nil { t.Fatalf("failed to insert header %d: %v", n, err) } @@ -836,7 +854,9 @@ func TestChainTxReorgs(t *testing.T) { } }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) if i, err := blockchain.InsertChain(chain); err != nil { t.Fatalf("failed to insert original chain[%d]: %v", i, err) } @@ -906,7 +926,10 @@ func TestLogReorgs(t *testing.T) { signer = types.NewEIP155Signer(gspec.Config.ChainID) ) code = tools.PatchBinary(code) - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() rmLogsCh := make(chan RemovedLogsEvent) @@ -983,7 +1006,9 @@ func TestLogRebirth(t *testing.T) { } } - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() logsCh := make(chan []*types.Log) @@ -1105,7 +1130,9 @@ func TestSideLogRebirth(t *testing.T) { } } - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() logsCh := make(chan []*types.Log) @@ -1160,7 +1187,9 @@ func TestReorgSideEvent(t *testing.T) { signer = types.NewEIP155Signer(gspec.Config.ChainID) ) - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) @@ -1290,7 +1319,9 @@ func TestEIP155Transition(t *testing.T) { genesis := gspec.MustCommit(db) - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { @@ -1399,7 +1430,9 @@ func TestEIP161AccountRemoval(t *testing.T) { gspec.Config.Dexcon = params.TestChainConfig.Dexcon genesis := gspec.MustCommit(db) - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { @@ -1477,7 +1510,9 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) { diskdb := ethdb.NewMemDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vmConfig, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1524,7 +1559,9 @@ func TestTrieForkGC(t *testing.T) { diskdb := ethdb.NewMemDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vmConfig, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1566,7 +1603,9 @@ func TestLargeReorgTrieGC(t *testing.T) { diskdb := ethdb.NewMemDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vmConfig, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1645,7 +1684,9 @@ func TestProcessBlock(t *testing.T) { engine := &dexconTest{ blockReward: big.NewInt(1e18), } - chain, err := NewBlockChain(db, nil, chainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(db, nil, chainConfig, engine, vmConfig, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } @@ -1847,7 +1888,9 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in diskdb := ethdb.NewMemDatabase() gspec.MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vmConfig, nil) if err != nil { b.Fatalf("failed to create tester chain: %v", err) } @@ -1936,7 +1979,9 @@ func TestLowDiffLongChain(t *testing.T) { diskdb := ethdb.NewMemDatabase() new(Genesis).MustCommit(diskdb) - chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vmConfig, nil) if err != nil { t.Fatalf("failed to create tester chain: %v", err) } diff --git a/core/chain_makers.go b/core/chain_makers.go index 50a537964..e1683a04f 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -27,6 +27,7 @@ import ( "github.com/dexon-foundation/dexon/consensus/misc" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -103,7 +104,9 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { b.SetCoinbase(common.Address{}) } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, evm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig) if err != nil { panic(err) } diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index 78c242df1..2b3643f43 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -22,7 +22,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -79,7 +80,9 @@ func ExampleGenerateChain() { }) // Import the chain. This runs all block validation rules. - blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vmConfig, nil) defer blockchain.Stop() if i, err := blockchain.InsertChain(chain); err != nil { diff --git a/core/dao_test.go b/core/dao_test.go index 7e437c1d9..b07a6bc07 100644 --- a/core/dao_test.go +++ b/core/dao_test.go @@ -21,7 +21,8 @@ import ( "testing" "github.com/dexon-foundation/dexon/consensus/ethash" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" ) @@ -46,7 +47,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { proConf.DAOForkBlock = forkBlock proConf.DAOForkSupport = true - proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vmConfig, nil) defer proBc.Stop() conDb := ethdb.NewMemDatabase() @@ -56,7 +59,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { conConf.DAOForkBlock = forkBlock conConf.DAOForkSupport = false - conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vmConfig, nil) defer conBc.Stop() if _, err := proBc.InsertChain(prefix); err != nil { @@ -70,7 +75,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Create a pro-fork block, and try to feed into the no-fork chain db = ethdb.NewMemDatabase() gspec.MustCommit(db) - bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vmConfig, nil) defer bc.Stop() blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) @@ -95,7 +102,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Create a no-fork block, and try to feed into the pro-fork chain db = ethdb.NewMemDatabase() gspec.MustCommit(db) - bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vmConfig, nil) defer bc.Stop() blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) @@ -121,7 +130,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Verify that contra-forkers accept pro-fork extra-datas after forking finishes db = ethdb.NewMemDatabase() gspec.MustCommit(db) - bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vmConfig, nil) defer bc.Stop() blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) @@ -141,7 +152,9 @@ func TestDAOForkRangeExtradata(t *testing.T) { // Verify that pro-forkers accept contra-fork extra-datas after forking finishes db = ethdb.NewMemDatabase() gspec.MustCommit(db) - bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil) + vmConfig = [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vmConfig, nil) defer bc.Stop() blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) diff --git a/core/dexon_chain_makers.go b/core/dexon_chain_makers.go index 6901a8bc2..e12c5921b 100644 --- a/core/dexon_chain_makers.go +++ b/core/dexon_chain_makers.go @@ -28,6 +28,7 @@ import ( "github.com/dexon-foundation/dexon/consensus" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -110,7 +111,9 @@ func (b *DexonBlockGen) ProcessTransactions(c ChainContext) { for _, tx := range b.txs { b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) // TODO: fix the chain context parameter - receipt, _, err := ApplyTransaction(b.config, c, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, evm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + receipt, _, err := ApplyTransaction(b.config, c, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig) if err != nil { panic(err) } diff --git a/core/evm.go b/core/evm.go index a2b61c535..6adf59881 100644 --- a/core/evm.go +++ b/core/evm.go @@ -45,8 +45,8 @@ type ChainContext interface { GetRoundHeight(uint64) (uint64, bool) } -// NewEVMContext creates a new context for use in the EVM. -func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) vm.Context { +// NewVMContext creates a new context for use in the EVM. +func NewVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) *vm.Context { // If we don't have an explicit author (i.e. not mining), extract from the header var beneficiary common.Address if author == nil { @@ -55,7 +55,7 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author beneficiary = *author } - return vm.Context{ + return &vm.Context{ CanTransfer: CanTransfer, Transfer: Transfer, GetHash: GetHashFn(header, chain), @@ -70,6 +70,7 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author Round: new(big.Int).SetUint64(header.Round), GasLimit: header.GasLimit, GasPrice: new(big.Int).Set(msg.GasPrice()), + IntPool: vm.NewIntPool(), } } diff --git a/core/genesis_test.go b/core/genesis_test.go index 718f65e9d..f0fd26701 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -25,7 +25,8 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core/rawdb" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" ) @@ -140,7 +141,9 @@ func TestSetupGenesis(t *testing.T) { // Advance to block #4, past the homestead transition block of customg. genesis := oldcustomg.MustCommit(db) - bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vmConfig, nil) defer bc.Stop() blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil) diff --git a/core/state_processor.go b/core/state_processor.go index ff2d5fbe4..20046c77a 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -22,7 +22,7 @@ import ( "github.com/dexon-foundation/dexon/consensus/misc" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/params" ) @@ -53,7 +53,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. -func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { +func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg [vm.NUMS]interface{}) (types.Receipts, []*types.Log, uint64, error) { var ( receipts types.Receipts usedGas = new(uint64) @@ -85,18 +85,18 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, vmConfig [vm.NUMS]interface{}) (*types.Receipt, uint64, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) if err != nil { return nil, 0, err } // Create a new context to be used in the EVM environment - context := NewEVMContext(msg, header, bc, author) + context := NewVMContext(msg, header, bc, author) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(context, statedb, config, cfg) + pack := vm.NewExecPack(context, statedb, config, vmConfig) // Apply the transaction to the current state (included in the env) - _, gas, failed, err := ApplyMessage(vmenv, msg, gp) + _, gas, failed, err := ApplyMessage(&pack, msg, gp) if err != nil { return nil, 0, err } @@ -116,7 +116,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo receipt.GasUsed = gas // if the transaction created a contract, store the creation address in the receipt. if msg.To() == nil { - receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce()) + receipt.ContractAddress = crypto.CreateAddress(pack.Context.Origin, tx.Nonce()) } // Set the receipt logs and create a bloom for filtering receipt.Logs = statedb.GetLogs(tx.Hash()) diff --git a/core/state_transition.go b/core/state_transition.go index 32589da90..7b5c782ed 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -71,7 +71,7 @@ type StateTransition struct { value *big.Int data []byte state vm.StateDB - evm *evm.EVM + execPack *vm.ExecPack } // Message represents a message sent to a contract. @@ -123,15 +123,15 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) } // NewStateTransition initialises and returns a new state transition object. -func NewStateTransition(evm *evm.EVM, msg Message, gp *GasPool) *StateTransition { +func NewStateTransition(pack *vm.ExecPack, msg Message, gp *GasPool) *StateTransition { return &StateTransition{ gp: gp, - evm: evm, + execPack: pack, msg: msg, gasPrice: msg.GasPrice(), value: msg.Value(), data: msg.Data(), - state: evm.StateDB, + state: pack.StateDB, } } @@ -142,8 +142,8 @@ func NewStateTransition(evm *evm.EVM, msg Message, gp *GasPool) *StateTransition // the gas used (which includes gas refunds) and an error if it failed. An error always // indicates a core error meaning that the message would always fail for that particular // state and would never be accepted within a block. -func ApplyMessage(evm *evm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) { - return NewStateTransition(evm, msg, gp).TransitionDb() +func ApplyMessage(pack *vm.ExecPack, msg Message, gp *GasPool) ([]byte, uint64, bool, error) { + return NewStateTransition(pack, msg, gp).TransitionDb() } // to returns the recipient of the message. @@ -201,14 +201,14 @@ func (st *StateTransition) inExtendedRound() bool { if h := lastInExtendedRoundResultCache.Load(); h != nil { res := h.(*lastInExtendedRoundResultType) - if res.Height == st.evm.BlockNumber.Uint64() { + if res.Height == st.execPack.Context.BlockNumber.Uint64() { return res.Result } } gs := evm.GovernanceState{st.state} - round := st.evm.Round.Uint64() + round := st.execPack.Context.Round.Uint64() if round < dexCore.ConfigRoundShift { round = 0 } else { @@ -216,23 +216,23 @@ func (st *StateTransition) inExtendedRound() bool { } configHeight := gs.RoundHeight(new(big.Int).SetUint64(round)) - state, err := st.evm.StateAtNumber(configHeight.Uint64()) + state, err := st.execPack.Context.StateAtNumber(configHeight.Uint64()) if err != nil { panic(err) } rgs := evm.GovernanceState{state} - roundEnd := gs.RoundHeight(st.evm.Round).Uint64() + rgs.RoundLength().Uint64() + roundEnd := gs.RoundHeight(st.execPack.Context.Round).Uint64() + rgs.RoundLength().Uint64() // Round 0 starts and height 0 instead of height 1. if round == 0 { - roundEnd += 1 + roundEnd++ } - res := st.evm.BlockNumber.Uint64() >= roundEnd + res := st.execPack.Context.BlockNumber.Uint64() >= roundEnd lastInExtendedRoundResultCache.Store(&lastInExtendedRoundResultType{ - Height: st.evm.BlockNumber.Uint64(), + Height: st.execPack.Context.BlockNumber.Uint64(), Result: res, }) return res @@ -247,7 +247,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo } msg := st.msg sender := vm.AccountRef(msg.From()) - homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber) + homestead := st.execPack.ChainConfig.IsHomestead(st.execPack.Context.BlockNumber) contractCreation := msg.To() == nil // Pay intrinsic gas @@ -266,13 +266,14 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo // error. vmerr error ) - i := st.evm.Interpreter().(*evm.EVMInterpreter) if contractCreation { - ret, _, st.gas, vmerr = vm.Create(sender, st.data, st.gas, st.value, i) + ret, _, st.gas, vmerr = vm.Create(sender, st.data, st.gas, + st.value, st.execPack) } else { // Increment the nonce for the next transaction st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) - ret, st.gas, vmerr = vm.Call(sender, st.to(), st.data, st.gas, st.value, i) + ret, st.gas, vmerr = vm.Call(sender, st.to(), st.data, st.gas, + st.value, st.execPack) } if vmerr != nil { log.Debug("VM returned with error", "err", vmerr) @@ -290,7 +291,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo st.dexonRefundGas() } - receiver := st.evm.Coinbase + receiver := st.execPack.Context.Coinbase if !*legacyEvm && st.inExtendedRound() { gs := evm.GovernanceState{st.state} receiver = gs.Owner() diff --git a/core/types.go b/core/types.go index b020a5df7..be0d4401c 100644 --- a/core/types.go +++ b/core/types.go @@ -20,7 +20,7 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" ) // Validator is an interface which defines the standard for block validation. It @@ -46,5 +46,5 @@ type Validator interface { // of gas used in the process and return an error if any of the internal rules // failed. type Processor interface { - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) + Process(block *types.Block, statedb *state.StateDB, vmConfig [vm.NUMS]interface{}) (types.Receipts, []*types.Log, uint64, error) } diff --git a/core/vm/evm/evm.go b/core/vm/evm/evm.go index e1c8c02ed..679d70b64 100644 --- a/core/vm/evm/evm.go +++ b/core/vm/evm/evm.go @@ -32,54 +32,7 @@ import ( var emptyCodeHash = crypto.Keccak256Hash(nil) func init() { - vm.Register(vm.EVM, &EVMImplement{}) -} - -type EVMImplement struct{} - -func (evmImpl *EVMImplement) Create(caller vm.ContractRef, code []byte, gas uint64, - value *big.Int, interpreter vm.Interpreter) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - i := interpreter.(*EVMInterpreter) - return i.evm.Create(caller, code, gas, value) -} - -func (evmImpl *EVMImplement) Create2(caller vm.ContractRef, code []byte, gas uint64, - endowment *big.Int, salt *big.Int, - interpreter vm.Interpreter) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - - i := interpreter.(*EVMInterpreter) - return i.evm.Create2(caller, code, gas, endowment, salt) -} - -func (evmImpl *EVMImplement) Call(caller vm.ContractRef, addr common.Address, - input []byte, gas uint64, value *big.Int, - interpreter vm.Interpreter) (ret []byte, leftOverGas uint64, err error) { - i := interpreter.(*EVMInterpreter) - return i.evm.Call(caller, addr, input, gas, value) - -} -func (evmImpl *EVMImplement) CallCode(caller vm.ContractRef, addr common.Address, - input []byte, gas uint64, value *big.Int, - interpreter vm.Interpreter) (ret []byte, leftOverGas uint64, err error) { - - i := interpreter.(*EVMInterpreter) - return i.evm.CallCode(caller, addr, input, gas, value) -} - -func (evmImpl *EVMImplement) DelegateCall(caller vm.ContractRef, addr common.Address, - input []byte, gas uint64, - interpreter vm.Interpreter) (ret []byte, leftOverGas uint64, err error) { - - i := interpreter.(*EVMInterpreter) - return i.evm.DelegateCall(caller, addr, input, gas) -} - -func (evmImpl *EVMImplement) StaticCall(caller vm.ContractRef, addr common.Address, - input []byte, gas uint64, - interpreter vm.Interpreter) (ret []byte, leftovergas uint64, err error) { - - i := interpreter.(*EVMInterpreter) - return i.evm.StaticCall(caller, addr, input, gas) + vm.Register(vm.EVM, NewEVM) } // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. @@ -123,11 +76,9 @@ func run(evm *EVM, contract *vm.Contract, input []byte, readOnly bool) ([]byte, // The EVM should never be reused and is not thread safe. type EVM struct { // Context provides auxiliary blockchain related information - vm.Context + *vm.Context // StateDB gives access to the underlying state StateDB vm.StateDB - // Depth is the current call stack - depth int // chainConfig contains information about the current chain chainConfig *params.ChainConfig @@ -143,19 +94,16 @@ type EVM struct { // abort is used to abort the EVM calling operations // NOTE: must be set atomically abort int32 - // callGasTemp holds the gas available for the current call. This is needed because the - // available gas is calculated in gasCall* according to the 63/64 rule and later - // applied in opCall*. - callGasTemp uint64 } // NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -func NewEVM(ctx vm.Context, statedb vm.StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { +func NewEVM(ctx *vm.Context, statedb vm.StateDB, chainConfig *params.ChainConfig, vmConfig interface{}) vm.VM { + cfg := vmConfig.(Config) evm := &EVM{ Context: ctx, StateDB: statedb, - vmConfig: vmConfig, + vmConfig: cfg, chainConfig: chainConfig, chainRules: chainConfig.Rules(ctx.BlockNumber), interpreters: make([]Interpreter, 0, 1), @@ -179,7 +127,7 @@ func NewEVM(ctx vm.Context, statedb vm.StateDB, chainConfig *params.ChainConfig, // vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here // as we always want to have the built-in EVM as the failover option. - evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) + evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, cfg)) evm.interpreter = evm.interpreters[0] return evm @@ -200,17 +148,17 @@ func (evm *EVM) Interpreter() Interpreter { // parameters. It also handles any necessary value transfer required and takes // the necessary steps to create accounts and reverses the state in case of an // execution error or failed value transfer. -func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { +func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int, pack *vm.ExecPack) (ret []byte, leftOverGas uint64, err error) { + if evm.NoRecursion && evm.Depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit - if evm.depth > int(params.CallCreateDepth) { + if evm.Depth > int(params.CallCreateDepth) { return nil, gas, vm.ErrDepth } // Fail if we're trying to transfer more than the available balance - if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { + if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { return nil, gas, vm.ErrInsufficientBalance } @@ -226,7 +174,7 @@ func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, g if precompiles[addr] == nil && OracleContracts[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { // Calling a non existing account, don't do anything, but ping the tracer - if evm.vmConfig.Debug && evm.depth == 0 { + if evm.vmConfig.Debug && evm.Depth == 0 { evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) } @@ -248,7 +196,7 @@ func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, g start := time.Now() // Capture the tracer start/end events in debug mode - if evm.vmConfig.Debug && evm.depth == 0 { + if evm.vmConfig.Debug && evm.Depth == 0 { evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) defer func() { // Lazy evaluation of the parameters @@ -276,13 +224,13 @@ func (evm *EVM) Call(caller vm.ContractRef, addr common.Address, input []byte, g // // CallCode differs from Call in the sense that it executes the given address' // code with the caller as context. -func (evm *EVM) CallCode(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { +func (evm *EVM) CallCode(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int, pack *vm.ExecPack) (ret []byte, leftOverGas uint64, err error) { + if evm.NoRecursion && evm.Depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit - if evm.depth > int(params.CallCreateDepth) { + if evm.Depth > int(params.CallCreateDepth) { return nil, gas, vm.ErrDepth } // Fail if we're trying to transfer more than the available balance @@ -320,12 +268,12 @@ func (evm *EVM) CallCode(caller vm.ContractRef, addr common.Address, input []byt // // DelegateCall differs from CallCode in the sense that it executes the given address' // code with the caller as context and the caller is set to the caller of the caller. -func (evm *EVM) DelegateCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { +func (evm *EVM) DelegateCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, pack *vm.ExecPack) (ret []byte, leftOverGas uint64, err error) { + if evm.NoRecursion && evm.Depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit - if evm.depth > int(params.CallCreateDepth) { + if evm.Depth > int(params.CallCreateDepth) { return nil, gas, vm.ErrDepth } @@ -357,12 +305,17 @@ func (evm *EVM) DelegateCall(caller vm.ContractRef, addr common.Address, input [ // as parameters while disallowing any modifications to the state during the call. // Opcodes that attempt to perform such modifications will result in exceptions // instead of performing the modifications. -func (evm *EVM) StaticCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { - if evm.vmConfig.NoRecursion && evm.depth > 0 { +func (evm *EVM) StaticCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, pack *vm.ExecPack) (ret []byte, leftOverGas uint64, err error) { + oldReadOnly := pack.Context.ReadOnly + pack.Context.ReadOnly = true + defer func() { + pack.Context.ReadOnly = oldReadOnly + }() + if evm.NoRecursion && evm.Depth > 0 { return nil, gas, nil } // Fail if we're trying to execute above the call depth limit - if evm.depth > int(params.CallCreateDepth) { + if evm.Depth > int(params.CallCreateDepth) { return nil, gas, vm.ErrDepth } @@ -404,7 +357,7 @@ func (evm *EVM) StaticCall(caller vm.ContractRef, addr common.Address, input []b func (evm *EVM) create(caller vm.ContractRef, codeAndHash *vm.CodeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { // Depth check execution. Fail if we're trying to execute above the // limit. - if evm.depth > int(params.CallCreateDepth) { + if evm.Depth > int(params.CallCreateDepth) { return nil, common.Address{}, gas, vm.ErrDepth } if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { @@ -432,11 +385,11 @@ func (evm *EVM) create(caller vm.ContractRef, codeAndHash *vm.CodeAndHash, gas u contract := vm.NewContract(caller, vm.AccountRef(address), value, gas) contract.SetCodeOptionalHash(&address, codeAndHash) - if evm.vmConfig.NoRecursion && evm.depth > 0 { + if evm.NoRecursion && evm.Depth > 0 { return nil, address, gas, nil } - if evm.vmConfig.Debug && evm.depth == 0 { + if evm.vmConfig.Debug && evm.Depth == 0 { evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.Code, gas, value) } start := time.Now() @@ -470,7 +423,7 @@ func (evm *EVM) create(caller vm.ContractRef, codeAndHash *vm.CodeAndHash, gas u if maxCodeSizeExceeded && err == nil { err = errMaxCodeSizeExceeded } - if evm.vmConfig.Debug && evm.depth == 0 { + if evm.vmConfig.Debug && evm.Depth == 0 { evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) } return ret, address, contract.Gas, err @@ -478,7 +431,7 @@ func (evm *EVM) create(caller vm.ContractRef, codeAndHash *vm.CodeAndHash, gas u } // Create creates a new contract using code as deployment code. -func (evm *EVM) Create(caller vm.ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { +func (evm *EVM) Create(caller vm.ContractRef, code []byte, gas uint64, value *big.Int, pack *vm.ExecPack) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) return evm.create(caller, &vm.CodeAndHash{Code: code}, gas, value, contractAddr) } @@ -487,7 +440,7 @@ func (evm *EVM) Create(caller vm.ContractRef, code []byte, gas uint64, value *bi // // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. -func (evm *EVM) Create2(caller vm.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { +func (evm *EVM) Create2(caller vm.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int, pack *vm.ExecPack) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { codeAndHash := &vm.CodeAndHash{Code: code} contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes()) return evm.create(caller, codeAndHash, gas, endowment, contractAddr) @@ -496,5 +449,8 @@ func (evm *EVM) Create2(caller vm.ContractRef, code []byte, gas uint64, endowmen // ChainConfig returns the environment's chain configuration func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } +// VMConfig returns the vm configuration. +func (evm *EVM) VMConfig() Config { return evm.vmConfig } + // IsBlockProposer returns whether or not we are a block proposer. func (evm *EVM) IsBlockProposer() bool { return evm.vmConfig.IsBlockProposer } diff --git a/core/vm/evm/evm_test.go b/core/vm/evm/evm_test.go index ef5e8a6b0..7fee1d435 100644 --- a/core/vm/evm/evm_test.go +++ b/core/vm/evm/evm_test.go @@ -91,15 +91,14 @@ func newTestVM() *testVM { Time: big.NewInt(time.Now().UnixNano() / 1000000000), BlockNumber: big.NewInt(0), } - - env := NewEVM(context, stateDB, params.TestChainConfig, Config{}) - evmInterpreter := NewEVMInterpreter(env, env.vmConfig) - - env.interpreter = evmInterpreter + vmConfig := [vmlib.NUMS]interface{}{} + vmConfig[vmlib.EVM] = Config{} + p := vmlib.NewExecPack(&context, stateDB, params.TestChainConfig, vmConfig) + evm := p.VMList[vmlib.EVM].(*EVM) return &testVM{ - evm: env, - interpreter: evmInterpreter, + evm: evm, + interpreter: NewEVMInterpreter(evm, evm.vmConfig), } } diff --git a/core/vm/evm/gas_table.go b/core/vm/evm/gas_table.go index 242494537..f0bf26726 100644 --- a/core/vm/evm/gas_table.go +++ b/core/vm/evm/gas_table.go @@ -415,11 +415,11 @@ func gasCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm.Stac return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.CallGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + if gas, overflow = math.SafeAdd(gas, evm.CallGasTemp); overflow { return 0, errGasUintOverflow } return gas, nil @@ -439,11 +439,11 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *vm. return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.CallGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + if gas, overflow = math.SafeAdd(gas, evm.CallGasTemp); overflow { return 0, errGasUintOverflow } return gas, nil @@ -493,11 +493,11 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.CallGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + if gas, overflow = math.SafeAdd(gas, evm.CallGasTemp); overflow { return 0, errGasUintOverflow } return gas, nil @@ -513,11 +513,11 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *vm.Contract, stack *v return 0, errGasUintOverflow } - evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) + evm.CallGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0)) if err != nil { return 0, err } - if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow { + if gas, overflow = math.SafeAdd(gas, evm.CallGasTemp); overflow { return 0, errGasUintOverflow } return gas, nil diff --git a/core/vm/evm/instructions.go b/core/vm/evm/instructions.go index ce95d2446..23e59aa4b 100644 --- a/core/vm/evm/instructions.go +++ b/core/vm/evm/instructions.go @@ -55,7 +55,7 @@ func opAdd(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor x, y := stack.Pop(), stack.Peek() math.U256(y.Add(x, y)) - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -63,7 +63,7 @@ func opSub(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor x, y := stack.Pop(), stack.Peek() math.U256(y.Sub(x, y)) - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -71,7 +71,7 @@ func opMul(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor x, y := stack.Pop(), stack.Pop() stack.Push(math.U256(x.Mul(x, y))) - interpreter.intPool.Put(y) + interpreter.evm.IntPool.Put(y) return nil, nil } @@ -83,13 +83,13 @@ func opDiv(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor } else { y.SetUint64(0) } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { x, y := math.S256(stack.Pop()), math.S256(stack.Pop()) - res := interpreter.intPool.GetZero() + res := interpreter.evm.IntPool.GetZero() if y.Sign() == 0 || x.Sign() == 0 { stack.Push(res) @@ -102,7 +102,7 @@ func opSdiv(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo } stack.Push(math.U256(res)) } - interpreter.intPool.Put(x, y) + interpreter.evm.IntPool.Put(x, y) return nil, nil } @@ -113,13 +113,13 @@ func opMod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor } else { stack.Push(math.U256(x.Mod(x, y))) } - interpreter.intPool.Put(y) + interpreter.evm.IntPool.Put(y) return nil, nil } func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { x, y := math.S256(stack.Pop()), math.S256(stack.Pop()) - res := interpreter.intPool.GetZero() + res := interpreter.evm.IntPool.GetZero() if y.Sign() == 0 { stack.Push(res) @@ -132,7 +132,7 @@ func opSmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo } stack.Push(math.U256(res)) } - interpreter.intPool.Put(x, y) + interpreter.evm.IntPool.Put(x, y) return nil, nil } @@ -140,12 +140,12 @@ func opExp(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor base, exponent := stack.Pop(), stack.Pop() if base.Cmp(big2) == 0 && exponent.Cmp(big256) == -1 { exp := exponent.Int64() - stack.Push(interpreter.intPool.Get().Set(power2[exp])) + stack.Push(interpreter.evm.IntPool.Get().Set(power2[exp])) } else { stack.Push(math.Exp(base, exponent)) } - interpreter.intPool.Put(base, exponent) + interpreter.evm.IntPool.Put(base, exponent) return nil, nil } @@ -166,7 +166,7 @@ func opSignExtend(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract stack.Push(math.U256(num)) } - interpreter.intPool.Put(back) + interpreter.evm.IntPool.Put(back) return nil, nil } @@ -183,7 +183,7 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory } else { y.SetUint64(0) } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -194,7 +194,7 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory } else { y.SetUint64(0) } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -218,7 +218,7 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor y.SetUint64(0) } } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -242,7 +242,7 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor y.SetUint64(0) } } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -253,7 +253,7 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory } else { y.SetUint64(0) } - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -271,7 +271,7 @@ func opAnd(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor x, y := stack.Pop(), stack.Pop() stack.Push(x.And(x, y)) - interpreter.intPool.Put(y) + interpreter.evm.IntPool.Put(y) return nil, nil } @@ -279,7 +279,7 @@ func opOr(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory x, y := stack.Pop(), stack.Peek() y.Or(x, y) - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -287,7 +287,7 @@ func opXor(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor x, y := stack.Pop(), stack.Peek() y.Xor(x, y) - interpreter.intPool.Put(x) + interpreter.evm.IntPool.Put(x) return nil, nil } @@ -299,7 +299,7 @@ func opByte(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo } else { val.SetUint64(0) } - interpreter.intPool.Put(th) + interpreter.evm.IntPool.Put(th) return nil, nil } @@ -312,7 +312,7 @@ func opAddmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me } else { stack.Push(x.SetUint64(0)) } - interpreter.intPool.Put(y, z) + interpreter.evm.IntPool.Put(y, z) return nil, nil } @@ -325,7 +325,7 @@ func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me } else { stack.Push(x.SetUint64(0)) } - interpreter.intPool.Put(y, z) + interpreter.evm.IntPool.Put(y, z) return nil, nil } @@ -335,7 +335,7 @@ func opMulmod(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards shift, value := math.U256(stack.Pop()), math.U256(stack.Peek()) - defer interpreter.intPool.Put(shift) // First operand back into the pool + defer interpreter.evm.IntPool.Put(shift) // First operand back into the pool if shift.Cmp(common.Big256) >= 0 { value.SetUint64(0) @@ -353,7 +353,7 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { // Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards shift, value := math.U256(stack.Pop()), math.U256(stack.Peek()) - defer interpreter.intPool.Put(shift) // First operand back into the pool + defer interpreter.evm.IntPool.Put(shift) // First operand back into the pool if shift.Cmp(common.Big256) >= 0 { value.SetUint64(0) @@ -371,7 +371,7 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memor func opSAR(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { // Note, S256 returns (potentially) a new bigint, so we're popping, not peeking this one shift, value := math.U256(stack.Pop()), math.S256(stack.Pop()) - defer interpreter.intPool.Put(shift) // First operand back into the pool + defer interpreter.evm.IntPool.Put(shift) // First operand back into the pool if shift.Cmp(common.Big256) >= 0 { if value.Sign() >= 0 { @@ -405,9 +405,9 @@ func opSha3(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo if evm.vmConfig.EnablePreimageRecording { evm.StateDB.AddPreimage(interpreter.hasherBuf, data) } - stack.Push(interpreter.intPool.Get().SetBytes(interpreter.hasherBuf[:])) + stack.Push(interpreter.evm.IntPool.Get().SetBytes(interpreter.hasherBuf[:])) - interpreter.intPool.Put(offset, size) + interpreter.evm.IntPool.Put(offset, size) return nil, nil } @@ -421,7 +421,7 @@ func opRand(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo binaryUsedIndex := make([]byte, binary.MaxVarintLen64) binary.PutUvarint(binaryUsedIndex, evm.RandCallIndex) - evm.RandCallIndex += 1 + evm.RandCallIndex++ hash := crypto.Keccak256( evm.Randomness, @@ -429,7 +429,7 @@ func opRand(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo binaryOriginNonce, binaryUsedIndex) - stack.Push(interpreter.intPool.Get().SetBytes(hash)) + stack.Push(interpreter.evm.IntPool.Get().SetBytes(hash)) return nil, nil } @@ -455,17 +455,17 @@ func opCaller(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me } func opCallValue(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().Set(contract.Value)) + stack.Push(interpreter.evm.IntPool.Get().Set(contract.Value)) return nil, nil } func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetBytes(vm.GetDataBig(contract.Input, stack.Pop(), big32))) + stack.Push(interpreter.evm.IntPool.Get().SetBytes(vm.GetDataBig(contract.Input, stack.Pop(), big32))) return nil, nil } func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetInt64(int64(len(contract.Input)))) + stack.Push(interpreter.evm.IntPool.Get().SetInt64(int64(len(contract.Input)))) return nil, nil } @@ -477,12 +477,12 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contra ) memory.Set(memOffset.Uint64(), length.Uint64(), vm.GetDataBig(contract.Input, dataOffset, length)) - interpreter.intPool.Put(memOffset, dataOffset, length) + interpreter.evm.IntPool.Put(memOffset, dataOffset, length) return nil, nil } func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetUint64(uint64(len(interpreter.returnData)))) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(uint64(len(interpreter.returnData)))) return nil, nil } @@ -491,9 +491,9 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Cont memOffset = stack.Pop() dataOffset = stack.Pop() length = stack.Pop() - end = interpreter.intPool.Get().Add(dataOffset, length) + end = interpreter.evm.IntPool.Get().Add(dataOffset, length) ) - defer interpreter.intPool.Put(memOffset, dataOffset, length, end) + defer interpreter.evm.IntPool.Put(memOffset, dataOffset, length, end) if end.BitLen() > 64 || uint64(len(interpreter.returnData)) < end.Uint64() { return nil, errReturnDataOutOfBounds @@ -511,7 +511,7 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contrac } func opCodeSize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - l := interpreter.intPool.Get().SetInt64(int64(len(contract.Code))) + l := interpreter.evm.IntPool.Get().SetInt64(int64(len(contract.Code))) stack.Push(l) return nil, nil @@ -526,7 +526,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, codeCopy := vm.GetDataBig(contract.Code, codeOffset, length) memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) - interpreter.intPool.Put(memOffset, codeOffset, length) + interpreter.evm.IntPool.Put(memOffset, codeOffset, length) return nil, nil } @@ -540,7 +540,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contrac codeCopy := vm.GetDataBig(interpreter.evm.StateDB.GetCode(addr), codeOffset, length) memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) - interpreter.intPool.Put(memOffset, codeOffset, length) + interpreter.evm.IntPool.Put(memOffset, codeOffset, length) return nil, nil } @@ -582,20 +582,20 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contrac } func opGasprice(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().Set(interpreter.evm.GasPrice)) + stack.Push(interpreter.evm.IntPool.Get().Set(interpreter.evm.GasPrice)) return nil, nil } func opBlockhash(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { num := stack.Pop() - n := interpreter.intPool.Get().Sub(interpreter.evm.BlockNumber, common.Big257) + n := interpreter.evm.IntPool.Get().Sub(interpreter.evm.BlockNumber, common.Big257) if num.Cmp(n) > 0 && num.Cmp(interpreter.evm.BlockNumber) < 0 { stack.Push(interpreter.evm.GetHash(num.Uint64()).Big()) } else { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } - interpreter.intPool.Put(num, n) + interpreter.evm.IntPool.Put(num, n) return nil, nil } @@ -605,36 +605,36 @@ func opCoinbase(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, } func opTimestamp(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Time))) + stack.Push(math.U256(interpreter.evm.IntPool.Get().Set(interpreter.evm.Time))) return nil, nil } func opNumber(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.BlockNumber))) + stack.Push(math.U256(interpreter.evm.IntPool.Get().Set(interpreter.evm.BlockNumber))) return nil, nil } func opDifficulty(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(math.U256(interpreter.intPool.Get().Set(interpreter.evm.Difficulty))) + stack.Push(math.U256(interpreter.evm.IntPool.Get().Set(interpreter.evm.Difficulty))) return nil, nil } func opGasLimit(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(math.U256(interpreter.intPool.Get().SetUint64(interpreter.evm.GasLimit))) + stack.Push(math.U256(interpreter.evm.IntPool.Get().SetUint64(interpreter.evm.GasLimit))) return nil, nil } func opPop(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - interpreter.intPool.Put(stack.Pop()) + interpreter.evm.IntPool.Put(stack.Pop()) return nil, nil } func opMload(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { offset := stack.Pop() - val := interpreter.intPool.Get().SetBytes(memory.Get(offset.Int64(), 32)) + val := interpreter.evm.IntPool.Get().SetBytes(memory.Get(offset.Int64(), 32)) stack.Push(val) - interpreter.intPool.Put(offset) + interpreter.evm.IntPool.Put(offset) return nil, nil } @@ -643,7 +643,7 @@ func opMstore(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me mStart, val := stack.Pop(), stack.Pop() memory.Set32(mStart.Uint64(), val) - interpreter.intPool.Put(mStart, val) + interpreter.evm.IntPool.Put(mStart, val) return nil, nil } @@ -666,7 +666,7 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me val := stack.Pop() interpreter.evm.StateDB.SetState(contract.Address(), loc, common.BigToHash(val)) - interpreter.intPool.Put(val) + interpreter.evm.IntPool.Put(val) return nil, nil } @@ -678,7 +678,7 @@ func opJump(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo } *pc = pos.Uint64() - interpreter.intPool.Put(pos) + interpreter.evm.IntPool.Put(pos) return nil, nil } @@ -694,7 +694,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, mem *pc++ } - interpreter.intPool.Put(pos, cond) + interpreter.evm.IntPool.Put(pos, cond) return nil, nil } @@ -703,17 +703,17 @@ func opJumpdest(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, } func opPc(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetUint64(*pc)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(*pc)) return nil, nil } func opMsize(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetInt64(int64(memory.Len()))) + stack.Push(interpreter.evm.IntPool.Get().SetInt64(int64(memory.Len()))) return nil, nil } func opGas(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Push(interpreter.intPool.Get().SetUint64(contract.Gas)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(contract.Gas)) return nil, nil } @@ -729,20 +729,20 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me gas -= gas / 64 } contract.UseGas(gas) - res, addr, returnGas, suberr := vm.Create(contract, input, gas, value, interpreter) + res, addr, returnGas, suberr := vm.Create(contract, input, gas, value, interpreter.evm.ExecPack) // Push item on the stack based on the returned error. If the ruleset is // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must // ignore this error and pretend the operation was successful. if interpreter.evm.ChainConfig().IsHomestead(interpreter.evm.BlockNumber) && suberr == vm.ErrCodeStoreOutOfGas { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else if suberr != nil && suberr != vm.ErrCodeStoreOutOfGas { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { stack.Push(addr.Big()) } contract.Gas += returnGas - interpreter.intPool.Put(value, offset, size) + interpreter.evm.IntPool.Put(value, offset, size) if suberr == errExecutionReverted { return res, nil @@ -762,15 +762,15 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, m // Apply EIP150 gas -= gas / 64 contract.UseGas(gas) - res, addr, returnGas, suberr := vm.Create2(contract, input, gas, endowment, salt, interpreter) + res, addr, returnGas, suberr := vm.Create2(contract, input, gas, endowment, salt, interpreter.evm.ExecPack) // Push item on the stack based on the returned error. if suberr != nil { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { stack.Push(addr.Big()) } contract.Gas += returnGas - interpreter.intPool.Put(endowment, offset, size, salt) + interpreter.evm.IntPool.Put(endowment, offset, size, salt) if suberr == errExecutionReverted { return res, nil @@ -779,9 +779,9 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, m } func opCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - // Pop gas. The actual gas in interpreter.evm.callGasTemp. - interpreter.intPool.Put(stack.Pop()) - gas := interpreter.evm.callGasTemp + // Pop gas. The actual gas in interpreter.evm.CallGasTemp. + interpreter.evm.IntPool.Put(stack.Pop()) + gas := interpreter.evm.CallGasTemp // Pop other call parameters. addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop() toAddr := common.BigToAddress(addr) @@ -792,25 +792,25 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memo if value.Sign() != 0 { gas += params.CallStipend } - ret, returnGas, err := vm.Call(contract, toAddr, args, gas, value, interpreter) + ret, returnGas, err := vm.Call(contract, toAddr, args, gas, value, interpreter.evm.ExecPack) if err != nil { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { - stack.Push(interpreter.intPool.Get().SetUint64(1)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } contract.Gas += returnGas - interpreter.intPool.Put(addr, value, inOffset, inSize, retOffset, retSize) + interpreter.evm.IntPool.Put(addr, value, inOffset, inSize, retOffset, retSize) return ret, nil } func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - interpreter.intPool.Put(stack.Pop()) - gas := interpreter.evm.callGasTemp + // Pop gas. The actual gas is in interpreter.evm.CallGasTemp. + interpreter.evm.IntPool.Put(stack.Pop()) + gas := interpreter.evm.CallGasTemp // Pop other call parameters. addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop() toAddr := common.BigToAddress(addr) @@ -821,68 +821,68 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, if value.Sign() != 0 { gas += params.CallStipend } - ret, returnGas, err := vm.CallCode(contract, toAddr, args, gas, value, interpreter) + ret, returnGas, err := vm.CallCode(contract, toAddr, args, gas, value, interpreter.evm.ExecPack) if err != nil { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { - stack.Push(interpreter.intPool.Get().SetUint64(1)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } contract.Gas += returnGas - interpreter.intPool.Put(addr, value, inOffset, inSize, retOffset, retSize) + interpreter.evm.IntPool.Put(addr, value, inOffset, inSize, retOffset, retSize) return ret, nil } func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - interpreter.intPool.Put(stack.Pop()) - gas := interpreter.evm.callGasTemp + // Pop gas. The actual gas is in interpreter.evm.CallGasTemp. + interpreter.evm.IntPool.Put(stack.Pop()) + gas := interpreter.evm.CallGasTemp // Pop other call parameters. addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop() toAddr := common.BigToAddress(addr) // Get arguments from the memory. args := memory.Get(inOffset.Int64(), inSize.Int64()) - ret, returnGas, err := vm.DelegateCall(contract, toAddr, args, gas, interpreter) + ret, returnGas, err := vm.DelegateCall(contract, toAddr, args, gas, interpreter.evm.ExecPack) if err != nil { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { - stack.Push(interpreter.intPool.Get().SetUint64(1)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } contract.Gas += returnGas - interpreter.intPool.Put(addr, inOffset, inSize, retOffset, retSize) + interpreter.evm.IntPool.Put(addr, inOffset, inSize, retOffset, retSize) return ret, nil } func opStaticCall(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - // Pop gas. The actual gas is in interpreter.evm.callGasTemp. - interpreter.intPool.Put(stack.Pop()) - gas := interpreter.evm.callGasTemp + // Pop gas. The actual gas is in interpreter.evm.CallGasTemp. + interpreter.evm.IntPool.Put(stack.Pop()) + gas := interpreter.evm.CallGasTemp // Pop other call parameters. addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop() toAddr := common.BigToAddress(addr) // Get arguments from the memory. args := memory.Get(inOffset.Int64(), inSize.Int64()) - ret, returnGas, err := vm.StaticCall(contract, toAddr, args, gas, interpreter) + ret, returnGas, err := vm.StaticCall(contract, toAddr, args, gas, interpreter.evm.ExecPack) if err != nil { - stack.Push(interpreter.intPool.GetZero()) + stack.Push(interpreter.evm.IntPool.GetZero()) } else { - stack.Push(interpreter.intPool.Get().SetUint64(1)) + stack.Push(interpreter.evm.IntPool.Get().SetUint64(1)) } if err == nil || err == errExecutionReverted { memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) } contract.Gas += returnGas - interpreter.intPool.Put(addr, inOffset, inSize, retOffset, retSize) + interpreter.evm.IntPool.Put(addr, inOffset, inSize, retOffset, retSize) return ret, nil } @@ -890,7 +890,7 @@ func opReturn(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me offset, size := stack.Pop(), stack.Pop() ret := memory.GetPtr(offset.Int64(), size.Int64()) - interpreter.intPool.Put(offset, size) + interpreter.evm.IntPool.Put(offset, size) return ret, nil } @@ -898,7 +898,7 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, me offset, size := stack.Pop(), stack.Pop() ret := memory.GetPtr(offset.Int64(), size.Int64()) - interpreter.intPool.Put(offset, size) + interpreter.evm.IntPool.Put(offset, size) return ret, nil } @@ -935,7 +935,7 @@ func makeLog(size int) executionFunc { BlockNumber: interpreter.evm.BlockNumber.Uint64(), }) - interpreter.intPool.Put(mStart, mSize) + interpreter.evm.IntPool.Put(mStart, mSize) return nil, nil } } @@ -955,7 +955,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { endMin = startMin + pushByteSize } - integer := interpreter.intPool.Get() + integer := interpreter.evm.IntPool.Get() stack.Push(integer.SetBytes(common.RightPadBytes(contract.Code[startMin:endMin], pushByteSize))) *pc += size @@ -966,7 +966,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { // make dup instruction function func makeDup(size int64) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error) { - stack.Dup(interpreter.intPool, int(size)) + stack.Dup(interpreter.evm.IntPool, int(size)) return nil, nil } } diff --git a/core/vm/evm/instructions_test.go b/core/vm/evm/instructions_test.go index bd3df271d..78d175aa9 100644 --- a/core/vm/evm/instructions_test.go +++ b/core/vm/evm/instructions_test.go @@ -35,14 +35,15 @@ type twoOperandTest struct { func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error)) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - pc = uint64(0) - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() + pc = uint64(0) ) - - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{IntPool: vm.NewIntPool()} + pack := vm.NewExecPack(vmctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) for i, test := range tests { x := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) shift := new(big.Int).SetBytes(common.Hex2Bytes(test.y)) @@ -57,13 +58,13 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 // Check pool usage // 1.pool is not allowed to contain anything on the stack // 2.pool is not allowed to contain the same pointers twice - if evmInterpreter.intPool.Pool.Len() > 0 { + if evm.IntPool.Pool.Len() > 0 { poolvals := make(map[*big.Int]struct{}) poolvals[actual] = struct{}{} - for evmInterpreter.intPool.Pool.Len() > 0 { - key := evmInterpreter.intPool.Get() + for evm.IntPool.Pool.Len() > 0 { + key := evm.IntPool.Get() if _, exist := poolvals[key]; exist { t.Errorf("Testcase %d, pool contains double-entry", i) } @@ -71,18 +72,19 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 } } } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.IntPool) } func TestByteOp(t *testing.T) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() ) - - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{IntPool: vm.NewIntPool()} + pack := vm.NewExecPack(vmctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) tests := []struct { v string th uint64 @@ -109,7 +111,7 @@ func TestByteOp(t *testing.T) { t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.v, test.th, test.expected, actual) } } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.IntPool) } func TestSHL(t *testing.T) { @@ -211,13 +213,15 @@ func TestSLT(t *testing.T) { func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *vm.Contract, memory *vm.Memory, stack *vm.Stack) ([]byte, error), args ...string) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{IntPool: vm.NewIntPool()} + pack := vm.NewExecPack(vmctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() // convert args byteArgs := make([][]byte, len(args)) for i, arg := range args { @@ -233,7 +237,7 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpret op(&pc, evmInterpreter, nil, nil, stack) stack.Pop() } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.IntPool) } func BenchmarkOpAdd64(b *testing.B) { @@ -446,14 +450,16 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - mem = vm.NewMemory() - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() + mem = vm.NewMemory() ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + ctx := &vm.Context{IntPool: vm.NewIntPool()} + pack := vm.NewExecPack(ctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() mem.Resize(64) pc := uint64(0) v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" @@ -467,19 +473,22 @@ func TestOpMstore(t *testing.T) { if common.Bytes2Hex(mem.Get(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { t.Fatalf("Mstore failed to overwrite previous value") } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.IntPool) } func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - mem = vm.NewMemory() - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() + mem = vm.NewMemory() ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{} + vmctx.IntPool = vm.NewIntPool() + pack := vm.NewExecPack(vmctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() mem.Resize(64) pc := uint64(0) memStart := big.NewInt(0) @@ -490,18 +499,21 @@ func BenchmarkOpMstore(bench *testing.B) { stack.PushN(value, memStart) opMstore(&pc, evmInterpreter, nil, mem, stack) } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.Context.IntPool) } func BenchmarkOpSHA3(bench *testing.B) { var ( - env = NewEVM(vm.Context{}, nil, params.TestChainConfig, Config{}) - stack = NewStack() - mem = vm.NewMemory() - evmInterpreter = NewEVMInterpreter(env, env.vmConfig) + stack = NewStack() + mem = vm.NewMemory() ) - env.interpreter = evmInterpreter - evmInterpreter.intPool = vm.PoolOfIntPools.Get() + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{} + vmctx.IntPool = vm.NewIntPool() + pack := vm.NewExecPack(vmctx, nil, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + evmInterpreter := NewEVMInterpreter(evm, vmConfig[vm.EVM].(Config)) mem.Resize(32) pc := uint64(0) start := big.NewInt(0) @@ -511,7 +523,7 @@ func BenchmarkOpSHA3(bench *testing.B) { stack.PushN(big.NewInt(32), start) opSha3(&pc, evmInterpreter, nil, mem, stack) } - vm.PoolOfIntPools.Put(evmInterpreter.intPool) + vm.PoolOfIntPools.Put(evm.IntPool) } func TestCreate2Addreses(t *testing.T) { diff --git a/core/vm/evm/interpreter.go b/core/vm/evm/interpreter.go index 9ed647c00..bcbd8b024 100644 --- a/core/vm/evm/interpreter.go +++ b/core/vm/evm/interpreter.go @@ -27,15 +27,11 @@ import ( "github.com/dexon-foundation/dexon/params" ) -// Config are the configuration options for the Interpreter type Config struct { // Debug enabled debugging Interpreter options Debug bool // Tracer is the op code logger Tracer Tracer - // NoRecursion disabled Interpreter call, callcode, - // delegate call and create. - NoRecursion bool // Enable recording of SHA3/keccak preimages EnablePreimageRecording bool // JumpTable contains the EVM instruction table. This @@ -88,12 +84,9 @@ type EVMInterpreter struct { cfg Config gasTable params.GasTable - intPool *vm.IntPool - hasher keccakState // Keccak256 hasher instance shared across opcodes hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes - readOnly bool // Whether to throw on stateful modifications returnData []byte // Last CALL's return data for subsequent reuse } @@ -114,17 +107,16 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { cfg.JumpTable = frontierInstructionSet } } - return &EVMInterpreter{ evm: evm, - cfg: cfg, gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), + cfg: cfg, } } func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *vm.Stack) error { if in.evm.chainRules.IsByzantium { - if in.readOnly { + if in.evm.ReadOnly { // If the interpreter is operating in readonly mode, make sure no // state-modifying operation is performed. The 3rd stack item // for a call operation is the value. Transferring value from one @@ -145,23 +137,23 @@ func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, st // considered a revert-and-consume-all-gas operation except for // errExecutionReverted which means revert-and-keep-gas-left. func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool) (ret []byte, err error) { - if in.intPool == nil { - in.intPool = vm.PoolOfIntPools.Get() + if in.evm.IntPool == nil { + in.evm.IntPool = vm.PoolOfIntPools.Get() defer func() { - vm.PoolOfIntPools.Put(in.intPool) - in.intPool = nil + vm.PoolOfIntPools.Put(in.evm.IntPool) + in.evm.IntPool = nil }() } // Increment the call depth which is restricted to 1024 - in.evm.depth++ - defer func() { in.evm.depth-- }() + in.evm.Depth++ + defer func() { in.evm.Depth-- }() // Make sure the readOnly is only set if we aren't in readOnly yet. // This makes also sure that the readOnly flag isn't removed for child calls. - if readOnly && !in.readOnly { - in.readOnly = true - defer func() { in.readOnly = false }() + if readOnly && !in.evm.ReadOnly { + in.evm.ReadOnly = true + defer func() { in.evm.ReadOnly = false }() } // Reset the previous call's return data. It's unimportant to preserve the old buffer @@ -189,17 +181,17 @@ func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool contract.Input = input // Reclaim the stack as an int pool when the execution stops defer func() { - in.intPool.Put(stack.Data...) + in.evm.IntPool.Put(stack.Data...) Recyclestack(stack) }() - if in.cfg.Debug { + if in.evm.vmConfig.Debug { defer func() { if err != nil { if !logged { - in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + in.evm.vmConfig.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.Depth, err) } else { - in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + in.evm.vmConfig.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.Depth, err) } } }() @@ -209,7 +201,7 @@ func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool // the execution of one of the operations or until the done flag is set by the // parent context. for atomic.LoadInt32(&in.evm.abort) == 0 { - if in.cfg.Debug { + if in.evm.vmConfig.Debug { // Capture pre-execution values for tracing. logged, pcCopy, gasCopy = false, pc, contract.Gas } @@ -254,8 +246,8 @@ func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool mem.Resize(memorySize) } - if in.cfg.Debug { - in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) + if in.evm.vmConfig.Debug { + in.evm.vmConfig.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.Depth, err) logged = true } @@ -264,7 +256,7 @@ func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool // verifyPool is a build flag. Pool verification makes sure the integrity // of the integer pool by comparing values to a default value. if vm.VerifyPool { - vm.VerifyIntegerPool(in.intPool) + vm.VerifyIntegerPool(in.evm.IntPool) } // if the operation clears the return data (e.g. it has returning data) // set the last return to the result of the operation. @@ -292,8 +284,3 @@ func (in *EVMInterpreter) Run(contract *vm.Contract, input []byte, readOnly bool func (in *EVMInterpreter) CanRun(code []byte) bool { return true } - -// StateDB return StateDB stored in evm -func (in *EVMInterpreter) StateDB() vm.StateDB { - return in.evm.StateDB -} diff --git a/core/vm/evm/logger_test.go b/core/vm/evm/logger_test.go index 3a293675b..782fcd11f 100644 --- a/core/vm/evm/logger_test.go +++ b/core/vm/evm/logger_test.go @@ -51,16 +51,19 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 } func TestStoreCapture(t *testing.T) { var ( - env = NewEVM(vm.Context{}, &dummyStatedb{}, params.TestChainConfig, Config{}) logger = NewStructLogger(nil) mem = vm.NewMemory() stack = NewStack() contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 0) ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{} + vmctx := &vm.Context{IntPool: vm.NewIntPool()} + pack := vm.NewExecPack(vmctx, &dummyStatedb{}, params.TestChainConfig, vmConfig) stack.Push(big.NewInt(1)) stack.Push(big.NewInt(0)) var index common.Hash - logger.CaptureState(env, 0, SSTORE, 0, 0, mem, stack, contract, 0, nil) + logger.CaptureState(pack.VMList[vm.EVM].(*EVM), 0, SSTORE, 0, 0, mem, stack, contract, 0, nil) if len(logger.changedValues[contract.Address()]) == 0 { t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(), len(logger.changedValues[contract.Address()])) } diff --git a/core/vm/evm/oracle_contracts_test.go b/core/vm/evm/oracle_contracts_test.go index 41bf0fb58..55a011f33 100644 --- a/core/vm/evm/oracle_contracts_test.go +++ b/core/vm/evm/oracle_contracts_test.go @@ -249,8 +249,11 @@ func (g *OracleContractsTestSuite) call( g.context.Time = big.NewInt(time.Now().UnixNano() / 1000000) - evm := NewEVM(g.context, g.stateDB, params.TestChainConfig, Config{IsBlockProposer: true}) - ret, _, err := evm.Call(vm.AccountRef(caller), contractAddr, input, 10000000, value) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = Config{IsBlockProposer: true} + pack := vm.NewExecPack(&g.context, g.stateDB, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*EVM) + ret, _, err := evm.Call(vm.AccountRef(caller), contractAddr, input, 10000000, value, &pack) return ret, err } @@ -1102,7 +1105,7 @@ func (g *OracleContractsTestSuite) TestResetDKG() { g.s.PutDKGSuccess(addr, true) g.s.IncDKGSuccessesCount() } - i += 1 + i++ } dkgSetSize := len(dkgSet) g.Require().Len(g.s.DKGMasterPublicKeys(), dkgSetSize) diff --git a/core/vm/evm/runtime/env.go b/core/vm/evm/runtime/env.go index 92cc8681c..a7a8f6b6c 100644 --- a/core/vm/evm/runtime/env.go +++ b/core/vm/evm/runtime/env.go @@ -20,15 +20,14 @@ import ( "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/vm" - "github.com/dexon-foundation/dexon/core/vm/evm" ) -func NewEnv(cfg *Config) *evm.EVM { +// NewExecPack is a wrapper for creating ExecPack. +func NewExecPack(cfg *Config) vm.ExecPack { context := vm.Context{ CanTransfer: core.CanTransfer, Transfer: core.Transfer, GetHash: func(uint64) common.Hash { return common.Hash{} }, - Origin: cfg.Origin, Coinbase: cfg.Coinbase, BlockNumber: cfg.BlockNumber, @@ -37,6 +36,7 @@ func NewEnv(cfg *Config) *evm.EVM { GasLimit: cfg.GasLimit, GasPrice: cfg.GasPrice, } - - return evm.NewEVM(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = cfg.EVMConfig + return vm.NewExecPack(&context, cfg.State, cfg.ChainConfig, vmConfig) } diff --git a/core/vm/evm/runtime/runtime.go b/core/vm/evm/runtime/runtime.go index c89f9dd11..3745f001b 100644 --- a/core/vm/evm/runtime/runtime.go +++ b/core/vm/evm/runtime/runtime.go @@ -5,8 +5,7 @@ // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, +// // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. @@ -104,19 +103,20 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { } var ( address = common.BytesToAddress([]byte("contract")) - vmenv = NewEnv(cfg) + pack = NewExecPack(cfg) sender = vm.AccountRef(cfg.Origin) ) cfg.State.CreateAccount(address) // set the receiver's (the executing contract) code for execution. cfg.State.SetCode(address, code) // Call the code with the given configuration. - ret, _, err := vmenv.Call( + ret, _, err := pack.VMList[vm.EVM].(*evm.EVM).Call( sender, common.BytesToAddress([]byte("contract")), input, cfg.GasLimit, cfg.Value, + &pack, ) return ret, cfg.State, err @@ -133,16 +133,17 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) } var ( - vmenv = NewEnv(cfg) + pack = NewExecPack(cfg) sender = vm.AccountRef(cfg.Origin) ) // Call the code with the given configuration. - code, address, leftOverGas, err := vmenv.Create( + code, address, leftOverGas, err := pack.VMList[vm.EVM].(*evm.EVM).Create( sender, input, cfg.GasLimit, cfg.Value, + &pack, ) return code, address, leftOverGas, err } @@ -155,16 +156,17 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) { setDefaults(cfg) - vmenv := NewEnv(cfg) - + pack := NewExecPack(cfg) + e := pack.VMList[vm.EVM].(*evm.EVM) sender := cfg.State.GetOrNewStateObject(cfg.Origin) // Call the code with the given configuration. - ret, leftOverGas, err := vmenv.Call( + ret, leftOverGas, err := e.Call( sender, address, input, cfg.GasLimit, cfg.Value, + &pack, ) return ret, leftOverGas, err diff --git a/core/vm/evm/runtime/runtime_test.go b/core/vm/evm/runtime/runtime_test.go index 762f3601d..46e4a934d 100644 --- a/core/vm/evm/runtime/runtime_test.go +++ b/core/vm/evm/runtime/runtime_test.go @@ -29,6 +29,7 @@ import ( "github.com/dexon-foundation/dexon/core/vm/tools" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" + "github.com/stretchr/testify/assert" ) func TestDefaults(t *testing.T) { @@ -121,6 +122,55 @@ func TestCall(t *testing.T) { } } +func TestStaticCallAndRand(t *testing.T) { + state, _ := state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) + address := common.HexToAddress("0x0a") + address2 := common.HexToAddress("0x0b") + code := []byte{ + byte(vm.EVM), + byte(evm.PUSH1), 0, // StaticCall retSize + byte(evm.PUSH1), 0, // StaticCall retOffset + byte(evm.PUSH1), 0, // StaticCall inputSize + byte(evm.PUSH1), 0, // StaticCall inputOffset + byte(evm.PUSH20), + } + code = append(code, address2.Bytes()...) + code = append(code, + byte(evm.PUSH1), 0xff, // StaticCall gas + byte(evm.STATICCALL), + byte(evm.RAND), + byte(evm.RETURN), + ) + state.SetCode(address, code) + + state.SetCode(address2, []byte{ + byte(vm.EVM), + byte(evm.RAND), + byte(evm.RETURN), + }) + + cfg := &Config{ + State: state, + } + setDefaults(cfg) + cfg.ChainConfig.ByzantiumBlock = new(big.Int).SetUint64(0) + + pack := NewExecPack(cfg) + e := pack.VMList[vm.EVM] + sender := cfg.State.GetOrNewStateObject(cfg.Origin) + _, _, err := e.Call( + sender, + address, + nil, + cfg.GasLimit, + cfg.Value, + &pack, + ) + assert.Equal(t, nil, err) + assert.Equal(t, uint64(2), pack.Context.RandCallIndex) + assert.Equal(t, false, pack.Context.ReadOnly) +} + func BenchmarkCall(b *testing.B) { var definition = `[{"constant":true,"inputs":[],"name":"seller","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"abort","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[],"name":"refund","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"buyer","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmReceived","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"name":"","type":"uint8"}],"type":"function"},{"constant":false,"inputs":[],"name":"confirmPurchase","outputs":[],"type":"function"},{"inputs":[],"type":"constructor"},{"anonymous":false,"inputs":[],"name":"Aborted","type":"event"},{"anonymous":false,"inputs":[],"name":"PurchaseConfirmed","type":"event"},{"anonymous":false,"inputs":[],"name":"ItemReceived","type":"event"},{"anonymous":false,"inputs":[],"name":"Refunded","type":"event"}]` diff --git a/core/vm/intpool.go b/core/vm/intpool.go index 9e73b8b71..5a2d6383f 100644 --- a/core/vm/intpool.go +++ b/core/vm/intpool.go @@ -23,6 +23,7 @@ import ( var checkVal = big.NewInt(-42) +// PoolLimit is the size of stack of IntPool const PoolLimit = 256 // IntPool is a Pool of big integers that @@ -31,11 +32,12 @@ type IntPool struct { Pool *Stack } -func newIntPool() *IntPool { +// NewIntPool return an IntPool instance. +func NewIntPool() *IntPool { return &IntPool{Pool: &Stack{Data: make([]*big.Int, 0, 1024)}} } -// get retrieves a big int from the Pool, allocating one if the Pool is empty. +// Get retrieves a big int from the Pool, allocating one if the Pool is empty. // Note, the returned int's value is arbitrary and will not be zeroed! func (p *IntPool) Get() *big.Int { if p.Pool.Len() > 0 { @@ -44,7 +46,7 @@ func (p *IntPool) Get() *big.Int { return new(big.Int) } -// getZero retrieves a big int from the Pool, setting it to zero or allocating +// GetZero retrieves a big int from the Pool, setting it to zero or allocating // a new one if the Pool is empty. func (p *IntPool) GetZero() *big.Int { if p.Pool.Len() > 0 { @@ -53,7 +55,7 @@ func (p *IntPool) GetZero() *big.Int { return new(big.Int) } -// put returns an allocated big int to the Pool to be later reused by get calls. +// Put returns an allocated big int to the Pool to be later reused by get calls. // Note, the values as saved as is; neither put nor get zeroes the ints out! func (p *IntPool) Put(is ...*big.Int) { if len(p.Pool.Data) > PoolLimit { @@ -69,7 +71,7 @@ func (p *IntPool) Put(is ...*big.Int) { } } -// The IntPool Pool's default capacity +// PoolDefaultCap is the IntPool Pool's default capacity const PoolDefaultCap = 25 // IntPoolPool manages a Pool of IntPools. @@ -78,11 +80,12 @@ type IntPoolPool struct { lock sync.Mutex } +// PoolOfIntPools is an instance of IntPoolPool. var PoolOfIntPools = &IntPoolPool{ Pools: make([]*IntPool, 0, PoolDefaultCap), } -// get is looking for an available Pool to return. +// Get is looking for an available Pool to return. func (ipp *IntPoolPool) Get() *IntPool { ipp.lock.Lock() defer ipp.lock.Unlock() @@ -92,10 +95,10 @@ func (ipp *IntPoolPool) Get() *IntPool { ipp.Pools = ipp.Pools[:len(ipp.Pools)-1] return ip } - return newIntPool() + return NewIntPool() } -// put a Pool that has been allocated with get. +// Put a Pool that has been allocated with get. func (ipp *IntPoolPool) Put(ip *IntPool) { ipp.lock.Lock() defer ipp.lock.Unlock() diff --git a/core/vm/sqlvm/sqlvm.go b/core/vm/sqlvm/sqlvm.go index fe2eee42b..26aeeab0b 100644 --- a/core/vm/sqlvm/sqlvm.go +++ b/core/vm/sqlvm/sqlvm.go @@ -8,60 +8,65 @@ import ( "github.com/dexon-foundation/dexon/params" ) +// SQLVM implements the required VM interface. type SQLVM struct { // Context provides auxiliary blockchain related information - vm.Context + *vm.Context // StateDB gives access to the underlying state StateDB vm.StateDB - // Depth is the current call stack - depth int - // chainConfig contains information about the current chain - chainConfig *params.ChainConfig - // chain rules contains the chain rules for the current epoch - chainRules params.Rules // abort is used to abort the SQLVM calling operations // NOTE: must be set atomically abort int32 - // callGasTemp holds the gas available for the current call. This is needed because the - // available gas is calculated in gasCall* according to the 63/64 rule and later - // applied in opCall*. - callGasTemp uint64 } func init() { - vm.Register(vm.SQLVM, &SQLVM{}) + vm.Register(vm.SQLVM, NewSQLVM) } +// NewSQLVM is the SQLVM constructor. +func NewSQLVM(context *vm.Context, stateDB vm.StateDB, chainConfig *params.ChainConfig, vmConfig interface{}) vm.VM { + return &SQLVM{Context: context, StateDB: stateDB} +} + +// Create creates SQL contract. func (sqlvm *SQLVM) Create(caller vm.ContractRef, code []byte, gas uint64, value *big.Int, - in vm.Interpreter) ([]byte, common.Address, uint64, error) { + pack *vm.ExecPack) ([]byte, common.Address, uint64, error) { // todo (jm) need to implemnt return nil, common.Address{}, gas, nil } +// Create2 mock interface. func (sqlvm *SQLVM) Create2(caller vm.ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int, - in vm.Interpreter) ([]byte, common.Address, uint64, error) { + pack *vm.ExecPack) ([]byte, common.Address, uint64, error) { // todo (jm) need to implemnt return nil, common.Address{}, gas, nil } + +// Call is the entry to call SQLVM contract. func (sqlvm *SQLVM) Call(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int, - in vm.Interpreter) ([]byte, uint64, error) { + pack *vm.ExecPack) ([]byte, uint64, error) { // todo (jm) need to implemnt return nil, gas, nil } + +// CallCode mock interface. func (sqlvm *SQLVM) CallCode(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, - value *big.Int, in vm.Interpreter) ([]byte, uint64, error) { + value *big.Int, pack *vm.ExecPack) ([]byte, uint64, error) { // todo (jm) need to implemnt return nil, gas, nil } +// DelegateCall mock interface. func (sqlvm *SQLVM) DelegateCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, - in vm.Interpreter) ([]byte, uint64, error) { + pack *vm.ExecPack) ([]byte, uint64, error) { // todo (jm) need to implemnt return nil, gas, nil } + +// StaticCall is the entry for read-only call on SQL contract. func (sqlvm *SQLVM) StaticCall(caller vm.ContractRef, addr common.Address, input []byte, gas uint64, - in vm.Interpreter) ([]byte, uint64, error) { + pack *vm.ExecPack) ([]byte, uint64, error) { // todo (jm) need to implemnt return nil, gas, nil } diff --git a/core/vm/stateDB.go b/core/vm/stateDB.go index 753b04247..7d8aed69b 100644 --- a/core/vm/stateDB.go +++ b/core/vm/stateDB.go @@ -16,7 +16,7 @@ type ( // GetHashFunc returns the nth block hash in the blockchain // and is used by the BLOCKHASH EVM op code. GetHashFunc func(uint64) common.Hash - // StateAtFunc returns the statedb given a root hash. + // StateAtNumberFunc returns the statedb given a root hash. StateAtNumberFunc func(uint64) (*state.StateDB, error) // GetRoundHeightFunc returns the round height. GetRoundHeightFunc func(uint64) (uint64, bool) @@ -50,7 +50,22 @@ type Context struct { Difficulty *big.Int // Provides information for DIFFICULTY Round *big.Int // Current round number. - RandCallIndex uint64 // Number of times opRand is called + // NoRecursion disabled Interpreter call, callcode, + // delegate call and create. + NoRecursion bool + // Depth is the current call stack + Depth int + // Whether to throw on stateful modifications + ReadOnly bool + // Number of times opRand is called + RandCallIndex uint64 + IntPool *IntPool + // CallGasTemp holds the gas available for the current call. This is needed because the + // available gas is calculated in gasCall* according to the 63/64 rule and later + // applied in opCall*. + CallGasTemp uint64 + + ExecPack *ExecPack } // StateDB is an EVM database for full state querying. diff --git a/core/vm/vm.go b/core/vm/vm.go index 99ab2ed90..780320d2b 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -4,93 +4,131 @@ import ( "math/big" "github.com/dexon-foundation/dexon/common" + "github.com/dexon-foundation/dexon/params" ) const ( - EVM = byte(iota) + // EVM enum + EVM = uint8(iota) + + // SQLVM enum SQLVM ) var ( + // MULTIVM flag MULTIVM = true ) +// NUMS represents the number of supported VM type. +const NUMS = 2 + +// VM Create and Call interface. type VM interface { Create(ContractRef, []byte, uint64, *big.Int, - Interpreter) ([]byte, common.Address, uint64, error) + *ExecPack) ([]byte, common.Address, uint64, error) Create2(ContractRef, []byte, uint64, *big.Int, *big.Int, - Interpreter) ([]byte, common.Address, uint64, error) + *ExecPack) ([]byte, common.Address, uint64, error) Call(ContractRef, common.Address, []byte, uint64, *big.Int, - Interpreter) ([]byte, uint64, error) + *ExecPack) ([]byte, uint64, error) CallCode(ContractRef, common.Address, []byte, uint64, - *big.Int, Interpreter) ([]byte, uint64, error) + *big.Int, *ExecPack) ([]byte, uint64, error) DelegateCall(ContractRef, common.Address, []byte, uint64, - Interpreter) ([]byte, uint64, error) + *ExecPack) ([]byte, uint64, error) StaticCall(ContractRef, common.Address, []byte, uint64, - Interpreter) ([]byte, uint64, error) + *ExecPack) ([]byte, uint64, error) } -type Interpreter interface { - StateDB() StateDB +type createFunc func(*Context, StateDB, *params.ChainConfig, interface{}) VM + +// ExecPack contains runtime context, stateDB, chain config, VM list and VM configs. +type ExecPack struct { + Context *Context + StateDB StateDB + ChainConfig *params.ChainConfig + VMList [NUMS]VM + VMConfig [NUMS]interface{} } -var vmList map[byte]VM +var createFuncs [NUMS]createFunc -func init() { - vmList = make(map[byte]VM) +// Register registers VM create function. +func Register(idx uint8, c createFunc) { + createFuncs[idx] = c } -func Register(vmType byte, vm VM) { - vmList[vmType] = vm + +// NewExecPack creates a ExecPack instance, and create all VM instance. +func NewExecPack(context *Context, stateDB StateDB, chainConfig *params.ChainConfig, vmConfigs [NUMS]interface{}) ExecPack { + p := ExecPack{ + Context: context, + StateDB: stateDB, + ChainConfig: chainConfig, + VMConfig: vmConfigs, + } + context.ExecPack = &p + for i := 0; i < NUMS; i++ { + if createFuncs[i] != nil { + p.VMList[i] = createFuncs[i](context, stateDB, chainConfig, vmConfigs[i]) + } + } + return p } + +// Create is the entry for multiple VMs' Create. func Create(caller ContractRef, code []byte, gas uint64, value *big.Int, - interpreter Interpreter) (ret []byte, contractAddr common.Address, + p *ExecPack) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - name, code := getVMAndCode(code) - return vmList[name].Create(caller, code, gas, value, interpreter) + v, code := getVMAndCode(code) + return p.VMList[v].Create(caller, code, gas, value, p) } +// Create2 is the entry for multiple VMs' Create2. func Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, - salt *big.Int, interpreter Interpreter) (ret []byte, + salt *big.Int, p *ExecPack) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - name, code := getVMAndCode(code) - return vmList[name].Create2(caller, code, gas, endowment, salt, interpreter) + v, code := getVMAndCode(code) + return p.VMList[v].Create2(caller, code, gas, endowment, salt, p) } +// Call is the entry for multiple VMs' Call. func Call(caller ContractRef, addr common.Address, input []byte, gas uint64, - value *big.Int, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + value *big.Int, p *ExecPack) (ret []byte, leftOverGas uint64, err error) { - code := interpreter.StateDB().GetCode(addr) - name, _ := getVMAndCode(code) - return vmList[name].Call(caller, addr, input, gas, value, interpreter) + code := p.StateDB.GetCode(addr) + v, _ := getVMAndCode(code) + return p.VMList[v].Call(caller, addr, input, gas, value, p) } +// CallCode is the entry for multiple VMs' CallCode. func CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, - value *big.Int, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + value *big.Int, p *ExecPack) (ret []byte, leftOverGas uint64, err error) { - code := interpreter.StateDB().GetCode(addr) - name, _ := getVMAndCode(code) - return vmList[name].CallCode(caller, addr, input, gas, value, interpreter) + code := p.StateDB.GetCode(addr) + v, _ := getVMAndCode(code) + return p.VMList[v].CallCode(caller, addr, input, gas, value, p) } +// DelegateCall is the entry for multiple VMs' DelegateCall. func DelegateCall(caller ContractRef, addr common.Address, input []byte, - gas uint64, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + gas uint64, p *ExecPack) (ret []byte, leftOverGas uint64, err error) { - code := interpreter.StateDB().GetCode(addr) - name, _ := getVMAndCode(code) - return vmList[name].DelegateCall(caller, addr, input, gas, interpreter) + code := p.StateDB.GetCode(addr) + v, _ := getVMAndCode(code) + return p.VMList[v].DelegateCall(caller, addr, input, gas, p) } +// StaticCall is the entry for multiple VMs' StaticCall. func StaticCall(caller ContractRef, addr common.Address, input []byte, - gas uint64, interpreter Interpreter) (ret []byte, leftOverGas uint64, err error) { + gas uint64, p *ExecPack) (ret []byte, leftOverGas uint64, err error) { - code := interpreter.StateDB().GetCode(addr) - name, _ := getVMAndCode(code) - return vmList[name].StaticCall(caller, addr, input, gas, interpreter) + code := p.StateDB.GetCode(addr) + v, _ := getVMAndCode(code) + return p.VMList[v].StaticCall(caller, addr, input, gas, p) } -func getVMAndCode(code []byte) (byte, []byte) { +func getVMAndCode(code []byte) (uint8, []byte) { if MULTIVM && len(code) > 0 { switch code[0] { case EVM, SQLVM: diff --git a/dex/api_backend.go b/dex/api_backend.go index 7bb5581ee..ad22cbf76 100644 --- a/dex/api_backend.go +++ b/dex/api_backend.go @@ -27,7 +27,8 @@ import ( "github.com/dexon-foundation/dexon/core/bloombits" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/eth/gasprice" "github.com/dexon-foundation/dexon/internal/ethapi" @@ -110,12 +111,13 @@ func (b *DexAPIBackend) GetTd(blockHash common.Hash) *big.Int { return b.dex.blockchain.GetTdByHash(blockHash) } -func (b *DexAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { +func (b *DexAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*evm.EVM, func() error, error) { state.SetBalance(msg.From(), math.MaxBig256) vmError := func() error { return nil } - context := core.NewEVMContext(msg, header, b.dex.BlockChain(), nil) - return vm.NewEVM(context, state, b.dex.chainConfig, *b.dex.blockchain.GetVMConfig()), vmError, nil + context := core.NewVMContext(msg, header, b.dex.BlockChain(), nil) + pack := vm.NewExecPack(context, state, b.dex.chainConfig, b.dex.blockchain.GetVMConfig()) + return pack.VMList[vm.EVM].(*evm.EVM), vmError, nil } func (b *DexAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { diff --git a/dex/api_tracer.go b/dex/api_tracer.go index 70f482bca..b8f4e46da 100644 --- a/dex/api_tracer.go +++ b/dex/api_tracer.go @@ -203,7 +203,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl // Trace all the transactions contained within for i, tx := range task.block.Transactions() { msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, task.block.Header(), api.dex.blockchain, nil) + vmctx := core.NewVMContext(msg, task.block.Header(), api.dex.blockchain, nil) res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) if err != nil { @@ -285,7 +285,10 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl traced += uint64(len(txs)) } // Generate the next state snapshot fast without tracing - _, _, _, err := api.dex.blockchain.Processor().Process(block, statedb, evm.Config{}) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + _, _, _, err := api.dex.blockchain.Processor().Process(block, statedb, vmConfig) if err != nil { failed = err break @@ -474,7 +477,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Fetch and execute the next transaction trace tasks for task := range jobs { msg, _ := txs[task.index].AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.dex.blockchain, nil) + vmctx := core.NewVMContext(msg, block.Header(), api.dex.blockchain, nil) res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) if err != nil { @@ -493,10 +496,12 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Generate the next state snapshot fast without tracing msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.dex.blockchain, nil) + vmctx := core.NewVMContext(msg, block.Header(), api.dex.blockchain, nil) - vmenv := evm.NewEVM(vmctx, statedb, api.config, evm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfig) + if _, _, _, err := core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { failed = err break } @@ -567,7 +572,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block // Prepare the trasaction for un-traced execution var ( msg, _ = tx.AsMessage(signer) - vmctx = core.NewEVMContext(msg, block.Header(), api.dex.blockchain, nil) + vmctx = core.NewVMContext(msg, block.Header(), api.dex.blockchain, nil) vmConf evm.Config dump *os.File @@ -592,8 +597,10 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block } } // Execute the transaction and flush any traces to disk - vmenv := evm.NewEVM(vmctx, statedb, api.config, vmConf) - _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + vmConfigs := [vm.NUMS]interface{}{} + vmConfigs[vm.EVM] = vmConf + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfigs) + _, _, _, err = core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(msg.Gas())) if dump != nil { dump.Close() @@ -604,7 +611,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block } // Finalize the state so any modifications are written to the trie // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) + statedb.Finalise(pack.ChainConfig.IsEIP158(block.Number())) // If we've traced the transaction we were looking for, abort if tx.Hash() == txHash { @@ -660,7 +667,10 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (* if block = api.dex.blockchain.GetBlockByNumber(block.NumberU64() + 1); block == nil { return nil, fmt.Errorf("block #%d not found", block.NumberU64()+1) } - _, _, _, err := api.dex.blockchain.Processor().Process(block, statedb, evm.Config{}) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + _, _, _, err := api.dex.blockchain.Processor().Process(block, statedb, vmConfig) if err != nil { return nil, fmt.Errorf("processing block %d failed: %v", block.NumberU64(), err) } @@ -706,7 +716,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx *vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { // Assemble the structured logger or the JavaScript tracer var ( tracer evm.Tracer @@ -740,9 +750,11 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v tracer = evm.NewStructLogger(config.LogConfig) } // Run the transaction with tracing enabled. - vmenv := evm.NewEVM(vmctx, statedb, api.config, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer} + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfig) - ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) + ret, gas, failed, err := core.ApplyMessage(&pack, message, new(core.GasPool).AddGas(message.Gas())) if err != nil { return nil, fmt.Errorf("tracing failed: %v", err) } @@ -765,19 +777,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v } // computeTxEnv returns the execution environment of a certain transaction. -func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { +func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, *vm.Context, *state.StateDB, error) { // Create the parent state database block := api.dex.blockchain.GetBlockByHash(blockHash) if block == nil { - return nil, vm.Context{}, nil, fmt.Errorf("block %#x not found", blockHash) + return nil, &vm.Context{}, nil, fmt.Errorf("block %#x not found", blockHash) } parent := api.dex.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { - return nil, vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) + return nil, &vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) } statedb, err := api.computeStateDB(parent, reexec) if err != nil { - return nil, vm.Context{}, nil, err + return nil, &vm.Context{}, nil, err } // Recompute transactions up to the target index. signer := types.MakeSigner(api.config, block.Number()) @@ -785,17 +797,19 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer) - context := core.NewEVMContext(msg, block.Header(), api.dex.blockchain, nil) + context := core.NewVMContext(msg, block.Header(), api.dex.blockchain, nil) if idx == txIndex { return msg, context, statedb, nil } // Not yet the searched for transaction, execute on top of the current state - vmenv := evm.NewEVM(context, statedb, api.config, evm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return nil, vm.Context{}, nil, fmt.Errorf("tx %#x failed: %v", tx.Hash(), err) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, statedb, api.config, vmConfig) + if _, _, _, err := core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { + return nil, &vm.Context{}, nil, fmt.Errorf("tx %#x failed: %v", tx.Hash(), err) } // Ensure any modifications are committed to the state statedb.Finalise(true) } - return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blockHash) + return nil, &vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blockHash) } diff --git a/dex/app_test.go b/dex/app_test.go index e4a46b116..4acf3c15f 100644 --- a/dex/app_test.go +++ b/dex/app_test.go @@ -20,6 +20,7 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/types" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" @@ -2336,8 +2337,10 @@ func newDexon(masterKey *ecdsa.PrivateKey, accountNum int) (*Dexon, []*ecdsa.Pri networkID: config.NetworkId, engine: engine, } + vmConfigs := [vm.NUMS]interface{}{} + vmConfigs[vm.EVM] = vmConfig - dex.blockchain, err = core.NewBlockChain(db, nil, chainConfig, engine, vmConfig, nil) + dex.blockchain, err = core.NewBlockChain(db, nil, chainConfig, engine, vmConfigs, nil) if err != nil { return nil, nil, err } diff --git a/dex/backend.go b/dex/backend.go index 8344c7973..97838750c 100644 --- a/dex/backend.go +++ b/dex/backend.go @@ -28,7 +28,8 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/bloombits" "github.com/dexon-foundation/dexon/core/rawdb" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/dex/downloader" "github.com/dexon-foundation/dexon/eth/filters" "github.com/dexon-foundation/dexon/eth/gasprice" @@ -118,7 +119,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Dexon, error) { } var ( - vmConfig = vm.Config{ + evmConfig = evm.Config{ EnablePreimageRecording: config.EnablePreimageRecording, EWASMInterpreter: config.EWASMInterpreter, EVMInterpreter: config.EVMInterpreter, @@ -126,6 +127,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Dexon, error) { } cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout} ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evmConfig dex.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, dex.chainConfig, dex.engine, vmConfig, nil) // Rewind the chain in case of an incompatible config upgrade. diff --git a/dex/helper_test.go b/dex/helper_test.go index 4d6330108..6b3c0bf4e 100644 --- a/dex/helper_test.go +++ b/dex/helper_test.go @@ -31,7 +31,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/dex/downloader" "github.com/dexon-foundation/dexon/ethdb" @@ -119,9 +120,12 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000), Staked: big.NewInt(0)}}, } - genesis = gspec.MustCommit(db) - blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil) + genesis = gspec.MustCommit(db) ) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vmConfig, nil) chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator) if _, err := blockchain.InsertChain(chain); err != nil { panic(err) diff --git a/eth/api_backend.go b/eth/api_backend.go index e50f62814..8c5b8bab3 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -27,7 +27,8 @@ import ( "github.com/dexon-foundation/dexon/core/bloombits" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/eth/gasprice" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -125,12 +126,13 @@ func (b *EthAPIBackend) GetTd(blockHash common.Hash) *big.Int { return b.eth.blockchain.GetTdByHash(blockHash) } -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { +func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*evm.EVM, func() error, error) { state.SetBalance(msg.From(), math.MaxBig256) vmError := func() error { return nil } - context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil) - return vm.NewEVM(context, state, b.eth.chainConfig, *b.eth.blockchain.GetVMConfig()), vmError, nil + context := core.NewVMContext(msg, header, b.eth.BlockChain(), nil) + pack := vm.NewExecPack(context, state, b.eth.chainConfig, b.eth.blockchain.GetVMConfig()) + return pack.VMList[vm.EVM].(*evm.EVM), vmError, nil } func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { diff --git a/eth/api_tracer.go b/eth/api_tracer.go index e05bbe0a2..10f5edeb7 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -207,7 +207,7 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl // Trace all the transactions contained within for i, tx := range task.block.Transactions() { msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil) + vmctx := core.NewVMContext(msg, task.block.Header(), api.eth.blockchain, nil) res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) if err != nil { @@ -290,7 +290,9 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl traced += uint64(len(txs)) } // Generate the next state snapshot fast without tracing - _, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, evm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + _, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, vmConfig) if err != nil { failed = err break @@ -481,7 +483,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Fetch and execute the next transaction trace tasks for task := range jobs { msg, _ := txs[task.index].AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) + vmctx := core.NewVMContext(msg, block.Header(), api.eth.blockchain, nil) res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) if err != nil { @@ -500,16 +502,17 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Generate the next state snapshot fast without tracing msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) - - vmenv := evm.NewEVM(vmctx, statedb, api.config, evm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { + vmctx := core.NewVMContext(msg, block.Header(), api.eth.blockchain, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfig) + if _, _, _, err := core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { failed = err break } // Finalize the state so any modifications are written to the trie // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) + statedb.Finalise(pack.ChainConfig.IsEIP158(block.Number())) } close(jobs) pend.Wait() @@ -575,7 +578,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block // Prepare the trasaction for un-traced execution var ( msg, _ = tx.AsMessage(signer) - vmctx = core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) + vmctx = core.NewVMContext(msg, block.Header(), api.eth.blockchain, nil) vmConf evm.Config dump *os.File @@ -600,8 +603,10 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block } } // Execute the transaction and flush any traces to disk - vmenv := evm.NewEVM(vmctx, statedb, api.config, vmConf) - _, _, _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) + vmConfigs := [vm.NUMS]interface{}{} + vmConfigs[vm.EVM] = vmConf + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfigs) + _, _, _, err = core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(msg.Gas())) if dump != nil { dump.Close() @@ -612,7 +617,7 @@ func (api *PrivateDebugAPI) standardTraceBlockToFile(ctx context.Context, block } // Finalize the state so any modifications are written to the trie // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) + statedb.Finalise(pack.ChainConfig.IsEIP158(block.Number())) // If we've traced the transaction we were looking for, abort if tx.Hash() == txHash { @@ -668,7 +673,9 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (* if block = api.eth.blockchain.GetBlockByNumber(block.NumberU64() + 1); block == nil { return nil, fmt.Errorf("block #%d not found", block.NumberU64()+1) } - _, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, evm.Config{}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + _, _, _, err := api.eth.blockchain.Processor().Process(block, statedb, vmConfig) if err != nil { return nil, fmt.Errorf("processing block %d failed: %v", block.NumberU64(), err) } @@ -714,7 +721,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx *vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { // Assemble the structured logger or the JavaScript tracer var ( tracer evm.Tracer @@ -748,9 +755,11 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v tracer = evm.NewStructLogger(config.LogConfig) } // Run the transaction with tracing enabled. - vmenv := evm.NewEVM(vmctx, statedb, api.config, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer, Debug: true} + pack := vm.NewExecPack(vmctx, statedb, api.config, vmConfig) - ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) + ret, gas, failed, err := core.ApplyMessage(&pack, message, new(core.GasPool).AddGas(message.Gas())) if err != nil { return nil, fmt.Errorf("tracing failed: %v", err) } @@ -773,19 +782,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v } // computeTxEnv returns the execution environment of a certain transaction. -func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { +func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, *vm.Context, *state.StateDB, error) { // Create the parent state database block := api.eth.blockchain.GetBlockByHash(blockHash) if block == nil { - return nil, vm.Context{}, nil, fmt.Errorf("block %#x not found", blockHash) + return nil, nil, nil, fmt.Errorf("block %#x not found", blockHash) } parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { - return nil, vm.Context{}, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) + return nil, nil, nil, fmt.Errorf("parent %#x not found", block.ParentHash()) } statedb, err := api.computeStateDB(parent, reexec) if err != nil { - return nil, vm.Context{}, nil, err + return nil, nil, nil, err } // Recompute transactions up to the target index. signer := types.MakeSigner(api.config, block.Number()) @@ -793,18 +802,21 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer) - context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) + context := core.NewVMContext(msg, block.Header(), api.eth.blockchain, nil) if idx == txIndex { return msg, context, statedb, nil } // Not yet the searched for transaction, execute on top of the current state - vmenv := evm.NewEVM(context, statedb, api.config, evm.Config{}) - if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return nil, vm.Context{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, statedb, api.config, vmConfig) + if _, _, _, err := core.ApplyMessage(&pack, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { + return nil, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } // Ensure any modifications are committed to the state // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect - statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) + statedb.Finalise(pack.ChainConfig.IsEIP158(block.Number())) } - return nil, vm.Context{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blockHash) + return nil, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blockHash) } diff --git a/eth/backend.go b/eth/backend.go index 815049251..09c1b0925 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -35,7 +35,8 @@ import ( "github.com/dexon-foundation/dexon/core/bloombits" "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/eth/downloader" "github.com/dexon-foundation/dexon/eth/filters" "github.com/dexon-foundation/dexon/eth/gasprice" @@ -151,14 +152,17 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) } var ( - vmConfig = vm.Config{ + vmConfig = evm.Config{ EnablePreimageRecording: config.EnablePreimageRecording, EWASMInterpreter: config.EWASMInterpreter, EVMInterpreter: config.EVMInterpreter, } cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieCleanLimit: config.TrieCleanCache, TrieDirtyLimit: config.TrieDirtyCache, TrieTimeLimit: config.TrieTimeout} ) - eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig, eth.shouldPreserve) + + vmConfigs := [vm.NUMS]interface{}{} + vmConfigs[vm.EVM] = vmConfig + eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfigs, eth.shouldPreserve) if err != nil { return nil, err } diff --git a/eth/handler_test.go b/eth/handler_test.go index 4041fbe59..a6bc31554 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -29,7 +29,8 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/eth/downloader" "github.com/dexon-foundation/dexon/ethdb" @@ -474,7 +475,9 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool gspec = &core.Genesis{Config: config} genesis = gspec.MustCommit(db) ) - blockchain, err := core.NewBlockChain(db, nil, config, pow, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, err := core.NewBlockChain(db, nil, config, pow, vmConfig, nil) if err != nil { t.Fatalf("failed to create new blockchain: %v", err) } @@ -555,7 +558,9 @@ func testBroadcastBlock(t *testing.T, totalPeers, broadcastExpected int) { gspec = &core.Genesis{Config: config} genesis = gspec.MustCommit(db) ) - blockchain, err := core.NewBlockChain(db, nil, config, pow, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, err := core.NewBlockChain(db, nil, config, pow, vmConfig, nil) if err != nil { t.Fatalf("failed to create new blockchain: %v", err) } diff --git a/eth/helper_test.go b/eth/helper_test.go index 7b2de4574..a3e928842 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -31,7 +31,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/eth/downloader" "github.com/dexon-foundation/dexon/ethdb" @@ -58,9 +59,11 @@ func newTestProtocolManager(mode downloader.SyncMode, blocks int, generator func Config: params.TestChainConfig, Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}}, } - genesis = gspec.MustCommit(db) - blockchain, _ = core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil) + genesis = gspec.MustCommit(db) ) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vmConfig, nil) chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator) if _, err := blockchain.InsertChain(chain); err != nil { panic(err) diff --git a/eth/tracers/tracer_test.go b/eth/tracers/tracer_test.go index 42343f91a..6d2c87088 100644 --- a/eth/tracers/tracer_test.go +++ b/eth/tracers/tracer_test.go @@ -52,12 +52,17 @@ type dummyStatedb struct { func (*dummyStatedb) GetRefund() uint64 { return 1337 } func runTrace(tracer *Tracer) (json.RawMessage, error) { - env := evm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer, Debug: true} + vmctx := &vm.Context{BlockNumber: big.NewInt(1)} + pack := vm.NewExecPack(vmctx, &dummyStatedb{}, params.TestChainConfig, vmConfig) + e := pack.VMList[vm.EVM].(*evm.EVM) + interpreter := evm.NewEVMInterpreter(e, e.VMConfig()) contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000) contract.Code = []byte{byte(evm.PUSH1), 0x1, byte(evm.PUSH1), 0x1, 0x0} - _, err := env.Interpreter().Run(contract, []byte{}, false) + _, err := interpreter.Run(contract, []byte{}, false) if err != nil { return nil, err } @@ -134,13 +139,18 @@ func TestHaltBetweenSteps(t *testing.T) { t.Fatal(err) } - env := evm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer, Debug: true} + vmctx := &vm.Context{BlockNumber: big.NewInt(1)} + pack := vm.NewExecPack(vmctx, &dummyStatedb{}, params.TestChainConfig, vmConfig) + evm := pack.VMList[vm.EVM].(*evm.EVM) + contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0) - tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) + tracer.CaptureState(evm, 0, 0, 0, 0, nil, nil, contract, 0, nil) timeout := errors.New("stahp") tracer.Stop(timeout) - tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil) + tracer.CaptureState(evm, 0, 0, 0, 0, nil, nil, contract, 0, nil) if _, err := tracer.GetResult(); err.Error() != timeout.Error() { t.Errorf("Expected timeout error, got %v", err) diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 0e41a6dd3..3ee12dd7f 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -179,13 +179,15 @@ func TestPrestateTracerCreate2(t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - evm := evm.NewEVM(context, statedb, params.MainnetChainConfig, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer, Debug: true} + pack := vm.NewExecPack(&context, statedb, params.MainnetChainConfig, vmConfig) msg, err := tx.AsMessage(signer) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) + st := core.NewStateTransition(&pack, msg, new(core.GasPool).AddGas(tx.Gas())) core.TestingMode = true if _, _, _, err = st.TransitionDb(); err != nil { t.Fatalf("failed to execute transaction: %v", err) @@ -287,12 +289,14 @@ func TestCallTracer(t *testing.T) { if err != nil { t.Fatalf("failed to create call tracer: %v", err) } - evm := evm.NewEVM(context, statedb, test.Genesis.Config, evm.Config{Debug: true, Tracer: tracer}) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{Tracer: tracer, Debug: true} + pack := vm.NewExecPack(&context, statedb, test.Genesis.Config, vmConfig) msg, err := tx.AsMessage(signer) if err != nil { t.Fatalf("failed to prepare transaction for tracing: %v", err) } - st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas())) + st := core.NewStateTransition(&pack, msg, new(core.GasPool).AddGas(tx.Gas())) if _, _, _, err = st.TransitionDb(); err != nil { t.Fatalf("failed to execute transaction: %v", err) } diff --git a/indexer/blockchain.go b/indexer/blockchain.go index 996bc891c..f21ae3b08 100644 --- a/indexer/blockchain.go +++ b/indexer/blockchain.go @@ -8,7 +8,7 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/event" "github.com/dexon-foundation/dexon/params" "github.com/dexon-foundation/dexon/rlp" @@ -43,7 +43,7 @@ type ReadOnlyBlockChain interface { GetTd(common.Hash, uint64) *big.Int GetTdByHash(common.Hash) *big.Int GetUnclesInChain(*types.Block, int) []*types.Header - GetVMConfig() *vm.Config + GetVMConfig() [vm.NUMS]interface{} HasBlock(common.Hash, uint64) bool HasBlockAndState(common.Hash, uint64) bool HasHeader(common.Hash, uint64) bool diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ccc383baf..7b8b0efe9 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -35,7 +35,8 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/log" "github.com/dexon-foundation/dexon/p2p" @@ -778,7 +779,10 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr // Setup the gas pool (also for unmetered requests) // and apply the message. gp := new(core.GasPool).AddGas(math.MaxUint64) - res, gas, failed, err := core.ApplyMessage(evm, msg, gp) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.VMConfig() + pack := vm.NewExecPack(evm.Context, evm.StateDB, evm.ChainConfig(), vmConfig) + res, gas, failed, err := core.ApplyMessage(&pack, msg, gp) if err := vmError(); err != nil { return nil, 0, false, err } @@ -871,7 +875,7 @@ type StructLogRes struct { } // formatLogs formats EVM returned structured logs for json output -func FormatLogs(logs []vm.StructLog) []StructLogRes { +func FormatLogs(logs []evm.StructLog) []StructLogRes { formatted := make([]StructLogRes, len(logs)) for index, trace := range logs { formatted[index] = StructLogRes{ diff --git a/les/api_backend.go b/les/api_backend.go index 2ca62c8a4..94661df4b 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -28,7 +28,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/eth/gasprice" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -105,10 +106,13 @@ func (b *LesApiBackend) GetTd(hash common.Hash) *big.Int { return b.eth.blockchain.GetTdByHash(hash) } -func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { +func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*evm.EVM, func() error, error) { state.SetBalance(msg.From(), math.MaxBig256) - context := core.NewEVMContext(msg, header, b.eth.blockchain, nil) - return vm.NewEVM(context, state, b.eth.chainConfig, vm.Config{}), state.Error, nil + context := core.NewVMContext(msg, header, b.eth.blockchain, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, state, b.eth.chainConfig, vmConfig) + return pack.VMList[vm.EVM].(*evm.EVM), state.Error, nil } func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { diff --git a/les/helper_test.go b/les/helper_test.go index 136c4e33e..804a0ac7d 100644 --- a/les/helper_test.go +++ b/les/helper_test.go @@ -30,6 +30,7 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" + "github.com/dexon-foundation/dexon/core/vm" "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/core/vm/tools" "github.com/dexon-foundation/dexon/crypto" @@ -169,7 +170,9 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor if lightSync { chain, _ = light.NewLightChain(odr, gspec.Config, engine) } else { - blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, evm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vmConfig, nil) gchain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, blocks, generator) if _, err := blockchain.InsertChain(gchain); err != nil { panic(err) diff --git a/les/odr_test.go b/les/odr_test.go index f6e6e873b..3c049b9a5 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -29,7 +29,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/light" "github.com/dexon-foundation/dexon/params" @@ -134,12 +135,14 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, bc, nil) - vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) + context := core.NewVMContext(msg, header, bc, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, statedb, config, vmConfig) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) gp := new(core.GasPool).AddGas(math.MaxUint64) - ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) + ret, _, _, _ := core.ApplyMessage(&pack, msg, gp) res = append(res, ret...) } } else { @@ -147,10 +150,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai state := light.NewState(ctx, header, lc.Odr()) state.SetBalance(testBankAddress, math.MaxBig256) msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, lc, nil) - vmenv := vm.NewEVM(context, state, config, vm.Config{}) + context := core.NewVMContext(msg, header, lc, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, state, config, vmConfig) gp := new(core.GasPool).AddGas(math.MaxUint64) - ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) + ret, _, _, _ := core.ApplyMessage(&pack, msg, gp) if state.Error() == nil { res = append(res, ret...) } diff --git a/light/odr_test.go b/light/odr_test.go index 267d1a346..f5020dfa7 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -31,7 +31,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/core/vm/tools" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" @@ -196,10 +197,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain // Perform read-only call. st.SetBalance(testBankAddress, math.MaxBig256) msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, chain, nil) - vmenv := vm.NewEVM(context, st, config, vm.Config{}) + context := core.NewVMContext(msg, header, chain, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + pack := vm.NewExecPack(context, st, config, vmConfig) gp := new(core.GasPool).AddGas(math.MaxUint64) - ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) + ret, _, _, _ := core.ApplyMessage(&pack, msg, gp) res = append(res, ret...) if st.Error() != nil { return res, st.Error() @@ -259,7 +262,9 @@ func testChainOdr(t *testing.T, protocol int, fn odrTestFn) { ) gspec.MustCommit(ldb) // Assemble the test environment - blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vmConfig, nil) gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, 4, testChainGen) if _, err := blockchain.InsertChain(gchain); err != nil { t.Fatal(err) diff --git a/light/trie_test.go b/light/trie_test.go index 72b709ea6..18324f2b9 100644 --- a/light/trie_test.go +++ b/light/trie_test.go @@ -26,7 +26,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" "github.com/dexon-foundation/dexon/trie" @@ -40,7 +41,9 @@ func TestNodeIterator(t *testing.T) { genesis = gspec.MustCommit(fulldb) ) gspec.MustCommit(lightdb) - blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(fulldb, nil, params.TestChainConfig, ethash.NewFullFaker(), vmConfig, nil) gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), fulldb, 4, testChainGen) if _, err := blockchain.InsertChain(gchain); err != nil { panic(err) diff --git a/light/txpool_test.go b/light/txpool_test.go index 4775261d9..c875ff2fa 100644 --- a/light/txpool_test.go +++ b/light/txpool_test.go @@ -27,7 +27,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" ) @@ -88,7 +89,10 @@ func TestTxPool(t *testing.T) { ) gspec.MustCommit(ldb) // Assemble the test environment - blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil) + + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + blockchain, _ := core.NewBlockChain(sdb, nil, params.TestChainConfig, ethash.NewFullFaker(), vmConfig, nil) gchain, _ := core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), sdb, poolTestBlocks, txPoolTestChainGen) if _, err := blockchain.InsertChain(gchain); err != nil { panic(err) diff --git a/miner/worker.go b/miner/worker.go index 1a3c64d7b..0686c3bee 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -691,7 +691,7 @@ func (w *worker) updateSnapshot() { func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) { snap := w.current.state.Snapshot() - receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig()) + receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, w.chain.GetVMConfig()) if err != nil { w.current.state.RevertToSnapshot(snap) return nil, err diff --git a/miner/worker_test.go b/miner/worker_test.go index 2c1c8b71a..cb3de5b98 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -27,7 +27,8 @@ import ( "github.com/dexon-foundation/dexon/consensus/ethash" "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/event" @@ -96,7 +97,10 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine } genesis := gspec.MustCommit(db) - chain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + + chain, _ := core.NewBlockChain(db, nil, gspec.Config, engine, vmConfig, nil) txpool := core.NewTxPool(testTxPoolConfig, chainConfig, chain) // Generate a small n-block chain and an uncle block for it diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 1bfcabd0c..b7a523fe4 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -32,7 +32,8 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" "github.com/dexon-foundation/dexon/rlp" @@ -118,7 +119,9 @@ func (t *BlockTest) Run() error { } else { engine = ethash.NewShared() } - chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanLimit: 0}, config, engine, vm.Config{}, nil) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = evm.Config{} + chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanLimit: 0}, config, engine, vmConfig, nil) if err != nil { return err } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 756de5ff4..5c50c9282 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -29,7 +29,8 @@ import ( "github.com/dexon-foundation/dexon/core" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/core/vm/evm" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/params" @@ -120,7 +121,7 @@ func (t *StateTest) Subtests() []StateSubtest { } // Run executes a specific subtest. -func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateDB, error) { +func (t *StateTest) Run(subtest StateSubtest, vmcfg evm.Config) (*state.StateDB, error) { config, ok := Forks[subtest.Fork] if !ok { return nil, UnsupportedForkError{subtest.Fork} @@ -133,14 +134,14 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD if err != nil { return nil, err } - context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase) + context := core.NewVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase) context.GetHash = vmTestBlockHash - evm := vm.NewEVM(context, statedb, config, vmconfig) - + vmConfigs := [vm.NUMS]interface{}{vmcfg} + pack := vm.NewExecPack(context, statedb, config, vmConfigs) gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit()) snapshot := statedb.Snapshot() - if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil { + if _, _, _, err := core.ApplyMessage(&pack, msg, gaspool); err != nil { statedb.RevertToSnapshot(snapshot) } // Commit block diff --git a/tests/vm_test.go b/tests/vm_test.go index b7746188c..d7e6b365a 100644 --- a/tests/vm_test.go +++ b/tests/vm_test.go @@ -19,7 +19,7 @@ package tests import ( "testing" - vm "github.com/dexon-foundation/dexon/core/vm/evm" + "github.com/dexon-foundation/dexon/core/vm/evm" ) func TestVM(t *testing.T) { @@ -29,7 +29,7 @@ func TestVM(t *testing.T) { vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution") vmt.walk(t, vmTestDir, func(t *testing.T, name string, test *VMTest) { - withTrace(t, test.json.Exec.GasLimit, func(vmconfig vm.Config) error { + withTrace(t, test.json.Exec.GasLimit, func(vmconfig evm.Config) error { return vmt.checkFailure(t, name, test.Run(vmconfig)) }) }) diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 09b30d19b..9ac5f0521 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -79,9 +79,9 @@ type vmExecMarshaling struct { GasPrice *math.HexOrDecimal256 } -func (t *VMTest) Run(vmconfig evm.Config) error { +func (t *VMTest) Run(cfg evm.Config) error { statedb := MakePreState(ethdb.NewMemDatabase(), t.json.Pre) - ret, gasRemaining, err := t.exec(statedb, vmconfig) + ret, gasRemaining, err := t.exec(statedb, cfg) if t.json.GasRemaining == nil { if err == nil { @@ -115,13 +115,13 @@ func (t *VMTest) Run(vmconfig evm.Config) error { return nil } -func (t *VMTest) exec(statedb *state.StateDB, vmconfig evm.Config) ([]byte, uint64, error) { - evm := t.newEVM(statedb, vmconfig) +func (t *VMTest) exec(statedb *state.StateDB, cfg evm.Config) ([]byte, uint64, error) { + evm := t.newEVM(statedb, cfg) e := t.json.Exec - return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value) + return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value, evm.ExecPack) } -func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig evm.Config) *evm.EVM { +func (t *VMTest) newEVM(statedb *state.StateDB, cfg evm.Config) *evm.EVM { initialCall := true canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool { if initialCall { @@ -142,9 +142,12 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig evm.Config) *evm.EVM { GasLimit: t.json.Env.GasLimit, Difficulty: t.json.Env.Difficulty, GasPrice: t.json.Exec.GasPrice, + NoRecursion: true, } - vmconfig.NoRecursion = true - return evm.NewEVM(context, statedb, params.EthereumMainnetChainConfig, vmconfig) + vmConfig := [vm.NUMS]interface{}{} + vmConfig[vm.EVM] = cfg + pack := vm.NewExecPack(&context, statedb, params.EthereumMainnetChainConfig, vmConfig) + return pack.VMList[vm.EVM].(*evm.EVM) } func vmTestBlockHash(n uint64) common.Hash { |