From 171ae812e65c1ee750d11e454c4211160ea2b103 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 7 Nov 2024 06:38:32 +0100 Subject: [PATCH] core/vm: switch push to non-pointer uint256 --- core/vm/eips.go | 17 +++++------ core/vm/instructions.go | 52 ++++++++++++++++----------------- core/vm/instructions_test.go | 48 +++++++++++++++--------------- core/vm/runtime/runtime_test.go | 8 ++--- core/vm/stack.go | 8 ++--- 5 files changed, 65 insertions(+), 68 deletions(-) diff --git a/core/vm/eips.go b/core/vm/eips.go index ae337ec1c7..178eccee10 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -89,7 +89,7 @@ func enable1884(jt *JumpTable) { func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) - scope.Stack.push(balance) + scope.Stack.push(*balance) return nil, nil } @@ -108,7 +108,7 @@ func enable1344(jt *JumpTable) { // opChainID implements CHAINID opcode func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID) - scope.Stack.push(chainId) + scope.Stack.push(*chainId) return nil, nil } @@ -219,7 +219,7 @@ func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b // opBaseFee implements BASEFEE opcode func opBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { baseFee, _ := uint256.FromBig(interpreter.evm.Context.BaseFee) - scope.Stack.push(baseFee) + scope.Stack.push(*baseFee) return nil, nil } @@ -288,7 +288,7 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ // opBlobBaseFee implements BLOBBASEFEE opcode func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee) - scope.Stack.push(blobBaseFee) + scope.Stack.push(*blobBaseFee) return nil, nil } @@ -358,11 +358,10 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { var ( codeLen = uint64(len(scope.Contract.Code)) - integer = new(uint256.Int) ) *pc += 1 if *pc < codeLen { - scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc]))) + scope.Stack.pushU64(uint64(scope.Contract.Code[*pc])) if !scope.Contract.IsDeployment && *pc%31 == 0 { // touch next chunk if PUSH1 is at the boundary. if so, *pc has @@ -375,7 +374,7 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext } } } else { - scope.Stack.push(integer.Clear()) + scope.Stack.pushU64(0) } return nil, nil } @@ -387,11 +386,11 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc { start = min(codeLen, int(*pc+1)) end = min(codeLen, start+pushByteSize) ) - scope.Stack.push(new(uint256.Int).SetBytes( + scope.Stack.pushBytes( common.RightPadBytes( scope.Contract.Code[start:end], pushByteSize, - )), + ), ) if !scope.Contract.IsDeployment { diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 62b6fd6ab2..62c9d2771b 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -30,70 +30,70 @@ import ( func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Add(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Sub(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Mul(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Div(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.SDiv(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Mod(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.SMod(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { base, exponent := scope.Stack.pop(), scope.Stack.pop() exponent.Exp(&base, &exponent) - scope.Stack.push(&exponent) + scope.Stack.push(exponent) return nil, nil } func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { back, num := scope.Stack.pop(), scope.Stack.pop() num.ExtendSign(&num, &back) - scope.Stack.push(&num) + scope.Stack.push(num) return nil, nil } func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x := scope.Stack.pop() x.Not(&x) - scope.Stack.push(&x) + scope.Stack.push(x) return nil, nil } @@ -160,42 +160,42 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.And(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Or(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y := scope.Stack.pop(), scope.Stack.pop() y.Xor(&x, &y) - scope.Stack.push(&y) + scope.Stack.push(y) return nil, nil } func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { th, val := scope.Stack.pop(), scope.Stack.pop() val.Byte(&th) - scope.Stack.push(&val) + scope.Stack.push(val) return nil, nil } func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.pop() z.AddMod(&x, &y, &z) - scope.Stack.push(&z) + scope.Stack.push(z) return nil, nil } func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.pop() z.MulMod(&x, &y, &z) - scope.Stack.push(&z) + scope.Stack.push(z) return nil, nil } @@ -207,7 +207,7 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte shift, value := scope.Stack.pop(), scope.Stack.pop() if shift.LtUint64(256) { value.Lsh(&value, uint(shift.Uint64())) - scope.Stack.push(&value) + scope.Stack.push(value) } else { scope.Stack.pushU64(0) } @@ -222,7 +222,7 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte shift, value := scope.Stack.pop(), scope.Stack.pop() if shift.LtUint64(256) { value.Rsh(&value, uint(shift.Uint64())) - scope.Stack.push(&value) + scope.Stack.push(value) } else { scope.Stack.pushU64(0) } @@ -240,12 +240,12 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte } else { // Max negative shift: all bits set value.SetAllOne() - scope.Stack.push(&value) + scope.Stack.push(value) } return nil, nil } value.SRsh(&value, uint(shift.Uint64())) - scope.Stack.push(&value) + scope.Stack.push(value) return nil, nil } @@ -277,7 +277,7 @@ func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([] func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.pop() address := common.Address(slot.Bytes20()) - scope.Stack.push(interpreter.evm.StateDB.GetBalance(address)) + scope.Stack.push(*interpreter.evm.StateDB.GetBalance(address)) return nil, nil } @@ -292,7 +292,7 @@ func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b } func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - scope.Stack.push(scope.Contract.value) + scope.Stack.push(*scope.Contract.value) return nil, nil } @@ -443,7 +443,7 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.GasPrice) - scope.Stack.push(v) + scope.Stack.push(*v) return nil, nil } @@ -486,13 +486,13 @@ func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber) - scope.Stack.push(v) + scope.Stack.push(*v) return nil, nil } func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty) - scope.Stack.push(v) + scope.Stack.push(*v) return nil, nil } @@ -989,7 +989,7 @@ func makePush(size uint64, pushByteSize int) executionFunc { if missing := pushByteSize - (end - start); missing > 0 { a.Lsh(a, uint(8*missing)) } - scope.Stack.push(a) + scope.Stack.push(*a) *pc += size return nil, nil } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 9e6fef855f..04222cf2d9 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -114,8 +114,8 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected)) - stack.push(x) - stack.push(y) + stack.push(*x) + stack.push(*y) opFn(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) if stack.len() != 1 { t.Errorf("Expected one item on stack after %v, got %d: ", name, stack.len()) @@ -228,9 +228,9 @@ func TestAddMod(t *testing.T) { y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y)) z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z)) expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected)) - stack.push(z) - stack.push(y) - stack.push(x) + stack.push(*z) + stack.push(*y) + stack.push(*x) opAddmod(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) actual := stack.pop() if actual.Cmp(expected) != 0 { @@ -256,8 +256,8 @@ func TestWriteExpectedValues(t *testing.T) { for i, param := range args { x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x)) y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y)) - stack.push(x) - stack.push(y) + stack.push(*x) + stack.push(*y) opFn(&pc, interpreter, &ScopeContext{nil, stack, nil}) actual := stack.pop() result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)} @@ -308,7 +308,7 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) { bench.ResetTimer() for i := 0; i < bench.N; i++ { for _, arg := range intArgs { - stack.push(arg) + stack.push(*arg) } op(&pc, evmInterpreter, scope) stack.pop() @@ -543,14 +543,14 @@ func TestOpMstore(t *testing.T) { mem.Resize(64) pc := uint64(0) v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700" - stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v))) - stack.push(new(uint256.Int)) + stack.push(*new(uint256.Int).SetBytes(common.Hex2Bytes(v))) + stack.push(*new(uint256.Int)) opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v { t.Fatalf("Mstore fail, got %v, expected %v", got, v) } - stack.push(new(uint256.Int).SetUint64(0x1)) - stack.push(new(uint256.Int)) + stack.push(*new(uint256.Int).SetUint64(0x1)) + stack.push(*new(uint256.Int)) opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" { t.Fatalf("Mstore failed to overwrite previous value") @@ -573,8 +573,8 @@ func BenchmarkOpMstore(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(value) - stack.push(memStart) + stack.push(*value) + stack.push(*memStart) opMstore(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) } } @@ -601,16 +601,16 @@ func TestOpTstore(t *testing.T) { env.interpreter = evmInterpreter pc := uint64(0) // push the value to the stack - stack.push(new(uint256.Int).SetBytes(value)) + stack.push(*new(uint256.Int).SetBytes(value)) // push the location to the stack - stack.push(new(uint256.Int)) + stack.push(*new(uint256.Int)) opTstore(&pc, evmInterpreter, &scopeContext) // there should be no elements on the stack after TSTORE if stack.len() != 0 { t.Fatal("stack wrong size") } // push the location to the stack - stack.push(new(uint256.Int)) + stack.push(*new(uint256.Int)) opTload(&pc, evmInterpreter, &scopeContext) // there should be one element on the stack after TLOAD if stack.len() != 1 { @@ -636,8 +636,8 @@ func BenchmarkOpKeccak256(bench *testing.B) { bench.ResetTimer() for i := 0; i < bench.N; i++ { - stack.push(uint256.NewInt(32)) - stack.push(start) + stack.push(*uint256.NewInt(32)) + stack.push(*start) opKeccak256(&pc, evmInterpreter, &ScopeContext{mem, stack, nil}) } } @@ -774,7 +774,7 @@ func TestBlobHash(t *testing.T) { pc = uint64(0) evmInterpreter = env.interpreter ) - stack.push(uint256.NewInt(tt.idx)) + stack.push(*uint256.NewInt(tt.idx)) opBlobHash(&pc, evmInterpreter, &ScopeContext{nil, stack, nil}) if stack.len() != 1 { t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, stack.len()) @@ -887,9 +887,9 @@ func TestOpMCopy(t *testing.T) { src, _ := uint256.FromHex(tc.src) dst, _ := uint256.FromHex(tc.dst) - stack.push(len) - stack.push(src) - stack.push(dst) + stack.push(*len) + stack.push(*src) + stack.push(*dst) wantErr := (tc.wantGas == 0) // Calc mem expansion var memorySize uint64 @@ -930,7 +930,7 @@ func TestOpMCopy(t *testing.T) { // TestPush sanity-checks how code with immediates are handled when the code size is // smaller than the size of the immediate. -func TestPush(t *testing.T) { +func Testpush2(t *testing.T) { code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121") push32 := makePush(32, 32) diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 8873f93b70..5b5c8d2dfa 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -990,11 +990,9 @@ func BenchmarkShortDeepStacks(b *testing.B) { // This piece of code will push a few items to the stack, and then call itself // recursively. var code []byte - code = append(code, byte(vm.PUSH0)) - code = append(code, byte(vm.PUSH0)) - for i := 0; i < 512; i++ { - code = append(code, byte(vm.PUSH0)) - code = append(code, byte(vm.ADD)) + for i := 0; i < 16; i++ { + code = append(code, byte(vm.PUSH1)) + code = append(code, byte(0x00)) } code = append(code, []byte{ byte(vm.ADDRESS), // address to call diff --git a/core/vm/stack.go b/core/vm/stack.go index 089c195ab0..153b197da6 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -51,12 +51,12 @@ func (st *Stack) Data() []uint256.Int { return st.data[0:st.size] } -func (st *Stack) push(d *uint256.Int) { +func (st *Stack) push(d uint256.Int) { // NOTE push limit (1024) is checked in baseCheck if st.size == len(st.data) { - st.data = append(st.data, *d) + st.data = append(st.data, d) } else { - st.data[st.size].Set(d) + st.data[st.size] = d } st.size++ } @@ -137,7 +137,7 @@ func (st *Stack) swap16() { } func (st *Stack) dup(n int) { - st.push(&st.data[st.len()-n]) + st.push(st.data[st.len()-n]) } // Back returns the n'th item in stack