0

I studied EVM implementations and the bytecode sequences used by them. I wondered that there are three opcodes which are recognized by the EVM but actually are invalid opcodes.

B0 PUSH
B1 DUP
B2 SWAP

If I execute the opcode B0 with Geth-EVM i get the following output:

./geth-evm-1.8.0-stable --json --code b0 run
{"pc":0,"op":176,"gas":"0x2540be400","gasCost":"0x0","memory":"0x","memSize":0,"stack":[],"depth":1,"opName":"PUSH","error":"invalid opcode 0xb0"}
{"output":"","gasUsed":"0x2540be400","time":137988,"error":"invalid opcode 0xb0"}
{"output":"","gasUsed":"0x2540be400","time":210042,"error":"invalid opcode 0xb0"}

As one can see, the opcode B0 is recognized and processed as PUSH opcode. At the same time the error field writes invalid opcode 0xb0. The same holds for the other two opcodes. I tested this also with the Parity-EVM implementation. Parity does not know the opcodes and prints directly an error:

./parity-evm --json --code b0
{"pc":0,"op":176,"opName":"","gas":"0xffffffffffffffff","gasCost":"0x0","memory":"0x","stack":[],"storage":{},"depth":1}
{"error":"EVM: Bad instruction b0","gasUsed":"ffffffffffffffff","time":9881}

Why do these opcodes exist and for what reason? Why does the EVM of go-ethereum know the opcodes but not the implementation of Parity?

EDIT:

I also found this const in the go-ethereum source code:

// unofficial opcodes used for parsing
const (
    PUSH OpCode = 0xb0 + iota
    DUP
    SWAP
)

They mention, that they use it for parsing and they are unofficial.

1

SPEC

I don't know what they are for, but they are something implementation specific. Indeed, according to the Ethereum Virtual Machine (EVM) specification (the yellow paper, Appendix H), there are no opcodes for 0xB0, 0xB1, 0xB2. Moreover, there are no PUSH,DUP and SWAP opcodes, but rather:

  1. 0x60 PUSH1, 0x61 PUSH2,..., 0x7f PUSH32
  2. 0x80 DUP1, 0x81 DUP2, ..., 0x8f DUP16
  3. 0x90 SWAP1, 0x91 SWAP2, ..., 0x9f SWAP16

GETH EVM

By inspecting the geth code one can see, that they define three additional opcodes PUSH, DUP and SWAP in the file core/vm/opcodes.go. The file core/vm/instructions.go implements the different opcodes, and it is easy to see that there is no function like (opPUSH1, opDUP1 and opSWAP1) but rather there are only three functions with these headers:

  1. makePush(size int64)
  2. makeDup(size int64)
  3. makeSwap(size int64)

Yes they are used for parsing, because they reduce the different PUSH1, etc. cases to only one case, at is easy to see in file core/vm/jump_table e

  • 1
    I know all opcodes from the yellow paper and how they work. Therefore, I was wondering about these three. That would be my question: Why are these implemented in the one Geth-EVM and not in Parity-EVM? – kedenk Sep 5 '18 at 10:00
  • I am currently inspecting the source code. I am not sure, but I do think, that they reduce the different PUSH1,...,PUSH32, function to a single PUSH instruction, so that they can call a single function PUSH(Amount of bytes).. – Briomkez Sep 5 '18 at 10:02
  • 1
    I found something in the source code. See my edit pls. – kedenk Sep 5 '18 at 10:06
  • 1
    Thanks for the explanation. I think you are right. I was just confused that the Geth-EVM accepted the opcode with a name. – kedenk Sep 5 '18 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.