Skip to content

Commit

Permalink
Migrate Cairo-VM test contracts (#677)
Browse files Browse the repository at this point in the history
* Move cairo vm programs to separate folder

* Add cairo vm contracts

* Add test contract cases structure

* Update fib.cairo to latest version

* Implement load cairo program with CairoRunner

* Implement run_vm_contract

* Add commented cases

* Add other cases

* Migrate all other tests

* Improve code legibility

* Fix clippy

* Add comment

* Add comment

* Add assert on failure flag

* Update to new corelib

* Reorder cases

* Ignore failing test

* Add better expect messages
  • Loading branch information
JulianGCalderon authored Jun 7, 2024
1 parent 7d273e8 commit 936d258
Show file tree
Hide file tree
Showing 62 changed files with 1,042 additions and 37 deletions.
291 changes: 290 additions & 1 deletion Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ sec1 = { version = "0.7.3", optional = true }
serde_json = { version = "1.0.117", optional = true }

[dev-dependencies]
cairo-vm = { version = "1.0.0-rc3", features = ["cairo-1-hints"] }
cairo-felt = "0.9.1"
cairo-lang-runner = "2.6.3"
cairo-lang-semantic = { version = "2.6.3", features = ["testing"] }
Expand Down
24 changes: 24 additions & 0 deletions tests/cases/cairo_vm/contracts/alloc_constant_size.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[starknet::contract]
mod AllocConstantSizeContract {
use box::BoxTrait;


#[storage]
struct Storage {}

// Calculates fib, but all variables are boxes.
#[external(v0)]
fn fib(self: @ContractState, a: felt252, b: felt252, n: felt252) -> felt252 {
let a = BoxTrait::new(a);
let b = BoxTrait::new(b);
let n = BoxTrait::new(n);


let unboxed_n = n.unbox();
if unboxed_n == 0 {
a.unbox()
} else {
fib(self, b.unbox(), a.unbox() + b.unbox(), unboxed_n - 1, )
}
}
}
23 changes: 23 additions & 0 deletions tests/cases/cairo_vm/contracts/alloc_segment.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#[starknet::contract]
mod AllocSegment {
use dict::{Felt252DictTrait, Felt252DictEntryTrait};
use traits::Index;
use array::{ArrayTrait, SpanTrait};

#[storage]
struct Storage {}

#[external(v0)]
fn alloc_segment(self: @ContractState) {
// generates hint AllocSegment for felt252 dict when compiled to casm
let mut dict: Felt252Dict<felt252> = Default::default();
dict.squash();

// generates hint AllocSegment for array
let mut arr: Array<felt252> = ArrayTrait::new();

arr.append(10);
assert(*arr[0] == 10, 'array[0] == 10');
}
}

16 changes: 16 additions & 0 deletions tests/cases/cairo_vm/contracts/assert_le_find_small_arcs.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#[starknet::contract]
mod Felt252Dict {
use dict::{felt252_dict_entry_finalize, Felt252DictTrait};

#[storage]
struct Storage {}

#[external(v0)]
fn update_dict(self: @ContractState) {
let mut dict = felt252_dict_new::<felt252>();
dict.insert(1, 64);
dict.insert(2, 75);
dict.insert(3, 75);
dict.squash();
}
}
38 changes: 38 additions & 0 deletions tests/cases/cairo_vm/contracts/dict_test.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#[starknet::contract]
mod DictTest {
use dict::Felt252DictTrait;
use traits::Index;

const KEY1: felt252 = 10;
const KEY2: felt252 = 21;
// KEY3 is ~37% * PRIME.
const KEY3: felt252 =
1343531647004637707094910297222796970954128321746173119103571679493202324940;
// KEY4 and KEY5 are ~92% * PRIME.
const KEY4: felt252 =
3334603141101959564751596861783084684819726025596122159217101666076094555684;
const KEY5: felt252 =
3334603141101959564751596861783084684819726025596122159217101666076094555685;

#[storage]
struct Storage {}

#[external(v0)]
fn test_dict_big_keys(self: @ContractState) -> felt252 {
let mut dict: Felt252Dict<felt252> = Default::default();

dict.insert(KEY1, 1);
dict.insert(KEY2, 2);
dict.insert(KEY3, 3);
dict.insert(KEY4, 4);
dict.insert(KEY5, 5);

assert(dict.index(KEY1) == 1, 'KEY1');
assert(dict.index(KEY2) == 2, 'KEY2');
assert(dict.index(KEY3) == 3, 'KEY3');
assert(dict.index(KEY4) == 4, 'KEY4');
assert(dict.index(KEY5) == 5, 'KEY5');

return dict.index(KEY5);
}
}
11 changes: 11 additions & 0 deletions tests/cases/cairo_vm/contracts/divmod.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[starknet::contract]
mod DivModTestContract {
#[storage]
struct Storage {}

#[external(v0)]
fn div_mod_test(self: @ContractState, x: u8, y: u8) -> u8 {
let (res, _) = integer::u8_safe_divmod(x, integer::u8_as_non_zero(y));
res
}
}
13 changes: 13 additions & 0 deletions tests/cases/cairo_vm/contracts/factorial.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[starknet::contract]
mod Factorial {
#[storage]
struct Storage {}

#[external(v0)]
fn factorial(self: @ContractState, n: felt252) -> felt252 {
if (n == 0) {
return 1;
}
n * factorial(self, n - 1)
}
}
24 changes: 24 additions & 0 deletions tests/cases/cairo_vm/contracts/felt252_dict_entry_init.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[starknet::contract]
mod DictEntryInitTest {
use dict::{Felt252DictTrait, Felt252DictEntryTrait};
use traits::Index;
use array::{ArrayTrait, SpanTrait};

#[storage]
struct Storage {}

#[external(v0)]
fn felt252_dict_entry_init(self: @ContractState) {
let mut dict: Felt252Dict<felt252> = Default::default();

// Generates hint Felt252DictEntryInit by creating a new dict entry
dict.insert(10, 110);
dict.insert(11, 111);
let val10 = dict.index(10);
let val11 = dict.index(11);
assert(val10 == 110, 'dict[10] == 110');
assert(val11 == 111, 'dict[11] == 111');

dict.squash();
}
}
18 changes: 18 additions & 0 deletions tests/cases/cairo_vm/contracts/felt252_dict_entry_update.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[starknet::contract]
mod Felt252Dict {
use dict::{felt252_dict_entry_finalize, Felt252DictTrait};

#[storage]
struct Storage {}

#[external(v0)]
fn update_dict(self: @ContractState) -> (felt252, felt252) {
let mut dict = felt252_dict_new::<felt252>();
dict.insert(1, 64);
let val = dict.get(1);
dict.insert(1, 75);
let val2 = dict.get(1);
dict.squash();
return (val, val2);
}
}
15 changes: 15 additions & 0 deletions tests/cases/cairo_vm/contracts/felt_252_dict.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[starknet::contract]
mod Felt252Dict {
#[storage]
struct Storage {}

use dict::{felt252_dict_entry_finalize, Felt252DictTrait};

/// An external method that requires the `segment_arena` builtin.
#[external(v0)]
fn squash_empty_dict(self: @ContractState) -> bool {
let x = felt252_dict_new::<felt252>();
x.squash();
return true;
}
}
13 changes: 13 additions & 0 deletions tests/cases/cairo_vm/contracts/fib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[starknet::contract]
mod Fibonacci {
#[storage]
struct Storage {}

#[external(v0)]
fn fib(self: @ContractState, a: felt252, b: felt252, n: felt252) -> felt252 {
match n {
0 => a,
_ => fib(self, b, a + b, n - 1),
}
}
}
20 changes: 20 additions & 0 deletions tests/cases/cairo_vm/contracts/field_sqrt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[starknet::contract]
mod FieldSqrt {
#[storage]
struct Storage {}

use core::traits::Into;
use option::OptionTrait;
use ec::ec_point_from_x_nz;
use ec::ec_point_unwrap;

#[external(v0)]
fn field_sqrt(self: @ContractState) -> felt252 {
let p_nz = ec_point_from_x_nz(10).unwrap();

let (qx, _) = ec_point_unwrap(p_nz);

assert(qx == 10, 'bad finalize x');
qx
}
}
14 changes: 14 additions & 0 deletions tests/cases/cairo_vm/contracts/get_segment_arena_index.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[starknet::contract]
mod SegmentArenaIndex {
#[storage]
struct Storage {}

use dict::Felt252DictTrait;

#[external(v0)]
fn test_arena_index(self: @ContractState) -> bool {
let mut dict: Felt252Dict<felt252> = Default::default();
dict.squash();
return true;
}
}
20 changes: 20 additions & 0 deletions tests/cases/cairo_vm/contracts/init_squash_data.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[starknet::contract]
mod TestDict {
#[storage]
struct Storage {}

use dict::Felt252DictTrait;
use nullable::NullableTrait;
use traits::Index;

#[external(v0)]
fn test_dict_init(self: @ContractState, test_value: felt252) -> felt252 {
let mut dict: Felt252Dict<felt252> = Default::default();

dict.insert(10, test_value);
let (_entry, value) = dict.entry(10);
assert(value == test_value, 'dict[10] == test_value');

return test_value;
}
}
12 changes: 12 additions & 0 deletions tests/cases/cairo_vm/contracts/linear_split.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#[starknet::contract]
mod LinearSplit {
#[storage]
struct Storage {}

use integer::u16_try_from_felt252;

#[external(v0)]
fn cast(self: @ContractState, a: felt252) -> Option<u16> {
u16_try_from_felt252(a)
}
}
28 changes: 28 additions & 0 deletions tests/cases/cairo_vm/contracts/random_ec_point.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#[starknet::contract]
mod RandomEcPoint{
#[storage]
struct Storage {}

use option::OptionTrait;
use ec::ec_state_init;
use ec::ec_state_add;
use ec::ec_state_try_finalize_nz;
use ec::ec_point_from_x_nz;
use ec::ec_point_unwrap;

// Test taken from https://github.com/starkware-libs/cairo/blob/a0ead7c0b8e297d281c7213151cd43ac11de5042/corelib/src/test/ec_test.cairo#L17
#[external(v0)]
fn random_ec_point(self: @ContractState) -> felt252{
let p_nz = ec_point_from_x_nz(1).unwrap();

let mut state = ec_state_init();
ec_state_add(ref state, p_nz);

let q = ec_state_try_finalize_nz(state).expect('zero point');
let (qx, _qy) = ec_point_unwrap(q);

assert(qx == 1, 'bad finalize x');
qx
}

}
13 changes: 13 additions & 0 deletions tests/cases/cairo_vm/contracts/should_skip_squash_loop.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[starknet::contract]
mod ShouldSkipSquashLoop {
#[storage]
struct Storage {}

use dict::Felt252DictTrait;

#[external(v0)]
fn should_skip_squash_loop(self: @ContractState) {
let x = felt252_dict_new::<felt252>();
x.squash();
}
}
20 changes: 20 additions & 0 deletions tests/cases/cairo_vm/contracts/test_less_than.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[starknet::contract]
mod TestLessThan {
#[storage]
struct Storage {}

use integer::upcast;
use integer::downcast;
use option::OptionTrait;

// tests whether the input (u128) can be downcast to an u8
#[external(v0)]
fn test_less_than_with_downcast(self: @ContractState, number: u128) -> bool {
let downcast_test: Option<u8> = downcast(number);

match downcast_test {
Option::Some(_) => { return true; },
Option::None(_) => { return false; }
}
}
}
19 changes: 19 additions & 0 deletions tests/cases/cairo_vm/contracts/u128_sqrt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[starknet::contract]
mod U128Sqrt {
#[storage]
struct Storage {}

use integer::u128_sqrt;
use core::traits::Into;
use traits::TryInto;
use option::OptionTrait;


#[external(v0)]
fn sqrt(self: @ContractState, num: felt252) -> felt252 {
let num_in_u128: u128 = num.try_into().unwrap();
let a: u64 = u128_sqrt(num_in_u128);
let to_return: felt252 = a.into();
to_return
}
}
19 changes: 19 additions & 0 deletions tests/cases/cairo_vm/contracts/u16_sqrt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#[starknet::contract]
mod U16Sqrt {
#[storage]
struct Storage {}

use integer::u16_sqrt;
use core::traits::Into;
use traits::TryInto;
use option::OptionTrait;


#[external(v0)]
fn sqrt(self: @ContractState, num: felt252) -> felt252 {
let num_in_u16: u16 = num.try_into().unwrap();
let a: u8 = u16_sqrt(num_in_u16);
let to_return: felt252 = a.into();
to_return
}
}
Loading

0 comments on commit 936d258

Please sign in to comment.