diff --git a/VMTests.md b/VMTests.md index ab8c09107..fb8dfd9bf 100644 --- a/VMTests.md +++ b/VMTests.md @@ -487,8 +487,8 @@ OK: 113/145 Fail: 31/145 Skip: 1/145 ## vmLogTest ```diff + log0_emptyMem.json OK -- log0_logMemStartTooHigh.json Fail -- log0_logMemsizeTooHigh.json Fail ++ log0_logMemStartTooHigh.json OK ++ log0_logMemsizeTooHigh.json OK + log0_logMemsizeZero.json OK + log0_nonEmptyMem.json OK + log0_nonEmptyMem_logMemSize1.json OK @@ -496,8 +496,8 @@ OK: 113/145 Fail: 31/145 Skip: 1/145 + log1_Caller.json OK + log1_MaxTopic.json OK + log1_emptyMem.json OK -- log1_logMemStartTooHigh.json Fail -- log1_logMemsizeTooHigh.json Fail ++ log1_logMemStartTooHigh.json OK ++ log1_logMemsizeTooHigh.json OK + log1_logMemsizeZero.json OK + log1_nonEmptyMem.json OK + log1_nonEmptyMem_logMemSize1.json OK @@ -505,8 +505,8 @@ OK: 113/145 Fail: 31/145 Skip: 1/145 + log2_Caller.json OK + log2_MaxTopic.json OK + log2_emptyMem.json OK -- log2_logMemStartTooHigh.json Fail -- log2_logMemsizeTooHigh.json Fail ++ log2_logMemStartTooHigh.json OK ++ log2_logMemsizeTooHigh.json OK + log2_logMemsizeZero.json OK + log2_nonEmptyMem.json OK + log2_nonEmptyMem_logMemSize1.json OK @@ -515,8 +515,8 @@ OK: 113/145 Fail: 31/145 Skip: 1/145 + log3_MaxTopic.json OK + log3_PC.json OK + log3_emptyMem.json OK -- log3_logMemStartTooHigh.json Fail -- log3_logMemsizeTooHigh.json Fail ++ log3_logMemStartTooHigh.json OK ++ log3_logMemsizeTooHigh.json OK + log3_logMemsizeZero.json OK + log3_nonEmptyMem.json OK + log3_nonEmptyMem_logMemSize1.json OK @@ -525,15 +525,15 @@ OK: 113/145 Fail: 31/145 Skip: 1/145 + log4_MaxTopic.json OK + log4_PC.json OK + log4_emptyMem.json OK -- log4_logMemStartTooHigh.json Fail -- log4_logMemsizeTooHigh.json Fail ++ log4_logMemStartTooHigh.json OK ++ log4_logMemsizeTooHigh.json OK + log4_logMemsizeZero.json OK + log4_nonEmptyMem.json OK + log4_nonEmptyMem_logMemSize1.json OK + log4_nonEmptyMem_logMemSize1_logMemStart31.json OK + log_2logs.json OK ``` -OK: 36/46 Fail: 10/46 Skip: 0/46 +OK: 46/46 Fail: 0/46 Skip: 0/46 ## vmPerformance ```diff ackermann31.json Skip diff --git a/nimbus/vm/interpreter/utils/macros_procs_opcodes.nim b/nimbus/vm/interpreter/utils/macros_procs_opcodes.nim index ec4e2e562..a079f0dc9 100644 --- a/nimbus/vm/interpreter/utils/macros_procs_opcodes.nim +++ b/nimbus/vm/interpreter/utils/macros_procs_opcodes.nim @@ -11,7 +11,8 @@ import macros, strformat, stint, ../../computation, ../../stack, ../../code_stream, - ../../../constants, ../../../vm_types + ../../../constants, ../../../vm_types, ../../memory, + ../../../errors, ../../message, ../../interpreter/[gas_meter, opcode_values] proc pop(tree: var NimNode): NimNode = ## Returns the last value of a NimNode and remove it @@ -98,60 +99,32 @@ macro genSwap*(): untyped = func `name`*(computation: var BaseComputation) {.inline.}= computation.stack.swap(`pos`) -proc logImpl(topicCount: int): NimNode = +proc logImpl(c: var BaseComputation, opcode: Op, topicCount: int) = + assert(topicCount in 0 .. 4) + let (memStartPosition, size) = c.stack.popInt(2) + let (memPos, len) = (memStartPosition.toInt, size.toInt) - # TODO: use toopenArray to avoid some string allocations + if memPos < 0 or len < 0: + raise newException(OutOfBoundsRead, "Out of bounds memory access") - if topicCount < 0 or topicCount > 4: - error(&"Invalid log topic len {topicCount} Must be 0, 1, 2, 3, or 4") - return + var topics = newSeqOfCap[UInt256](topicCount) + for i in 0 ..< topicCount: + topics.add(c.stack.popInt()) + c.gasMeter.consumeGas( + c.gasCosts[opcode].m_handler(c.memory.len, memPos, len), + reason="Memory expansion, Log topic and data gas cost") - let name = ident(&"log{topicCount}") - let computation = ident("computation") - let topics = ident("topics") - let topicsTuple = ident("topicsTuple") - let len = ident("len") - let memPos = ident("memPos") - result = quote: - proc `name`*(`computation`: var BaseComputation) = - let (memStartPosition, size) = `computation`.stack.popInt(2) - let (`memPos`, `len`) = (memStartPosition.toInt, size.toInt) - var `topics`: seq[UInt256] + c.memory.extend(memPos, len) + let logData = c.memory.read(memPos, len) + addLogEntry( + c, + account = c.msg.storageAddress, + topics = topics, + data = logData) - var topicCode: NimNode - if topicCount == 0: - topicCode = quote: - `topics` = @[] - elif topicCount > 1: - topicCode = quote: - let `topicsTuple` = `computation`.stack.popInt(`topicCount`) - topicCode = nnkStmtList.newTree(topicCode) - for z in 0 ..< topicCount: - let topicPush = quote: - `topics`.add(`topicsTuple`[`z`]) - topicCode.add(topicPush) - else: - topicCode = quote: - `topics` = @[`computation`.stack.popInt()] - - result.body.add(topicCode) - - let OpName = ident(&"Log{topicCount}") - let logicCode = quote do: - `computation`.gasMeter.consumeGas( - `computation`.gasCosts[`OpName`].m_handler(`computation`.memory.len, `memPos`, `len`), - reason="Memory expansion, Log topic and data gas cost") - `computation`.memory.extend(`memPos`, `len`) - let logData = `computation`.memory.read(`memPos`, `len`) - addLogEntry( - `computation`, - account = `computation`.msg.storageAddress, - topics = `topics`, - data = log_data) - - result.body.add(logicCode) - -macro genLog*(): untyped = - result = newStmtList() - for i in 0..4: - result.add logImpl(i) +template genLog*() = + proc log0*(c: var BaseComputation) {.inline.} = logImpl(c, Log0, 0) + proc log1*(c: var BaseComputation) {.inline.} = logImpl(c, Log1, 1) + proc log2*(c: var BaseComputation) {.inline.} = logImpl(c, Log2, 2) + proc log3*(c: var BaseComputation) {.inline.} = logImpl(c, Log3, 3) + proc log4*(c: var BaseComputation) {.inline.} = logImpl(c, Log4, 4)