diff --git a/cmd/state/commands/opcode_tracer.go b/cmd/state/commands/opcode_tracer.go index a5ab6d83695..18d1212b9e6 100644 --- a/cmd/state/commands/opcode_tracer.go +++ b/cmd/state/commands/opcode_tracer.go @@ -370,7 +370,7 @@ func (ot *opcodeTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, lseg := len(currentEntry.Bblocks) isFirstBblock := lseg == 0 - isContinuous := pc16 == currentEntry.lastPc16+1 || currentEntry.lastOp.IsPush() + isContinuous := pc16 == currentEntry.lastPc16+1 || currentEntry.lastOp.IsPushWithImmediateArgs() if isFirstBblock || !isContinuous { // Record the end of the past bblock, if there is one if !isFirstBblock { diff --git a/core/asm/asm.go b/core/asm/asm.go index fd3ead7b446..8345ca9e5b8 100644 --- a/core/asm/asm.go +++ b/core/asm/asm.go @@ -68,7 +68,7 @@ func (it *instructionIterator) Next() bool { } it.op = vm.OpCode(it.code[it.pc]) - if it.op.IsPush() { + if it.op.IsPushWithImmediateArgs() { a := uint64(it.op) - uint64(vm.PUSH1) + 1 u := it.pc + 1 + a if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u { diff --git a/core/vm/absint_cfg_proof_gen.go b/core/vm/absint_cfg_proof_gen.go index 86a9b191ab5..26891a45abd 100644 --- a/core/vm/absint_cfg_proof_gen.go +++ b/core/vm/absint_cfg_proof_gen.go @@ -106,7 +106,7 @@ func toProgram(code []byte) *Program { stmt.ends = stmt.operation == nil //fmt.Printf("%v %v %v", pc, stmt.opcode, stmt.operation.valid) - if op.IsPush() { + if op.IsPushWithImmediateArgs() { pushByteSize := stmt.operation.opNum startMin := pc + 1 if startMin >= codeLen { @@ -334,7 +334,7 @@ func post(cfg *Cfg, st0 *astate, edge edge, maxStackLen int) (*astate, error) { stack1 := stack0.Copy() - if stmt.opcode.IsPush() { + if stmt.opcode.IsPushWithImmediateArgs() { if cfg.Program.isJumpDest(&stmt.value) || isFF(&stmt.value) { stack1.Push(AbsValueConcrete(stmt.value)) } else { @@ -530,7 +530,7 @@ func (cfg *Cfg) PrintAnlyState() { } var valueStr string - if stmt.opcode.IsPush() { + if stmt.opcode.IsPushWithImmediateArgs() { valueStr = fmt.Sprintf("%v %v", stmt.opcode, stmt.value.Hex()) } else { valueStr = fmt.Sprintf("%v", stmt.opcode) diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index ae81e88d9eb..46cdc6aac46 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -26,13 +26,11 @@ import ( // OpCode is an EVM opcode type OpCode byte -// IsPush specifies if an opcode is a PUSH opcode. -func (op OpCode) IsPush() bool { - switch op { - case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32: - return true - } - return false +// IsPushWithImmediateArgs specifies if an opcode is a PUSH opcode with immediate arguments +// (i.e. excluding PUSH0) +// TODO(racytech): revisit in EOF (see immediates in https://github.com/ethereum/go-ethereum/pull/30418/files) +func (op OpCode) IsPushWithImmediateArgs() bool { + return PUSH1 <= op && op <= PUSH32 } // IsStaticJump specifies if an opcode is JUMP. diff --git a/core/vm/opcodes_test.go b/core/vm/opcodes_test.go new file mode 100644 index 00000000000..9681397b4a1 --- /dev/null +++ b/core/vm/opcodes_test.go @@ -0,0 +1,32 @@ +// Copyright 2025 The Erigon Authors +// This file is part of Erigon. +// +// Erigon is free software: you can redistribute it and/or modify +// 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. +// +// Erigon 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. +// +// You should have received a copy of the GNU Lesser General Public License +// along with Erigon. If not, see . + +package vm + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsPushWithImmediateArgs(t *testing.T) { + assert.False(t, MCOPY.IsPushWithImmediateArgs()) + assert.False(t, PUSH0.IsPushWithImmediateArgs()) + assert.True(t, PUSH1.IsPushWithImmediateArgs()) + assert.True(t, PUSH10.IsPushWithImmediateArgs()) + assert.True(t, PUSH32.IsPushWithImmediateArgs()) + assert.False(t, DUP1.IsPushWithImmediateArgs()) +} diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 7421136864e..9714961a756 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -536,7 +536,7 @@ func (o *opObj) ToString() string { } func (o *opObj) IsPush() bool { - return o.op.IsPush() + return o.op == vm.PUSH0 || o.op.IsPushWithImmediateArgs() } func (o *opObj) setupObject() *goja.Object {