diff --git a/evms/besu.go b/evms/besu.go index 94a00c3c..d3b37f75 100644 --- a/evms/besu.go +++ b/evms/besu.go @@ -112,7 +112,13 @@ func (vm *BesuVM) ParseStateRoot(data []byte) (string, error) { root := string(data[start : start+2+64]) return root, nil } - return "", errors.New("besu: no stateroot found") + start = strings.Index(string(data), `"stateRoot":"`) + if start > 0 { + start = start + len(`"stateRoot":"`) + root := string(data[start : start+2+64]) + return root, nil + } + return "", errors.New("besu: no stateroot/posthash found") } // feed reads from the reader, does some geth-specific filtering and @@ -128,6 +134,10 @@ func (evm *BesuVM) copyUntilEnd(out io.Writer, input io.Reader) stateRoot { var elem opLog for scanner.Next(&elem) == nil { // If we have a stateroot, we're done + if len(elem.StateRoot1) != 0 { + stateRoot.StateRoot = elem.StateRoot1 + break + } if len(elem.StateRoot2) != 0 { stateRoot.StateRoot = elem.StateRoot2 break @@ -142,6 +152,8 @@ func (evm *BesuVM) copyUntilEnd(out io.Writer, input io.Reader) stateRoot { fmt.Fprintf(os.Stderr, "Error writing to out: %v\n", err) return stateRoot } + elem.FunctionDepth = 0 // function depth is optional and "gets dirty" if not set + elem.Section = 0 } root, _ := json.Marshal(stateRoot) if _, err := out.Write(append(root, '\n')); err != nil { diff --git a/evms/gen_oplog.go b/evms/gen_oplog.go index 1445525e..10b87cfc 100644 --- a/evms/gen_oplog.go +++ b/evms/gen_oplog.go @@ -16,23 +16,28 @@ var _ = (*opLogMarshaling)(nil) // MarshalJSON marshals as JSON. func (o opLog) MarshalJSON() ([]byte, error) { type opLog struct { - Pc uint64 `json:"pc"` - Op vm.OpCode `json:"op"` - Gas math.HexOrDecimal64 `json:"gas"` - GasCost math.HexOrDecimal64 `json:"gasCost"` - Memory hexutil.Bytes `json:"memory,omitempty"` - MemorySize math.HexOrDecimal64 `json:"memSize"` - Stack []hexutil.U256 `json:"stack"` - ReturnData hexutil.Bytes `json:"returnData,omitempty"` - Depth int `json:"depth"` - Err error `json:"-"` - StateRoot1 string `json:"stateRoot"` - StateRoot2 string `json:"postHash"` - OpName string `json:"opName"` + Pc uint64 `json:"pc"` + Section uint64 `json:"section,omitempty"` + Op math.HexOrDecimal64 `json:"op"` + Gas math.HexOrDecimal64 `json:"gas"` + GasCost math.HexOrDecimal64 `json:"gasCost"` + Memory hexutil.Bytes `json:"memory,omitempty"` + MemorySize math.HexOrDecimal64 `json:"memSize"` + Stack []hexutil.U256 `json:"stack"` + ReturnData hexutil.Bytes `json:"returnData,omitempty"` + Depth int `json:"depth"` + FunctionDepth int `json:"functionDepth,omitempty"` + Err error `json:"-"` + StateRoot1 string `json:"stateRoot"` + StateRoot2 string `json:"postHash"` + OpName string `json:"opName"` } var enc opLog enc.Pc = o.Pc - enc.Op = o.Op + if !IgnoreEOF { + enc.Section = o.Section + } + enc.Op = math.HexOrDecimal64(o.Op) enc.Gas = math.HexOrDecimal64(o.Gas) enc.GasCost = math.HexOrDecimal64(o.GasCost) enc.Memory = o.Memory @@ -45,6 +50,9 @@ func (o opLog) MarshalJSON() ([]byte, error) { } enc.ReturnData = o.ReturnData enc.Depth = o.Depth + if !IgnoreEOF { + enc.FunctionDepth = o.FunctionDepth + } enc.Err = o.Err enc.StateRoot1 = o.StateRoot1 enc.StateRoot2 = o.StateRoot2 @@ -55,18 +63,20 @@ func (o opLog) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (o *opLog) UnmarshalJSON(input []byte) error { type opLog struct { - Pc *uint64 `json:"pc"` - Op *vm.OpCode `json:"op"` - Gas *math.HexOrDecimal64 `json:"gas"` - GasCost *math.HexOrDecimal64 `json:"gasCost"` - Memory *hexutil.Bytes `json:"memory,omitempty"` - MemorySize *math.HexOrDecimal64 `json:"memSize"` - Stack []hexutil.U256 `json:"stack"` - ReturnData *hexutil.Bytes `json:"returnData,omitempty"` - Depth *int `json:"depth"` - Err error `json:"-"` - StateRoot1 *string `json:"stateRoot"` - StateRoot2 *string `json:"postHash"` + Pc *uint64 `json:"pc"` + Section *uint64 `json:"section,omitempty"` + Op *math.HexOrDecimal64 `json:"op"` + Gas *math.HexOrDecimal64 `json:"gas"` + GasCost *math.HexOrDecimal64 `json:"gasCost"` + Memory *hexutil.Bytes `json:"memory,omitempty"` + MemorySize *math.HexOrDecimal64 `json:"memSize"` + Stack []hexutil.U256 `json:"stack"` + ReturnData *hexutil.Bytes `json:"returnData,omitempty"` + Depth *int `json:"depth"` + FunctionDepth *int `json:"functionDepth,omitempty"` + Err error `json:"-"` + StateRoot1 *string `json:"stateRoot"` + StateRoot2 *string `json:"postHash"` } var dec opLog if err := json.Unmarshal(input, &dec); err != nil { @@ -75,8 +85,15 @@ func (o *opLog) UnmarshalJSON(input []byte) error { if dec.Pc != nil { o.Pc = *dec.Pc } + if !IgnoreEOF { + if dec.Section != nil { + o.Section = *dec.Section + } else { + o.Section = 0 + } + } if dec.Op != nil { - o.Op = *dec.Op + o.Op = vm.OpCode(uint64(*dec.Op)) } if dec.Gas != nil { o.Gas = uint64(*dec.Gas) @@ -102,6 +119,13 @@ func (o *opLog) UnmarshalJSON(input []byte) error { if dec.Depth != nil { o.Depth = *dec.Depth } + if !IgnoreEOF { + if dec.FunctionDepth != nil { + o.FunctionDepth = *dec.FunctionDepth + } else { + o.FunctionDepth = 0 + } + } if dec.Err != nil { o.Err = dec.Err } diff --git a/evms/geth.go b/evms/geth.go index 0292a91c..52db4638 100644 --- a/evms/geth.go +++ b/evms/geth.go @@ -144,7 +144,7 @@ func (evm *GethEVM) copyUntilEnd(out io.Writer, input io.Reader) stateRoot { if current == nil { // final flush return } - if prev.Pc == current.Pc && prev.Depth == current.Depth { + if prev.Pc == current.Pc && prev.Depth == current.Depth && prev.FunctionDepth == current.FunctionDepth { // Yup, that happened here. Set the error and continue prev = nil } else { diff --git a/evms/marshalling.go b/evms/marshalling.go index 0f7dd05d..8ed1e569 100644 --- a/evms/marshalling.go +++ b/evms/marshalling.go @@ -25,14 +25,32 @@ func CustomMarshal(log *opLog) []byte { b = append(b, []byte(`,"pc":`)...) b = strconv.AppendUint(b, uint64(log.Pc), 10) + if !IgnoreEOF { + // code section, if not zero + if log.Section != 0 { + b = append(b, []byte(`,"section":`)...) + b = strconv.AppendUint(b, uint64(log.Section), 10) + } + + // function call depth, if not zero + if log.FunctionDepth != 0 { + b = append(b, []byte(`,"functionDepth":`)...) + b = strconv.AppendUint(b, uint64(log.FunctionDepth), 10) + } + } + // Gas remaining b = append(b, []byte(`,"gas":`)...) b = strconv.AppendUint(b, uint64(log.Gas), 10) // Op - b = append(b, []byte(`,"op":`)...) - b = strconv.AppendUint(b, uint64(log.Op), 10) - b = append(b, []byte(`,"opName":"`)...) + b = append(b, []byte(`,"op":"0x`)...) + opcode := uint64(log.Op) + if opcode < 0x10 { + b = append(b, []byte(`0`)...) + } + b = strconv.AppendUint(b, opcode, 16) + b = append(b, []byte(`","opName":"`)...) b = append(b, []byte(log.Op.String())...) b = append(b, '"') diff --git a/evms/oplog.go b/evms/oplog.go index 7d8d6946..3699bb94 100644 --- a/evms/oplog.go +++ b/evms/oplog.go @@ -14,16 +14,18 @@ import ( // - also has the ability to soup up a stateroot, // - and is a bit more lax in parsing (e.g allows negative refund) type opLog struct { - Pc uint64 `json:"pc"` - Op vm.OpCode `json:"op"` - Gas uint64 `json:"gas"` - GasCost uint64 `json:"gasCost"` - Memory []byte `json:"memory,omitempty"` - MemorySize int `json:"memSize"` - Stack []uint256.Int `json:"stack"` - ReturnData []byte `json:"returnData,omitempty"` - Depth int `json:"depth"` - Err error `json:"-"` + Pc uint64 `json:"pc"` + Section uint64 `json:"section,omitempty"` + Op vm.OpCode `json:"op"` + Gas uint64 `json:"gas"` + GasCost uint64 `json:"gasCost"` + Memory []byte `json:"memory,omitempty"` + MemorySize int `json:"memSize"` + Stack []uint256.Int `json:"stack"` + ReturnData []byte `json:"returnData,omitempty"` + Depth int `json:"depth"` + FunctionDepth int `json:"functionDepth,omitempty"` + Err error `json:"-"` // stateroot as output by geth, reth, eels, nethermind StateRoot1 string `json:"stateRoot"` diff --git a/evms/utils.go b/evms/utils.go index 7e8da7a3..9606bdaa 100644 --- a/evms/utils.go +++ b/evms/utils.go @@ -27,6 +27,9 @@ const ( // Besu sometimes reports GasCost of 0x7fffffffffffffff, along with ,"error":"Out of gas" ClearGascost = true + + // EOF is not universally ready + IgnoreEOF = false //FIXME ) // StdErrOutput runs the command and returns its standard error. diff --git a/ops/forks.go b/ops/forks.go index 4ed99522..eff4332f 100644 --- a/ops/forks.go +++ b/ops/forks.go @@ -151,8 +151,48 @@ var ( CREATE, CALL, CALLCODE, RETURN, DELEGATECALL, CREATE2, STATICCALL, REVERT, INVALID, SELFDESTRUCT}, } + prague = Fork{ + Name: "Prague", + //ActivePrecompiles: nil, + ValidOpcodes: []OpCode{ + STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP, SIGNEXTEND, + LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE, SHL, SHR, SAR, + KECCAK256, + ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE, EXTCODESIZE, EXTCODECOPY, RETURNDATASIZE, RETURNDATACOPY, EXTCODEHASH, BLOCKHASH, + COINBASE, TIMESTAMP, NUMBER, DIFFICULTY, GASLIMIT, CHAINID, SELFBALANCE, BASEFEE, BLOBHASH, BLOBBASEFEE, + POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE, JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, TLOAD, TSTORE, MCOPY, + PUSH0, 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, + DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16, + SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16, + LOG0, LOG1, LOG2, LOG3, LOG4, + CREATE, CALL, CALLCODE, RETURN, DELEGATECALL, CREATE2, STATICCALL, REVERT, INVALID, + RETURNDATACOPY, + SELFDESTRUCT}, + } + osaka = Fork{ + Name: "Osaka", + //ActivePrecompiles: nil, + ValidOpcodes: []OpCode{ + STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, MULMOD, EXP, SIGNEXTEND, + LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE, SHL, SHR, SAR, + KECCAK256, + ADDRESS, BALANCE, ORIGIN, CALLER, CALLVALUE, CALLDATALOAD, CALLDATASIZE, CALLDATACOPY, CODESIZE, CODECOPY, GASPRICE, EXTCODESIZE, EXTCODECOPY, RETURNDATASIZE, RETURNDATACOPY, EXTCODEHASH, BLOCKHASH, + COINBASE, TIMESTAMP, NUMBER, DIFFICULTY, GASLIMIT, CHAINID, SELFBALANCE, BASEFEE, BLOBHASH, BLOBBASEFEE, + POP, MLOAD, MSTORE, MSTORE8, SLOAD, SSTORE, JUMP, JUMPI, PC, MSIZE, GAS, JUMPDEST, TLOAD, TSTORE, MCOPY, + PUSH0, 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, + DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16, + SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16, + LOG0, LOG1, LOG2, LOG3, LOG4, + DATALOAD, DATALOADN, DATASIZE, DATACOPY, // New for Osaka + RJUMP, RJUMPI, RJUMPV, CALLF, RETF, JUMPF, DUPN, SWAPN, EXCHANGE, EOFCREATE, RETURNCONTRACT, // New for Osaka + CREATE, CALL, CALLCODE, RETURN, DELEGATECALL, CREATE2, STATICCALL, REVERT, INVALID, + RETURNDATACOPY, EXTCALL, EXTDELEGATECALL, EXTSTATICCALL, // New for Osaka + SELFDESTRUCT}, + } forks = []Fork{ - istanbul, berlin, london, merged, shanghai, cancun, + istanbul, berlin, london, merged, shanghai, cancun, prague, osaka, } ) @@ -266,6 +306,42 @@ func LookupRules(fork string) params.Rules { IsShanghai: true, IsCancun: true, } + case "Prague": + return params.Rules{ + IsHomestead: true, + IsEIP150: true, + IsEIP155: true, + IsEIP158: true, + IsByzantium: true, + IsConstantinople: true, + IsPetersburg: true, + IsIstanbul: true, + IsBerlin: true, + IsLondon: true, + IsMerge: true, + IsShanghai: true, + IsCancun: true, + IsPrague: true, + } + case "Osaka": + return params.Rules{ + IsHomestead: true, + IsEIP150: true, + IsEIP155: true, + IsEIP158: true, + IsByzantium: true, + IsConstantinople: true, + IsPetersburg: true, + IsIstanbul: true, + IsBerlin: true, + IsLondon: true, + IsMerge: true, + IsShanghai: true, + IsCancun: true, + IsPrague: true, + // Depends on Geth EOF support + // IsOsaka: true, + } default: panic(fmt.Sprintf("Unsupported: %v", fork)) @@ -295,6 +371,9 @@ func LookupChainConfig(fork string) (*params.ChainConfig, error) { var merge = cpy(london, func(p *params.ChainConfig) { p.MergeNetsplitBlock = big.NewInt(0) }) var shanghai = cpy(merge, func(p *params.ChainConfig) { p.ShanghaiTime = new(uint64) }) var cancun = cpy(shanghai, func(p *params.ChainConfig) { p.CancunTime = new(uint64) }) + var prague = cpy(cancun, func(p *params.ChainConfig) { p.PragueTime = new(uint64) }) + // Depends on Geth EOF support + //var osaka = cpy(prague, func(p *params.ChainConfig) { p.OsakaTime = new(uint64) }) switch fork { case "Frontier": @@ -321,8 +400,11 @@ func LookupChainConfig(fork string) (*params.ChainConfig, error) { return merge, nil case "Shanghai": return shanghai, nil - case "Cancun": - return cancun, nil + case "Prague": + return prague, nil + // Depends on Geth EOF support + //case "Osaka": + // return osaka, nil } return nil, fmt.Errorf("unknown fork %v", fork) } diff --git a/ops/operations.go b/ops/operations.go index 98f95dc5..a815f41b 100644 --- a/ops/operations.go +++ b/ops/operations.go @@ -30,28 +30,22 @@ func (op OpCode) IsPush() bool { // HasImmediate returns true if the op has immediate after the op. func (op OpCode) HasImmediate() bool { - switch { - case op >= PUSH1 && op <= PUSH32: - return true - //case op == RJUMP || op == RJUMPI || op == RJUMPV: - // return true - } - return false + return opCodeInfo[op].immediates > 0 } func (op OpCode) IsCall() bool { return op == CALL || op == DELEGATECALL || op == CALLCODE || - op == STATICCALL + op == STATICCALL || + op == EXTCALL || + op == EXTSTATICCALL || + op == EXTDELEGATECALL } -func (op OpCode) PushSize() int { - if op.IsPush() { - return (int(op) - int(PUSH1) + 1) - } - return 0 +func (op OpCode) ImmediateSize() int { + return opCodeInfo[op].immediates // FIXME for RJUMPV it is variable based on byte 1 } // 0x0 range - arithmetic ops. @@ -140,10 +134,6 @@ const ( GAS = OpCode(0x5A) JUMPDEST = OpCode(0x5B) - //RJUMP = OpCode(0x5c) // Cancun - //RJUMPI = OpCode(0x5d) // Cancun - //RJUMPV = OpCode(0x5e) // Cancun - TLOAD = OpCode(0x5c) // Cancun TSTORE = OpCode(0x5d) // Cancun MCOPY = OpCode(0x5e) // Cancun @@ -236,33 +226,27 @@ const ( LOG4 = OpCode(0xa4) ) -// 0xb0 range +// 0xd0 range - EOF data operations const ( -// CALLF = OpCode(0xb0) -// RETF = OpCode(0xb1) + DATALOAD = OpCode(0xd0) // osaka + DATALOADN = OpCode(0xd1) // osaka + DATASIZE = OpCode(0xd2) // osaka + DATACOPY = OpCode(0xd3) // osaka ) -// 0xd0 range - eof operations. +// 0xe0 range - EOF opcodes with immediates const ( - DATALOAD OpCode = 0xd0 - DATALOADN OpCode = 0xd1 - DATASIZE OpCode = 0xd2 - DATACOPY OpCode = 0xd3 -) - -// 0xe0 range - eof operations. -const ( - RJUMP OpCode = 0xe0 - RJUMPI OpCode = 0xe1 - RJUMPV OpCode = 0xe2 - CALLF OpCode = 0xe3 - RETF OpCode = 0xe4 - JUMPF OpCode = 0xe5 - DUPN OpCode = 0xe6 - SWAPN OpCode = 0xe7 - EXCHANGE OpCode = 0xe8 - EOFCREATE OpCode = 0xec - RETURNCONTRACT OpCode = 0xee + RJUMP = OpCode(0xe0) // osaka + RJUMPI = OpCode(0xe1) // osaka + RJUMPV = OpCode(0xe2) // osaka + CALLF = OpCode(0xe3) // osaka + RETF = OpCode(0xe4) // osaka + JUMPF = OpCode(0xe5) // osaka + DUPN = OpCode(0xe6) // osaka + SWAPN = OpCode(0xe7) // osaka + EXCHANGE = OpCode(0xe8) // osaka + EOFCREATE = OpCode(0xec) // osaka + RETURNCONTRACT = OpCode(0xee) // osaka ) // 0xf0 range - closures. @@ -274,15 +258,15 @@ const ( DELEGATECALL = OpCode(0xf4) CREATE2 = OpCode(0xf5) - RETURNDATALOAD = OpCode(0xf7) // EOA - EXTCALL = OpCode(0xf8) // EOA - EXTDELEGATECALL = OpCode(0xf9) // EOA + RETURNDATALOAD = OpCode(0xf7) // osaka + EXTCALL = OpCode(0xf8) // osaka + EXTDELEGATECALL = OpCode(0xf9) // osaka + STATICCALL = OpCode(0xfa) + EXTSTATICCALL = OpCode(0xfb) // osaka - STATICCALL = OpCode(0xfa) - EXTSTATICCALL = OpCode(0xfb) // EOA - INVALID = OpCode(0xfe) - REVERT = OpCode(0xfd) - SELFDESTRUCT = OpCode(0xff) + REVERT = OpCode(0xfd) + INVALID = OpCode(0xfe) + SELFDESTRUCT = OpCode(0xff) ) func (op OpCode) String() string { @@ -297,14 +281,6 @@ func IsDefined(op OpCode) bool { return ok } -func IsValid(op OpCode) bool { - //if op == RJUMP || op == RJUMPV || op == RJUMPI { - // return false - //} - _, ok := opCodeInfo[op] - return ok -} - // stringToOp is a mapping from strings to OpCode var stringToOp map[string]OpCode @@ -324,187 +300,200 @@ func StringToOp(str string) OpCode { } type opInfo struct { - name string - pops []string - pushes []string + name string + immediates int + pops []string + pushes []string } var opCodeInfo = map[OpCode]opInfo{ - STOP: {"STOP", nil, nil}, - ADD: {"ADD", []string{"a", "b"}, []string{"a + b"}}, - MUL: {"MUL", []string{"a", "b"}, []string{"a * b"}}, - SUB: {"SUB", []string{"a", "b"}, []string{"a - b"}}, - DIV: {"DIV", []string{"a", "b"}, []string{"a / b"}}, - SDIV: {"SDIV", []string{"a", "b"}, []string{"a / b (signed)"}}, - MOD: {"MOD", []string{"a", "b"}, []string{"a % b"}}, - SMOD: {"SMOD", []string{"a", "b"}, []string{"a mod b (signed)"}}, - EXP: {"EXP", []string{"base", "exp"}, []string{"base^exp"}}, - NOT: {"NOT", []string{"a"}, []string{"not(a)"}}, - LT: {"LT", []string{"a", "b"}, []string{"a < b"}}, - GT: {"GT", []string{"a", "b"}, []string{"a > b"}}, - SLT: {"SLT", []string{"a", "b"}, []string{"a < b (signed)"}}, - SGT: {"SGT", []string{"a", "b"}, []string{"a > b (signed)"}}, - EQ: {"EQ", []string{"a", "b"}, []string{"a == b"}}, - ISZERO: {"ISZERO", []string{"a"}, []string{"a == 0"}}, - SIGNEXTEND: {"SIGNEXTEND", []string{"bitlen", "a"}, []string{"signextend(a, bitlen)"}}, - - AND: {"AND", []string{"a", "b"}, []string{"a && b"}}, - OR: {"OR", []string{"a", "b"}, []string{"a || b"}}, - XOR: {"XOR", []string{"a", "b"}, []string{"a xor b"}}, - BYTE: {"BYTE", []string{"index", "val"}, []string{"byte at val[index]"}}, - SHL: {"SHL", []string{"shift", "x"}, []string{"x << shift"}}, - SHR: {"SHR", []string{"shift", "x"}, []string{"x >> shift"}}, - SAR: {"SAR", []string{"shift", "x"}, []string{"x >>> shift"}}, - ADDMOD: {"ADDMOD", []string{"a", "b", "x"}, []string{"(a + b) mod x"}}, - MULMOD: {"MULMOD", []string{"a", "b", "x"}, []string{"(a * b) mod x"}}, + STOP: {"STOP", 0, nil, nil}, + ADD: {"ADD", 0, []string{"a", "b"}, []string{"a + b"}}, + MUL: {"MUL", 0, []string{"a", "b"}, []string{"a * b"}}, + SUB: {"SUB", 0, []string{"a", "b"}, []string{"a - b"}}, + DIV: {"DIV", 0, []string{"a", "b"}, []string{"a / b"}}, + SDIV: {"SDIV", 0, []string{"a", "b"}, []string{"a / b (signed)"}}, + MOD: {"MOD", 0, []string{"a", "b"}, []string{"a % b"}}, + SMOD: {"SMOD", 0, []string{"a", "b"}, []string{"a mod b (signed)"}}, + EXP: {"EXP", 0, []string{"base", "exp"}, []string{"base^exp"}}, + NOT: {"NOT", 0, []string{"a"}, []string{"not(a)"}}, + LT: {"LT", 0, []string{"a", "b"}, []string{"a < b"}}, + GT: {"GT", 0, []string{"a", "b"}, []string{"a > b"}}, + SLT: {"SLT", 0, []string{"a", "b"}, []string{"a < b (signed)"}}, + SGT: {"SGT", 0, []string{"a", "b"}, []string{"a > b (signed)"}}, + EQ: {"EQ", 0, []string{"a", "b"}, []string{"a == b"}}, + ISZERO: {"ISZERO", 0, []string{"a"}, []string{"a == 0"}}, + SIGNEXTEND: {"SIGNEXTEND", 0, []string{"bitlen", "a"}, []string{"signextend(a, bitlen)"}}, + + AND: {"AND", 0, []string{"a", "b"}, []string{"a && b"}}, + OR: {"OR", 0, []string{"a", "b"}, []string{"a || b"}}, + XOR: {"XOR", 0, []string{"a", "b"}, []string{"a xor b"}}, + BYTE: {"BYTE", 0, []string{"index", "val"}, []string{"byte at val[index]"}}, + SHL: {"SHL", 0, []string{"shift", "x"}, []string{"x << shift"}}, + SHR: {"SHR", 0, []string{"shift", "x"}, []string{"x >> shift"}}, + SAR: {"SAR", 0, []string{"shift", "x"}, []string{"x >>> shift"}}, + ADDMOD: {"ADDMOD", 0, []string{"a", "b", "x"}, []string{"(a + b) mod x"}}, + MULMOD: {"MULMOD", 0, []string{"a", "b", "x"}, []string{"(a * b) mod x"}}, // 0x20 range - crypto. - KECCAK256: {"KECCAK256", []string{"offset", "size"}, []string{"keccak256(mem[offset:offset+size])"}}, + KECCAK256: {"KECCAK256", 0, []string{"offset", "size"}, []string{"keccak256(mem[offset:offset+size])"}}, // 0x30 range - closure state. - ADDRESS: {"ADDRESS", nil, []string{"address of current context"}}, - BALANCE: {"BALANCE", []string{"address"}, []string{"balance of address"}}, - ORIGIN: {"ORIGIN", nil, []string{"transaction origin"}}, - CALLER: {"CALLER", nil, []string{"sender"}}, - CALLVALUE: {"CALLVALUE", nil, []string{"call value"}}, - CALLDATALOAD: {"CALLDATALOAD", []string{"offset"}, []string{"calldata[offset:offset+32]"}}, - CALLDATASIZE: {"CALLDATASIZE", nil, []string{"size of calldata"}}, - CALLDATACOPY: {"CALLDATACOPY", []string{"memOffset", "dataOffset", "length"}, nil}, - CODESIZE: {"CODESIZE", nil, []string{"size of code in this context"}}, - CODECOPY: {"CODECOPY", []string{"memOffset", "codeOffset", "length"}, nil}, - GASPRICE: {"GASPRICE", nil, []string{"transaction gasprice"}}, - - EXTCODESIZE: {"EXTCODESIZE", []string{"address"}, []string{"code size at 'address'"}}, - EXTCODECOPY: {"EXTCODECOPY", []string{"address", "memOffset", "codeOffset", "length"}, nil}, - - RETURNDATASIZE: {"RETURNDATASIZE", nil, []string{"size of returndata"}}, - RETURNDATACOPY: {"RETURNDATACOPY", []string{"memOffset", "dataOffset", "length"}, nil}, - EXTCODEHASH: {"EXTCODEHASH", []string{"address"}, []string{"codehash at 'address'"}}, + ADDRESS: {"ADDRESS", 0, nil, []string{"address of current context"}}, + BALANCE: {"BALANCE", 0, []string{"address"}, []string{"balance of address"}}, + ORIGIN: {"ORIGIN", 0, nil, []string{"transaction origin"}}, + CALLER: {"CALLER", 0, nil, []string{"sender"}}, + CALLVALUE: {"CALLVALUE", 0, nil, []string{"call value"}}, + CALLDATALOAD: {"CALLDATALOAD", 0, []string{"offset"}, []string{"calldata[offset:offset+32]"}}, + CALLDATASIZE: {"CALLDATASIZE", 0, nil, []string{"size of calldata"}}, + CALLDATACOPY: {"CALLDATACOPY", 0, []string{"memOffset", "dataOffset", "length"}, nil}, + CODESIZE: {"CODESIZE", 0, nil, []string{"size of code in this context"}}, + CODECOPY: {"CODECOPY", 0, []string{"memOffset", "codeOffset", "length"}, nil}, + GASPRICE: {"GASPRICE", 0, nil, []string{"transaction gasprice"}}, + + EXTCODESIZE: {"EXTCODESIZE", 0, []string{"address"}, []string{"code size at 'address'"}}, + EXTCODECOPY: {"EXTCODECOPY", 0, []string{"address", "memOffset", "codeOffset", "length"}, nil}, + + RETURNDATASIZE: {"RETURNDATASIZE", 0, nil, []string{"size of returndata"}}, + RETURNDATACOPY: {"RETURNDATACOPY", 0, []string{"memOffset", "dataOffset", "length"}, nil}, + EXTCODEHASH: {"EXTCODEHASH", 0, []string{"address"}, []string{"codehash at 'address'"}}, // 0x40 range - block operations. - BLOCKHASH: {"BLOCKHASH", []string{"blocknum"}, []string{"hash of block at blocknum"}}, - COINBASE: {"COINBASE", nil, []string{"block miner address"}}, - TIMESTAMP: {"TIMESTAMP", nil, []string{"unix time of current block"}}, - NUMBER: {"NUMBER", nil, []string{"current block number"}}, - DIFFICULTY: {"DIFFICULTY", nil, []string{"current block difficulty"}}, - GASLIMIT: {"GASLIMIT", nil, []string{"block gas limit"}}, - CHAINID: {"CHAINID", nil, []string{"chain id"}}, - SELFBALANCE: {"SELFBALANCE", nil, []string{"balance at current context"}}, - BASEFEE: {"BASEFEE", nil, []string{"basefee in current block"}}, - BLOBHASH: {"BLOBHASH", []string{"index"}, []string{"blobhash at index"}}, - BLOBBASEFEE: {"BLOBBASEFEE", nil, []string{"blob basefee in current block"}}, - - POP: {"POP", []string{"value to pop"}, nil}, - MLOAD: {"MLOAD", []string{"offset"}, []string{"value"}}, - MSTORE: {"MSTORE", []string{"offset", "value"}, nil}, - MSTORE8: {"MSTORE8", []string{"offset", "value"}, nil}, - SLOAD: {"SLOAD", []string{"slot"}, []string{"value"}}, - SSTORE: {"SSTORE", []string{"slot", "value"}, nil}, - JUMP: {"JUMP", []string{"loc"}, nil}, - JUMPI: {"JUMPI", []string{"loc", "cond"}, nil}, - PC: {"PC", nil, []string{"current PC"}}, - MSIZE: {"MSIZE", nil, []string{"size of memory"}}, - GAS: {"GAS", nil, []string{"current gas remaining"}}, - JUMPDEST: {"JUMPDEST", nil, nil}, - MCOPY: {"MCOPY", []string{"dest", "source", "length"}, nil}, - TLOAD: {"TLOAD", []string{"t-slot"}, []string{"value"}}, - TSTORE: {"TSTORE", []string{"t-slot", "value"}, nil}, - PUSH0: {"PUSH0", nil, []string{"zero"}}, - - //RJUMP: {"RJUMP", nil, nil}, - //RJUMPI: {"RJUMPI", []string{"cond"}, nil}, - //RJUMPV: {"RJUMPV", []string{"case"}, nil}, + BLOCKHASH: {"BLOCKHASH", 0, []string{"blocknum"}, []string{"hash of block at blocknum"}}, + COINBASE: {"COINBASE", 0, nil, []string{"block miner address"}}, + TIMESTAMP: {"TIMESTAMP", 0, nil, []string{"unix time of current block"}}, + NUMBER: {"NUMBER", 0, nil, []string{"current block number"}}, + DIFFICULTY: {"DIFFICULTY", 0, nil, []string{"current block difficulty"}}, + GASLIMIT: {"GASLIMIT", 0, nil, []string{"block gas limit"}}, + CHAINID: {"CHAINID", 0, nil, []string{"chain id"}}, + SELFBALANCE: {"SELFBALANCE", 0, nil, []string{"balance at current context"}}, + BASEFEE: {"BASEFEE", 0, nil, []string{"basefee in current block"}}, + BLOBHASH: {"BLOBHASH", 0, []string{"index"}, []string{"blobhash at index"}}, + BLOBBASEFEE: {"BLOBBASEFEE", 0, nil, []string{"blob basefee in current block"}}, + + POP: {"POP", 0, []string{"value to pop"}, nil}, + MLOAD: {"MLOAD", 0, []string{"offset"}, []string{"value"}}, + MSTORE: {"MSTORE", 0, []string{"offset", "value"}, nil}, + MSTORE8: {"MSTORE8", 0, []string{"offset", "value"}, nil}, + SLOAD: {"SLOAD", 0, []string{"slot"}, []string{"value"}}, + SSTORE: {"SSTORE", 0, []string{"slot", "value"}, nil}, + JUMP: {"JUMP", 0, []string{"loc"}, nil}, + JUMPI: {"JUMPI", 0, []string{"loc", "cond"}, nil}, + PC: {"PC", 0, nil, []string{"current PC"}}, + MSIZE: {"MSIZE", 0, nil, []string{"size of memory"}}, + GAS: {"GAS", 0, nil, []string{"current gas remaining"}}, + JUMPDEST: {"JUMPDEST", 0, nil, nil}, + MCOPY: {"MCOPY", 0, []string{"dest", "source", "length"}, nil}, + TLOAD: {"TLOAD", 0, []string{"t-slot"}, []string{"value"}}, + TSTORE: {"TSTORE", 0, []string{"t-slot", "value"}, nil}, + PUSH0: {"PUSH0", 0, nil, []string{"zero"}}, // 0x60 through 0x7F range - push. - PUSH1: {"PUSH1", nil, []string{"1 byte pushed value"}}, - PUSH2: {"PUSH2", nil, []string{"2 bytes pushed value"}}, - PUSH3: {"PUSH3", nil, []string{"3 bytes pushed value"}}, - PUSH4: {"PUSH4", nil, []string{"4 bytes pushed value"}}, - PUSH5: {"PUSH5", nil, []string{"5 bytes pushed value"}}, - PUSH6: {"PUSH6", nil, []string{"6 bytes pushed value"}}, - PUSH7: {"PUSH7", nil, []string{"7 bytes pushed value"}}, - PUSH8: {"PUSH8", nil, []string{"8 bytes pushed value"}}, - PUSH9: {"PUSH9", nil, []string{"9 bytes pushed value"}}, - PUSH10: {"PUSH10", nil, []string{"10 bytes pushed value"}}, - PUSH11: {"PUSH11", nil, []string{"11 bytes pushed value"}}, - PUSH12: {"PUSH12", nil, []string{"12 bytes pushed value"}}, - PUSH13: {"PUSH13", nil, []string{"13 bytes pushed value"}}, - PUSH14: {"PUSH14", nil, []string{"14 bytes pushed value"}}, - PUSH15: {"PUSH15", nil, []string{"15 bytes pushed value"}}, - PUSH16: {"PUSH16", nil, []string{"16 bytes pushed value"}}, - PUSH17: {"PUSH17", nil, []string{"17 bytes pushed value"}}, - PUSH18: {"PUSH18", nil, []string{"18 bytes pushed value"}}, - PUSH19: {"PUSH19", nil, []string{"19 bytes pushed value"}}, - PUSH20: {"PUSH20", nil, []string{"19 bytes pushed value"}}, - PUSH21: {"PUSH21", nil, []string{"21 bytes pushed value"}}, - PUSH22: {"PUSH22", nil, []string{"22 bytes pushed value"}}, - PUSH23: {"PUSH23", nil, []string{"23 bytes pushed value"}}, - PUSH24: {"PUSH24", nil, []string{"24 bytes pushed value"}}, - PUSH25: {"PUSH25", nil, []string{"25 bytes pushed value"}}, - PUSH26: {"PUSH26", nil, []string{"26 bytes pushed value"}}, - PUSH27: {"PUSH27", nil, []string{"27 bytes pushed value"}}, - PUSH28: {"PUSH28", nil, []string{"28 bytes pushed value"}}, - PUSH29: {"PUSH29", nil, []string{"29 bytes pushed value"}}, - PUSH30: {"PUSH30", nil, []string{"30 bytes pushed value"}}, - PUSH31: {"PUSH31", nil, []string{"31 bytes pushed value"}}, - PUSH32: {"PUSH32", nil, []string{"32 bytes pushed value"}}, + PUSH1: {"PUSH1", 1, nil, []string{"1 byte pushed value"}}, + PUSH2: {"PUSH2", 2, nil, []string{"2 bytes pushed value"}}, + PUSH3: {"PUSH3", 3, nil, []string{"3 bytes pushed value"}}, + PUSH4: {"PUSH4", 4, nil, []string{"4 bytes pushed value"}}, + PUSH5: {"PUSH5", 5, nil, []string{"5 bytes pushed value"}}, + PUSH6: {"PUSH6", 6, nil, []string{"6 bytes pushed value"}}, + PUSH7: {"PUSH7", 7, nil, []string{"7 bytes pushed value"}}, + PUSH8: {"PUSH8", 8, nil, []string{"8 bytes pushed value"}}, + PUSH9: {"PUSH9", 9, nil, []string{"9 bytes pushed value"}}, + PUSH10: {"PUSH10", 10, nil, []string{"10 bytes pushed value"}}, + PUSH11: {"PUSH11", 11, nil, []string{"11 bytes pushed value"}}, + PUSH12: {"PUSH12", 12, nil, []string{"12 bytes pushed value"}}, + PUSH13: {"PUSH13", 13, nil, []string{"13 bytes pushed value"}}, + PUSH14: {"PUSH14", 14, nil, []string{"14 bytes pushed value"}}, + PUSH15: {"PUSH15", 15, nil, []string{"15 bytes pushed value"}}, + PUSH16: {"PUSH16", 16, nil, []string{"16 bytes pushed value"}}, + PUSH17: {"PUSH17", 17, nil, []string{"17 bytes pushed value"}}, + PUSH18: {"PUSH18", 18, nil, []string{"18 bytes pushed value"}}, + PUSH19: {"PUSH19", 19, nil, []string{"19 bytes pushed value"}}, + PUSH20: {"PUSH20", 20, nil, []string{"19 bytes pushed value"}}, + PUSH21: {"PUSH21", 21, nil, []string{"21 bytes pushed value"}}, + PUSH22: {"PUSH22", 22, nil, []string{"22 bytes pushed value"}}, + PUSH23: {"PUSH23", 23, nil, []string{"23 bytes pushed value"}}, + PUSH24: {"PUSH24", 24, nil, []string{"24 bytes pushed value"}}, + PUSH25: {"PUSH25", 25, nil, []string{"25 bytes pushed value"}}, + PUSH26: {"PUSH26", 26, nil, []string{"26 bytes pushed value"}}, + PUSH27: {"PUSH27", 27, nil, []string{"27 bytes pushed value"}}, + PUSH28: {"PUSH28", 28, nil, []string{"28 bytes pushed value"}}, + PUSH29: {"PUSH29", 29, nil, []string{"29 bytes pushed value"}}, + PUSH30: {"PUSH30", 30, nil, []string{"30 bytes pushed value"}}, + PUSH31: {"PUSH31", 31, nil, []string{"31 bytes pushed value"}}, + PUSH32: {"PUSH32", 32, nil, []string{"32 bytes pushed value"}}, // cover your eyes, here comes ugly - DUP1: {"DUP1", []string{"x"}, []string{"x", "x"}}, - DUP2: {"DUP2", []string{"-", "x"}, []string{"x", "-", "x"}}, - DUP3: {"DUP3", []string{"-", "-", "x"}, []string{"x", "-", "-", "x"}}, - DUP4: {"DUP4", []string{"-", "-", "-", "x"}, []string{"x", "-", "-", "-", "x"}}, - DUP5: {"DUP5", []string{"-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "x"}}, - DUP6: {"DUP6", []string{"-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "x"}}, - DUP7: {"DUP7", []string{"-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "x"}}, - DUP8: {"DUP8", []string{"-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP9: {"DUP9", []string{"-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP10: {"DUP10", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP11: {"DUP11", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP12: {"DUP12", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP13: {"DUP13", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP14: {"DUP14", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP15: {"DUP15", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - DUP16: {"DUP16", []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, - - SWAP1: {"SWAP1", []string{"a", "b"}, []string{"b", "a"}}, - SWAP2: {"SWAP2", []string{"a", "", "b"}, []string{"b", "", "a"}}, - SWAP3: {"SWAP3", []string{"a", "", "", "b"}, []string{"b", "", "", "a"}}, - SWAP4: {"SWAP4", []string{"a", "", "", "", "b"}, []string{"b", "", "", "", "a"}}, - SWAP5: {"SWAP5", []string{"a", "", "", "", "", "b"}, []string{"b", "", "", "", "", "a"}}, - SWAP6: {"SWAP6", []string{"a", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "a"}}, - SWAP7: {"SWAP7", []string{"a", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "a"}}, - SWAP8: {"SWAP8", []string{"a", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "a"}}, - SWAP9: {"SWAP9", []string{"a", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "a"}}, - SWAP10: {"SWAP10", []string{"a", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP11: {"SWAP11", []string{"a", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP12: {"SWAP12", []string{"a", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP13: {"SWAP13", []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP14: {"SWAP14", []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP15: {"SWAP15", []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, - SWAP16: {"SWAP16", []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, - - LOG0: {"LOG0", []string{"mStart", "mSize"}, nil}, - LOG1: {"LOG1", []string{"mStart", "mSize", "topic"}, nil}, - LOG2: {"LOG2", []string{"mStart", "mSize", "topic", "topic"}, nil}, - LOG3: {"LOG3", []string{"mStart", "mSize", "topic", "topic", "topic"}, nil}, - LOG4: {"LOG4", []string{"mStart", "mSize", "topic", "topic", "topic", "topic"}, nil}, - - // 0xb0 range. - //CALLF: {"CALLF", nil, nil}, - //RETF: {"RETF", nil, nil}, + DUP1: {"DUP1", 0, []string{"x"}, []string{"x", "x"}}, + DUP2: {"DUP2", 0, []string{"-", "x"}, []string{"x", "-", "x"}}, + DUP3: {"DUP3", 0, []string{"-", "-", "x"}, []string{"x", "-", "-", "x"}}, + DUP4: {"DUP4", 0, []string{"-", "-", "-", "x"}, []string{"x", "-", "-", "-", "x"}}, + DUP5: {"DUP5", 0, []string{"-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "x"}}, + DUP6: {"DUP6", 0, []string{"-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "x"}}, + DUP7: {"DUP7", 0, []string{"-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "x"}}, + DUP8: {"DUP8", 0, []string{"-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP9: {"DUP9", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP10: {"DUP10", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP11: {"DUP11", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP12: {"DUP12", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP13: {"DUP13", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP14: {"DUP14", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP15: {"DUP15", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + DUP16: {"DUP16", 0, []string{"-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}, []string{"x", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "x"}}, + + SWAP1: {"SWAP1", 0, []string{"a", "b"}, []string{"b", "a"}}, + SWAP2: {"SWAP2", 0, []string{"a", "", "b"}, []string{"b", "", "a"}}, + SWAP3: {"SWAP3", 0, []string{"a", "", "", "b"}, []string{"b", "", "", "a"}}, + SWAP4: {"SWAP4", 0, []string{"a", "", "", "", "b"}, []string{"b", "", "", "", "a"}}, + SWAP5: {"SWAP5", 0, []string{"a", "", "", "", "", "b"}, []string{"b", "", "", "", "", "a"}}, + SWAP6: {"SWAP6", 0, []string{"a", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "a"}}, + SWAP7: {"SWAP7", 0, []string{"a", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "a"}}, + SWAP8: {"SWAP8", 0, []string{"a", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "a"}}, + SWAP9: {"SWAP9", 0, []string{"a", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "a"}}, + SWAP10: {"SWAP10", 0, []string{"a", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP11: {"SWAP11", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP12: {"SWAP12", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP13: {"SWAP13", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP14: {"SWAP14", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP15: {"SWAP15", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, + SWAP16: {"SWAP16", 0, []string{"a", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "b"}, []string{"b", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a"}}, + + LOG0: {"LOG0", 0, []string{"mStart", "mSize"}, nil}, + LOG1: {"LOG1", 0, []string{"mStart", "mSize", "topic"}, nil}, + LOG2: {"LOG2", 0, []string{"mStart", "mSize", "topic", "topic"}, nil}, + LOG3: {"LOG3", 0, []string{"mStart", "mSize", "topic", "topic", "topic"}, nil}, + LOG4: {"LOG4", 0, []string{"mStart", "mSize", "topic", "topic", "topic", "topic"}, nil}, + + DATALOAD: {"DATALOAD", 0, []string{"offset"}, []string{"data"}}, + DATALOADN: {"DATALOADN", 1, nil, []string{"data"}}, + DATASIZE: {"DATASIZE", 0, nil, []string{"data"}}, + DATACOPY: {"DATACOPY", 0, []string{"mem_offset", "offset", "size"}, nil}, + RJUMP: {"RJUMP", 2, nil, nil}, + RJUMPI: {"RJUMPI", 2, []string{"condition"}, nil}, + RJUMPV: {"RJUMPV", 3, []string{"case"}, nil}, + CALLF: {"CALLF", 2, nil, []string{"0 or more items, depends on type headers"}}, + RETF: {"RETF", 0, nil, nil}, + JUMPF: {"JUMPF", 2, nil, nil}, + DUPN: {"DUPN", 1, nil, nil}, + SWAPN: {"SWAPN", 1, nil, nil}, + EXCHANGE: {"EXCHANGE", 1, nil, nil}, + EOFCREATE: {"EOFCREATE", 2, []string{"value", "salt", "input_offset", "input_size"}, []string{"address"}}, + RETURNCONTRACT: {"RETURNCONTRACT", 2, []string{"aux_data_offset", "aux_data_size"}, nil}, // 0xf0 range. - CREATE: {"CREATE", []string{"value", "mem offset", "mem size"}, []string{"address or zero"}}, - CALL: {"CALL", []string{"gas", "address", "value", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, - RETURN: {"RETURN", []string{"offset", "size"}, nil}, - CALLCODE: {"CALLCODE", []string{"gas", "address", "value", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, - DELEGATECALL: {"DELEGATECALL", []string{"gas", "address", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, - CREATE2: {"CREATE2", []string{"value", "mem offset", "mem size", "salt"}, []string{"address or zero"}}, - STATICCALL: {"STATICCALL", []string{"gas", "address", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, - REVERT: {"REVERT", []string{"offset", "size"}, nil}, - INVALID: {"INVALID", nil, nil}, - SELFDESTRUCT: {"SELFDESTRUCT", []string{"beneficiary address"}, nil}, + CREATE: {"CREATE", 0, []string{"value", "mem offset", "mem size"}, []string{"address or zero"}}, + CALL: {"CALL", 0, []string{"gas", "address", "value", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, + RETURN: {"RETURN", 0, []string{"offset", "size"}, nil}, + CALLCODE: {"CALLCODE", 0, []string{"gas", "address", "value", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, + DELEGATECALL: {"DELEGATECALL", 0, []string{"gas", "address", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, + CREATE2: {"CREATE2", 0, []string{"value", "mem offset", "mem size", "salt"}, []string{"address or zero"}}, + RETURNDATALOAD: {"RETURNDATALOAD", 0, []string{"offset"}, []string{"data"}}, + EXTCALL: {"EXTCALL", 0, []string{"target_address", "input_offset", "input_size", "value"}, []string{"status"}}, + EXTDELEGATECALL: {"EXTDELEGATECALL", 0, []string{"target_address", "input_offset", "input_size"}, []string{"status"}}, + STATICCALL: {"STATICCALL", 0, []string{"gas", "address", "in offset", "in size", "out offset", "out size"}, []string{"exitcode (1 for success)"}}, + EXTSTATICCALL: {"EXTSTATICCALL", 0, []string{"target_address", "input_offset", "input_size"}, []string{"status"}}, + REVERT: {"REVERT", 0, []string{"offset", "size"}, nil}, + INVALID: {"INVALID", 0, nil, nil}, + SELFDESTRUCT: {"SELFDESTRUCT", 0, []string{"beneficiary address"}, nil}, } func (op OpCode) Pops() []string { diff --git a/ops/operations_test.go b/ops/operations_test.go index 12ab0c04..f2192819 100644 --- a/ops/operations_test.go +++ b/ops/operations_test.go @@ -29,15 +29,12 @@ func TestSanity(t *testing.T) { for i := 0; i < 256; i++ { - // Skip over EOA - if i >= int(DATALOAD) && i <= int(RETURNCONTRACT) || - i == int(RETURNDATALOAD) || - i == int(EXTCALL) || - i == int(EXTDELEGATECALL) || - i == int(EXTSTATICCALL) { + // We have the EOF opcodes defined, geth doesn't yet. + switch i { + case 0x5c, 0x5d, 0x5e, 0xb0, 0xb1, 0xb3, 0xb4: continue - } + } // Lookup the name via opcode gethOp := vm.OpCode(byte(i)) ourOp := OpCode(byte(i)) diff --git a/traces/reader.go b/traces/reader.go index 3a427a52..894c8dd4 100644 --- a/traces/reader.go +++ b/traces/reader.go @@ -79,6 +79,9 @@ func (t *TraceLine) Get(title string) string { return fmt.Sprintf("%v (0x%x)", op.Pc/ChunkSize, op.Pc/ChunkSize) case "pc": return fmt.Sprintf("%v (0x%x)", op.Pc, op.Pc) + // Depends on Geth EOF support + //case "section": + // return fmt.Sprintf("%v", op.Section) case "opname": return op.OpName() case "opcode": @@ -89,6 +92,9 @@ func (t *TraceLine) Get(title string) string { return fmt.Sprintf("%d", op.GasCost) case "depth": return fmt.Sprintf("%d", op.Depth) + // Depends on Geth EOF support + //case "functiondepth": + // return fmt.Sprintf("%d", op.FunctionDepth) case "refund": return fmt.Sprintf("%d", op.RefundCounter) case "memsize": @@ -137,6 +143,12 @@ func (t *TraceLine) Equals(other *TraceLine) bool { t.log.Gas != other.log.Gas { return false } + // EIP-7756 fields. If both are non-zero they must match + // Depends on Geth EOF support + //if (t.log.Section != 0 && other.log.Section != 0 && t.log.Section != other.log.Section) || + // (t.log.FunctionDepth != 0 && other.log.FunctionDepth != 0 && t.log.FunctionDepth != other.log.FunctionDepth) { + // return false + //} // Also inspect stack for i, elem := range t.log.Stack { if elem != other.log.Stack[i] { @@ -180,6 +192,9 @@ func convertToStructLog(op map[string]interface{}) (*logger.StructLog, error) { switch k { case "pc": log.Pc = uint64(intify(v)) + // Depends on Geth EOF support + //case "section": + // log.Section = uint64(intify(v)) case "memSize": log.MemorySize = intify(v) case "op": @@ -191,6 +206,9 @@ func convertToStructLog(op map[string]interface{}) (*logger.StructLog, error) { log.GasCost = uint64(intify(v)) case "depth": log.Depth = int(v.(float64)) + // Depends on Geth EOF support + //case "functionDepth": + // log.FunctionDepth = int(v.(float64)) case "refund": log.RefundCounter = uint64(intify(v)) case "stack": diff --git a/ui/viewmanager.go b/ui/viewmanager.go index 32f2f0d1..42075773 100644 --- a/ui/viewmanager.go +++ b/ui/viewmanager.go @@ -18,6 +18,7 @@ package ui import ( "fmt" + "github.com/holiman/goevmlab/evms" "strings" "github.com/gdamore/tcell/v2" @@ -204,7 +205,13 @@ func (mgr *viewManager) onStepSelected(line *traces.TraceLine) { mgr.opView.AddFormItem(field) } - for _, l := range []string{"pc", "opcode", "opName", "gasCost", "gas", "memSize", "addr"} { + var headers []string + if evms.IgnoreEOF { + headers = []string{"pc", "section", "opcode", "opName", "gasCost", "gas", "memSize", "addr", "functionDepth"} + } else { + headers = []string{"pc", "opcode", "opName", "gasCost", "gas", "memSize", "addr"} + } + for _, l := range headers { add(l, line.Get(l)) } // Add the call stack info @@ -252,8 +259,8 @@ func (mgr *viewManager) init(trace *traces.Traces) { { // The operations table table := mgr.traceView - headings := []string{"step", "pc", "opName", "opCode", - "gas", "gasCost", "depth", "refund"} + headings := []string{"step", "pc", "section", "opName", "opCode", + "gas", "gasCost", "depth", "functionDepth", "refund"} if mgr.config != nil && mgr.config.HasChunking { headings = append(headings, "chunk")