Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Jan 7, 2025
1 parent 72c1e1c commit e29c345
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 32 deletions.
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"asyncify",
"auditability",
"authwit",
"authwits",
"authwitness",
"authwits",
"Automine",
"autonat",
"autorun",
Expand Down Expand Up @@ -228,6 +228,7 @@
"Reserialize",
"retag",
"rethrown",
"revertibles",
"rollup",
"rollups",
"rushstack",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl PrivateKernelData {
self.vk_index
};
let index_hint = unsafe {
//@safety The index is checked to be in the allowed list below.
find_index_hint(allowed_indices, |index: u32| index == index_in_allowed_list)
};
assert(index_hint < N, "Invalid vk index");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ pub fn debug_log<let N: u32>(msg: str<N>) {
/// debug_log_format("get_2(slot:{0}) =>\n\t0:{1}\n\t1:{2}", [storage_slot, note0_hash, note1_hash]);
/// debug_log_format("whole array: {}", [e1, e2, e3, e4]);
pub fn debug_log_format<let M: u32, let N: u32>(msg: str<M>, args: [Field; N]) {
// This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call.
unsafe { debug_log_oracle_wrapper(msg, args) };
unsafe {
//@safety This oracle call returns nothing: we only call it for its side effects. It is therefore always safe
// to call.
debug_log_oracle_wrapper(msg, args)
};
}

pub unconstrained fn debug_log_oracle_wrapper<let M: u32, let N: u32>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ impl VariableMerkleTree {
//
pub fn new_sha<let N: u32>(leaves: [Field; N], num_non_empty_leaves: u32) -> Self {
// Find size of tree required
let height = unsafe { get_height(num_non_empty_leaves, 0) };
let height = unsafe {
//@safety This is safe because we derive next and previous powers of 2 below based on the value
// and the powers are then checked against the num non empty leaves.
get_height(num_non_empty_leaves, 0)
};
let next_power_2 = 2 << height;
let prev_power_2 = next_power_2 / 2;
assert(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ impl<let VK_LENGTH: u32> VkData<VK_LENGTH> {
pub fn validate_in_vk_tree<let N: u32>(self, vk_tree_root: Field, allowed_indices: [u32; N]) {
self.vk.check_hash();

let index_hint =
unsafe { find_index_hint(allowed_indices, |index: u32| index == self.vk_index) };
let index_hint = unsafe {
//@safety The index is checked to be in the allowed list below.
find_index_hint(allowed_indices, |index: u32| index == self.vk_index)
};
assert(index_hint < N, "Invalid vk index");
assert_eq(allowed_indices[index_hint], self.vk_index, "Invalid vk index");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ where
BoundedVec::from_parts_unchecked(array, len)
}

// Helper function to find the index of the first element in an array that satisfies a given predicate.
pub unconstrained fn find_index_hint<T, let N: u32, Env>(
array: [T; N],
find: fn[Env](T) -> bool,
) -> u32 {
let mut index = N;
for i in 0..N {
// We check `index == N` to ensure that we only update the index if we haven't found a match yet.
if (index == N) & find(array[i]) {
index = i;
}
Expand Down Expand Up @@ -104,7 +106,11 @@ pub fn array_length<T, let N: u32>(array: [T; N]) -> u32
where
T: Empty + Eq,
{
let length = unsafe { find_index_hint(array, |elem: T| is_empty(elem)) };
// We get the length by checking the index of the first empty element.
let length = unsafe {
//@safety This is safe because we have validated the array and the element emptyness is checked below.
find_index_hint(array, |elem: T| is_empty(elem))
};
if length != 0 {
assert(!is_empty(array[length - 1]));
}
Expand Down Expand Up @@ -243,24 +249,30 @@ fn test_array_length_invalid_arrays() {
fn find_index_greater_than_min() {
let values = [10, 20, 30, 40];
let min = 22;
let index = unsafe { find_index_hint(values, |v: Field| min.lt(v)) };
let index = unsafe {
//@safety The result is checked in the assert_eq below.
find_index_hint(values, |v: Field| min.lt(v))
};
assert_eq(index, 2);
}

#[test]
fn find_index_not_found() {
let values = [10, 20, 30, 40];
let min = 100;
let index = unsafe { find_index_hint(values, |v: Field| min.lt(v)) };
let index = unsafe {
//@safety The result is checked in the assert_eq below.
find_index_hint(values, |v: Field| min.lt(v))
};
assert_eq(index, 4);
}

#[test]
fn test_array_concat() {
let array0 = [1, 2, 3];
let array1 = [4, 5];
let concated = array_concat(array0, array1);
assert_eq(concated, [1, 2, 3, 4, 5]);
let concatenated = array_concat(array0, array1);
assert_eq(concatenated, [1, 2, 3, 4, 5]);
}

#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ mod tests {
}

pub fn check_and_execute(self) {
let combined =
unsafe { combine_arrays(self.original_array_lt, self.original_array_gte) };
let combined = unsafe {
//@safety The value is checked against the combined array below.
combine_arrays(self.original_array_lt, self.original_array_gte)
};
assert_eq(combined, self.combined_array);

self.execute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ mod tests {

pub fn check_and_execute(self) {
let combined = unsafe {
//@safety The value is checked against the combined array below.
combine_and_transform_arrays(
self.original_array_lt,
self.original_array_gte,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,18 @@ mod tests {

impl<let N: u32> TestBuilder<N> {
pub fn asc_to_equal(self, expected: [OrderHint; N]) {
let hints = unsafe { get_order_hints_asc(self.array) };
let hints = unsafe {
//@safety The value is checked against expected below.
get_order_hints_asc(self.array)
};
assert_eq(hints, expected);
}

pub fn desc_to_equal(self, expected: [OrderHint; N]) {
let hints = unsafe { get_order_hints_desc(self.array) };
let hints = unsafe {
//@safety The value is checked against expected below.
get_order_hints_desc(self.array)
};
assert_eq(hints, expected);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,18 @@ mod tests {

impl<let N: u32> TestBuilder<N> {
pub fn asc_to_equal(self, expected: SplitOrderHints<N>) {
let hints = unsafe { get_split_order_hints_asc(self.array, self.split_counter) };
let hints = unsafe {
//@safety The value is checked against expected below.
get_split_order_hints_asc(self.array, self.split_counter)
};
assert_eq(hints, expected);
}

pub fn desc_to_equal(self, expected: SplitOrderHints<N>) {
let hints = unsafe { get_split_order_hints_desc(self.array, self.split_counter) };
let hints = unsafe {
//@safety The value is checked against expected below.
get_split_order_hints_desc(self.array, self.split_counter)
};
assert_eq(hints, expected);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ where
T: Ordered + Empty + Eq,
S: Empty + Eq,
{
let num_non_revertibles =
unsafe { find_index_hint(sorted_array, |n: T| n.counter() >= split_counter) };
let num_non_revertibles = unsafe {
//@safety The value is checked in the assert below.
find_index_hint(sorted_array, |n: T| n.counter() >= split_counter)
};

assert_split_transformed_value_arrays_with_hint(
sorted_array,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ pub unconstrained fn get_sorted_result<let N: u32, T>(
#[test]
fn get_sorted_hints_asc_non_padded() {
let values = [40, 60, 20, 50];
let res = unsafe { get_sorted_result(values, |a: u32, b: u32| a < b) };
let res = unsafe {
//@safety The result is checked in the assert_eq below.
get_sorted_result(values, |a: u32, b: u32| a < b)
};
assert_eq(res.sorted_array, [20, 40, 50, 60]);
assert_eq(res.sorted_index_hints, [1, 3, 0, 2]);
assert_eq(res.original_index_hints, [2, 0, 3, 1]);
Expand All @@ -35,16 +38,21 @@ fn get_sorted_hints_asc_non_padded() {
#[test]
fn get_sorted_hints_desc_non_padded() {
let values = [40, 20, 60, 50];
let res = unsafe { get_sorted_result(values, |a: u32, b: u32| b < a) };
let res = unsafe {
//@safety The result is checked in the assert_eq below.
get_sorted_result(values, |a: u32, b: u32| b < a)
};
assert_eq(res.sorted_array, [60, 50, 40, 20]);
assert_eq(res.sorted_index_hints, [2, 3, 0, 1]);
}

#[test]
fn get_sorted_hints_asc_padded() {
let values = [40, 60, 20, 50, 0, 0];
let res =
unsafe { get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (a < b))) };
let res = unsafe {
//@safety The result is checked in the assert_eq below.
get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (a < b)))
};
assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]);
assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 4, 5]);
assert_eq(res.original_index_hints, [2, 0, 3, 1, 4, 5]);
Expand All @@ -53,8 +61,10 @@ fn get_sorted_hints_asc_padded() {
#[test]
fn get_sorted_hints_desc_padded() {
let values = [40, 60, 20, 50, 0, 0];
let res =
unsafe { get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (b < a))) };
let res = unsafe {
//@safety The result is checked in the assert_eq below.
get_sorted_result(values, |a: u32, b: u32| (a != 0) & ((b == 0) | (b < a)))
};
assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]);
assert_eq(res.sorted_index_hints, [2, 0, 3, 1, 4, 5]);
assert_eq(res.original_index_hints, [1, 3, 0, 2, 4, 5]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ fn get_sorted_tuple_asc() {
SortedTuple { elem: 5, original_index: 3 },
SortedTuple { elem: 9, original_index: 2 },
];
let sorted = unsafe { get_sorted_tuple(original, |a: u64, b: u64| a < b) };
let sorted = unsafe {
//@safety The result is checked in the assert_eq below.
get_sorted_tuple(original, |a: u64, b: u64| a < b)
};
for i in 0..4 {
assert_eq(sorted[i].elem, expected[i].elem);
assert_eq(sorted[i].original_index, expected[i].original_index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ pub unconstrained fn sort_by<T, let N: u32, Env>(
ordering: fn[Env](T, T) -> bool,
) -> [T; N] {
let mut result = array;
let sorted_index = unsafe { get_sorting_index(array, ordering) };
let sorted_index = get_sorting_index(array, ordering);
// Ensure the indexes are correct
for i in 0..N {
let pos = unsafe { find_index_hint(sorted_index, |index: u32| index == i) };
let pos = find_index_hint(sorted_index, |index: u32| index == i);
assert(sorted_index[pos] == i);
}
// Sort the array using the indexes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ mod tests {

fn asc_values_to_equal<let N: u32>(values: [u32; N], expected: [u32; N]) {
let items = values.map(|value| TestValue { value: value as Field, counter: value });
let sorted = unsafe { sort_by_counter_asc(items).map(|item: TestValue| item.counter) };
let sorted = unsafe {
//@safety The result is checked in the assert_eq below.
sort_by_counter_asc(items).map(|item: TestValue| item.counter)
};
assert_eq(sorted, expected);
}

fn desc_values_to_equal<let N: u32>(values: [u32; N], expected: [u32; N]) {
let items = values.map(|value| TestValue { value: value as Field, counter: value });
let sorted = unsafe { sort_by_counter_desc(items).map(|item: TestValue| item.counter) };
let sorted = unsafe {
//@safety The result is checked in the assert_eq below.
sort_by_counter_desc(items).map(|item: TestValue| item.counter)
};
assert_eq(sorted, expected);
}

Expand Down Expand Up @@ -119,7 +125,10 @@ mod tests {
TestValue::empty(),
TestValue::empty(),
];
let sorted = unsafe { sort_by_counter_asc(original) };
let sorted = unsafe {
//@safety The result is checked in the assert_eq below.
sort_by_counter_asc(original)
};
assert_eq(sorted, expected);
}

Expand All @@ -143,7 +152,10 @@ mod tests {
TestValue::empty(),
TestValue::empty(),
];
let sorted = unsafe { sort_by_counter_desc(original) };
let sorted = unsafe {
//@safety The result is checked in the assert_eq below.
sort_by_counter_desc(original)
};
assert_eq(sorted, expected);
}
}

0 comments on commit e29c345

Please sign in to comment.