diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index eb7442271..108722cb3 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -560,6 +560,7 @@ op jumpSub, inline = true, jumpTarget: if jumpTarget >= c.code.len.u256: raise newException(InvalidJumpDestination, "JumpSub destination exceeds code len") + let returnPC = c.code.pc let jt = jumpTarget.truncate(int) c.code.pc = jt @@ -570,7 +571,7 @@ op jumpSub, inline = true, jumpTarget: if c.returnStack.len == 1023: raise newException(FullStack, "Out of returnStack") - push: jt + 1 + c.returnStack.push returnPC inc c.code.pc # ########################################## diff --git a/tests/macro_assembler.nim b/tests/macro_assembler.nim index d6f3180bb..38dc0fe3d 100644 --- a/tests/macro_assembler.nim +++ b/tests/macro_assembler.nim @@ -172,6 +172,10 @@ proc parseFork(fork: NimNode): Fork = fork[0].expectKind({nnkIdent, nnkStrLit}) parseEnum[Fork](strip(fork[0].strVal)) +proc parseGasUsed(gas: NimNode): GasInt = + gas[0].expectKind(nnkIntLit) + result = gas[0].intVal + proc generateVMProxy(boa: Assembler): NimNode = let vmProxy = genSym(nskProc, "vmProxy") @@ -262,10 +266,9 @@ proc initComputation(blockNumber: Uint256, chainDB: BaseChainDB, code, data: seq proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool = var computation = initComputation(blockNumber, chainDB, boa.code, boa.data, boa.fork) - # TODO: support gas comsumption validation - # let gas = computation.gasMeter.gasRemaining + let gas = computation.gasMeter.gasRemaining execComputation(computation) - # let gasUsed = gas - computation.gasMeter.gasRemaining + let gasUsed = gas - computation.gasMeter.gasRemaining if computation.isSuccess: if boa.success == false: @@ -276,6 +279,11 @@ proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool = error "different success value", expected=boa.success, actual=false return false + if boa.gasUsed != -1: + if boa.gasUsed != gasUsed: + error "different gasUsed", expected=boa.gasUsed, actual=gasUsed + return false + if boa.stack.len != computation.stack.values.len: error "different stack len", expected=boa.stack.len, actual=computation.stack.values.len return false @@ -355,7 +363,7 @@ proc runVM*(blockNumber: Uint256, chainDB: BaseChainDB, boa: Assembler): bool = result = true macro assembler*(list: untyped): untyped = - var boa = Assembler(success: true, fork: FkFrontier) + var boa = Assembler(success: true, fork: FkFrontier, gasUsed: -1) list.expectKind nnkStmtList for callSection in list: callSection.expectKind(nnkCall) @@ -375,6 +383,7 @@ macro assembler*(list: untyped): untyped = of "data": boa.data = parseData(body) of "output": boa.output = parseData(body) of "fork": boa.fork = parseFork(body) + of "gasused": boa.gasUsed = parseGasUsed(body) else: error("unknown section '" & label & "'", callSection[0]) result = boa.generateVMProxy() diff --git a/tests/test_op_misc.nim b/tests/test_op_misc.nim index 28c806059..0f65aecfe 100644 --- a/tests/test_op_misc.nim +++ b/tests/test_op_misc.nim @@ -175,3 +175,102 @@ proc opMiscMain*() = memory: "0xA0B0C0D0E0F0A1B1C1D1E1F1A2B2C2D2E2F2A3B3C3D3E3F3A4B4C4D4E4F4A1B1" "0x00" + + assembler: + title: "Simple routine" + code: + PUSH1 "0x04" + JUMPSUB + STOP + BEGINSUB + RETURNSUB + gasUsed: 18 + fork: Berlin + + assembler: + title: "Two levels of subroutines" + code: + PUSH9 "0x00000000000000000C" + JUMPSUB + STOP + BEGINSUB + PUSH1 "0x11" + JUMPSUB + RETURNSUB + BEGINSUB + RETURNSUB + gasUsed: 36 + fork: Berlin + + assembler: + title: "Failure 1: invalid jump" + code: + PUSH9 "0x01000000000000000C" + JUMPSUB + STOP + BEGINSUB + PUSH1 "0x11" + JUMPSUB + RETURNSUB + BEGINSUB + RETURNSUB + success: false + fork: Berlin + + assembler: + title: "Failure 2: shallow return stack" + code: + RETURNSUB + PC + PC + success: false + fork: Berlin + + assembler: + title: "Subroutine at end of code" + code: + PUSH1 "0x05" + JUMP + BEGINSUB + RETURNSUB + JUMPDEST + PUSH1 "0x03" + JUMPSUB + gasUsed: 30 + fork: Berlin + + assembler: + title: "Error on 'walk-into-subroutine'" + code: + BEGINSUB + RETURNSUB + STOP + success: false + fork: Berlin + + assembler: + title: "sol test" + code: + PUSH1 "0x02" + PUSH1 "0x03" + PUSH1 "0x08" # jumpdest + JUMPSUB + STOP + + # 0x08 + BEGINSUB + PUSH1 "0x0D" # jumpdest + JUMPSUB + RETURNSUB + + # 0x0D + BEGINSUB + MUL + RETURNSUB + gasUsed: 47 + fork: Berlin + stack: + "0x06" + +when isMainModule: + opMiscMain()