From 59bef848aa313fa987615f1e4e4e3ac249125fa4 Mon Sep 17 00:00:00 2001 From: Alexander Ivanov Date: Tue, 30 Jan 2018 15:07:37 +0200 Subject: [PATCH] Memory and storage opcodes: TODO stateDB handler for the storage to work --- src/constants.nim | 2 +- src/logic/memory_opcodes.nim | 30 ---------------- src/logic/memory_ops.nim | 36 ++++++++++++++++++++ src/logic/storage.nim | 66 ++++++++++++++++++++++++++++++++++++ src/runner.nim | 13 ++++--- 5 files changed, 112 insertions(+), 35 deletions(-) delete mode 100644 src/logic/memory_opcodes.nim create mode 100644 src/logic/memory_ops.nim create mode 100644 src/logic/storage.nim diff --git a/src/constants.nim b/src/constants.nim index bec61ccd3..7b50cadd5 100644 --- a/src/constants.nim +++ b/src/constants.nim @@ -111,7 +111,7 @@ let GAS_COINBASE* = 20.i256 GAS_SLOAD_COST* = 20.i256 GAS_SELF_DESTRUCT_COST* = 5_000.i256 - + REFUNDS_CLEAR* = 15_000.i256 GAS_SELF_DESTRUCT* = 0.i256 diff --git a/src/logic/memory_opcodes.nim b/src/logic/memory_opcodes.nim deleted file mode 100644 index 39315a033..000000000 --- a/src/logic/memory_opcodes.nim +++ /dev/null @@ -1,30 +0,0 @@ -import - ../constants, ../computation, .. / vm / [stack, memory], ../utils/padding - - -proc mstoreX(computation: var BaseComputation, x: int) = - let start = computation.stack.popInt() - let value = computation.stack.popBinary() - - let paddedValue = pad_left(value, x, cstring"\x00") - let normalizedValue = cstring(($paddedValue)[^x .. ^1]) - - computation.extendMemory(start, x.int256) - computation.memory.write(start, 32.int256, normalizedValue) - -template mstore*(computation: var BaseComputation) = - mstoreX(32) - -template mstore8*(computation: var BaseComputation) = - mstoreX(1) - -proc mload*(computation: var BaseComputation) = - let start = computation.stack.popInt() - - computation.extendMemory(start, 32.int256) - - let value = computation.memory.read(start, 32.int256) - computation.stack.push(value) - -proc msize*(computation: var BaseComputation) = - computation.stack.push(computation.memory.len) diff --git a/src/logic/memory_ops.nim b/src/logic/memory_ops.nim new file mode 100644 index 000000000..42f453daf --- /dev/null +++ b/src/logic/memory_ops.nim @@ -0,0 +1,36 @@ +import + ../constants, ../computation, .. / vm / [stack, memory], .. / utils / [padding, bytes] + + +{.this: computation.} +{.experimental.} + +using + computation: var BaseComputation + +proc mstoreX(computation; x: int) = + let start = stack.popInt() + let value = stack.popBinary() + + let paddedValue = padLeft(value, x, cstring"\x00") + let normalizedValue = cstring(($paddedValue)[^x .. ^1]) + + extendMemory(start, x.int256) + memory.write(start, 32.int256, normalizedValue) + +proc mstore*(computation) {.inline.} = + mstoreX(32) + +proc mstore8*(computation) {.inline.} = + mstoreX(1) + +proc mload*(computation) = + let start = stack.popInt() + + extendMemory(start, 32.int256) + + let value = memory.read(start, 32.int256).toCstring + stack.push(value) + +proc msize*(computation) = + stack.push(memory.len) diff --git a/src/logic/storage.nim b/src/logic/storage.nim new file mode 100644 index 000000000..6caac3518 --- /dev/null +++ b/src/logic/storage.nim @@ -0,0 +1,66 @@ +import + ../constants, ../errors, ../computation, .. / db / state_db, .. / vm / [stack, gas_meter, message] + +{.this: computation.} +{.experimental.} + +using + computation: var BaseComputation + +proc sstore*(computation) = + let (slot, value) = stack.popInt(2) + + # TODO: stateDB + # with computation.vm_state.state_db(read_only=True) as state_db: + # current_value = state_db.get_storage( + # address=computation.msg.storage_address, + # slot=slot, + # ) + + # let isCurrentlyEmpty = not bool(current_value) + # let isGoingToBeEmpty = not bool(value) + + # if is_currently_empty: + # gas_refund = 0 + # elif is_going_to_be_empty: + # gas_refund = constants.REFUND_SCLEAR + # else: + # gas_refund = 0 + + # if is_currently_empty and is_going_to_be_empty: + # gas_cost = constants.GAS_SRESET + # elif is_currently_empty: + # gas_cost = constants.GAS_SSET + # elif is_going_to_be_empty: + # gas_cost = constants.GAS_SRESET + # else: + # gas_cost = constants.GAS_SRESET + + # computation.gas_meter.consume_gas(gas_cost, reason="SSTORE: {0}[{1}] -> {2} ({3})".format( + # encode_hex(computation.msg.storage_address), + # slot, + # value, + # current_value, + # )) + + # if gas_refund: + # computation.gas_meter.refund_gas(gas_refund) + + # with computation.vm_state.state_db() as state_db: + # state_db.set_storage( + # address=computation.msg.storage_address, + # slot=slot, + # value=value, + # ) + + +proc sload*(computation) = + let slot = stack.popInt() + + # TODO: with + # with computation.vm_state.state_db(read_only=True) as state_db: + # value = state_db.get_storage( + # address=computation.msg.storage_address, + # slot=slot, + # ) + # computation.stack.push(value) diff --git a/src/runner.nim b/src/runner.nim index 89d537e9d..c16c55f7a 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, block_ops, stack_ops, duplication, swap] + logic / [arithmetic, comparison, sha3, context, block_ops, stack_ops, duplication, swap, memory_ops, storage] var opcodes = initOpcodes: # arithmetic @@ -67,11 +67,16 @@ var opcodes = initOpcodes: 1..16 Op.DupXX: GAS_VERY_LOW dupXX 1..16 Op.SwapXX: GAS_VERY_LOW swapXX - # Op.MLoad: GAS_VERY_LOW mload + + # memory + Op.MLoad: GAS_VERY_LOW mload # Op.MStore: GAS_VERY_LOW mstore # Op.MStore8: GAS_VERY_LOW mstore8 - # Op.SLoad: GAS_SLOAD_COST sload - # Op.SStore: 0.i256 sstore + + + # storage + Op.SLoad: GAS_SLOAD_COST sload + Op.SStore: GAS_ZERO sstore # Op.Jump: GAS_MID jump