Estudié las implementaciones de EVM y las secuencias de bytecode utilizadas por ellas. Me preguntaba si hay tres códigos de operación que son reconocidos por el EVM pero que en realidad son códigos de operación no válidos.
B0 PUSH
B1 DUP
B2 SWAP
Si ejecuto el código de operación B0
con Geth-EVM, obtengo el siguiente resultado:
./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"}
Como se puede ver, el código de operación B0
se reconoce y procesa como PUSH
código de operación. Al mismo tiempo, el campo de error escribe invalid opcode 0xb0
. Lo mismo vale para los otros dos códigos de operación. Probé esto también con la implementación de Parity-EVM. Parity no conoce los códigos de operación e imprime directamente un 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}
¿Por qué existen estos códigos de operación y por qué motivo? ¿Por qué el EVM de go-ethereum conoce los códigos de operación pero no la implementación de Parity?
EDITAR:
También encontré esto const
en el código fuente de go-ethereum:
// unofficial opcodes used for parsing
const (
PUSH OpCode = 0xb0 + iota
DUP
SWAP
)
Mencionan que lo usan para analizar y no son oficiales.
No sé para qué sirven, pero son algo específico de la implementación. De hecho, de acuerdo con la especificación Ethereum Virtual Machine (EVM) ( el documento amarillo, Apéndice H ), no hay códigos de operación para 0xB0, 0xB1, 0xB2
. Además, no hay códigos de operación PUSH,DUP
y SWAP
, sino más bien:
0x60 PUSH1, 0x61 PUSH2,..., 0x7f PUSH32
0x80 DUP1, 0x81 DUP2, ..., 0x8f DUP16
0x90 SWAP1, 0x91 SWAP2, ..., 0x9f SWAP16
Al inspeccionar el código geth, se puede ver que definen tres códigos de operación adicionales PUSH, DUP and SWAP
en el archivo core/vm/opcodes.go
. El archivo core/vm/instructions.go
implementa los diferentes códigos de operación, y es fácil ver que no hay ninguna función como ( opPUSH1
, opDUP1
y opSWAP1
) sino que solo hay tres funciones con estos encabezados:
makePush(size int64)
makeDup(size int64)
makeSwap(size int64)
Sí, se usan para analizar, porque reducen los diferentes casos de PUSH1, etc. a un solo caso, es fácil de ver en el archivo.core/vm/jump_table
kedenk
Briomkez
kedenk
kedenk