Go-Ethereum

操作碼 PUSH、DUP 和 SWAP?

  • September 5, 2018

我研究了 EVM 實現和它們使用的字節碼序列。我想知道有三個操作碼被 EVM 辨識但實際上是無效的操作碼。

B0 PUSH
B1 DUP
B2 SWAP

如果我B0使用 Geth-EVM 執行操作碼,我會得到以下輸出:

./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"}

可以看到,操作碼B0被辨識並作為PUSH操作碼處理。同時錯誤欄位寫入invalid opcode 0xb0。其他兩個操作碼也是如此。我還使用 Parity-EVM 實現對此進行了測試。Parity 不知道操作碼並直接列印錯誤:

./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}

為什麼這些操作碼存在,出於什麼原因?為什麼 go-ethereum 的 EVM 知道操作碼但不知道 Parity 的實現?

編輯:

我還在constgo-ethereum 原始碼中發現了這一點:

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

他們提到,他們用它來解析並且他們是非官方的。

規格

我不知道它們的用途,但它們是特定於實現的。事實上,根據乙太坊虛擬機 (EVM) 規範(黃皮書,附錄 H),沒有0xB0, 0xB1, 0xB2. 此外,沒有PUSH,DUPSWAP操作碼,而是:

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

GETH EVM

通過檢查 geth 程式碼可以看到,他們PUSH, DUP and SWAP在文件中定義了三個額外的操作碼core/vm/opcodes.go。該文件core/vm/instructions.go實現了不同的操作碼,很容易看出沒有像 (和) 這樣的函式opPUSH1,而是只有三個帶有這些標頭檔的函式:opDUP1``opSWAP1

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

是的,它們用於解析,因為它們將不同的 PUSH1 等案例減少到只有一個案例,在文件中很容易看到core/vm/jump_table 和

引用自:https://ethereum.stackexchange.com/questions/58108