core/vm: EIP-2315, JUMPSUB for the EVM (#20619)
* core/vm: implement EIP 2315, subroutines for the EVM * core/vm: eip 2315 - lintfix + check jump dest validity + check ret stack size constraints logger: markdown-friendly traces, validate jumpdest, more testcase, correct opcodes * core/vm: update subroutines acc to eip: disallow walk-into * core/vm/eips: gas cost changes for subroutines * core/vm: update opcodes for EIP-2315 * core/vm: define RETURNSUB as a 'jumping' operation + review concerns Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
@ -94,6 +94,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
rstack = newReturnStack()
|
||||
pc = uint64(0)
|
||||
evmInterpreter = env.interpreter.(*EVMInterpreter)
|
||||
)
|
||||
@ -109,7 +110,7 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
|
||||
expected := new(big.Int).SetBytes(common.Hex2Bytes(test.Expected))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, evmInterpreter, &callCtx{nil, stack, nil})
|
||||
opFn(&pc, evmInterpreter, &callCtx{nil, stack, rstack, nil})
|
||||
actual := stack.pop()
|
||||
|
||||
if actual.Cmp(expected) != 0 {
|
||||
@ -211,10 +212,10 @@ func TestSAR(t *testing.T) {
|
||||
// getResult is a convenience function to generate the expected values
|
||||
func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
pc = uint64(0)
|
||||
interpreter = env.interpreter.(*EVMInterpreter)
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack, rstack = newstack(), newReturnStack()
|
||||
pc = uint64(0)
|
||||
interpreter = env.interpreter.(*EVMInterpreter)
|
||||
)
|
||||
interpreter.intPool = poolOfIntPools.get()
|
||||
result := make([]TwoOperandTestcase, len(args))
|
||||
@ -223,7 +224,7 @@ func getResult(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcas
|
||||
y := new(big.Int).SetBytes(common.Hex2Bytes(param.y))
|
||||
stack.push(x)
|
||||
stack.push(y)
|
||||
opFn(&pc, interpreter, &callCtx{nil, stack, nil})
|
||||
opFn(&pc, interpreter, &callCtx{nil, stack, rstack, nil})
|
||||
actual := stack.pop()
|
||||
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
|
||||
}
|
||||
@ -263,7 +264,7 @@ func TestJsonTestcases(t *testing.T) {
|
||||
func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
stack, rstack = newstack(), newReturnStack()
|
||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||
)
|
||||
|
||||
@ -281,7 +282,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
|
||||
a := new(big.Int).SetBytes(arg)
|
||||
stack.push(a)
|
||||
}
|
||||
op(&pc, evmInterpreter, &callCtx{nil, stack, nil})
|
||||
op(&pc, evmInterpreter, &callCtx{nil, stack, rstack, nil})
|
||||
stack.pop()
|
||||
}
|
||||
poolOfIntPools.put(evmInterpreter.intPool)
|
||||
@ -498,7 +499,7 @@ func BenchmarkOpIsZero(b *testing.B) {
|
||||
func TestOpMstore(t *testing.T) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
stack, rstack = newstack(), newReturnStack()
|
||||
mem = NewMemory()
|
||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||
)
|
||||
@ -509,12 +510,12 @@ func TestOpMstore(t *testing.T) {
|
||||
pc := uint64(0)
|
||||
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
|
||||
stack.pushN(new(big.Int).SetBytes(common.Hex2Bytes(v)), big.NewInt(0))
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil})
|
||||
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
|
||||
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
|
||||
}
|
||||
stack.pushN(big.NewInt(0x1), big.NewInt(0))
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil})
|
||||
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
|
||||
t.Fatalf("Mstore failed to overwrite previous value")
|
||||
}
|
||||
@ -524,7 +525,7 @@ func TestOpMstore(t *testing.T) {
|
||||
func BenchmarkOpMstore(bench *testing.B) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
stack, rstack = newstack(), newReturnStack()
|
||||
mem = NewMemory()
|
||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||
)
|
||||
@ -539,7 +540,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||
bench.ResetTimer()
|
||||
for i := 0; i < bench.N; i++ {
|
||||
stack.pushN(value, memStart)
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, nil})
|
||||
opMstore(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil})
|
||||
}
|
||||
poolOfIntPools.put(evmInterpreter.intPool)
|
||||
}
|
||||
@ -547,7 +548,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
||||
func BenchmarkOpSHA3(bench *testing.B) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
stack, rstack = newstack(), newReturnStack()
|
||||
mem = NewMemory()
|
||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||
)
|
||||
@ -560,7 +561,7 @@ func BenchmarkOpSHA3(bench *testing.B) {
|
||||
bench.ResetTimer()
|
||||
for i := 0; i < bench.N; i++ {
|
||||
stack.pushN(big.NewInt(32), start)
|
||||
opSha3(&pc, evmInterpreter, &callCtx{mem, stack, nil})
|
||||
opSha3(&pc, evmInterpreter, &callCtx{mem, stack, rstack, nil})
|
||||
}
|
||||
poolOfIntPools.put(evmInterpreter.intPool)
|
||||
}
|
||||
|
Reference in New Issue
Block a user