From b119ba4a2056441f76ed72bb2b6e3547cdc9b0e1 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Sun, 5 Nov 2023 11:56:01 +0100 Subject: [PATCH] refactor VM core and core unit tests (#99) * refactor VM core and unit tests * clean up * clean up computeRes calls args * clean up * CairoVM.init fmt * MaybeRelocatable test null fmt * various fmt * various fmt * revert core test fmt * reformat test parts --------- Co-authored-by: lanaivina <31368580+lana-shanghai@users.noreply.github.com> --- src/vm/core.zig | 126 ++++------ src/vm/core_test.zig | 554 ++++++++++++------------------------------- 2 files changed, 208 insertions(+), 472 deletions(-) diff --git a/src/vm/core.zig b/src/vm/core.zig index 2c689347..c9c1b85e 100644 --- a/src/vm/core.zig +++ b/src/vm/core.zig @@ -273,46 +273,32 @@ pub const CairoVM = struct { operands: OperandsResult, ) !void { switch (instruction.pc_update) { - // ************************************************************ - // * PC UPDATE REGULAR * - // ************************************************************ - instructions.PcUpdate.Regular => { - // Update the PC. + // PC update regular + instructions.PcUpdate.Regular => { // Update the PC. self.run_context.pc.*.addUintInPlace(instruction.size()); }, - // ************************************************************ - // * PC UPDATE JUMP * - // ************************************************************ + // PC update jump instructions.PcUpdate.Jump => { // Check that the res is not null. - if (operands.res == null) { + if (operands.res) |val| { + // Check that the res is a relocatable. + self.run_context.pc.* = val.tryIntoRelocatable() catch + return error.PcUpdateJumpResNotRelocatable; + } else { return error.ResUnconstrainedUsedWithPcUpdateJump; } - // Check that the res is a relocatable. - const res = operands.res.?.tryIntoRelocatable() catch { - return error.PcUpdateJumpResNotRelocatable; - }; - // Update the PC. - self.run_context.pc.* = res; }, - // ************************************************************ - // * PC UPDATE JUMP REL * - // ************************************************************ + // PC update Jump Rel instructions.PcUpdate.JumpRel => { // Check that the res is not null. - if (operands.res == null) { + if (operands.res) |val| { + // Check that the res is a felt. + try self.run_context.pc.*.addFeltInPlace(val.tryIntoFelt() catch return error.PcUpdateJumpRelResNotFelt); + } else { return error.ResUnconstrainedUsedWithPcUpdateJumpRel; } - // Check that the res is a felt. - const res = operands.res.?.tryIntoFelt() catch { - return error.PcUpdateJumpRelResNotFelt; - }; - // Update the PC. - try self.run_context.pc.*.addFeltInPlace(res); }, - // ************************************************************ - // * PC UPDATE JNZ * - // ************************************************************ + // PC update Jnz instructions.PcUpdate.Jnz => { if (operands.dst.isZero()) { // Update the PC. @@ -335,26 +321,21 @@ pub const CairoVM = struct { operands: OperandsResult, ) !void { switch (instruction.ap_update) { - // ********************************************************* - // * AP UPDATE ADD * - // ********************************************************* + // AP update Add instructions.ApUpdate.Add => { // Check that Res is not null. - if (operands.res == null) { + if (operands.res) |val| { + // Update AP. + try self.run_context.ap.*.addMaybeRelocatableInplace(val); + } else { return error.ApUpdateAddResUnconstrained; } - // Update AP. - try self.run_context.ap.*.addMaybeRelocatableInplace(operands.res.?); }, - // ********************************************************* - // * AP UPDATE ADD1 * - // ********************************************************* + // AP update Add1 instructions.ApUpdate.Add1 => { self.run_context.ap.*.addUintInPlace(1); }, - // ********************************************************* - // * AP UPDATE ADD2 * - // ********************************************************* + // AP update Add2 instructions.ApUpdate.Add2 => { self.run_context.ap.*.addUintInPlace(2); }, @@ -372,17 +353,12 @@ pub const CairoVM = struct { operands: OperandsResult, ) !void { switch (instruction.fp_update) { - // ********************************************************* - // * FP UPDATE AP PLUS 2 * - // ********************************************************* - instructions.FpUpdate.APPlus2 => { - // Update the FP. + // FP update Add + 2 + instructions.FpUpdate.APPlus2 => { // Update the FP. // FP = AP + 2. self.run_context.fp.*.offset = self.run_context.ap.*.offset + 2; }, - // ********************************************************* - // * FP UPDATE DST * - // ********************************************************* + // FP update Dst instructions.FpUpdate.Dst => { switch (operands.dst) { .relocatable => |rel| { @@ -481,20 +457,13 @@ pub fn computeRes( instruction: *const Instruction, op_0: MaybeRelocatable, op_1: MaybeRelocatable, -) CairoVMError!MaybeRelocatable { - var res = switch (instruction.res_logic) { - instructions.ResLogic.Op1 => op_1, - instructions.ResLogic.Add => { - var sum = try addOperands(op_0, op_1); - return sum; - }, - instructions.ResLogic.Mul => { - var product = try mulOperands(op_0, op_1); - return product; - }, - instructions.ResLogic.Unconstrained => null, +) CairoVMError!?MaybeRelocatable { + return switch (instruction.res_logic) { + .Op1 => op_1, + .Add => return try addOperands(op_0, op_1), + .Mul => return try mulOperands(op_0, op_1), + .Unconstrained => null, }; - return res.?; } /// Add two operands which can either be a "relocatable" or a "felt". @@ -523,20 +492,17 @@ pub fn addOperands( const felt_op = if (op_0.isRelocatable()) op_1 else op_0; var reloc = try reloc_op.tryIntoRelocatable(); - var felt = try felt_op.tryIntoFelt(); // Add the felt to the relocatable's offset - try reloc.addFeltInPlace(felt); + try reloc.addFeltInPlace(try felt_op.tryIntoFelt()); return relocatable.newFromRelocatable(reloc); } - // Both operands are felts - const op_0_felt = try op_0.tryIntoFelt(); - const op_1_felt = try op_1.tryIntoFelt(); - // Add the felts and return as a new felt wrapped in a relocatable - return relocatable.fromFelt(op_0_felt.add(op_1_felt)); + return relocatable.fromFelt((try op_0.tryIntoFelt()).add( + try op_1.tryIntoFelt(), + )); } /// Compute the product of two operands op 0 and op 1. @@ -554,11 +520,10 @@ pub fn mulOperands( return CairoVMError.MulRelocForbidden; } - const op_0_felt = try op_0.tryIntoFelt(); - const op_1_felt = try op_1.tryIntoFelt(); - // Multiply the felts and return as a new felt wrapped in a relocatable - return relocatable.fromFelt(op_0_felt.mul(op_1_felt)); + return relocatable.fromFelt( + (try op_0.tryIntoFelt()).mul(try op_1.tryIntoFelt()), + ); } /// Subtracts a `MaybeRelocatable` from this one and returns the new value. @@ -568,12 +533,16 @@ pub fn mulOperands( pub fn subOperands(self: MaybeRelocatable, other: MaybeRelocatable) !MaybeRelocatable { switch (self) { .felt => |self_value| switch (other) { - .felt => |other_value| return relocatable.fromFelt(self_value.sub(other_value)), + .felt => |other_value| return relocatable.fromFelt( + self_value.sub(other_value), + ), .relocatable => return error.TypeMismatchNotFelt, }, .relocatable => |self_value| switch (other) { .felt => return error.TypeMismatchNotFelt, - .relocatable => |other_value| return relocatable.newFromRelocatable(try self_value.sub(other_value)), + .relocatable => |other_value| return relocatable.newFromRelocatable( + try self_value.sub(other_value), + ), }, } } @@ -601,7 +570,10 @@ pub fn deduceOp1( return .{ dst_val.*, dst_val.* }; }, .Add => if (dst != null and op0 != null) { - return .{ try subOperands(dst.?.*, op0.?.*), dst.?.* }; + return .{ try subOperands( + dst.?.*, + op0.?.*, + ), dst.?.* }; }, .Mul => { if (dst != null and op0 != null and @@ -609,7 +581,9 @@ pub fn deduceOp1( !op0.?.felt.isZero()) { return .{ - relocatable.fromFelt(try dst.?.felt.div(op0.?.felt)), + relocatable.fromFelt( + try dst.?.felt.div(op0.?.felt), + ), dst.?.*, }; } diff --git a/src/vm/core_test.zig b/src/vm/core_test.zig index ac569379..f95e4301 100644 --- a/src/vm/core_test.zig +++ b/src/vm/core_test.zig @@ -25,9 +25,6 @@ const computeRes = @import("core.zig").computeRes; const OperandsResult = @import("core.zig").OperandsResult; const deduceOp1 = @import("core.zig").deduceOp1; -// ************************************************************ -// * TESTS * -// ************************************************************ const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; const expectError = std.testing.expectError; @@ -89,11 +86,7 @@ test "CairoVM: deduceMemoryCell builtin valid" { } test "update pc regular no imm" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Regular; @@ -103,17 +96,13 @@ test "update pc regular no imm" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -125,11 +114,7 @@ test "update pc regular no imm" { } test "update pc regular with imm" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Regular; @@ -139,17 +124,13 @@ test "update pc regular with imm" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -161,11 +142,7 @@ test "update pc regular with imm" { } test "update pc jump with operands res null" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jump; @@ -175,9 +152,7 @@ test "update pc jump with operands res null" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError(error.ResUnconstrainedUsedWithPcUpdateJump, vm.updatePc( &instruction, operands, @@ -185,11 +160,7 @@ test "update pc jump with operands res null" { } test "update pc jump with operands res not relocatable" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jump; @@ -199,9 +170,7 @@ test "update pc jump with operands res not relocatable" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError(error.PcUpdateJumpResNotRelocatable, vm.updatePc( &instruction, operands, @@ -209,11 +178,7 @@ test "update pc jump with operands res not relocatable" { } test "update pc jump with operands res relocatable" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jump; @@ -226,17 +191,13 @@ test "update pc jump with operands res relocatable" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -248,11 +209,7 @@ test "update pc jump with operands res relocatable" { } test "update pc jump rel with operands res null" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.JumpRel; @@ -262,9 +219,7 @@ test "update pc jump rel with operands res null" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError(error.ResUnconstrainedUsedWithPcUpdateJumpRel, vm.updatePc( &instruction, operands, @@ -272,11 +227,7 @@ test "update pc jump rel with operands res null" { } test "update pc jump rel with operands res not felt" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.JumpRel; @@ -289,9 +240,7 @@ test "update pc jump rel with operands res not felt" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError(error.PcUpdateJumpRelResNotFelt, vm.updatePc( &instruction, operands, @@ -299,11 +248,7 @@ test "update pc jump rel with operands res not felt" { } test "update pc jump rel with operands res felt" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.JumpRel; @@ -313,17 +258,13 @@ test "update pc jump rel with operands res felt" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -335,11 +276,7 @@ test "update pc jump rel with operands res felt" { } test "update pc update jnz with operands dst zero" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jnz; @@ -349,17 +286,13 @@ test "update pc update jnz with operands dst zero" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -371,11 +304,7 @@ test "update pc update jnz with operands dst zero" { } test "update pc update jnz with operands dst not zero op1 not felt" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jnz; @@ -389,9 +318,7 @@ test "update pc update jnz with operands dst not zero op1 not felt" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError( error.TypeMismatchNotFelt, vm.updatePc( @@ -402,11 +329,7 @@ test "update pc update jnz with operands dst not zero op1 not felt" { } test "update pc update jnz with operands dst not zero op1 felt" { - - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.pc_update = instructions.PcUpdate.Jnz; @@ -417,17 +340,13 @@ test "update pc update jnz with operands dst not zero op1 felt" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updatePc( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const pc = vm.getPc(); try expectEqual( @as( @@ -439,10 +358,7 @@ test "update pc update jnz with operands dst not zero op1 felt" { } test "update ap add with operands res unconstrained" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.ap_update = instructions.ApUpdate.Add; @@ -452,9 +368,7 @@ test "update ap add with operands res unconstrained" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try expectError(error.ApUpdateAddResUnconstrained, vm.updateAp( &instruction, operands, @@ -462,10 +376,7 @@ test "update ap add with operands res unconstrained" { } test "update ap add1" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.ap_update = instructions.ApUpdate.Add1; @@ -474,17 +385,13 @@ test "update ap add1" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updateAp( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the AP offset was incremented by 1. const ap = vm.getAp(); try expectEqual( @@ -497,10 +404,7 @@ test "update ap add1" { } test "update ap add2" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.ap_update = instructions.ApUpdate.Add2; @@ -509,17 +413,13 @@ test "update ap add2" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updateAp( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the AP offset was incremented by 2. const ap = vm.getAp(); try expectEqual( @@ -532,10 +432,7 @@ test "update ap add2" { } test "update fp appplus2" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.fp_update = instructions.FpUpdate.APPlus2; @@ -544,17 +441,13 @@ test "update fp appplus2" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updateFp( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the FP offset was incremented by 2. const fp = vm.getFp(); try expectEqual( @@ -567,10 +460,7 @@ test "update fp appplus2" { } test "update fp dst relocatable" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.fp_update = instructions.FpUpdate.Dst; @@ -583,17 +473,13 @@ test "update fp dst relocatable" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updateFp( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the FP offset was incremented by 2. const fp = vm.getFp(); try expectEqual( @@ -606,10 +492,7 @@ test "update fp dst relocatable" { } test "update fp dst felt" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction.default(); instruction.fp_update = instructions.FpUpdate.Dst; @@ -619,17 +502,13 @@ test "update fp dst felt" { var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body try vm.updateFp( &instruction, operands, ); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the FP offset was incremented by 2. const fp = vm.getFp(); try expectEqual( @@ -642,10 +521,7 @@ test "update fp dst felt" { } test "trace is enabled" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; // Create a new VM instance. @@ -657,14 +533,10 @@ test "trace is enabled" { ); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body // Do nothing - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Check that trace was initialized if (!vm.trace_context.isEnabled()) { return error.TraceShouldHaveBeenEnabled; @@ -672,24 +544,17 @@ test "trace is enabled" { } test "trace is disabled" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; // Create a new VM instance. var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body // Do nothing - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Check that trace was initialized if (vm.trace_context.isEnabled()) { return error.TraceShouldHaveBeenDisabled; @@ -713,15 +578,11 @@ const deduceOpTestInstr = instructions.Instruction{ }; test "deduceOp0 when opcode == .Call" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .Call; @@ -729,9 +590,7 @@ test "deduceOp0 when opcode == .Call" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = relocatable.newFromRelocatable(relocatable.Relocatable.new(0, 1)); // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual(expected_op_0, op0); @@ -739,15 +598,11 @@ test "deduceOp0 when opcode == .Call" { } test "deduceOp0 when opcode == .AssertEq, res_logic == .Add, input is felt" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Add; @@ -759,23 +614,17 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Add, input is felt" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expect(op0.?.eq(relocatable.fromU64(1))); try expect(res.?.eq(relocatable.fromU64(3))); } test "deduceOp0 when opcode == .AssertEq, res_logic == .Add, with no input" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Add; @@ -784,9 +633,7 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Add, with no input" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual(expected_op_0, op0); @@ -794,15 +641,11 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Add, with no input" { } test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 1" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Mul; @@ -814,9 +657,7 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 1" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = relocatable.fromU64(2); // temp var needed for type inference const expected_res: ?MaybeRelocatable = relocatable.fromU64(4); try expectEqual(expected_op_0, op0); @@ -824,15 +665,11 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 1" { } test "deduceOp0 when opcode == .AssertEq, res_logic == .Op1, input is felt" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Op1; @@ -844,9 +681,7 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Op1, input is felt" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual(expected_op_0, op0); @@ -854,15 +689,11 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Op1, input is felt" { } test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 2" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Mul; @@ -874,9 +705,7 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 2" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual(expected_op_0, op0); @@ -884,15 +713,11 @@ test "deduceOp0 when opcode == .AssertEq, res_logic == .Mul, input is felt 2" { } test "deduceOp0 when opcode == .Ret, res_logic == .Mul, input is felt" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context var vm = try CairoVM.init(std.testing.allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .Ret; instr.res_logic = .Mul; @@ -904,9 +729,7 @@ test "deduceOp0 when opcode == .Ret, res_logic == .Mul, input is felt" { const op0 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_0: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual(expected_op_0, op0); @@ -914,14 +737,10 @@ test "deduceOp0 when opcode == .Ret, res_logic == .Mul, input is felt" { } test "deduceOp1 when opcode == .Call" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .Call; @@ -929,9 +748,7 @@ test "deduceOp1 when opcode == .Call" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_1: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual( @@ -945,14 +762,10 @@ test "deduceOp1 when opcode == .Call" { } test "deduceOp1 when opcode == .AssertEq, res_logic == .Add, input is felt" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Add; @@ -964,22 +777,16 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Add, input is felt" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expect(op1.?.eq(relocatable.fromU64(1))); try expect(res.?.eq(relocatable.fromU64(3))); } test "deduceOp1 when opcode == .AssertEq, res_logic == .Mul, non-zero op0" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Mul; @@ -991,22 +798,16 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Mul, non-zero op0" { const op1 = op1_and_result[0]; const res = op1_and_result[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expect(op1.?.eq(relocatable.fromU64(2))); try expect(res.?.eq(relocatable.fromU64(4))); } test "deduceOp1 when opcode == .AssertEq, res_logic == .Mul, zero op0" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Mul; @@ -1018,9 +819,7 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Mul, zero op0" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_1: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual( @@ -1034,14 +833,10 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Mul, zero op0" { } test "deduceOp1 when opcode == .AssertEq, res_logic = .Mul, no input" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Mul; @@ -1050,9 +845,7 @@ test "deduceOp1 when opcode == .AssertEq, res_logic = .Mul, no input" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_1: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual( @@ -1066,14 +859,10 @@ test "deduceOp1 when opcode == .AssertEq, res_logic = .Mul, no input" { } test "deduceOp1 when opcode == .AssertEq, res_logic == .Op1, no dst" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing. - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Op1; @@ -1084,9 +873,7 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Op1, no dst" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks const expected_op_1: ?MaybeRelocatable = null; // temp var needed for type inference const expected_res: ?MaybeRelocatable = null; try expectEqual( @@ -1100,14 +887,10 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Op1, no dst" { } test "deduceOp1 when opcode == .AssertEq, res_logic == .Op1, no op0" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ + // Setup test context // Nothing/ - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body var instr = deduceOpTestInstr; instr.opcode = .AssertEq; instr.res_logic = .Op1; @@ -1118,27 +901,20 @@ test "deduceOp1 when opcode == .AssertEq, res_logic == .Op1, no op0" { const op1 = tuple[0]; const res = tuple[1]; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expect(op1.?.eq(relocatable.fromU64(7))); try expect(res.?.eq(relocatable.fromU64(7))); } test "set get value in vm memory" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; // Create a new VM instance. var vm = try CairoVM.init(allocator, .{}); defer vm.deinit(); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body _ = vm.segments.addSegment(); _ = vm.segments.addSegment(); @@ -1147,9 +923,7 @@ test "set get value in vm memory" { _ = try vm.segments.memory.set(address, value); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks // Verify the value is correctly set to 42. const actual_value = try vm.segments.memory.get(address); const expected_value = value; @@ -1160,10 +934,7 @@ test "set get value in vm memory" { } test "compute res op1 works" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1184,9 +955,7 @@ test "compute res op1 works" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(2)); const value_op1 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(3)); @@ -1194,20 +963,15 @@ test "compute res op1 works" { const actual_res = try computeRes(&instruction, value_op0, value_op1); const expected_res = value_op1; - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectEqual( expected_res, - actual_res, + actual_res.?, ); } test "compute res add felts works" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1228,9 +992,7 @@ test "compute res add felts works" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(2)); const value_op1 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(3)); @@ -1238,20 +1000,15 @@ test "compute res add felts works" { const actual_res = try computeRes(&instruction, value_op0, value_op1); const expected_res = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(5)); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectEqual( expected_res, - actual_res, + actual_res.?, ); } test "compute res add felt to offset works" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1272,9 +1029,7 @@ test "compute res add felt to offset works" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = Relocatable.new(1, 1); const op0 = relocatable.newFromRelocatable(value_op0); @@ -1285,20 +1040,15 @@ test "compute res add felt to offset works" { const res = Relocatable.new(1, 4); const expected_res = relocatable.newFromRelocatable(res); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectEqual( expected_res, - actual_res, + actual_res.?, ); } test "compute res add fails two relocs" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1319,9 +1069,7 @@ test "compute res add fails two relocs" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = Relocatable.new(1, 0); const value_op1 = Relocatable.new(1, 1); @@ -1329,17 +1077,12 @@ test "compute res add fails two relocs" { const op0 = relocatable.newFromRelocatable(value_op0); const op1 = relocatable.newFromRelocatable(value_op1); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectError(error.AddRelocToRelocForbidden, computeRes(&instruction, op0, op1)); } test "compute res mul works" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1360,9 +1103,7 @@ test "compute res mul works" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(2)); const value_op1 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(3)); @@ -1370,20 +1111,15 @@ test "compute res mul works" { const actual_res = try computeRes(&instruction, value_op0, value_op1); const expected_res = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(6)); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectEqual( expected_res, - actual_res, + actual_res.?, ); } test "compute res mul fails two relocs" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1404,9 +1140,7 @@ test "compute res mul fails two relocs" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = Relocatable.new(1, 0); const value_op1 = Relocatable.new(1, 1); @@ -1414,17 +1148,12 @@ test "compute res mul fails two relocs" { const op0 = relocatable.newFromRelocatable(value_op0); const op1 = relocatable.newFromRelocatable(value_op1); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectError(error.MulRelocForbidden, computeRes(&instruction, op0, op1)); } test "compute res mul fails felt and reloc" { - // ************************************************************ - // * SETUP TEST CONTEXT * - // ************************************************************ - // Initialize an allocator. + // Test setup var allocator = std.testing.allocator; var instruction = Instruction{ .off_0 = 0, @@ -1445,20 +1174,53 @@ test "compute res mul fails felt and reloc" { defer vm.deinit(); vm.run_context.ap.* = Relocatable.new(1, 0); - // ************************************************************ - // * TEST BODY * - // ************************************************************ + // Test body const value_op0 = Relocatable.new(1, 0); const op0 = relocatable.newFromRelocatable(value_op0); const op1 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(2)); - // ************************************************************ - // * TEST CHECKS * - // ************************************************************ + // Test checks try expectError(error.MulRelocForbidden, computeRes(&instruction, op0, op1)); } +test "compute res Unconstrained should return null" { + // Test setup + var allocator = std.testing.allocator; + var instruction = Instruction{ + .off_0 = 0, + .off_1 = 1, + .off_2 = 2, + .dst_reg = instructions.Register.AP, + .op_0_reg = instructions.Register.AP, + .op_1_addr = instructions.Op1Src.AP, + .res_logic = instructions.ResLogic.Unconstrained, + .pc_update = instructions.PcUpdate.Regular, + .ap_update = instructions.ApUpdate.Regular, + .fp_update = instructions.FpUpdate.Regular, + .opcode = instructions.Opcode.NOp, + }; + + // Create a new VM instance. + var vm = try CairoVM.init(allocator, .{}); + defer vm.deinit(); + + vm.run_context.ap.* = Relocatable.new(1, 0); + // Test body + + const value_op0 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(2)); + const value_op1 = relocatable.fromFelt(starknet_felt.Felt252.fromInteger(3)); + + const actual_res = try computeRes(&instruction, value_op0, value_op1); + const expected_res: ?MaybeRelocatable = null; + + // Test checks + try expectEqual( + expected_res, + actual_res, + ); +} + test "memory is not leaked upon allocation failure during initialization" { var i: usize = 0; while (i < 20) {