Skip to content

Commit

Permalink
feat(vm): implement computeOp0Deductions method (keep-starknet-stra…
Browse files Browse the repository at this point in the history
…nge#120)

add computeOp0Deductions in CairoVM and unit tests

Co-authored-by: lanaivina <[email protected]>
  • Loading branch information
tcoratger and lana-shanghai authored Nov 8, 2023
1 parent d63738c commit f706576
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 23 deletions.
44 changes: 25 additions & 19 deletions src/vm/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -199,27 +199,33 @@ pub const CairoVM = struct {
};
}

/// Runs deductions for Op0, first runs builtin deductions, if this fails, attempts to deduce it based on dst and op1
/// Also returns res if it was also deduced in the process
/// Inserts the deduced operand
/// Fails if Op0 was not deduced or if an error arose in the process.
/// # Arguments
/// Compute Op0 deductions based on the provided instruction, destination, and Op1.
///
/// This function first attempts to deduce Op0 using built-in deductions. If that returns a null,
/// it falls back to deducing Op0 based on the provided destination and Op1.
///
/// ## Arguments
/// - `op_0_addr`: The address of the operand to deduce.
/// - `instruction`: The instruction to deduce the operand for.
/// - `dst`: The destination.
/// - `op1`: The op1.
/// - `dst`: The destination of the instruction.
/// - `op1`: The Op1 operand.
///
/// ## Returns
/// - `MaybeRelocatable`: The deduced Op0 operand or an error if deducing Op0 fails.
pub fn computeOp0Deductions(
self: *Self,
op_0_addr: MaybeRelocatable,
op_0_addr: Relocatable,
instruction: *const instructions.Instruction,
dst: ?MaybeRelocatable,
op1: ?MaybeRelocatable,
) void {
_ = op1;
_ = dst;
_ = instruction;
const op_o = try self.deduceMemoryCell(op_0_addr);
_ = op_o;
dst: ?*const MaybeRelocatable,
op1: ?*const MaybeRelocatable,
) !MaybeRelocatable {
const op0_op = try self.deduceMemoryCell(op_0_addr) orelse (try self.deduceOp0(
instruction,
dst,
op1,
))[0];

return op0_op orelse CairoVMError.FailedToComputeOperands;
}

/// Attempts to deduce `op0` and `res` for an instruction, given `dst` and `op1`.
Expand Down Expand Up @@ -321,7 +327,7 @@ pub const CairoVM = struct {
) !void {
switch (instruction.ap_update) {
// AP update Add
instructions.ApUpdate.Add => {
.Add => {
// Check that Res is not null.
if (operands.res) |val| {
// Update AP.
Expand All @@ -331,11 +337,11 @@ pub const CairoVM = struct {
}
},
// AP update Add1
instructions.ApUpdate.Add1 => {
.Add1 => {
self.run_context.ap.*.addUintInPlace(1);
},
// AP update Add2
instructions.ApUpdate.Add2 => {
.Add2 => {
self.run_context.ap.*.addUintInPlace(2);
},
else => {},
Expand Down
95 changes: 91 additions & 4 deletions src/vm/core_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ test "trace is disabled" {

// This instruction is used in the functions that test the `deduceOp1` function. Only the
// `opcode` and `res_logic` fields are usually changed.
const deduceOpTestInstr = instructions.Instruction{
const deduceOpTestInstr = Instruction{
.off_0 = 1,
.off_1 = 2,
.off_2 = 3,
Expand Down Expand Up @@ -592,7 +592,7 @@ test "deduceOp0 when opcode == .Call" {
const res = tuple[1];

// Test checks
const expected_op_0: ?MaybeRelocatable = relocatable.newFromRelocatable(relocatable.Relocatable.new(0, 1)); // temp var needed for type inference
const expected_op_0: ?MaybeRelocatable = relocatable.newFromRelocatable(Relocatable.new(0, 1)); // temp var needed for type inference
const expected_res: ?MaybeRelocatable = null;
try expectEqual(expected_op_0, op0);
try expectEqual(expected_res, res);
Expand Down Expand Up @@ -1256,7 +1256,7 @@ test "memory is not leaked upon allocation failure during initialization" {

test "updateRegisters all regular" {
// Test setup
var instruction = instructions.Instruction{
var instruction = Instruction{
.off_0 = 1,
.off_1 = 2,
.off_2 = 3,
Expand Down Expand Up @@ -1318,7 +1318,7 @@ test "updateRegisters all regular" {

test "updateRegisters with mixed types" {
// Test setup
var instruction = instructions.Instruction{
var instruction = Instruction{
.off_0 = 1,
.off_1 = 2,
.off_2 = 3,
Expand Down Expand Up @@ -1380,3 +1380,90 @@ test "updateRegisters with mixed types" {
vm.getFp(),
);
}

test "CairoVM: computeOp0Deductions should return op0 from deduceOp0 if deduceMemoryCell is null" {
// Test setup
var vm = try CairoVM.init(std.testing.allocator, .{});
defer vm.deinit();

var instr = deduceOpTestInstr;
instr.opcode = .Call;

// Test check
try expectEqual(
MaybeRelocatable{ .relocatable = Relocatable.new(0, 1) },
try vm.computeOp0Deductions(
Relocatable.new(0, 7),
&instr,
null,
null,
),
);
}

test "CairoVM: computeOp0Deductions with a valid built in and non null deduceMemoryCell should return deduceMemoryCell" {
// Test setup
var vm = try CairoVM.init(
std.testing.allocator,
.{},
);
defer vm.deinit();
var instance_def: BitwiseInstanceDef = .{ .ratio = null, .total_n_bits = 2 };
try vm.builtin_runners.append(BuiltinRunner{ .Bitwise = BitwiseBuiltinRunner.new(
&instance_def,
true,
) });
try vm.segments.memory.set(
Relocatable.new(
0,
5,
),
relocatable.fromFelt(Felt252.fromInteger(10)),
);
try vm.segments.memory.set(
Relocatable.new(
0,
6,
),
relocatable.fromFelt(Felt252.fromInteger(12)),
);
try vm.segments.memory.set(
Relocatable.new(
0,
7,
),
relocatable.fromFelt(Felt252.fromInteger(0)),
);

// Test check
try expectEqual(
MaybeRelocatable{ .felt = Felt252.fromInteger(8) },
try vm.computeOp0Deductions(
Relocatable.new(0, 7),
&deduceOpTestInstr,
&.{ .relocatable = .{} },
&.{ .relocatable = .{} },
),
);
}

test "CairoVM: computeOp0Deductions should return VM error if deduceOp0 and deduceMemoryCell are null" {
// Test setup
var vm = try CairoVM.init(std.testing.allocator, .{});
defer vm.deinit();

var instr = deduceOpTestInstr;
instr.opcode = .Ret;
instr.res_logic = .Mul;

// Test check
try expectError(
CairoVMError.FailedToComputeOperands,
vm.computeOp0Deductions(
Relocatable.new(0, 7),
&instr,
&relocatable.fromU64(4),
&relocatable.fromU64(0),
),
);
}
1 change: 1 addition & 0 deletions src/vm/error.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub const CairoVMError = error{
RunnerError,
TypeMismatchNotRelocatable,
ValueTooLarge,
FailedToComputeOperands,
};

pub const MemoryError = error{
Expand Down

0 comments on commit f706576

Please sign in to comment.