Block and stack ops, elegant stack/dup/swap multiple opcode short def

This commit is contained in:
Alexander Ivanov 2018-01-30 14:51:43 +02:00
parent e6e3f09ebd
commit 0ec03afced
6 changed files with 130 additions and 23 deletions

29
src/logic/block_ops.nim Normal file
View File

@ -0,0 +1,29 @@
import
../constants, ../errors, ../computation, ../vm_state, .. / vm / [stack]
{.this: computation.}
{.experimental.}
using
computation: var BaseComputation
proc blockhash*(computation) =
let blockNumber = stack.popInt()
let blockHash = vmState.getAncestorHash(blockNumber)
stack.push(blockHash)
proc coinbase*(computation) =
stack.push(vmState.coinbase)
proc timestamp*(computation) =
stack.push(vmState.timestamp)
proc number*(computation) =
stack.push(vmState.blockNumber)
proc difficulty*(computation) =
stack.push(vmState.difficulty)
proc gaslimit*(computation) =
stack.push(vmState.gasLimit)

60
src/logic/stack_ops.nim Normal file
View File

@ -0,0 +1,60 @@
import
strformat, macros,
../constants, ../errors, ../computation, .. / vm / [stack, code_stream], .. / utils / [padding, bytes], bigints
{.this: computation.}
{.experimental.}
using
computation: var BaseComputation
proc pop*(computation) =
discard stack.pop()
macro pushXX(size: static[int]): untyped =
let computation = ident("computation")
let value = ident("value")
let name = ident(&"push{size}")
result = quote:
proc `name`*(`computation`: var BaseComputation) =
let `value` = `computation`.code.read(`size`).toCString
let stripped = `value`.strip(0.char)
if stripped.len == 0:
`computation`.stack.push(0.i256)
else:
let paddedValue = `value`.padRight(`size`, cstring"\x00")
`computation`.stack.push(paddedValue)
pushXX(1)
pushXX(2)
pushXX(3)
pushXX(4)
pushXX(5)
pushXX(6)
pushXX(7)
pushXX(8)
pushXX(9)
pushXX(10)
pushXX(11)
pushXX(12)
pushXX(13)
pushXX(14)
pushXX(15)
pushXX(16)
pushXX(17)
pushXX(18)
pushXX(19)
pushXX(20)
pushXX(21)
pushXX(22)
pushXX(23)
pushXX(24)
pushXX(25)
pushXX(26)
pushXX(27)
pushXX(28)
pushXX(29)
pushXX(30)
pushXX(31)
pushXX(32)

View File

@ -25,4 +25,3 @@ swapXX(13)
swapXX(14)
swapXX(15)
swapXX(16)

View File

@ -36,16 +36,31 @@ macro initOpcodes*(spec: untyped): untyped =
var `value` = initTable[Op, Opcode]()
for child in spec:
let op = child[0]
let gasCost = child[1][0][0]
let handler = child[1][0][1]
let opcode = if gasCost.repr[0].isLowerAscii():
quote:
`value`[`op`] = Opcode(kind: `op`, gasCostHandler: `gasCost`, runLogic: `handler`)
var ops, gasCosts, handlers: seq[NimNode]
if child.kind == nnkInfix and child[0].repr == "..":
ops = @[]
gasCosts = @[]
handlers = @[]
let first = child[1].repr.parseInt
let last = child[2][0].repr.parseInt
let op = child[2][1][1].repr
for z in first .. last:
ops.add(nnkDotExpr.newTree(ident("Op"), ident(op.replace("XX", $z))))
gasCosts.add(child[3][0][0])
handlers.add(ident(child[3][0][1].repr.replace("XX", $z)))
else:
quote:
`value`[`op`] = Opcode(kind: `op`, gasCostConstant: `gasCost`, runLogic: `handler`)
result[1].add(opcode)
ops = @[child[0]]
gasCosts = @[child[1][0][0]]
handlers = @[child[1][0][1]]
for z in 0 ..< ops.len:
let (op, gasCost, handler) = (ops[z], gasCosts[z], handlers[z])
let opcode = if gasCost.repr[0].isLowerAscii():
quote:
`value`[`op`] = Opcode(kind: `op`, gasCostHandler: `gasCost`, runLogic: `handler`)
else:
quote:
`value`[`op`] = Opcode(kind: `op`, gasCostConstant: `gasCost`, runLogic: `handler`)
result[1].add(opcode)
result[1].add(value)

View File

@ -2,7 +2,7 @@ import
strformat, strutils, tables, macros,
constants, bigints, errors, logging, vm_state,
vm / [gas_meter, stack, code_stream, memory, message, value, gas_costs], db / chain, computation, opcode, opcode_values, utils / [header, address],
logic / [arithmetic, comparison, sha3, context]
logic / [arithmetic, comparison, sha3, context, block_ops, stack_ops, duplication, swap]
var opcodes = initOpcodes:
# arithmetic
@ -52,13 +52,21 @@ var opcodes = initOpcodes:
Op.ExtCodeCopy: GAS_EXT_CODE_COST extCodeCopy
# Op.Blockhash: GAS_BASE blockhash
# Op.Coinbase: GAS_COINBASE coinbase
# Op.Timestamp: GAS_BASE timestamp
# Op.Number: GAS_BASE number
# Op.Difficulty: GAS_BASE difficulty
# Op.GasLimit: GAS_BASE gasLimitOp
# Op.Pop: GAS_BASE popOp
# block
Op.Blockhash: GAS_BASE block_ops.blockhash
Op.Coinbase: GAS_COINBASE coinbase
Op.Timestamp: GAS_BASE timestamp
Op.Number: GAS_BASE number
Op.Difficulty: GAS_BASE difficulty
Op.GasLimit: GAS_BASE gaslimit
# stack
Op.Pop: GAS_BASE stack_ops.pop
1..32 Op.PushXX: GAS_VERY_LOW pushXX # XX replaced by macro
1..16 Op.DupXX: GAS_VERY_LOW dupXX
1..16 Op.SwapXX: GAS_VERY_LOW swapXX
# Op.MLoad: GAS_VERY_LOW mload
# Op.MStore: GAS_VERY_LOW mstore
# Op.MStore8: GAS_VERY_LOW mstore8
@ -72,9 +80,6 @@ var opcodes = initOpcodes:
# Op.MSize: GAS_BASE msize
# Op.Gas: GAS_BASE gasOp
# Op.JumpDest: GAS_JUMP_DEST jumpDest
# Op.Push: GAS_VERY_LOW push
# Op.Dup: GAS_VERY_LOW dup
# Op.Swap: GAS_VERY_LOW swap
# Op.Log0: GAS_LOG log0
# Op.Log1: 2 * GAS_LOG log1
# Op.Log2: 3 * GAS_LOG log2
@ -168,5 +173,4 @@ runOpcodes(c):
Op.Div
Op.Sub
Op.Mul
Op.Mul

View File

@ -28,7 +28,7 @@ method coinbase*(vmState: BaseVMState): cstring =
method timestamp*(vmState: BaseVMState): int =
vmState.blockHeader.timestamp
method blockBumber*(vmState: BaseVMState): Int256 =
method blockNumber*(vmState: BaseVMState): Int256 =
vmState.blockHeader.blockNumber
method difficulty*(vmState: BaseVMState): Int256 =