diff --git a/src/air/public_input.cairo b/src/air/public_input.cairo index 8f73c2414..5b9834d13 100644 --- a/src/air/public_input.cairo +++ b/src/air/public_input.cairo @@ -47,7 +47,7 @@ impl PublicInputImpl of PublicInputTrait { i += 1; }; - let mut hash_data = ArrayTrait::::new(); + let mut hash_data = ArrayTrait::::new(); ArrayAppendTrait::<_, u256>::append_big_endian(ref hash_data, (*self.log_n_steps).into()); ArrayAppendTrait::<_, u256>::append_big_endian(ref hash_data, (*self.rc_min).into()); ArrayAppendTrait::<_, u256>::append_big_endian(ref hash_data, (*self.rc_max).into()); @@ -85,10 +85,10 @@ impl PublicInputImpl of PublicInputTrait { ArrayAppendTrait::<_, u256>::append_big_endian(ref hash_data, (*self.padding_addr).into()); ArrayAppendTrait::<_, u256>::append_big_endian(ref hash_data, (*self.padding_value).into()); - hash_data.append(1 + self.continuous_page_headers.len()); + hash_data.append_big_endian(1 + self.continuous_page_headers.len()); // Main page. - hash_data.append(self.main_page.len()); + hash_data.append_big_endian(self.main_page.len()); ArrayAppendTrait::< _, u256 >::append_big_endian(ref hash_data, main_page_hash_state.finalize().into()); diff --git a/src/channel/channel.cairo b/src/channel/channel.cairo index 187cec869..138938343 100644 --- a/src/channel/channel.cairo +++ b/src/channel/channel.cairo @@ -21,7 +21,7 @@ impl ChannelImpl of ChannelTrait { } fn random_uint256_to_prover(ref self: Channel) -> u256 { - let mut hash_data = ArrayTrait::::new(); + let mut hash_data = ArrayTrait::::new(); hash_data.append_big_endian(self.digest); hash_data.append_big_endian(self.counter); self.counter += 1; @@ -60,7 +60,7 @@ impl ChannelImpl of ChannelTrait { } fn read_felt_from_prover(ref self: Channel, value: felt252) { - let mut hash_data = ArrayTrait::::new(); + let mut hash_data = ArrayTrait::::new(); assert(self.digest.low != BoundedU128::max(), 'digest low is 2^128-1'); hash_data.append_big_endian(self.digest + 1); @@ -76,7 +76,7 @@ impl ChannelImpl of ChannelTrait { } fn read_felt_vector_from_prover(ref self: Channel, values: Span) { - let mut hash_data = ArrayTrait::::new(); + let mut hash_data = ArrayTrait::::new(); assert(self.digest.low != BoundedU128::max(), 'digest low is 2^128-1'); hash_data.append_big_endian(self.digest + 1); @@ -95,15 +95,14 @@ impl ChannelImpl of ChannelTrait { } fn read_uint64_from_prover(ref self: Channel, value: u64) { - let mut hash_data = ArrayTrait::::new(); + let mut hash_data = ArrayTrait::::new(); assert(self.digest.low != BoundedU128::max(), 'digest low is 2^128-1'); hash_data.append_big_endian(self.digest + 1); let low: u32 = (value % 0x100000000).try_into().unwrap(); let high: u32 = (value / 0x100000000).try_into().unwrap(); - hash_data.append(high.flip_endianness()); - hash_data.append(low.flip_endianness()); + hash_data.append_big_endian(value); self.digest = blake2s(hash_data).flip_endianness(); self.counter = 0; diff --git a/src/common/array_append.cairo b/src/common/array_append.cairo index 8ecba931a..9d99561b7 100644 --- a/src/common/array_append.cairo +++ b/src/common/array_append.cairo @@ -45,6 +45,18 @@ impl ArrayU32AppendFelt of ArrayAppendTrait { } } +// input's MSB is padded with 0s +// (internally felt252 is converted to u256) +impl ArrayU8AppendFelt of ArrayAppendTrait { + fn append_little_endian(ref self: Array, element: felt252) { + self.append_little_endian(Into::::into(element)); + } + + fn append_big_endian(ref self: Array, element: felt252) { + self.append_big_endian(Into::::into(element)); + } +} + impl ArrayU32AppendU128 of ArrayAppendTrait { fn append_little_endian(ref self: Array, mut element: u128) { let mut i = 4; @@ -103,4 +115,106 @@ impl ArrayU32AppendU64 of ArrayAppendTrait { } } } -} \ No newline at end of file +} + +impl ArrayU8AppendU256 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, element: u256) { + self.append_little_endian(element.low); + self.append_little_endian(element.high); + } + + fn append_big_endian(ref self: Array, element: u256) { + self.append_big_endian(element.high); + self.append_big_endian(element.low); + } +} + +impl ArrayU8AppendU128 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u128) { + let mut i = 16; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U128maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u128) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} + +impl ArrayU8AppendU64 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u64) { + let mut i = 8; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U64maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u64) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} + +impl ArrayU8AppendU32 of ArrayAppendTrait { + fn append_little_endian(ref self: Array, mut element: u32) { + let mut i = 4; + loop { + if i != 0 { + i -= 1; + let (q, r) = DivRem::div_rem(element, U32maxU8.try_into().unwrap()); + self.append(r.try_into().unwrap()); + element = q; + } else { + break; + } + } + } + + fn append_big_endian(ref self: Array, mut element: u32) { + let mut array = ArrayTrait::::new(); + array.append_little_endian(element); + let mut i = array.len(); + loop { + if i != 0 { + i -= 1; + self.append(*array.at(i)); + } else { + break; + } + } + } +} diff --git a/src/common/blake2s.cairo b/src/common/blake2s.cairo index a0a78fc8f..d7d137560 100644 --- a/src/common/blake2s.cairo +++ b/src/common/blake2s.cairo @@ -3,7 +3,7 @@ use cairo_verifier::common::array_append::ArrayAppendTrait; use cairo_verifier::common::flip_endianness::FlipEndiannessTrait; -fn blake2s(data: Array) -> u256 { +fn blake2s(data: Array) -> u256 { let mut state = blake2s_init(); state = blake2s_update(state, data); blake2s_final(state) @@ -13,7 +13,7 @@ fn blake2s(data: Array) -> u256 { // hash: // blake2s(x, y) & ~((1<<96) - 1). fn truncated_blake2s(x: felt252, y: felt252) -> felt252 { - let mut data = ArrayTrait::::new(); + let mut data = ArrayTrait::::new(); data.append_big_endian(x); data.append_big_endian(y); @@ -78,7 +78,7 @@ struct blake2s_state { t0: u32, t1: u32, f0: u32, - buf: Array, // length: 16 (64 bytes) + buf: Array, // length: 64 buflen: u32, } @@ -96,7 +96,7 @@ fn blake2s_init() -> blake2s_state { let mut buf = ArrayTrait::new(); let mut i = 0; loop { - if i == 16 { + if i == 64 { break; } buf.append(0); @@ -106,8 +106,19 @@ fn blake2s_init() -> blake2s_state { blake2s_state { h: blake2s_IV, t0: 0, t1: 0, f0: 0, buf: buf, buflen: 0 } } -fn blake2s_compress(mut s: blake2s_state, m: Array) -> blake2s_state { - assert(m.len() == 16, 'in array must have length 16'); +fn blake2s_compress(mut s: blake2s_state, in: Array) -> blake2s_state { + assert(in.len() == 64, 'in array must have length 64'); + + let mut m: Array = ArrayTrait::new(); + + let mut i: u32 = 0; + loop { + if i == 16 { + break; + } + m.append(load32(*in[4 * i + 0], *in[4 * i + 1], *in[4 * i + 2], *in[4 * i + 3])); + i += 1; + }; let mut v0: u32 = *s.h[0]; let mut v1: u32 = *s.h[1]; @@ -277,13 +288,13 @@ fn blake2s_compress(mut s: blake2s_state, m: Array) -> blake2s_state { s } -fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { +fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { let mut in_len = in.len(); let mut in_shift = 0; let in_span = in.span(); if in_len != 0 { let left = s.buflen; - let fill = 16 - left; + let fill = 64 - left; if in_len > fill { s.buflen = 0; @@ -319,7 +330,7 @@ fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { in_len -= fill; loop { - if in_len <= 16 { + if in_len <= 64_u32 { break; } @@ -332,7 +343,7 @@ fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { let mut compress_in = ArrayTrait::new(); i = 0; loop { - if i == 16 { + if i == 64_u32 { break; } compress_in.append(*in_span[in_shift + i]); @@ -341,8 +352,8 @@ fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { s = blake2s_compress(s, compress_in); - in_shift += 16; - in_len -= 16; + in_shift += 64_u32; + in_len -= 64_u32; }; } @@ -365,7 +376,7 @@ fn blake2s_update(mut s: blake2s_state, in: Array) -> blake2s_state { i += 1; }; loop { - if new_buf.len() == 16 { + if new_buf.len() == 64_u32 { break; } new_buf.append(0); @@ -381,7 +392,7 @@ fn blake2s_final(mut s: blake2s_state) -> u256 { assert(s.f0 == 0, 'blake2s_is_lastblock'); // blake2s_increment_counter - s.t0 = u32_wrapping_add(s.t0, s.buflen * 4); + s.t0 = u32_wrapping_add(s.t0, s.buflen); if s.t0 < s.buflen { s.t1 = u32_wrapping_add(s.t1, 1); } @@ -399,7 +410,7 @@ fn blake2s_final(mut s: blake2s_state) -> u256 { i += 1; }; loop { - if i == 16 { + if i == 64 { break; } buf.append(0); diff --git a/src/common/tests/test_blake2s.cairo b/src/common/tests/test_blake2s.cairo index cc3df43dc..3bc0e9ee3 100644 --- a/src/common/tests/test_blake2s.cairo +++ b/src/common/tests/test_blake2s.cairo @@ -1,6 +1,6 @@ use cairo_verifier::common::blake2s::{blake2s, truncated_blake2s, load32}; -fn get_arr_v1(n: u32) -> Array { +fn get_arr_v1(n: u32) -> Array { let mut arr = ArrayTrait::new(); let mut i: u32 = 1; loop { @@ -13,7 +13,10 @@ fn get_arr_v1(n: u32) -> Array { let mut out = ArrayTrait::new(); i = 0; loop { - out.append(load32(*arr[4 * i], *arr[4 * i + 1], *arr[4 * i + 2], *arr[4 * i + 3])); + out.append(*arr[4 * i]); + out.append(*arr[4 * i + 1]); + out.append(*arr[4 * i + 2]); + out.append(*arr[4 * i + 3]); i += 1; if i == n { break; @@ -22,7 +25,7 @@ fn get_arr_v1(n: u32) -> Array { out } -fn get_arr_v2(n: u32) -> Array { +fn get_arr_v2(n: u32) -> Array { let mut arr = ArrayTrait::new(); let mut s: u32 = 1; let mut i: u32 = 1; @@ -39,7 +42,10 @@ fn get_arr_v2(n: u32) -> Array { let mut out = ArrayTrait::new(); i = 0; loop { - out.append(load32(*arr[4 * i], *arr[4 * i + 1], *arr[4 * i + 2], *arr[4 * i + 3])); + out.append(*arr[4 * i]); + out.append(*arr[4 * i + 1]); + out.append(*arr[4 * i + 2]); + out.append(*arr[4 * i + 3]); i += 1; if i == n { break; diff --git a/src/common/tests/test_blake2s_big.cairo b/src/common/tests/test_blake2s_big.cairo index 95bcc59e2..091884f72 100644 --- a/src/common/tests/test_blake2s_big.cairo +++ b/src/common/tests/test_blake2s_big.cairo @@ -83,41 +83,3 @@ fn test_blake2s_v2_big() { 'invalid hash (272)' ); } - -#[test] -#[available_gas(9999999999)] -fn test_blake2s_big() { - let mut sum: u256 = 0; - let mut arr = ArrayTrait::new(); - let mut i: u32 = 0; - loop { - arr.append(i); - i += 1; - if i == 512 { - break; - }; - }; - loop { - let mut new_arr: Array = ArrayTrait::new(); - let arr_span = arr.span(); - let mut j = 0; - loop { - new_arr.append(*arr_span[j]); - j += 1; - if j == arr_span.len() { - break; - }; - }; - let res = blake2s(new_arr); - sum = sum ^ res; - let to_append: u32 = (res % 0x100000000).try_into().unwrap(); - arr.append(to_append); - i += 1; - if i == 529 { - break; - }; - }; - assert( - sum == 0x75dab924b6592ce2d9e0173c0d69ed45b4d8125da10a9db234fbdac721477df5, 'invalid hash' - ); -} diff --git a/src/proof_of_work/proof_of_work.cairo b/src/proof_of_work/proof_of_work.cairo index 3bda3a0a2..d0bf663aa 100644 --- a/src/proof_of_work/proof_of_work.cairo +++ b/src/proof_of_work/proof_of_work.cairo @@ -36,40 +36,49 @@ fn verify_proof_of_work(digest: u256, n_bits: u8, nonce: u64) { // + digest / POW_2_12 * POW_2_4 + n_bits.into() * POW_2_3; let mut init_hash_data = ArrayTrait::::new(); - init_hash_data.append_big_endian(u256{low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C}); - init_hash_data.append_big_endian(u256{low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000}); - let span = init_hash_data.span().slice(0,41); + init_hash_data + .append_big_endian( + u256 { + low: 0xD7CA1D48A19D8FF802A71D94169DE383, high: 0x0123456789ABCDED1C5A5F4381DF1F5C + } + ); + init_hash_data + .append_big_endian( + u256 { + low: 0x00000000000000000000000000000000, high: 0x82621FDC5514A10A1400000000000000 + } + ); + let span = init_hash_data.span().slice(0, 41); let mut arr = ArrayTrait::::new(); - let mut i:u32 = 0; + let mut i: u32 = 0; loop { if i == span.len() { break; } arr.append(*span.at(i)); - i+=1; + i += 1; }; let init_hash = blake2s(arr).flip_endianness(); init_hash.print(); +// correct hash on test data: +// 0x6ae49da749fbe3fc98f114c0f8342a4d +// 0x26438c9c119a3b222f70d564d5df2ebc - // correct hash on test data: - // 0x6ae49da749fbe3fc98f114c0f8342a4d - // 0x26438c9c119a3b222f70d564d5df2ebc +// // Compute Hash(init_hash || nonce ) +// // 32 bytes || 8 bytes +// // Total of 0x28 = 40 bytes. - // // Compute Hash(init_hash || nonce ) - // // 32 bytes || 8 bytes - // // Total of 0x28 = 40 bytes. +// // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 +// let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; - // // init_hash >> 12 -> init_hash << 8 + 4 -> nonce << 4 - // let hash_value: u256 = init_hash / POW_2_12 * POW_2_12 + nonce.into() * POW_2_4; +// let mut hash_data = ArrayTrait::::new(); +// hash_data.append_big_endian(hash_value); +// let hash = blake2s(hash_data); +// let work_limit = pow(2, 128 - n_bits.into()); - // let mut hash_data = ArrayTrait::::new(); - // hash_data.append_big_endian(hash_value); - // let hash = blake2s(hash_data); - // let work_limit = pow(2, 128 - n_bits.into()); - - // assert( - // Into::::into(hash.high) < Into::::into(work_limit), - // 'proof of work failed' - // ) +// assert( +// Into::::into(hash.high) < Into::::into(work_limit), +// 'proof of work failed' +// ) } diff --git a/src/proof_of_work/tests.cairo b/src/proof_of_work/tests.cairo index 1164558f8..57bb36e70 100644 --- a/src/proof_of_work/tests.cairo +++ b/src/proof_of_work/tests.cairo @@ -1 +1 @@ -mod test_proof_of_work; \ No newline at end of file +mod test_proof_of_work;