WIP opcode dsl, code stream changes
This commit is contained in:
parent
72c8ad4877
commit
7b5f7e762b
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
../constants, ../utils_numeric, ../computation,
|
../constants, ../utils_numeric, ../computation,
|
||||||
.. / vm / [gas_meter, stack],
|
.. / vm / [gas_meter, stack], ../opcode, ../opcode_values,
|
||||||
helpers, bigints
|
helpers, bigints
|
||||||
|
|
||||||
proc add*(computation: var BaseComputation) =
|
proc add*(computation: var BaseComputation) =
|
||||||
|
@ -101,3 +101,19 @@ proc signextend(computation: var BaseComputation) =
|
||||||
else:
|
else:
|
||||||
res = value
|
res = value
|
||||||
pushRes()
|
pushRes()
|
||||||
|
|
||||||
|
# TODO: why fail
|
||||||
|
# newOpcode(Op.Mul, GAS_VERY_LOW, mul)
|
||||||
|
|
||||||
|
# type
|
||||||
|
# OpcodeMul* = ref object of Opcode
|
||||||
|
# method kind*(opcode247321: OpcodeMul): Op =
|
||||||
|
# Op.Mul
|
||||||
|
|
||||||
|
# method gasCost*(opcode247323: OpcodeMul): Int256 =
|
||||||
|
# GAS_VERY_LOW
|
||||||
|
|
||||||
|
# method run*(opcode247325: OpcodeMul; computation: var BaseComputation) =
|
||||||
|
# computation.gasMeter.consumeGas(GAS_VERY_LOW, reason = $Op.Mul)
|
||||||
|
# mul(computation)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import
|
||||||
|
strformat, strutils, sequtils, macros,
|
||||||
|
constants, logging, errors, opcode_values, computation, vm/stack, bigints
|
||||||
|
|
||||||
|
type
|
||||||
|
Opcode* = ref object of RootObj
|
||||||
|
|
||||||
|
method run*(opcode: var Opcode, computation: var BaseComputation) {.base.} =
|
||||||
|
# Hook for performing the actual VM execution.
|
||||||
|
raise newException(ValueError, "Must be implemented by subclasses")
|
||||||
|
|
||||||
|
method kind*(opcode: Opcode): Op {.base.} =
|
||||||
|
raise newException(ValueError, "Must be implemented by subclasses")
|
||||||
|
|
||||||
|
method gasCost*(opcode: Opcode): Op {.base.} =
|
||||||
|
raise newException(ValueError, "Must be implemented by subclasses")
|
||||||
|
|
||||||
|
method logger*(opcode: Opcode): Logger =
|
||||||
|
logging.getLogger(&"vm.logic.call.{$opcode.kind}")
|
||||||
|
|
||||||
|
# TODO: not extremely happy with the method approach, maybe optimize
|
||||||
|
# a bit the run, so we directly replace it with handler's body
|
||||||
|
macro newOpcode*(kind: untyped, gasCost: untyped, handler: untyped): untyped =
|
||||||
|
# newOpcode(Op.Mul, GAS_LOW, mul)
|
||||||
|
let name = ident(&"Opcode{kind[1].repr}")
|
||||||
|
let computation = ident("computation")
|
||||||
|
result = quote:
|
||||||
|
type
|
||||||
|
`name`* = ref object of Opcode
|
||||||
|
|
||||||
|
method kind*(opcode: `name`): Op =
|
||||||
|
`kind`
|
||||||
|
|
||||||
|
method gasCost*(opcode: `name`): Int256 =
|
||||||
|
`gasCost`
|
||||||
|
|
||||||
|
var code: NimNode
|
||||||
|
if handler.kind != nnkStmtList:
|
||||||
|
code = quote:
|
||||||
|
method `run`*(opcode: `name`, `computation`: var BaseComputation) =
|
||||||
|
`computation`.gasMeter.consumeGas(`gasCost`, reason = $`kind`)
|
||||||
|
`handler`(`computation`)
|
||||||
|
else:
|
||||||
|
code = quote:
|
||||||
|
method `run*`(opcode: `name`, `computation`: var BaseComputation) =
|
||||||
|
`computation`.gasMeter.consumeGas(`gasCost`, reason = $`kind`)
|
||||||
|
`handler`
|
||||||
|
|
||||||
|
result.add(code)
|
||||||
|
echo result.repr
|
|
@ -1,159 +1,160 @@
|
||||||
# TODO : hex
|
# TODO : hex
|
||||||
const
|
type
|
||||||
STOP* = 0.byte
|
Op* {.pure.} = enum
|
||||||
ADD* = 1.byte
|
STOP, # 0
|
||||||
MUL* = 2.byte
|
ADD, # 1
|
||||||
SUB* = 3.byte
|
MUL, # 2
|
||||||
DIV* = 4.byte
|
SUB, # 3
|
||||||
SDIV* = 5.byte
|
DIV, # 4
|
||||||
MOD* = 6.byte
|
SDIV, # 5
|
||||||
SMOD* = 7.byte
|
MOD, # 6
|
||||||
ADDMOD* = 8.byte
|
SMOD, # 7
|
||||||
MULMOD* = 9.byte
|
ADDMOD, # 8
|
||||||
EXP* = 10.byte
|
MULMOD, # 9
|
||||||
SIGNEXTEND* = 11.byte
|
EXP, # 10
|
||||||
|
SIGNEXTEND, # 11
|
||||||
|
|
||||||
LT* = 16.byte
|
LT, # 16
|
||||||
GT* = 17.byte
|
GT, # 17
|
||||||
SLT* = 18.byte
|
SLT, # 18
|
||||||
SGT* = 19.byte
|
SGT, # 19
|
||||||
EQ* = 20.byte
|
EQ, # 20
|
||||||
ISZERO* = 21.byte
|
ISZERO, # 21
|
||||||
AND* = 22.byte
|
AND, # 22
|
||||||
OR* = 23.byte
|
OR, # 23
|
||||||
XOR* = 24.byte
|
XOR, # 24
|
||||||
NOT* = 25.byte
|
NOT, # 25
|
||||||
BYTE* = 26.byte
|
BYTE, # 26
|
||||||
|
|
||||||
SHA3* = 32.byte
|
SHA3, # 32
|
||||||
|
|
||||||
ADDRESS* = 48.byte
|
ADDRESS, # 48
|
||||||
BALANCE* = 49.byte
|
BALANCE, # 49
|
||||||
ORIGIN* = 50.byte
|
ORIGIN, # 50
|
||||||
|
|
||||||
CALLER* = 51.byte
|
CALLER, # 51
|
||||||
CALLVALUE* = 52.byte
|
CALLVALUE, # 52
|
||||||
CALLDATALOAD* = 53.byte
|
CALLDATALOAD, # 53
|
||||||
CALLDATASIZE* = 54.byte
|
CALLDATASIZE, # 54
|
||||||
CALLDATACOPY* = 55.byte
|
CALLDATACOPY, # 55
|
||||||
|
|
||||||
CODESIZE* = 56.byte
|
CODESIZE, # 56
|
||||||
CODECOPY* = 57.byte
|
CODECOPY, # 57
|
||||||
|
|
||||||
GASPRICE* = 58.byte
|
GASPRICE, # 58
|
||||||
|
|
||||||
EXTCODESIZE* = 59.byte
|
EXTCODESIZE, # 59
|
||||||
EXTCODECOPY* = 60.byte
|
EXTCODECOPY, # 60
|
||||||
|
|
||||||
RETURNDATASIZE* = 61.byte
|
RETURNDATASIZE, # 61
|
||||||
RETURNDATACOPY* = 62.byte
|
RETURNDATACOPY, # 62
|
||||||
|
|
||||||
BLOCKHASH* = 64.byte
|
BLOCKHASH, # 64
|
||||||
|
|
||||||
COINBASE* = 65.byte
|
COINBASE, # 65
|
||||||
|
|
||||||
TIMESTAMP* = 66.byte
|
TIMESTAMP, # 66
|
||||||
|
|
||||||
NUMBER* = 67.byte
|
NUMBER, # 67
|
||||||
|
|
||||||
DIFFICULTY* = 68.byte
|
DIFFICULTY, # 68
|
||||||
|
|
||||||
GASLIMIT* = 69.byte
|
GASLIMIT, # 69
|
||||||
|
|
||||||
POP* = 80.byte
|
POP, # 80
|
||||||
|
|
||||||
MLOAD* = 81.byte
|
MLOAD, # 81
|
||||||
MSTORE* = 82.byte
|
MSTORE, # 82
|
||||||
MSTORE8 = 83.byte
|
MSTORE8 # 83
|
||||||
|
|
||||||
SLOAD* = 84.byte
|
SLOAD, # 84
|
||||||
SSTORE* = 85.byte
|
SSTORE, # 85
|
||||||
|
|
||||||
JUMP* = 86.byte
|
JUMP, # 86
|
||||||
JUMPI* = 87.byte
|
JUMPI, # 87
|
||||||
|
|
||||||
PC* = 88.byte
|
PC, # 88
|
||||||
|
|
||||||
MSIZE* = 89.byte
|
MSIZE, # 89
|
||||||
|
|
||||||
GAS* = 90.byte
|
GAS, # 90
|
||||||
|
|
||||||
JUMPDEST* = 91.byte
|
JUMPDEST, # 91
|
||||||
|
|
||||||
PUSH1* = 96.byte
|
PUSH1, # 96
|
||||||
PUSH2* = 97.byte
|
PUSH2, # 97
|
||||||
PUSH3* = 98.byte
|
PUSH3, # 98
|
||||||
PUSH4* = 99.byte
|
PUSH4, # 99
|
||||||
PUSH5* = 100.byte
|
PUSH5, # 100
|
||||||
PUSH6* = 101.byte
|
PUSH6, # 101
|
||||||
PUSH7* = 102.byte
|
PUSH7, # 102
|
||||||
PUSH8* = 103.byte
|
PUSH8, # 103
|
||||||
PUSH9* = 104.byte
|
PUSH9, # 104
|
||||||
PUSH10* = 105.byte
|
PUSH10, # 105
|
||||||
PUSH11* = 106.byte
|
PUSH11, # 106
|
||||||
PUSH12* = 107.byte
|
PUSH12, # 107
|
||||||
PUSH13* = 108.byte
|
PUSH13, # 108
|
||||||
PUSH14* = 109.byte
|
PUSH14, # 109
|
||||||
PUSH15* = 110.byte
|
PUSH15, # 110
|
||||||
PUSH16* = 111.byte
|
PUSH16, # 111
|
||||||
PUSH17* = 112.byte
|
PUSH17, # 112
|
||||||
PUSH18* = 113.byte
|
PUSH18, # 113
|
||||||
PUSH19* = 114.byte
|
PUSH19, # 114
|
||||||
PUSH20* = 115.byte
|
PUSH20, # 115
|
||||||
PUSH21* = 116.byte
|
PUSH21, # 116
|
||||||
PUSH22* = 117.byte
|
PUSH22, # 117
|
||||||
PUSH23* = 118.byte
|
PUSH23, # 118
|
||||||
PUSH24* = 119.byte
|
PUSH24, # 119
|
||||||
PUSH25* = 120.byte
|
PUSH25, # 120
|
||||||
PUSH26* = 121.byte
|
PUSH26, # 121
|
||||||
PUSH27* = 122.byte
|
PUSH27, # 122
|
||||||
PUSH28* = 123.byte
|
PUSH28, # 123
|
||||||
PUSH29* = 124.byte
|
PUSH29, # 124
|
||||||
PUSH30* = 125.byte
|
PUSH30, # 125
|
||||||
PUSH31* = 126.byte
|
PUSH31, # 126
|
||||||
PUSH32* = 127.byte
|
PUSH32, # 127
|
||||||
DUP1* = 128.byte
|
DUP1, # 128
|
||||||
DUP2* = 129.byte
|
DUP2, # 129
|
||||||
DUP3* = 130.byte
|
DUP3, # 130
|
||||||
DUP4* = 131.byte
|
DUP4, # 131
|
||||||
DUP5* = 132.byte
|
DUP5, # 132
|
||||||
DUP6* = 133.byte
|
DUP6, # 133
|
||||||
DUP7* = 134.byte
|
DUP7, # 134
|
||||||
DUP8* = 135.byte
|
DUP8, # 135
|
||||||
DUP9* = 136.byte
|
DUP9, # 136
|
||||||
DUP10* = 137.byte
|
DUP10, # 137
|
||||||
DUP11* = 138.byte
|
DUP11, # 138
|
||||||
DUP12* = 139.byte
|
DUP12, # 139
|
||||||
DUP13* = 140.byte
|
DUP13, # 140
|
||||||
DUP14* = 141.byte
|
DUP14, # 141
|
||||||
DUP15* = 142.byte
|
DUP15, # 142
|
||||||
DUP16* = 143.byte
|
DUP16, # 143
|
||||||
SWAP1* = 144.byte
|
SWAP1, # 144
|
||||||
SWAP2* = 145.byte
|
SWAP2, # 145
|
||||||
SWAP3* = 146.byte
|
SWAP3, # 146
|
||||||
SWAP4* = 147.byte
|
SWAP4, # 147
|
||||||
SWAP5* = 148.byte
|
SWAP5, # 148
|
||||||
SWAP6* = 149.byte
|
SWAP6, # 149
|
||||||
SWAP7* = 150.byte
|
SWAP7, # 150
|
||||||
SWAP8* = 151.byte
|
SWAP8, # 151
|
||||||
SWAP9* = 152.byte
|
SWAP9, # 152
|
||||||
SWAP10* = 153.byte
|
SWAP10, # 153
|
||||||
SWAP11* = 154.byte
|
SWAP11, # 154
|
||||||
SWAP12* = 155.byte
|
SWAP12, # 155
|
||||||
SWAP13* = 156.byte
|
SWAP13, # 156
|
||||||
SWAP14* = 157.byte
|
SWAP14, # 157
|
||||||
SWAP15* = 158.byte
|
SWAP15, # 158
|
||||||
SWAP16* = 159.byte
|
SWAP16, # 159
|
||||||
LOG0* = 160.byte
|
LOG0, # 160
|
||||||
LOG1* = 161.byte
|
LOG1, # 161
|
||||||
LOG2* = 162.byte
|
LOG2, # 162
|
||||||
LOG3* = 163.byte
|
LOG3, # 163
|
||||||
LOG4* = 164.byte
|
LOG4, # 164
|
||||||
CREATE* = 240.byte
|
CREATE, # 240
|
||||||
CALL* = 241.byte
|
CALL, # 241
|
||||||
CALLCODE* = 242.byte
|
CALLCODE, # 242
|
||||||
RETURN* = 243.byte
|
RETURN, # 243
|
||||||
DELEGATECALL* = 244.byte
|
DELEGATECALL, # 244
|
||||||
STATICCALL* = 250.byte
|
STATICCALL, # 250
|
||||||
REVERT* = 253.byte
|
REVERT, # 253
|
||||||
SELFDESTRUCT* = 255.byte
|
SELFDESTRUCT # 255
|
||||||
|
|
|
@ -30,24 +30,24 @@ proc read*(c: var CodeStream, size: int): seq[byte] =
|
||||||
proc len*(c: CodeStream): int =
|
proc len*(c: CodeStream): int =
|
||||||
len(c.bytes)
|
len(c.bytes)
|
||||||
|
|
||||||
proc next*(c: var CodeStream): byte =
|
proc next*(c: var CodeStream): Op =
|
||||||
var nextOpcode = c.read(1)
|
var nextOpcode = c.read(1)
|
||||||
if nextOpcode[0] != 0x0.byte:
|
if nextOpcode[0] != 0x0.byte:
|
||||||
return nextOpcode[0]
|
return Op(nextOpcode[0])
|
||||||
else:
|
else:
|
||||||
return opcode_values.STOP
|
return Op.STOP
|
||||||
|
|
||||||
|
|
||||||
iterator items*(c: var CodeStream): byte =
|
iterator items*(c: var CodeStream): Op =
|
||||||
var nextOpcode = c.next()
|
var nextOpcode = c.next()
|
||||||
while nextOpcode != opcode_values.STOP:
|
while nextOpcode != Op.STOP:
|
||||||
yield nextOpcode
|
yield nextOpcode
|
||||||
nextOpcode = c.next()
|
nextOpcode = c.next()
|
||||||
|
|
||||||
proc `[]`*(c: CodeStream, offset: int): byte =
|
proc `[]`*(c: CodeStream, offset: int): byte =
|
||||||
c.bytes[offset]
|
c.bytes[offset]
|
||||||
|
|
||||||
proc peek*(c: var CodeStream): byte =
|
proc peek*(c: var CodeStream): Op =
|
||||||
var currentPc = c.pc
|
var currentPc = c.pc
|
||||||
result = c.next()
|
result = c.next()
|
||||||
c.pc = currentPc
|
c.pc = currentPc
|
||||||
|
@ -74,8 +74,8 @@ proc isValidOpcode*(c: var CodeStream, position: int): bool =
|
||||||
else:
|
else:
|
||||||
var i = c.depthProcessed
|
var i = c.depthProcessed
|
||||||
while i <= position:
|
while i <= position:
|
||||||
var opcode = c[i]
|
var opcode = Op(c[i])
|
||||||
if opcode >= opcode_values.PUSH1 and opcode <= opcode_values.PUSH32:
|
if opcode >= Op.PUSH1 and opcode <= Op.PUSH32:
|
||||||
var leftBound = (i + 1)
|
var leftBound = (i + 1)
|
||||||
var rightBound = leftBound + (opcode.int - 95)
|
var rightBound = leftBound + (opcode.int - 95)
|
||||||
for z in leftBound ..< rightBound:
|
for z in leftBound ..< rightBound:
|
||||||
|
|
Loading…
Reference in New Issue