Ich habe EVM-Implementierungen und die von ihnen verwendeten Bytecode-Sequenzen studiert. Ich habe mich gewundert, dass es drei Opcodes gibt, die vom EVM erkannt werden, aber eigentlich ungültige Opcodes sind.
B0 PUSH
B1 DUP
B2 SWAP
Wenn ich den Opcode B0
mit Geth-EVM ausführe bekomme ich folgende Ausgabe:
./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"}
Wie man sieht, B0
wird der Opcode als Opcode erkannt und verarbeitet PUSH
. Gleichzeitig schreibt das Fehlerfeld invalid opcode 0xb0
. Dasselbe gilt für die anderen beiden Opcodes. Ich habe dies auch mit der Parity-EVM-Implementierung getestet. Parity kennt die Opcodes nicht und gibt direkt einen Fehler aus:
./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}
Warum existieren diese Opcodes und aus welchem Grund? Warum kennt die EVM von go-ethereum die Opcodes, aber nicht die Implementierung von Parity?
BEARBEITEN:
Das habe ich auch const
im Quellcode von go-ethereum gefunden:
// unofficial opcodes used for parsing
const (
PUSH OpCode = 0xb0 + iota
DUP
SWAP
)
Sie erwähnen, dass sie es zum Parsen verwenden und inoffiziell sind.
Ich weiß nicht, wofür sie sind, aber sie sind etwas Implementierungsspezifisch. Tatsächlich gibt es gemäß der Ethereum Virtual Machine (EVM)-Spezifikation ( das gelbe Papier, Anhang H ) keine Opcodes für 0xB0, 0xB1, 0xB2
. Außerdem gibt es keine PUSH,DUP
und- SWAP
Opcodes, sondern:
0x60 PUSH1, 0x61 PUSH2,..., 0x7f PUSH32
0x80 DUP1, 0x81 DUP2, ..., 0x8f DUP16
0x90 SWAP1, 0x91 SWAP2, ..., 0x9f SWAP16
Wenn man sich den Geth-Code ansieht, kann man sehen, dass sie drei zusätzliche Opcodes PUSH, DUP and SWAP
in der Datei definieren core/vm/opcodes.go
. Die Datei core/vm/instructions.go
implementiert die verschiedenen Opcodes, und es ist leicht zu erkennen, dass es keine Funktion wie ( opPUSH1
, opDUP1
und opSWAP1
) gibt, sondern nur drei Funktionen mit diesen Headern:
makePush(size int64)
makeDup(size int64)
makeSwap(size int64)
Ja, sie werden zum Parsen verwendet, da sie die verschiedenen Fälle von PUSH1 usw. auf nur einen Fall reduzieren, was in der Datei leicht zu erkennen istcore/vm/jump_table
kedenk
Briomkez
kedenk
kedenk