Skip to content

Commit

Permalink
ProgramJson to Program in Cairo runner (keep-starknet-strange#392)
Browse files Browse the repository at this point in the history
* ProgramJson to Program in Cairo runner

* fix build
  • Loading branch information
tcoratger authored Feb 23, 2024
1 parent 42ff5c1 commit 22d164a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 64 deletions.
15 changes: 12 additions & 3 deletions src/vm/cairo_run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,21 @@ pub fn runConfig(allocator: Allocator, config: Config) !void {
config,
);

const parsed_program = try ProgramJson.parseFromFile(allocator, config.filename);
var parsed_program = try ProgramJson.parseFromFile(allocator, config.filename);
const instructions = try parsed_program.value.readData(allocator);
defer parsed_program.deinit();

var runner = try CairoRunner.init(allocator, parsed_program.value, config.layout, instructions, vm, config.proof_mode);
defer runner.deinit();
var entrypoint: []const u8 = "main";

var runner = try CairoRunner.init(
allocator,
try parsed_program.value.parseProgramJson(allocator, &entrypoint),
config.layout,
instructions,
vm,
config.proof_mode,
);
defer runner.deinit(allocator);
const end = try runner.setupExecutionState();
try runner.runUntilPC(end);
try runner.endRun();
Expand Down
91 changes: 47 additions & 44 deletions src/vm/runners/cairo_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const CairoVM = @import("../core.zig").CairoVM;
const CairoLayout = @import("../types/layout.zig").CairoLayout;
const Relocatable = @import("../memory/relocatable.zig").Relocatable;
const MaybeRelocatable = @import("../memory/relocatable.zig").MaybeRelocatable;
const ProgramJson = @import("../types/programjson.zig").ProgramJson;
const Program = @import("../types/program.zig").Program;
const CairoRunnerError = @import("../error.zig").CairoRunnerError;
const CairoVMError = @import("../error.zig").CairoVMError;
Expand Down Expand Up @@ -117,7 +116,7 @@ const BuiltinInfo = struct { segment_index: usize, stop_pointer: usize };
pub const CairoRunner = struct {
const Self = @This();

program: ProgramJson,
program: Program,
allocator: Allocator,
vm: CairoVM,
program_base: Relocatable = undefined,
Expand All @@ -139,7 +138,7 @@ pub const CairoRunner = struct {

pub fn init(
allocator: Allocator,
program: ProgramJson,
program: Program,
layout: []const u8,
instructions: std.ArrayList(MaybeRelocatable),
vm: CairoVM,
Expand Down Expand Up @@ -172,7 +171,7 @@ pub const CairoRunner = struct {
self.layout,
self.allocator,
self.isProofMode(),
self.program.builtins.?,
self.program.builtins,
);
}

Expand Down Expand Up @@ -282,7 +281,8 @@ pub const CairoRunner = struct {
}
self.execution_public_memory = execution_public_memory;

try self.initState(try (self.program.getStartPc() orelse RunnerError.NoProgramStart), &stack_prefix);
try self.initState(try (self.program.shared_program_data.start orelse
RunnerError.NoProgramStart), &stack_prefix);
} else {
target_offset = stack.items.len + 2;

Expand All @@ -291,13 +291,15 @@ pub const CairoRunner = struct {
try stack.append(MaybeRelocatable.fromRelocatable(return_fp));
try stack.append(MaybeRelocatable.fromRelocatable(end));

try self.initState(try (self.program.getStartPc() orelse RunnerError.NoProgramStart), &stack);
try self.initState(try (self.program.shared_program_data.start orelse
RunnerError.NoProgramStart), &stack);
}

self.initial_fp = try self.execution_base.addUint(target_offset);
self.initial_ap = self.initial_fp;

return self.program_base.addUint(try (self.program.getEndPc() orelse RunnerError.NoProgramEnd));
return self.program_base.addUint(try (self.program.shared_program_data.end orelse
RunnerError.NoProgramEnd));
}

const return_fp = try self.vm.segments.addSegment();
Expand All @@ -307,13 +309,9 @@ pub const CairoRunner = struct {
// Concatenate strings
const full_entrypoint_name = try std.fmt.bufPrint(&buffer, "__main__.{s}", .{self.entrypoint_name});

if (self.program.identifiers) |identifiers| {
if (identifiers.map.get(full_entrypoint_name)) |identifier| {
if (identifier.pc) |pc| {
return self.initFunctionEntrypoint(pc, return_fp, &stack);
}
}
}
if (self.program.shared_program_data.identifiers.get(full_entrypoint_name)) |identifier|
if (identifier.pc) |pc|
return self.initFunctionEntrypoint(pc, return_fp, &stack);

return RunnerError.MissingMain;
}
Expand Down Expand Up @@ -354,7 +352,13 @@ pub const CairoRunner = struct {
const hints_collection = try self.program.getHintsCollections(self.allocator);
for (hints_collection.hints.items) |hint| {
try result.append(
try (hint_processor.compileHint(self.allocator, hint.code, hint.flow_tracking_data.ap_tracking, hint.flow_tracking_data.reference_ids, references) catch CairoVMError.CompileHintFail),
try (hint_processor.compileHint(
self.allocator,
hint.code,
hint.flow_tracking_data.ap_tracking,
hint.flow_tracking_data.reference_ids,
references,
) catch CairoVMError.CompileHintFail),
);
}

Expand Down Expand Up @@ -539,10 +543,10 @@ pub const CairoRunner = struct {
return res;
}

pub fn deinit(self: *Self) void {
pub fn deinit(self: *Self, allocator: Allocator) void {
// currently handling the deinit of the json.Parsed(ProgramJson) outside of constructor
// otherwise the runner would always assume json in its interface
// self.program.deinit();
self.program.deinit(allocator);

if (self.execution_public_memory) |execution_public_memory| execution_public_memory.deinit();

Expand All @@ -556,7 +560,7 @@ pub const CairoRunner = struct {
test "CairoRunner: initMainEntrypoint no main" {
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"all_cairo",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -566,7 +570,7 @@ test "CairoRunner: initMainEntrypoint no main" {
false,
);

defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Add an OutputBuiltinRunner to the CairoRunner without setting the stop pointer.
try cairo_runner.vm.builtin_runners.append(.{ .Output = OutputBuiltinRunner.initDefault(std.testing.allocator) });
Expand All @@ -580,9 +584,8 @@ test "CairoRunner: initVM should initialize the VM properly with no builtins" {
// Initialize a CairoRunner with an empty program, "plain" layout, and empty instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",

ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
std.testing.allocator,
Expand All @@ -592,7 +595,7 @@ test "CairoRunner: initVM should initialize the VM properly with no builtins" {
);

// Defer the deinitialization of the CairoRunner to ensure proper cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Set initial values for program_base, initial_pc, initial_ap, and initial_fp.
cairo_runner.program_base = Relocatable.init(0, 0);
Expand Down Expand Up @@ -624,14 +627,14 @@ test "CairoRunner: initVM should initialize the VM properly with Range Check bui
// Initialize a CairoRunner with an empty program, "plain" layout, and empty instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(std.testing.allocator, .{}),
false,
);
// Defer the deinitialization of the CairoRunner to ensure proper cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Append a RangeCheckBuiltinRunner to the CairoRunner's list of built-in runners.
try cairo_runner.vm.builtin_runners.append(.{ .RangeCheck = RangeCheckBuiltinRunner{} });
Expand Down Expand Up @@ -682,7 +685,7 @@ test "CairoRunner: initVM should return an error with invalid Range Check builti
// Initialize a CairoRunner with an empty program, "plain" layout, and empty instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -692,7 +695,7 @@ test "CairoRunner: initVM should return an error with invalid Range Check builti
false,
);
// Defer the deinitialization of the CairoRunner to ensure proper cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Append a RangeCheckBuiltinRunner to the CairoRunner's list of built-in runners.
try cairo_runner.vm.builtin_runners.append(.{ .RangeCheck = RangeCheckBuiltinRunner{} });
Expand Down Expand Up @@ -770,7 +773,7 @@ test "CairoRunner: getBuiltinSegmentsInfo with segment info empty should return
// Create a CairoRunner instance for testing.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -779,7 +782,7 @@ test "CairoRunner: getBuiltinSegmentsInfo with segment info empty should return
),
false,
);
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Retrieve the builtin segment info from the CairoRunner.
var builtin_segment_info = try cairo_runner.getBuiltinSegmentsInfo(std.testing.allocator);
Expand All @@ -793,7 +796,7 @@ test "CairoRunner: getBuiltinSegmentsInfo info based not finished" {
// Create a CairoRunner instance for testing.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -802,7 +805,7 @@ test "CairoRunner: getBuiltinSegmentsInfo info based not finished" {
),
false,
);
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Add an OutputBuiltinRunner to the CairoRunner without setting the stop pointer.
try cairo_runner.vm.builtin_runners.append(.{ .Output = OutputBuiltinRunner.initDefault(std.testing.allocator) });
Expand All @@ -818,7 +821,7 @@ test "CairoRunner: getBuiltinSegmentsInfo should provide builtin segment informa
// Create a CairoRunner instance for testing.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -827,7 +830,7 @@ test "CairoRunner: getBuiltinSegmentsInfo should provide builtin segment informa
),
false,
);
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Create instances of OutputBuiltinRunner and BitwiseBuiltinRunner with stop pointers.
var output_builtin = OutputBuiltinRunner.initDefault(std.testing.allocator);
Expand Down Expand Up @@ -865,7 +868,7 @@ test "CairoRunner: relocateMemory should relocated memory properly with gaps" {
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -875,7 +878,7 @@ test "CairoRunner: relocateMemory should relocated memory properly with gaps" {
false,
);
// Ensure CairoRunner resources are cleaned up.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Create four memory segments in the VM.
inline for (0..4) |_| {
Expand Down Expand Up @@ -929,7 +932,7 @@ test "CairoRunner: initSegments should initialize the segments properly with bas
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -939,7 +942,7 @@ test "CairoRunner: initSegments should initialize the segments properly with bas
false,
);
// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Append an OutputBuiltinRunner to the CairoRunner's list of built-in runners.
try cairo_runner.vm.builtin_runners.append(.{ .Output = OutputBuiltinRunner.initDefault(std.testing.allocator) });
Expand Down Expand Up @@ -984,7 +987,7 @@ test "CairoRunner: initSegments should initialize the segments properly with no
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -994,7 +997,7 @@ test "CairoRunner: initSegments should initialize the segments properly with no
false,
);
// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Append an OutputBuiltinRunner to the CairoRunner's list of built-in runners.
try cairo_runner.vm.builtin_runners.append(.{ .Output = OutputBuiltinRunner.initDefault(std.testing.allocator) });
Expand Down Expand Up @@ -1034,7 +1037,7 @@ test "CairoRunner: getPermRangeCheckLimits with no builtin" {
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -1045,7 +1048,7 @@ test "CairoRunner: getPermRangeCheckLimits with no builtin" {
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Set up memory for the CairoRunner with a single memory cell.
try cairo_runner.vm.segments.memory.setUpMemory(
Expand Down Expand Up @@ -1087,7 +1090,7 @@ test "CairoRunner: getPermRangeCheckLimits with range check builtin" {
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -1098,7 +1101,7 @@ test "CairoRunner: getPermRangeCheckLimits with range check builtin" {
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Set up memory for the CairoRunner with a single memory cell.
try cairo_runner.vm.segments.memory.setUpMemory(
Expand All @@ -1121,7 +1124,7 @@ test "CairoRunner: getPermRangeCheckLimits with null range limit" {
// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
ProgramJson{},
try Program.initDefault(std.testing.allocator),
"plain",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
try CairoVM.init(
Expand All @@ -1132,7 +1135,7 @@ test "CairoRunner: getPermRangeCheckLimits with null range limit" {
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit();
defer cairo_runner.deinit(std.testing.allocator);

// Invoke the `getPermRangeCheckLimits` function and expect the result to be null.
try expectEqual(
Expand Down
10 changes: 5 additions & 5 deletions src/vm/types/layout.zig
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub const CairoLayout = struct {
self: Self,
allocator: Allocator,
proof_mode: bool,
program_builtins: []const []const u8,
program_builtins: std.ArrayList(BuiltinName),
) !ArrayList(BuiltinRunner) {
var builtin_runners = ArrayList(BuiltinRunner).init(allocator);

Expand All @@ -196,12 +196,12 @@ pub const CairoLayout = struct {
// If not in proof_mode, we iterate through the compiled program's json builtins array.
// For each builtin, we check if it exists in a layout, if not, we throw an error.
// If it does we include it's initialized builtin runner in the builtin_runners array.
for (program_builtins) |builtin| {
const case = std.meta.stringToEnum(BuiltinName, builtin) orelse return RunnerError.BuiltinNotInLayout;
for (program_builtins.items) |builtin| {
// const case = std.meta.stringToEnum(BuiltinName, builtin) orelse return RunnerError.BuiltinNotInLayout;

if (!self.containsBuiltin(case)) return RunnerError.BuiltinNotInLayout;
if (!self.containsBuiltin(builtin)) return RunnerError.BuiltinNotInLayout;

switch (case) {
switch (builtin) {
.output => try builtin_runners.append(BuiltinRunner{ .Output = OutputBuiltinRunner.initDefault(allocator) }),

// TODO: implement initDefault for the rest of the builtin runners.
Expand Down
Loading

0 comments on commit 22d164a

Please sign in to comment.