Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Cairo 1 programs and Hint processor #97

Merged
merged 45 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
dbb5dbe
feat: add Cairo v2.6.4 execution with compilation artifacts from twea…
zmalatrax Jun 28, 2024
173d05f
chore: trunk fmt
zmalatrax Jun 28, 2024
559b600
submodule: pin cairo-vm to main branch
zmalatrax Jul 1, 2024
ff1197a
feat: add parsing and validation of Cairo hints
zmalatrax Jul 3, 2024
5a62dd3
feat: add hint processor
zmalatrax Jul 3, 2024
748c466
feat: run Cairo programs with hints
zmalatrax Jul 3, 2024
aeeb0dc
dev: add u32_overflowing_sub Cairo programs
zmalatrax Jul 3, 2024
cbe96e4
chore: trunk fmt
zmalatrax Jul 3, 2024
2191a27
feat: update trunk config to ignore Cairo prgms for cairo-format
zmalatrax Jul 3, 2024
e7e16b8
fix: add valueOf to properly compare Felts
zmalatrax Jul 4, 2024
137d013
chore: fmt
zmalatrax Jul 4, 2024
bc66186
feat: add TestLessThan programs returning true or false
zmalatrax Jul 4, 2024
a6bd6ff
feat: add TestLessThan unit tests on both cases
zmalatrax Jul 4, 2024
2e533d9
feat: add AllocSegment unit tests
zmalatrax Jul 4, 2024
aa746d0
refactor: update Cairo compilation artifacts
zmalatrax Jul 4, 2024
9a28814
refactor: move edcsa_recover to hints folder
zmalatrax Jul 4, 2024
b6fced4
dev: add Cairo program with arguments
zmalatrax Jul 4, 2024
7f07f1d
refactor: make hintSchema enum as string
zmalatrax Jul 5, 2024
daf186e
doc: add JSDoc to HintProcessor
zmalatrax Jul 5, 2024
0a7d7e6
doc: add JSDoc to hintSchema primitives
zmalatrax Jul 5, 2024
fd1b02d
doc: add JSDoc to hints
zmalatrax Jul 5, 2024
bc4f371
refactor: rename fromProgram to fromCairoZeroProgram and fromCairo1Pr…
zmalatrax Jul 5, 2024
6c7e993
refactor: rename Cairo1 to Cairo
zmalatrax Jul 5, 2024
c005dd2
refactor: enforce snake case on program.ts zod variables
zmalatrax Jul 5, 2024
87614fd
chore: rename parseCairo1Program in program tests
zmalatrax Jul 5, 2024
85cf890
refactor: merge HintProcessor into VirtualMachine and remove circular…
zmalatrax Jul 5, 2024
194a11a
chore: reorder imports
zmalatrax Jul 5, 2024
a47329d
refactor: rename hintBaseSchema to hintParamsSchema
zmalatrax Jul 5, 2024
8bf082a
refactor: make a base object for program parsing and rename parseProgram
zmalatrax Jul 5, 2024
21707c9
dev: update compilation artifacts
zmalatrax Jul 12, 2024
4c2c395
refactor: update CairoRunner for compilation artifacts
zmalatrax Jul 12, 2024
2138ba6
feat: execute any cairo zero function with default to main
zmalatrax Jul 15, 2024
bd4cdda
feat: add cairo compiler submodule
zmalatrax Jul 15, 2024
b1eb6de
dev: pin cairo compiler to feat/add-main-casm
zmalatrax Jul 15, 2024
8881b27
chore: remove compilation artifacts from git
zmalatrax Jul 15, 2024
d7cd296
feat: add cairo compilation target
zmalatrax Jul 15, 2024
f975466
chore: move .PHONY on multiple lines
zmalatrax Jul 15, 2024
02405a8
refactor: remove cairo flag and add a unified program parser and Cair…
zmalatrax Jul 15, 2024
afe1903
refactor: throw if given function identifier is not found in cairo ze…
zmalatrax Jul 15, 2024
2cf3176
refactor: rename hint parser variables to a explicit and generic name
zmalatrax Jul 15, 2024
61d6cd2
test: add test cases around the rhs bound on TestLessThan hint
zmalatrax Jul 15, 2024
6349558
refactor: rename mainOffset to initialPc in CairoRunner constructor
zmalatrax Jul 15, 2024
14d5947
feat: add rust cairo compiler to CI
zmalatrax Jul 15, 2024
e911866
fix: make getOutput throw for Cairo programs until output serializati…
zmalatrax Jul 16, 2024
02c26de
chore: remove tensor_new program
zmalatrax Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ dist

# Cairo compilation artifacts
cairo_programs/**/*.json
cairo_programs/**/*.sierra
5 changes: 5 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
[submodule "ziggy-starkdust"]
path = ziggy-starkdust
url = [email protected]:keep-starknet-strange/ziggy-starkdust.git
shallow = true
[submodule "cairo"]
path = cairo
url = [email protected]:zmalatrax/cairo.git
shallow = true
4 changes: 4 additions & 0 deletions .trunk/trunk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ lint:
- [email protected]
- [email protected]
- [email protected]
ignore:
- linters: [cairo]
paths:
- cairo_programs/cairo/**
actions:
disabled:
- trunk-announce
Expand Down
39 changes: 37 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.PHONY: compile run-all diff-test bench build build-cairo-vm-cli build-cairo-vm-rs-cli build-cairo-vm-zig-cli clean-diff-test clean--bench clean-tmp
.PHONY: compile-cairo-zero compile-cairo compile build build-cairo-vm-cli \
build-cairo-vm-rs-cli build-cairo-vm-zig-cli build-cairo build-sierra-compiler build-cairo-compiler \
run-all diff-test bench clean-diff-test clean-bench clean-tmp

# Clone & build the other VMs - Assume that related lang are installed
CAIRO_VM_RS_CLI:=cairo-vm/target/release/cairo-vm-cli
Expand All @@ -23,6 +25,23 @@ build-cairo-vm-zig-cli: | $(CAIRO_VM_ZIG_CLI)

build-cairo-vm-cli: build build-cairo-vm-rs-cli build-cairo-vm-zig-cli

CAIRO_COMPILER=cairo/target/release/cairo-compile
SIERRA_COMPILER=cairo/target/release/sierra-compile-json

$(CAIRO_COMPILER):
@git submodule init; \
git submodule update; \
cd cairo; cargo build --release --bin cairo-compile

$(SIERRA_COMPILER):
@git submodule init; \
git submodule update; \
cd cairo; cargo build --release --bin sierra-compile-json

build-cairo-compiler: | $(CAIRO_COMPILER)
build-sierra-compiler: | $(SIERRA_COMPILER)
build-cairo: build-cairo-compiler build-sierra-compiler

TMP_PREFIX="cairo-vm-ts"

CAIRO_0_PATH=cairo_programs/cairo_0
Expand All @@ -34,11 +53,27 @@ COMPILED_CAIRO_0_FILES:=$(CAIRO_0_FILES:%.cairo=%.json)
COMPILED_CAIRO_0_BENCHMARK_FILES:=$(CAIRO_0_BENCHMARK_FILES:%.cairo=%.json)
VALID_COMPILED_CAIRO_0_FILES:=$(VALID_CAIRO_0_FILES:%.cairo=%.json)

compile: $(COMPILED_CAIRO_0_FILES)
CAIRO_PATH=cairo_programs/cairo/
CAIRO_FILES:=$(shell find $(CAIRO_PATH) -name '*.cairo')
SIERRA_FILES:=$(CAIRO_FILES:%.cairo=%.sierra)
COMPILED_CAIRO_FILES:=$(SIERRA_FILES:%.sierra=%.json)

$(COMPILED_CAIRO_FILES): %.json: %.sierra
$(SIERRA_COMPILER) $< $@

%.json: %.cairo
poetry run cairo-compile $< --output $@

%.sierra: %.cairo
$(CAIRO_COMPILER) -r -s $< $@


compile-cairo-zero: $(COMPILED_CAIRO_0_FILES)
compile-cairo: $(COMPILED_CAIRO_FILES)
compile: compile-cairo-zero compile-cairo



run-all: $(VALID_COMPILED_CAIRO_0_FILES)
@failed_tests_ctr=0; \
failed_tests=""; \
Expand Down
1 change: 1 addition & 0 deletions cairo
Submodule cairo added at bf13ff
2 changes: 1 addition & 1 deletion cairo-vm
Submodule cairo-vm updated 357 files
3 changes: 3 additions & 0 deletions cairo_programs/cairo/add.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() -> felt252 {
12 + 10
}
9 changes: 9 additions & 0 deletions cairo_programs/cairo/hints/multiple_fn.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn main() -> (bool, bool) {
let a = 10_u32;
let b = 12_u32;
(a < b, b < a)
}

fn foo() -> u32 {
12_u32 ^ 10_u32
}
65 changes: 65 additions & 0 deletions cairo_programs/cairo/hints/tensor_new.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// FP16x16
#[derive(Serde, Copy, Drop)]
struct FP16x16 {
mag: u32,
sign: bool
}

trait FixedTrait<T, MAG> {
fn new(mag: MAG, sign: bool) -> T;
}

impl FP16x16Impl of FixedTrait<FP16x16, u32> {
fn new(mag: u32, sign: bool) -> FP16x16 {
FP16x16 { mag: mag, sign: sign }
}
}

//Tensor
#[derive(Copy, Drop)]
struct Tensor<T> {
shape: Span<usize>,
data: Span<T>,
}

trait TensorTrait<T> {
fn new(shape: Span<usize>, data: Span<T>) -> Tensor<T>;
}

impl FP16x16Tensor of TensorTrait<FP16x16> {
fn new(shape: Span<usize>, data: Span<FP16x16>) -> Tensor<FP16x16> {
new_tensor(shape, data)
}
}

fn new_tensor<T>(shape: Span<usize>, data: Span<T>) -> Tensor<T> {
check_shape::<T>(shape, data);
Tensor::<T> { shape, data }
}

fn check_shape<T>(shape: Span<usize>, data: Span<T>) {
assert(len_from_shape(shape) == data.len(), 'wrong tensor shape');
}

fn len_from_shape(mut shape: Span<usize>) -> usize {
let mut result: usize = 1;

loop {
match shape.pop_front() {
Option::Some(item) => { result *= *item; },
Option::None => { break; }
};
};

result
}

fn main() -> Tensor<FP16x16> {
TensorTrait::new(
array![1, 2].span(),
array![
FixedTrait::new(1, false),
FixedTrait::new(1, true)
].span()
)
}
3 changes: 3 additions & 0 deletions cairo_programs/cairo/hints/test_less_than_args.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main(a: u32, b: u32, c: u32) {
(a < b, b < c);
}
3 changes: 3 additions & 0 deletions cairo_programs/cairo/hints/test_less_than_false.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() -> bool {
12_u32 < 10_u32
}
3 changes: 3 additions & 0 deletions cairo_programs/cairo/hints/test_less_than_true.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() -> bool {
10_u32 < 12_u32
}
3 changes: 3 additions & 0 deletions cairo_programs/cairo/hints/u32_overflowing_sub_err.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() -> Result<u32, u32> {
integer::u32_overflowing_sub(10_u32, 12_u32)
}
3 changes: 3 additions & 0 deletions cairo_programs/cairo/hints/u32_overflowing_sub_valid.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() -> Result<u32, u32> {
integer::u32_overflowing_sub(12_u32, 10_u32)
}
5 changes: 4 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#! /usr/bin/env bun

import { Command, Option } from '@commander-js/extra-typings';

import { consola } from 'consola';
import { Argument } from 'commander';

import { run } from 'scripts/run';

consola.options = {
Expand All @@ -30,6 +30,9 @@ program
})
)
.option('-s, --silent', 'silent all logs')
.addOption(
new Option('--fn <NAME>', 'Function to be executed').default('main')
)
.option('--no-relocate', 'do not relocate memory')
.addOption(
new Option(
Expand Down
8 changes: 8 additions & 0 deletions src/errors/cairoRunner.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
class CairoRunnerError extends Error {}

export class EmptyRelocatedMemory extends CairoRunnerError {}

export class CairoZeroHintsNotSupported extends CairoRunnerError {}

export class UndefinedEntrypoint extends CairoRunnerError {
constructor(name: string) {
super(`The function to be executed doesn't exist: ${name}`);
}
}
22 changes: 22 additions & 0 deletions src/errors/hints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CellRef } from 'hints/hintParamsSchema';
import { Hint } from 'hints/hintSchema';

class HintError extends Error {}

export class InvalidCellRefRegister extends HintError {
constructor(cell: CellRef) {
super(`Invalid register, expected AP or FP, got ${cell}`);
}
}

export class InvalidOperation extends HintError {
constructor(op: string) {
super(`Invalid BinOp operator - Expected Add or Mul, received ${op}`);
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
}
}

export class UnknownHint extends HintError {
constructor(hint: Hint) {
super(`Unknown hint: ${hint}`);
}
}
40 changes: 40 additions & 0 deletions src/hints/allocSegment.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, expect, test } from 'bun:test';

import { Relocatable } from 'primitives/relocatable';
import { Register } from 'vm/instruction';
import { VirtualMachine } from 'vm/virtualMachine';
import { HintName } from 'hints/hintName';
import { allocSegmentZod } from './allocSegment';

const ALLOC_SEGMENT = {
AllocSegment: {
dst: {
register: 'AP',
offset: 0,
},
},
};

describe('AllocSegment', () => {
test('should properly parse AllocSegment hint', () => {
const hint = allocSegmentZod.parse(ALLOC_SEGMENT);
expect(hint).toEqual({
type: HintName.AllocSegment,
dst: {
register: Register.Ap,
offset: 0,
},
});
});

test('should properly execute AllocSegment hint', () => {
const hint = allocSegmentZod.parse(ALLOC_SEGMENT);
const vm = new VirtualMachine();
vm.memory.addSegment();
vm.memory.addSegment();
expect(vm.memory.getSegmentNumber()).toEqual(2);
vm.executeHint(hint);
expect(vm.memory.getSegmentNumber()).toEqual(3);
expect(vm.memory.get(vm.ap)).toEqual(new Relocatable(2, 0));
});
});
28 changes: 28 additions & 0 deletions src/hints/allocSegment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { z } from 'zod';

import { VirtualMachine } from 'vm/virtualMachine';
import { cellRef, CellRef } from 'hints/hintParamsSchema';
import { HintName } from 'hints/hintName';

/** Zod object to parse AllocSegment hint */
export const allocSegmentZod = z
zmalatrax marked this conversation as resolved.
Show resolved Hide resolved
.object({ AllocSegment: z.object({ dst: cellRef }) })
.transform(({ AllocSegment: { dst } }) => ({
type: HintName.AllocSegment,
dst,
}));

/**
* AllocSegment hint
*
* Add a new segment and store its pointer to `dst`
*/
export type AllocSegment = z.infer<typeof allocSegmentZod>;

/**
* Add a new segment and store its pointer at `dst`
*/
export const allocSegment = (vm: VirtualMachine, dst: CellRef) => {
const segmentId = vm.memory.addSegment();
vm.memory.assertEq(vm.cellRefToRelocatable(dst), segmentId);
};
5 changes: 5 additions & 0 deletions src/hints/hintName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** Name to identify which hint is executed */
export enum HintName {
AllocSegment = 'AllocSegment',
TestLessThan = 'TestLessThan',
}
Loading
Loading