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

Cairo 2.1.1 #138

Merged
merged 12 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
Corelib v2.1.1
  • Loading branch information
shramee committed Aug 20, 2023
commit 6133ab20bfe0e7ea152b5f671f9d60dbadd71856
2 changes: 1 addition & 1 deletion corelib/Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "core"
version = "2.1.0"
version = "2.1.1"

# NOTE: This is non-public, unstable Scarb's field, which instructs resolver that this package does not
# depend on `core`, which is only true for this particular package. Nobody else should use it.
Expand Down
2 changes: 1 addition & 1 deletion corelib/src/array.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl ArraySerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Array<T>
}
fn deserialize(ref serialized: Span<felt252>) -> Option<Array<T>> {
let length = *serialized.pop_front()?;
let mut arr = Default::default();
let mut arr = array![];
deserialize_array_helper(ref serialized, arr, length)
}
}
Expand Down
71 changes: 62 additions & 9 deletions corelib/src/byte_array.cairo
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use traits::{Into, TryInto};
use bytes_31::{U128IntoBytes31, U8IntoBytes31};
use array::{ArrayTrait, SpanTrait};
use option::OptionTrait;
use clone::Clone;
use integer::{u128_safe_divmod, U32TryIntoNonZero};
use bytes_31::{
BYTES_IN_BYTES31, Bytes31Trait, one_shift_left_bytes_felt252, one_shift_left_bytes_u128,
POW_2_128
POW_2_128, POW_2_8, U128IntoBytes31, U8IntoBytes31
};
use clone::Clone;
use cmp::min;
use integer::{u128_safe_divmod, U32TryIntoNonZero};
use option::OptionTrait;
use traits::{Into, TryInto};
use zeroable::NonZeroIntoImpl;

const BYTES_IN_U128: usize = 16;
// TODO(yuval): change to `BYTES_IN_BYTES31 - 1` once consteval_int supports non-literals.
const BYTES_IN_BYTES31_MINUS_ONE: usize = consteval_int!(31 - 1);
const POW_2_8: felt252 = 256;

// TODO(yuval): don't allow creation of invalid ByteArray?
#[derive(Drop, Clone)]
#[derive(Drop, Clone, PartialEq)]
struct ByteArray {
// Full "words" of 31 bytes each. The first byte of each word in the byte array
// is the most significant byte in the word.
Expand Down Expand Up @@ -167,7 +166,7 @@ impl ByteArrayImpl of ByteArrayTrait {
return;
}

let new_pending = self.pending_word * POW_2_8 + byte.into();
let new_pending = self.pending_word * POW_2_8.into() + byte.into();

if self.pending_word_len != BYTES_IN_BYTES31_MINUS_ONE {
self.pending_word = new_pending;
Expand Down Expand Up @@ -212,6 +211,60 @@ impl ByteArrayImpl of ByteArrayTrait {
Option::Some(self.data.at(word_index).at(index_from_lsb))
}

/// Returns a ByteArray with the reverse order of `self`.
fn rev(self: @ByteArray) -> ByteArray {
let mut result = Default::default();

result.append_word_rev(*self.pending_word, *self.pending_word_len);

let mut data = self.data.span();
loop {
match data.pop_back() {
Option::Some(current_word) => {
result.append_word_rev((*current_word).into(), BYTES_IN_BYTES31);
},
Option::None => {
break;
}
};
};
result
}

/// Appends the reverse of the given word to the end `self`.
/// Assumptions:
/// 1. len < 31
/// 2. word is validly convertible to bytes31 of length `len`.
fn append_word_rev(ref self: ByteArray, word: felt252, len: usize) {
let mut index = 0;

let u256{low, high } = word.into();
let low_part_limit = min(len, BYTES_IN_U128);
loop {
if index == low_part_limit {
break;
}
let curr_byte_as_u128 = (low / one_shift_left_bytes_u128(index)) % POW_2_8;

self.append_byte(curr_byte_as_u128.try_into().unwrap());
index += 1;
};
if low_part_limit == BYTES_IN_U128 {
let mut index_in_high_part = 0;
let high_part_len = len - BYTES_IN_U128;
loop {
if index_in_high_part == high_part_len {
break;
}
let curr_byte_as_u128 = (high
/ one_shift_left_bytes_u128(index_in_high_part)) % POW_2_8;

self.append_byte(curr_byte_as_u128.try_into().unwrap());
index_in_high_part += 1;
}
}
}

// === Helpers ===

// Appends a single word of `len` bytes to the end of the ByteArray, assuming there
Expand Down
2 changes: 1 addition & 1 deletion corelib/src/debug.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use option::Option;
//
// get_caller_address().print();
//
// let mut arr = Default::default();
// let mut arr = array![];
// arr.append('1234567890123456789012345678901');
// arr.append('Sca');
// arr.append('SomeVeryLongMessage');
Expand Down
15 changes: 7 additions & 8 deletions corelib/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use traits::{
TryInto, Index, IndexView, Destruct, Default, Felt252DictValue, PanicDestruct
};
use serde::Serde;
use array::SpanTrait;

type usize = u32;

#[derive(Copy, Drop)]
enum bool {
Expand Down Expand Up @@ -215,16 +216,14 @@ use box::{Box, BoxTrait};

// Nullable
mod nullable;
use nullable::{Nullable, match_nullable, null, nullable_from_box};
use nullable::{Nullable, NullableTrait, match_nullable, null, nullable_from_box};

// Arrays.
// Array.
mod array;
use array::{Array, ArrayTrait};
type usize = u32;

// Span.
use array::Span;

use array::{Span, SpanTrait};

// Dictionary.
mod dict;
Expand All @@ -234,11 +233,11 @@ use dict::{

// Result.
mod result;
use result::Result;
use result::{Result, ResultTrait};

// Option.
mod option;
use option::Option;
use option::{Option, OptionTrait};

// Clone.
mod clone;
Expand Down
4 changes: 4 additions & 0 deletions corelib/src/nullable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern fn match_nullable<T>(value: Nullable<T>) -> FromNullableResult<T> nopanic

trait NullableTrait<T> {
fn deref(self: Nullable<T>) -> T;
fn new(value: T) -> Nullable<T>;
}

impl NullableImpl<T> of NullableTrait<T> {
Expand All @@ -25,6 +26,9 @@ impl NullableImpl<T> of NullableTrait<T> {
FromNullableResult::NotNull(value) => value.unbox(),
}
}
fn new(value: T) -> Nullable<T> {
nullable_from_box(BoxTrait::new(value))
}
}

impl NullableDefault<T> of Default<Nullable<T>> {
Expand Down
5 changes: 1 addition & 4 deletions corelib/src/starknet/event.cairo
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
use serde::Serde;
use traits::Into;

trait Event<T> {
fn append_keys_and_data(self: @T, ref keys: Array<felt252>, ref data: Array<felt252>);
fn deserialize(ref keys: Span<felt252>, ref data: Span<felt252>) -> Option<T>;
}

trait EventEmitter<T, TEvent> {
fn emit<S, impl IntoImp: Into<S, TEvent>>(ref self: T, event: S);
fn emit<S, impl IntoImp: traits::Into<S, TEvent>>(ref self: T, event: S);
}
7 changes: 5 additions & 2 deletions corelib/src/starknet/secp256_trait.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ struct Signature {
}


/// Creates an ECDSA signature from the v, r and s values.
/// Creates an ECDSA signature from the `v`, `r` and `s` values.
/// `v` is the sum of an odd number and the parity of the y coordinate of the ec point whose x
/// coordinate is `r`.
/// See https://eips.ethereum.org/EIPS/eip-155 for more details.
fn signature_from_vrs(v: u32, r: u256, s: u256) -> Signature {
Signature { r, s, y_parity: v % 2 == 1, }
Signature { r, s, y_parity: v % 2 == 0 }
}

trait Secp256Trait<Secp256Point> {
Expand Down
4 changes: 0 additions & 4 deletions corelib/src/test/array_test.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
use array::{ArrayTrait, SpanTrait};
use box::BoxTrait;
use clone::Clone;
use option::OptionTrait;
use test::test_utils::{assert_eq, assert_ne};

#[test]
Expand Down
1 change: 0 additions & 1 deletion corelib/src/test/bool_test.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use test::test_utils::{assert_eq, assert_ne};
use traits::Into;

#[test]
fn test_bool_operators() {
Expand Down
1 change: 0 additions & 1 deletion corelib/src/test/box_test.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use box::BoxTrait;
use test::test_utils::{assert_eq, assert_ne};

#[test]
Expand Down
113 changes: 108 additions & 5 deletions corelib/src/test/byte_array_test.cairo
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use array::{ArrayTrait, SpanTrait};
use byte_array::ByteArrayTrait;
use bytes_31::Bytes31IntoFelt252;
use option::OptionTrait;
use traits::Into;
use test::test_utils::{assert_eq, assert_ne};

#[test]
#[available_gas(1000000)]
Expand Down Expand Up @@ -365,6 +361,113 @@ fn test_index_view_out_of_bounds() {
let x = ba[79];
}

#[test]
fn test_string_literals() {
let ba: ByteArray = "12345"; // len < 16
let ba: ByteArray = "1234567890123456"; // len == 16
let ba: ByteArray = "123456789012345678"; // 16 < len < 31
let ba: ByteArray = "1234567890123456789012345678901"; // len == 31
let ba: ByteArray = "123456789012345678901234567890123"; // 31 < len < 47
let ba: ByteArray = "12345678901234567890123456789012345678901234567"; // len == 47
let ba: ByteArray = "123456789012345678901234567890123456789012345678"; // len > 47
}

#[test]
#[available_gas(100000000)]
fn test_equality() {
let byte_array: ByteArray = "a";
assert(@byte_array == @"a", 'Same strings are not equal');
assert(@byte_array != @"b", 'Different strings are equal');

let mut ba1 = test_byte_array_2();
ba1.append(@test_byte_array_31());
let ba2 = test_byte_array_33();
let ba3 = test_byte_array_32();
let mut ba4 = test_byte_array_32();
ba4.append(@test_byte_array_1());

assert(@ba1 == @ba1, 'Same ByteArrays are not equal');
assert(@ba2 == @ba2, 'Same ByteArrays are not equal');
assert(@ba3 == @ba3, 'Same ByteArrays are not equal');
assert(@ba4 == @ba4, 'Same ByteArrays are not equal');

// Different data
assert(@ba1 != @ba2, 'Different ByteArrays are equal');

// Different pending word length
assert(@ba2 != @ba3, 'Different ByteArrays are equal');

// Different pending word
assert(@ba2 != @ba4, 'Different ByteArrays are equal');
}

#[test]
#[available_gas(100000000)]
fn test_reverse() {
// Arrays of length < 16
let ba: ByteArray = "abc";
let ba_rev: ByteArray = "cba";
let palindrome: ByteArray = "rotator";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of length 16
let ba: ByteArray = "my length is 16.";
let ba_rev: ByteArray = ".61 si htgnel ym";
let palindrome: ByteArray = "nolemon nomelon";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of 16 < length < 31
let ba: ByteArray = "I am a medium byte array";
let ba_rev: ByteArray = "yarra etyb muidem a ma I";
let palindrome: ByteArray = "nolemon nomelon";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of length 31
let ba: ByteArray = "I didn't find a good palindrome";
let ba_rev: ByteArray = "emordnilap doog a dnif t'ndid I";
let palindrome: ByteArray = "kayak level rotator level kayak";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of 31 < length < 47 (31+16)
let ba: ByteArray = "This time I did find a good palindrome!";
let ba_rev: ByteArray = "!emordnilap doog a dnif did I emit sihT";
let palindrome: ByteArray = "noitneverpropagatesifisetagaporprevention";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of length 47 (31+16)
let ba: ByteArray = "I have found a palindrome, exactly 47 in length";
let ba_rev: ByteArray = "htgnel ni 74 yltcaxe ,emordnilap a dnuof evah I";
let palindrome: ByteArray = "onacloverifaliveeruptsavastpureevilafirevolcano";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');

// Arrays of length > 47 (31+16)
let ba: ByteArray = "This palindrome is not as good, but at least it's long enough";
let ba_rev: ByteArray = "hguone gnol s'ti tsael ta tub ,doog sa ton si emordnilap sihT";
let palindrome: ByteArray = "docnoteidissentafastneverpreventsafatnessidietoncod";
assert_ne(@ba, @ba.rev(), 'ba == ba.rev()');
assert_ne(@ba_rev, @ba_rev.rev(), 'ba_rev == ba_rev.rev()');
assert_eq(@ba, @ba_rev.rev(), 'ba != ba_rev.rev()');
assert_eq(@palindrome, @palindrome.rev(), 'palindrome is not a palindrome');
}

// ========= Test helper functions =========

use debug::PrintTrait;
Expand Down
4 changes: 1 addition & 3 deletions corelib/src/test/bytes31_test.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use option::OptionTrait;
use traits::{Into, TryInto};
use bytes_31::{Bytes31Trait, split_bytes31, U128IntoBytes31, U8IntoBytes31};
use bytes_31::split_bytes31;

const POW_2_248: felt252 = 0x100000000000000000000000000000000000000000000000000000000000000;

Expand Down
3 changes: 1 addition & 2 deletions corelib/src/test/cmp_test.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use cmp::min;
use cmp::max;
use cmp::{max, min};
use test::test_utils::{assert_eq, assert_ne};

// Integer tests
Expand Down
7 changes: 2 additions & 5 deletions corelib/src/test/dict_test.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use box::BoxTrait;
use dict::{Felt252DictTrait, Felt252DictEntryTrait};
use nullable::NullableTrait;
use traits::Index;
use dict::Felt252DictEntryTrait;
use test::test_utils::{assert_eq, assert_ne};

#[test]
Expand All @@ -17,7 +14,7 @@ fn test_dict_squash_empty() {

#[test]
fn test_dict_default_val() {
let mut dict = Default::default();
let mut dict: Felt252Dict = Default::default();
let default_val = dict.get(0);
assert_eq(@default_val, @0, 'default_val == 0');
}
Expand Down
1 change: 0 additions & 1 deletion corelib/src/test/felt_test.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use clone::Clone;
use test::test_utils::{assert_eq, assert_ne};

#[test]
Expand Down
Loading