Skip to content

Commit

Permalink
CairoVM.updatePc function and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelStark committed Oct 20, 2023
1 parent 066f6ec commit 53bf297
Show file tree
Hide file tree
Showing 3 changed files with 319 additions and 35 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@

> _Note that `cairo-zig` is still experimental. Breaking changes will be made before the first stable release. The library is also NOT audited or reviewed for security at the moment. Use at your own risk._
## TODOs

- [ ] Add test coverage (investigate using [kcov](https://github.com/SimonKagstrom/kcov), [code coverage for zig article](https://zig.news/squeek502/code-coverage-for-zig-1dk1)).
- [ ] Benchmark performances.
- [ ] Enable usage as a library.
- [ ] Fuzzing.
- [ ] Differential testing against Cairo VM in Rust.
- [ ] Memory leaks detection (i.e use tools like [valgrind](https://valgrind.org/)).
- [ ] Check [Zig style guide](https://ziglang.org/documentation/master/#Style-Guide) and apply it.
- [ ] Go through the code and check carefully for memory safety issues, i.e make sure we have safe deallocation of memory everywhere.
- [ ] Create documentation.

## 📦 Installation

### 📋 Prerequisites
Expand Down Expand Up @@ -76,6 +64,18 @@ OPTIONS:
zig build test --summary all
```

## 🔤 TODOs

- [ ] Add test coverage (investigate using [kcov](https://github.com/SimonKagstrom/kcov), [code coverage for zig article](https://zig.news/squeek502/code-coverage-for-zig-1dk1)).
- [ ] Benchmark performances.
- [ ] Enable usage as a library.
- [ ] Fuzzing.
- [ ] Differential testing against Cairo VM in Rust.
- [ ] Memory leaks detection (i.e use tools like [valgrind](https://valgrind.org/)).
- [ ] Check [Zig style guide](https://ziglang.org/documentation/master/#Style-Guide) and apply it.
- [ ] Go through the code and check carefully for memory safety issues, i.e make sure we have safe deallocation of memory everywhere.
- [ ] Create documentation.

## 📄 License

This project is licensed under the MIT license.
Expand Down
274 changes: 265 additions & 9 deletions src/vm/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -173,23 +173,55 @@ pub const CairoVM = struct {
/// - `instruction`: The instruction that was executed.
/// - `operands`: The operands of the instruction.
pub fn updatePc(self: *CairoVM, instruction: *const instructions.Instruction, operands: OperandsResult) !void {
_ = operands;

switch (instruction.pc_update) {
// ************************************************************
// * PC UPDATE REGULAR *
// ************************************************************
instructions.PcUpdate.Regular => {
// Update the PC.
self.run_context.pc.*.addUintInPlace(instruction.size());
},
// ************************************************************
// * PC UPDATE JUMP *
// ************************************************************
instructions.PcUpdate.Jump => {
// TODO: Implement this.
return;
// Check that the res is not null.
if (operands.res == null) {
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 *
// ************************************************************
instructions.PcUpdate.JumpRel => {
// TODO: Implement this.
return;
// Check that the res is not null.
if (operands.res == null) {
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 *
// ************************************************************
instructions.PcUpdate.Jnz => {
// TODO: Implement this.
return;
if (operands.dst.isZero()) {
// Update the PC.
self.run_context.pc.*.addUintInPlace(instruction.size());
} else {
// Update the PC.
try self.run_context.pc.*.addMaybeRelocatableInplace(operands.op_1);
}
},
}
}
Expand Down Expand Up @@ -234,7 +266,7 @@ pub const CairoVM = struct {
/// Represents the operands for an instruction.
const OperandsResult = struct {
dst: relocatable.MaybeRelocatable,
res: relocatable.MaybeRelocatable,
res: ?relocatable.MaybeRelocatable,
op_0: relocatable.MaybeRelocatable,
op_1: relocatable.MaybeRelocatable,
dst_addr: relocatable.MaybeRelocatable,
Expand Down Expand Up @@ -316,3 +348,227 @@ test "update pc regular with imm" {
const pc = vm.getPc();
try expectEqual(pc.offset, 2);
}

test "update pc jump with operands res null" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jump;
var operands = OperandsResult.default();
operands.res = null;
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try expectError(error.ResUnconstrainedUsedWithPcUpdateJump, vm.updatePc(&instruction, operands));
}

test "update pc jump with operands res not relocatable" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jump;
var operands = OperandsResult.default();
operands.res = relocatable.fromU64(0);
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try expectError(error.PcUpdateJumpResNotRelocatable, vm.updatePc(&instruction, operands));
}

test "update pc jump with operands res relocatable" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jump;
var operands = OperandsResult.default();
operands.res = relocatable.newFromRelocatable(relocatable.Relocatable.new(0, 42));
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 42);
}

test "update pc jump rel with operands res null" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.JumpRel;
var operands = OperandsResult.default();
operands.res = null;
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try expectError(error.ResUnconstrainedUsedWithPcUpdateJumpRel, vm.updatePc(&instruction, operands));
}

test "update pc jump rel with operands res not felt" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.JumpRel;
var operands = OperandsResult.default();
operands.res = relocatable.newFromRelocatable(relocatable.Relocatable.new(0, 42));
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try expectError(error.PcUpdateJumpRelResNotFelt, vm.updatePc(&instruction, operands));
}

test "update pc jump rel with operands res felt" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.JumpRel;
var operands = OperandsResult.default();
operands.res = relocatable.fromU64(42);
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 42);
}

test "update pc update jnz with operands dst zero" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jnz;
var operands = OperandsResult.default();
operands.dst = relocatable.fromU64(0);
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 2);
}

test "update pc update jnz with operands dst not zero op1 not felt" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jnz;
var operands = OperandsResult.default();
operands.dst = relocatable.fromU64(1);
operands.op_1 = relocatable.newFromRelocatable(relocatable.Relocatable.new(0, 42));
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try expectError(error.TypeMismatchNotFelt, vm.updatePc(&instruction, operands));
}

test "update pc update jnz with operands dst not zero op1 felt" {

// ************************************************************
// * SETUP TEST CONTEXT *
// ************************************************************
// Initialize an allocator.
// TODO: Consider using a testing allocator.
var allocator = std.heap.page_allocator;
var instruction = instructions.Instruction.default();
instruction.pc_update = instructions.PcUpdate.Jnz;
var operands = OperandsResult.default();
operands.dst = relocatable.fromU64(1);
operands.op_1 = relocatable.fromU64(42);
// Create a new VM instance.
var vm = try CairoVM.init(&allocator);
defer vm.deinit();

// ************************************************************
// * TEST BODY *
// ************************************************************
try vm.updatePc(&instruction, operands);

// ************************************************************
// * TEST CHECKS *
// ************************************************************
const pc = vm.getPc();
try expectEqual(pc.offset, 42);
}
Loading

0 comments on commit 53bf297

Please sign in to comment.