diff options
author | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-03-27 18:49:38 +0800 |
---|---|---|
committer | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-05-06 10:50:26 +0800 |
commit | e715414cae9b4654b4784dfb924880a0787d1d55 (patch) | |
tree | a0772b2a0ef3be4ac03fc608a21ee0b7ccbd167a | |
parent | 996310cbd484b5ff1ea76068578314d71973770f (diff) | |
download | dexon-e715414cae9b4654b4784dfb924880a0787d1d55.tar.gz dexon-e715414cae9b4654b4784dfb924880a0787d1d55.tar.zst dexon-e715414cae9b4654b4784dfb924880a0787d1d55.zip |
core: vm: refactor vm config and context
To support multiple VMs, there must be a shared execution environment for each VM,
so this pull request moved some shared component to vm.Context and
implemented the vm.ExecPack to hold the list of VM, list of VM configures,
context and some shared resources.
The adjustment includes:
* Move NoRecursion, Depth, ReadOnly, RandCallIndex, IntPool and CallGasTemp to Context.
* Adjust VM enumeration from byte to uint8, and the VMList from map to
array.
* Register VM constructor in each VM package's init function.
* Initialize all VM instance in NewExecPack.
* Remove EVMImplement, and modify EVM, such that EVM can do the same
functions with EVMImplement.
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 { |