Skip to content

Commit

Permalink
update runtime to use proper felt abi
Browse files Browse the repository at this point in the history
  • Loading branch information
edg-l committed May 21, 2024
1 parent 75759f3 commit a02993e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 90 deletions.
175 changes: 97 additions & 78 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use lazy_static::lazy_static;
use starknet_crypto::FieldElement;
use starknet_curve::AffinePoint;
use starknet_types_core::felt::Felt;
use std::{collections::HashMap, fs::File, io::Write, os::fd::FromRawFd, ptr::NonNull, slice};
use std::{collections::HashMap, fs::File, io::Write, os::fd::FromRawFd, ptr::NonNull};

lazy_static! {
pub static ref HALF_PRIME: FieldElement = FieldElement::from_dec_str(
Expand All @@ -18,6 +18,10 @@ lazy_static! {
(DICT_SQUASH_UNIQUE_KEY_COST.cost() - DICT_SQUASH_REPEATED_ACCESS_COST.cost()) as u64;
}

#[derive(Debug, Clone, Hash, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C, align(16))]
pub struct Felt252Abi(pub [u8; 32]);

/// Based on `cairo-lang-runner`'s implementation.
///
/// Source: <https://github.com/starkware-libs/cairo/blob/main/crates/cairo-lang-runner/src/casm_run/mod.rs#L1946-L1948>
Expand All @@ -29,13 +33,14 @@ lazy_static! {
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__debug__print(
target_fd: i32,
data: *const [u8; 32],
data: *const Felt252Abi,
len: u32,
) -> i32 {
let mut target = File::from_raw_fd(target_fd);

for i in 0..len as usize {
let data = *data.add(i);
let data = data.add(i);
let data = (*data).0;

let value = Felt::from_bytes_le(&data);
if write!(target, "[DEBUG]\t{value:x}",).is_err() {
Expand Down Expand Up @@ -92,14 +97,14 @@ pub unsafe extern "C" fn cairo_native__libfunc__debug__print(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__pedersen(
dst: *mut u8,
lhs: *const u8,
rhs: *const u8,
dst: *mut Felt252Abi,
lhs: *const Felt252Abi,
rhs: *const Felt252Abi,
) {
// Extract arrays from the pointers.
let dst = slice::from_raw_parts_mut(dst, 32);
let lhs = slice::from_raw_parts(lhs, 32);
let rhs = slice::from_raw_parts(rhs, 32);
let dst = &mut (*dst).0;
let lhs = &(*lhs).0;
let rhs = &(*rhs).0;

// Convert to FieldElement.
let lhs = FieldElement::from_byte_slice_be(lhs).unwrap();
Expand All @@ -124,14 +129,14 @@ pub unsafe extern "C" fn cairo_native__libfunc__pedersen(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__hades_permutation(
op0: *mut u8,
op1: *mut u8,
op2: *mut u8,
op0: *mut Felt252Abi,
op1: *mut Felt252Abi,
op2: *mut Felt252Abi,
) {
// Extract arrays from the pointers.
let op0 = slice::from_raw_parts_mut(op0, 32);
let op1 = slice::from_raw_parts_mut(op1, 32);
let op2 = slice::from_raw_parts_mut(op2, 32);
let op0 = &mut (*op0).0;
let op1 = &mut (*op1).0;
let op2 = &mut (*op2).0;

// Convert to FieldElement.
let mut state = [
Expand All @@ -157,7 +162,7 @@ pub unsafe extern "C" fn cairo_native__libfunc__hades_permutation(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__alloc_dict() -> *mut std::ffi::c_void {
Box::into_raw(Box::<(HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64)>::default()) as _
Box::into_raw(Box::<(HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64)>::default()) as _
}

/// Frees the dictionary.
Expand All @@ -168,7 +173,7 @@ pub unsafe extern "C" fn cairo_native__alloc_dict() -> *mut std::ffi::c_void {
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__dict_free(
ptr: *mut (HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64),
ptr: *mut (HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64),
) {
let mut map = Box::from_raw(ptr);

Expand All @@ -187,10 +192,10 @@ pub unsafe extern "C" fn cairo_native__dict_free(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__dict_get(
ptr: *mut (HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64),
key: &[u8; 32],
ptr: *mut (HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64),
key: &Felt252Abi,
) -> *mut std::ffi::c_void {
let dict: &mut (HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64) = &mut *ptr;
let dict: &mut (HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64) = &mut *ptr;
let map = &dict.0;
dict.1 += 1;

Expand All @@ -209,8 +214,8 @@ pub unsafe extern "C" fn cairo_native__dict_get(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__dict_insert(
ptr: *mut (HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64),
key: &[u8; 32],
ptr: *mut (HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64),
key: &Felt252Abi,
value: NonNull<std::ffi::c_void>,
) -> *mut std::ffi::c_void {
let dict = &mut *ptr;
Expand All @@ -231,7 +236,7 @@ pub unsafe extern "C" fn cairo_native__dict_insert(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__dict_gas_refund(
ptr: *const (HashMap<[u8; 32], NonNull<std::ffi::c_void>>, u64),
ptr: *const (HashMap<Felt252Abi, NonNull<std::ffi::c_void>>, u64),
) -> u64 {
let dict = &*ptr;
(dict.1 - dict.0.len() as u64) * *DICT_GAS_REFUND_PER_ACCESS
Expand All @@ -249,12 +254,12 @@ pub unsafe extern "C" fn cairo_native__dict_gas_refund(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_point_from_x_nz(
mut point_ptr: NonNull<[[u8; 32]; 2]>,
mut point_ptr: NonNull<[Felt252Abi; 2]>,
) -> bool {
let x = FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap();

Expand All @@ -264,8 +269,10 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_point_from_x_nz(
if point.y >= *HALF_PRIME {
point.y = -point.y
}
point_ptr.as_mut()[1].copy_from_slice(&point.y.to_bytes_be());
point_ptr.as_mut()[1].reverse();
point_ptr.as_mut()[1]
.0
.copy_from_slice(&point.y.to_bytes_be());
point_ptr.as_mut()[1].0.reverse();

true
}
Expand All @@ -285,18 +292,18 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_point_from_x_nz(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_point_try_new_nz(
point_ptr: NonNull<[[u8; 32]; 2]>,
point_ptr: NonNull<[Felt252Abi; 2]>,
) -> bool {
let x = FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap();
let y = FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap();

Expand All @@ -315,47 +322,51 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_point_try_new_nz(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_add(
mut state_ptr: NonNull<[[u8; 32]; 4]>,
point_ptr: NonNull<[[u8; 32]; 2]>,
mut state_ptr: NonNull<[Felt252Abi; 4]>,
point_ptr: NonNull<[Felt252Abi; 2]>,
) {
let mut state = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
};
let point = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
};

state += &point;

state_ptr.as_mut()[0].copy_from_slice(&state.x.to_bytes_be());
state_ptr.as_mut()[1].copy_from_slice(&state.y.to_bytes_be());
state_ptr.as_mut()[0]
.0
.copy_from_slice(&state.x.to_bytes_be());
state_ptr.as_mut()[1]
.0
.copy_from_slice(&state.y.to_bytes_be());

state_ptr.as_mut()[0].reverse();
state_ptr.as_mut()[1].reverse();
state_ptr.as_mut()[0].0.reverse();
state_ptr.as_mut()[1].0.reverse();
}

/// Compute `ec_state_add_mul(state, scalar, point)` and store the state back.
Expand All @@ -370,54 +381,58 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_add(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_add_mul(
mut state_ptr: NonNull<[[u8; 32]; 4]>,
scalar_ptr: NonNull<[u8; 32]>,
point_ptr: NonNull<[[u8; 32]; 2]>,
mut state_ptr: NonNull<[Felt252Abi; 4]>,
scalar_ptr: NonNull<Felt252Abi>,
point_ptr: NonNull<[Felt252Abi; 2]>,
) {
let mut state = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
};
let scalar = FieldElement::from_bytes_be(&{
let mut data = *scalar_ptr.as_ref();
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap();
let point = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = point_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
};

state += &(&point * &scalar.to_bits_le());

state_ptr.as_mut()[0].copy_from_slice(&state.x.to_bytes_be());
state_ptr.as_mut()[1].copy_from_slice(&state.y.to_bytes_be());
state_ptr.as_mut()[0]
.0
.copy_from_slice(&state.x.to_bytes_be());
state_ptr.as_mut()[1]
.0
.copy_from_slice(&state.y.to_bytes_be());

state_ptr.as_mut()[0].reverse();
state_ptr.as_mut()[1].reverse();
state_ptr.as_mut()[0].0.reverse();
state_ptr.as_mut()[1].0.reverse();
}

/// Compute `ec_state_try_finalize_nz(state)` and store the result.
Expand All @@ -432,35 +447,35 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_add_mul(
/// definitely unsafe to use manually.
#[no_mangle]
pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_try_finalize_nz(
mut point_ptr: NonNull<[[u8; 32]; 2]>,
state_ptr: NonNull<[[u8; 32]; 4]>,
mut point_ptr: NonNull<[Felt252Abi; 2]>,
state_ptr: NonNull<[Felt252Abi; 4]>,
) -> bool {
let state = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[0];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[1];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
};
let random = AffinePoint {
x: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[2];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
y: FieldElement::from_bytes_be(&{
let mut data = state_ptr.as_ref()[3];
data.reverse();
data
data.0.reverse();
data.0
})
.unwrap(),
infinity: false,
Expand All @@ -471,11 +486,15 @@ pub unsafe extern "C" fn cairo_native__libfunc__ec__ec_state_try_finalize_nz(
} else {
let point = &state - &random;

point_ptr.as_mut()[0].copy_from_slice(&point.x.to_bytes_be());
point_ptr.as_mut()[1].copy_from_slice(&point.y.to_bytes_be());
point_ptr.as_mut()[0]
.0
.copy_from_slice(&point.x.to_bytes_be());
point_ptr.as_mut()[1]
.0
.copy_from_slice(&point.y.to_bytes_be());

point_ptr.as_mut()[0].reverse();
point_ptr.as_mut()[1].reverse();
point_ptr.as_mut()[0].0.reverse();
point_ptr.as_mut()[1].0.reverse();

true
}
Expand Down
Loading

0 comments on commit a02993e

Please sign in to comment.