diff options
author | Guillaume Ballet <gballet@gmail.com> | 2018-07-25 20:56:39 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-25 20:56:39 +0800 |
commit | 7abedf9bbb725da8d610762d051af43085be1cda (patch) | |
tree | 7640e475868c575115cbcfde8bddb7b4484eee20 /core/vm/instructions_test.go | |
parent | 27a278e6e35836999ac8e4d9a19c406407db8ae5 (diff) | |
download | dexon-7abedf9bbb725da8d610762d051af43085be1cda.tar.gz dexon-7abedf9bbb725da8d610762d051af43085be1cda.tar.zst dexon-7abedf9bbb725da8d610762d051af43085be1cda.zip |
core/vm: support for multiple interpreters (#17093)
- Define an Interpreter interface
- One contract can call contracts from other interpreter types.
- Pass the interpreter to the operands instead of the evm.
This is meant to prevent type assertions in operands.
Diffstat (limited to 'core/vm/instructions_test.go')
-rw-r--r-- | core/vm/instructions_test.go | 75 |
1 files changed, 45 insertions, 30 deletions
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 1643da967..ec5de94ed 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -30,20 +30,23 @@ type twoOperandTest struct { expected string } -func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) { +func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + stack = newstack() + pc = uint64(0) + evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) - env.interpreter.intPool = poolOfIntPools.get() + + env.interpreter = evmInterpreter + evmInterpreter.intPool = poolOfIntPools.get() for i, test := range tests { x := new(big.Int).SetBytes(common.Hex2Bytes(test.x)) shift := new(big.Int).SetBytes(common.Hex2Bytes(test.y)) expected := new(big.Int).SetBytes(common.Hex2Bytes(test.expected)) stack.push(x) stack.push(shift) - opFn(&pc, env, nil, nil, stack) + opFn(&pc, evmInterpreter, nil, nil, stack) actual := stack.pop() if actual.Cmp(expected) != 0 { t.Errorf("Testcase %d, expected %v, got %v", i, expected, actual) @@ -51,13 +54,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 env.interpreter.intPool.pool.len() > 0 { + if evmInterpreter.intPool.pool.len() > 0 { poolvals := make(map[*big.Int]struct{}) poolvals[actual] = struct{}{} - for env.interpreter.intPool.pool.len() > 0 { - key := env.interpreter.intPool.get() + for evmInterpreter.intPool.pool.len() > 0 { + key := evmInterpreter.intPool.get() if _, exist := poolvals[key]; exist { t.Errorf("Testcase %d, pool contains double-entry", i) } @@ -65,15 +68,18 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 } } } - poolOfIntPools.put(env.interpreter.intPool) + poolOfIntPools.put(evmInterpreter.intPool) } func TestByteOp(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + stack = newstack() + evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) - env.interpreter.intPool = poolOfIntPools.get() + + env.interpreter = evmInterpreter + evmInterpreter.intPool = poolOfIntPools.get() tests := []struct { v string th uint64 @@ -94,13 +100,13 @@ func TestByteOp(t *testing.T) { th := new(big.Int).SetUint64(test.th) stack.push(val) stack.push(th) - opByte(&pc, env, nil, nil, stack) + opByte(&pc, evmInterpreter, nil, nil, stack) actual := stack.pop() if actual.Cmp(test.expected) != 0 { t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.v, test.th, test.expected, actual) } } - poolOfIntPools.put(env.interpreter.intPool) + poolOfIntPools.put(evmInterpreter.intPool) } func TestSHL(t *testing.T) { @@ -200,11 +206,14 @@ func TestSLT(t *testing.T) { testTwoOperandOp(t, tests, opSlt) } -func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) { +func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + stack = newstack() + evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) + + env.interpreter = evmInterpreter // convert args byteArgs := make([][]byte, len(args)) for i, arg := range args { @@ -217,7 +226,7 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contr a := new(big.Int).SetBytes(arg) stack.push(a) } - op(&pc, env, nil, nil, stack) + op(&pc, evmInterpreter, nil, nil, stack) stack.pop() } } @@ -432,33 +441,39 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + stack = newstack() + mem = NewMemory() + evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) - env.interpreter.intPool = poolOfIntPools.get() + + env.interpreter = evmInterpreter + evmInterpreter.intPool = poolOfIntPools.get() mem.Resize(64) pc := uint64(0) v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" stack.pushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0)) - opMstore(&pc, env, nil, mem, stack) + opMstore(&pc, evmInterpreter, nil, mem, stack) if got := common.Bytes2Hex(mem.Get(0, 32)); got != v { t.Fatalf("Mstore fail, got %v, expected %v", got, v) } stack.pushN(big.NewInt(0x1), big.NewInt(0)) - opMstore(&pc, env, nil, mem, stack) + opMstore(&pc, evmInterpreter, nil, mem, stack) if common.Bytes2Hex(mem.Get(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { t.Fatalf("Mstore failed to overwrite previous value") } - poolOfIntPools.put(env.interpreter.intPool) + poolOfIntPools.put(evmInterpreter.intPool) } func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() + env = NewEVM(Context{}, nil, params.TestChainConfig, Config{}) + stack = newstack() + mem = NewMemory() + evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) + + env.interpreter = evmInterpreter mem.Resize(64) pc := uint64(0) memStart := big.NewInt(0) @@ -467,6 +482,6 @@ func BenchmarkOpMstore(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { stack.pushN(value, memStart) - opMstore(&pc, env, nil, mem, stack) + opMstore(&pc, evmInterpreter, nil, mem, stack) } } |