From 0ec03afced0c5d0a242dc16b8479123a2b35d5ce Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Tue, 30 Jan 2018 14:51:43 +0200 Subject: [PATCH] Block and stack ops, elegant stack/dup/swap multiple opcode short def --- src/logic/block_ops.nim | 29 ++++++++++++++++++++ src/logic/stack_ops.nim | 60 +++++++++++++++++++++++++++++++++++++++++ src/logic/swap.nim | 1 - src/opcode.nim | 33 ++++++++++++++++------- src/runner.nim | 28 ++++++++++--------- src/vm_state.nim | 2 +- 6 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 src/logic/block_ops.nim create mode 100644 src/logic/stack_ops.nim diff --git a/src/logic/block_ops.nim b/src/logic/block_ops.nim new file mode 100644 index 000000000..7a7db63e0 --- /dev/null +++ b/src/logic/block_ops.nim @@ -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) + diff --git a/src/logic/stack_ops.nim b/src/logic/stack_ops.nim new file mode 100644 index 000000000..58705d6ee --- /dev/null +++ b/src/logic/stack_ops.nim @@ -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) diff --git a/src/logic/swap.nim b/src/logic/swap.nim index ba5cf5222..989dd78fd 100644 --- a/src/logic/swap.nim +++ b/src/logic/swap.nim @@ -25,4 +25,3 @@ swapXX(13) swapXX(14) swapXX(15) swapXX(16) - diff --git a/src/opcode.nim b/src/opcode.nim index 1917bd693..abbcfe642 100644 --- a/src/opcode.nim +++ b/src/opcode.nim @@ -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) diff --git a/src/runner.nim b/src/runner.nim index 6bcbd17db..89d537e9d 100644 --- a/src/runner.nim +++ b/src/runner.nim @@ -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 diff --git a/src/vm_state.nim b/src/vm_state.nim index 579b55071..1e2679714 100644 --- a/src/vm_state.nim +++ b/src/vm_state.nim @@ -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 =