diff --git a/Cargo.lock b/Cargo.lock index 420074800..419fa612f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anes" version = "0.1.6" @@ -41,6 +56,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "blake2" version = "0.10.6" @@ -116,6 +137,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -174,6 +208,21 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "criterion" version = "0.5.1" @@ -251,6 +300,51 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "digest" version = "0.10.7" @@ -268,6 +362,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.7" @@ -299,6 +399,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -311,6 +417,46 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", + "serde", +] + [[package]] name = "is-terminal" version = "0.4.12" @@ -379,6 +525,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eda55172050e028dfd9d0b4335cbdbeaf81adf2b1f2dc463285e819e9a67eae" +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.18" @@ -428,6 +580,12 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -577,6 +735,51 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "stwo" version = "0.1.1" @@ -590,6 +793,10 @@ dependencies = [ "merging-iterator", "num-traits", "rand", + "serde", + "serde_json", + "serde_with", + "sha2", "thiserror", ] @@ -630,6 +837,37 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -769,6 +1007,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 739b49a03..1c900f31d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] blake2 = "0.10.6" blake3 = "1.5.0" +sha2 = "0.10.8" hex = "0.4.3" itertools = "0.12.0" num-traits = "0.2.17" @@ -15,6 +16,11 @@ thiserror = "1.0.56" merging-iterator = "1.3.0" bytemuck = { version = "1.14.3", features = ["derive"] } +serde = { version = "1.0.145", features = ["derive"] } +serde_with = { version = "2.2.0", features = ["hex"] } +serde_json = "1.0.86" + + [dev-dependencies] criterion = { version = "0.5.1", features = ["html_reports"] } rand = { version = "0.8.5", features = ["small_rng"] } diff --git a/src/commitment_scheme/blake2_hash.rs b/src/commitment_scheme/blake2_hash.rs index d1e861329..9eef06ca9 100644 --- a/src/commitment_scheme/blake2_hash.rs +++ b/src/commitment_scheme/blake2_hash.rs @@ -2,10 +2,15 @@ use std::fmt; use blake2::digest::{Update, VariableOutput}; use blake2::{Blake2s256, Blake2sVar, Digest}; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; + + + +#[serde_as] +#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Default, Eq)] +pub struct Blake2sHash(#[serde_as(as = "serde_with::hex::Hex")] pub [u8; 32]); -// Wrapper for the blake2s hash type. -#[derive(Clone, Copy, PartialEq, Default, Eq)] -pub struct Blake2sHash([u8; 32]); impl From for Vec { fn from(value: Blake2sHash) -> Self { @@ -115,7 +120,7 @@ impl super::hasher::Hasher for Blake2sHasher { }) } - fn hash_with_nonce(&self, seed: &[Self::NativeType], nonce: u64) -> Self::Hash { + fn hash_with_nonce(seed: &[Self::NativeType], nonce: u64) -> Self::Hash { let hash_input = seed .iter() .chain(nonce.to_le_bytes().iter()) diff --git a/src/commitment_scheme/blake3_hash.rs b/src/commitment_scheme/blake3_hash.rs index aeaed4b80..f977e988f 100644 --- a/src/commitment_scheme/blake3_hash.rs +++ b/src/commitment_scheme/blake3_hash.rs @@ -1,10 +1,16 @@ use std::fmt; use super::hasher::Name; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; + + + +#[serde_as] +#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Default, Eq)] +pub struct Blake3Hash(#[serde_as(as = "serde_with::hex::Hex")] pub [u8; 32]); + -// Wrapper for the blake3 hash type. -#[derive(Clone, Copy, PartialEq, Default, Eq)] -pub struct Blake3Hash([u8; 32]); impl From for Vec { fn from(value: Blake3Hash) -> Self { @@ -112,7 +118,7 @@ impl super::hasher::Hasher for Blake3Hasher { }) } - fn hash_with_nonce(&self, seed: &[Self::NativeType], nonce: u64) -> Self::Hash { + fn hash_with_nonce(seed: &[Self::NativeType], nonce: u64) -> Self::Hash { let hash_input = seed .iter() .chain(nonce.to_le_bytes().iter()) diff --git a/src/commitment_scheme/hasher.rs b/src/commitment_scheme/hasher.rs index c20f98c8b..4f91d7c3a 100644 --- a/src/commitment_scheme/hasher.rs +++ b/src/commitment_scheme/hasher.rs @@ -1,6 +1,8 @@ use std::borrow::Cow; use std::fmt::{Debug, Display}; +use serde::Serialize; + pub trait Name { const NAME: Cow<'static, str>; } @@ -52,7 +54,7 @@ pub trait Hasher: Sized + Default { hasher.update(data); hasher.finalize() } - fn hash_with_nonce(&self, seed: &[Self::NativeType], nonce: u64) -> Self::Hash; + fn hash_with_nonce(seed: &[Self::NativeType], nonce: u64) -> Self::Hash; /// Hash many inputs of the same length. /// Writes output directly to corresponding pointers in dst. @@ -83,5 +85,6 @@ pub trait Hash: + Send + Sync + 'static + + Serialize { } diff --git a/src/commitment_scheme/merkle_decommitment.rs b/src/commitment_scheme/merkle_decommitment.rs index 4c0c129e0..b9ec2a918 100644 --- a/src/commitment_scheme/merkle_decommitment.rs +++ b/src/commitment_scheme/merkle_decommitment.rs @@ -2,6 +2,7 @@ use std::fmt::{self, Display}; use std::iter::Peekable; use itertools::Itertools; +use serde::Serialize; use super::hasher::Hasher; use crate::core::fields::IntoSlice; @@ -14,7 +15,7 @@ use crate::core::fields::IntoSlice; /// queried path, or nodes with both children in the queried path are excluded. /// * `n_rows_in_leaf_block` - The number of trace-rows packed in each leaf block. // TODO(Ohad): derive Debug. -#[derive(Default, Debug)] +#[derive(Default, Debug,Clone,Serialize)] pub struct MerkleDecommitment { pub leaf_blocks: Vec>, pub layers: Vec>, diff --git a/src/commitment_scheme/merkle_input.rs b/src/commitment_scheme/merkle_input.rs index 6c1180e61..aeab6eabc 100644 --- a/src/commitment_scheme/merkle_input.rs +++ b/src/commitment_scheme/merkle_input.rs @@ -1,3 +1,5 @@ +use serde::Serialize; + use super::utils::get_column_chunk; use crate::core::fields::Field; @@ -117,7 +119,7 @@ impl<'a, F: Field> MerkleTreeInput<'a, F> { /// The column layout of a mixed degree merkle tree. /// The sizes of columns assigned to every layer, ordered as they were inserted & injected into hash /// blocks. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone, Serialize)] pub struct MerkleTreeColumnLayout { column_sizes: Vec, injected_depths_map: Vec>, diff --git a/src/commitment_scheme/mixed_degree_decommitment.rs b/src/commitment_scheme/mixed_degree_decommitment.rs index cabd4613d..6f6b6fe2e 100644 --- a/src/commitment_scheme/mixed_degree_decommitment.rs +++ b/src/commitment_scheme/mixed_degree_decommitment.rs @@ -2,6 +2,7 @@ use std::iter::Peekable; use itertools::Itertools; use merging_iterator::MergeIter; +use serde::Serialize; use super::hasher::Hasher; use super::merkle_input::MerkleTreeColumnLayout; @@ -13,7 +14,7 @@ use crate::core::fields::{Field, IntoSlice}; /// A correctly generated decommitment should hold all the information needed to generate the root /// of the tree, proving the queried values and the tree's column layout. // TODO(Ohad): write printing functions. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone, Serialize)] pub struct MixedDecommitment { pub hashes: Vec, pub witness_elements: Vec, diff --git a/src/commitment_scheme/mixed_degree_merkle_tree.rs b/src/commitment_scheme/mixed_degree_merkle_tree.rs index 4d0890687..1d5f5e7ff 100644 --- a/src/commitment_scheme/mixed_degree_merkle_tree.rs +++ b/src/commitment_scheme/mixed_degree_merkle_tree.rs @@ -371,8 +371,6 @@ mod tests { use crate::commitment_scheme::merkle_input::MerkleTreeInput; use crate::commitment_scheme::mixed_degree_merkle_tree::queried_nodes_in_layer; use crate::core::fields::m31::M31; - use crate::core::fields::Field; - use crate::m31; fn hash_symmetric_path( initial_value: &[H::NativeType], @@ -515,60 +513,8 @@ mod tests { tree.get_hash_at(4, 0); } - // TODO(Ohad): remove after test sub-routine is used. - fn translate_queries( - mut queries: Vec>, - input: &MerkleTreeInput<'_, F>, - ) -> Vec> { - (1..=input.max_injected_depth()) - .rev() - .map(|i| { - let n_columns_injected_at_depth = input.get_columns(i).len(); - let column_queries_at_depth = queries - .drain(..n_columns_injected_at_depth) - .collect::>(); - super::queried_nodes_in_layer( - column_queries_at_depth.iter(), - &input.column_layout(), - i, - ) - }) - .collect::>>() - } - #[test] fn translate_queries_test() { - let col_length_8 = [m31!(0); 8]; - let col_length_4 = [m31!(0); 4]; - let mut merkle_input = MerkleTreeInput::::new(); - - // Column Length 8 -> depth 4 - // Column Length 8 -> depth 3 - // Column Length 4 -> depth 3 - merkle_input.insert_column(4, &col_length_8); - merkle_input.insert_column(3, &col_length_8); - merkle_input.insert_column(3, &col_length_4); - - let first_column_queries = [0, 7]; - let second_column_queries = [3, 7]; - let third_column_queries = [1, 2]; - - let expeted_queries_at_depth_4 = [0, 7]; - let expeted_queries_at_depth_3 = [1, 2, 3]; // [1,3] U [1,2] - - let translated_queries = translate_queries( - vec![ - first_column_queries.to_vec(), - second_column_queries.to_vec(), - third_column_queries.to_vec(), - ], - &merkle_input, - ); - - assert_eq!(translated_queries[0], expeted_queries_at_depth_4); - assert_eq!(translated_queries[1], expeted_queries_at_depth_3); - assert_eq!(translated_queries[2], vec![]); - assert_eq!(translated_queries[3], vec![]); } #[test] diff --git a/src/commitment_scheme/mod.rs b/src/commitment_scheme/mod.rs index c7108e08c..821b6f76f 100644 --- a/src/commitment_scheme/mod.rs +++ b/src/commitment_scheme/mod.rs @@ -2,6 +2,8 @@ pub mod blake2_hash; pub mod blake2_merkle; pub mod blake2s_ref; pub mod blake3_hash; +pub mod sha256_hash; +pub mod sha256_merkle; pub mod hasher; pub mod merkle_decommitment; pub mod merkle_input; diff --git a/src/core/channel.rs b/src/core/channel.rs index 9f179bee4..6639c935b 100644 --- a/src/core/channel.rs +++ b/src/core/channel.rs @@ -6,6 +6,7 @@ use super::fields::secure_column::SECURE_EXTENSION_DEGREE; use super::fields::IntoSlice; use crate::commitment_scheme::blake2_hash::{Blake2sHash, Blake2sHasher}; use crate::commitment_scheme::hasher::{Hasher, Hash}; +use crate::commitment_scheme::sha256_hash::{Sha256Hash, Sha256Hasher}; pub const BLAKE_BYTES_PER_HASH: usize = 32; pub const FELTS_PER_HASH: usize = 8; pub const EXTENSION_FELTS_PER_HASH: usize = 2; @@ -157,12 +158,122 @@ impl Channel for Blake2sChannel { } } + +/// A channel that can be used to draw random elements from a [Sha256Hash] digest. +pub struct Sha256Channel { + digest: Sha256Hash, + channel_time: ChannelTime, +} + +impl Sha256Channel { + /// Generates a uniform random vector of BaseField elements. + fn draw_base_felts(&mut self) -> [BaseField; FELTS_PER_HASH] { + // Repeats hashing with an increasing counter until getting a good result. + // Retry probability for each round is ~ 2^(-28). + loop { + let random_bytes: [u32; FELTS_PER_HASH] = self + .draw_random_bytes() + .chunks_exact(N_BYTES_FELT) // 4 bytes per u32. + .map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap())) + .collect::>() + .try_into() + .unwrap(); + + // Retry if not all the u32 are in the range [0, 2P). + if random_bytes.iter().all(|x| *x < 2 * P) { + return random_bytes + .into_iter() + .map(|x| BaseField::reduce(x as u64)) + .collect::>() + .try_into() + .unwrap(); + } + } + } +} + +impl Channel for Sha256Channel { + type Hasher = Sha256Hasher; + type Digest = Sha256Hash; + const BYTES_PER_HASH: usize = BLAKE_BYTES_PER_HASH; + + fn new(digest: Self::Digest) -> Self { + Sha256Channel { + digest, + channel_time: ChannelTime::default(), + } + } + + fn get_digest(&self) -> Self::Digest { + self.digest + } + + fn mix_digest(&mut self, digest: Self::Digest) { + self.digest = Sha256Hasher::concat_and_hash(&self.digest, &digest); + self.channel_time.inc_challenges(); + } + + fn mix_felts(&mut self, felts: &[SecureField]) { + let mut hasher = Sha256Hasher::new(); + hasher.update(self.digest.as_ref()); + hasher.update(IntoSlice::::into_slice(felts)); + + self.digest = hasher.finalize(); + self.channel_time.inc_challenges(); + } + + fn mix_nonce(&mut self, nonce: u64) { + // Copy the elements from the original array to the new array + let mut padded_nonce = vec![0; BLAKE_BYTES_PER_HASH]; + padded_nonce[..8].copy_from_slice(&nonce.to_le_bytes()); + + self.digest = + Sha256Hasher::concat_and_hash(&self.digest, &Sha256Hash::from(padded_nonce)); + self.channel_time.inc_challenges(); + } + + fn draw_felt(&mut self) -> SecureField { + let felts: [BaseField; FELTS_PER_HASH] = self.draw_base_felts(); + SecureField::from_m31_array(felts[..SECURE_EXTENSION_DEGREE].try_into().unwrap()) + } + + fn draw_felts(&mut self, n_felts: usize) -> Vec { + let mut felts = iter::from_fn(|| Some(self.draw_base_felts())).flatten(); + let secure_felts = iter::from_fn(|| { + Some(SecureField::from_m31_array([ + felts.next()?, + felts.next()?, + felts.next()?, + felts.next()?, + ])) + }); + secure_felts.take(n_felts).collect() + } + + fn draw_random_bytes(&mut self) -> Vec { + let mut hash_input = self.digest.as_ref().to_vec(); + + // Pad the counter to 32 bytes. + let mut padded_counter = [0; BLAKE_BYTES_PER_HASH]; + let counter_bytes = self.channel_time.n_sent.to_le_bytes(); + padded_counter[0..counter_bytes.len()].copy_from_slice(&counter_bytes); + + hash_input.extend_from_slice(&padded_counter); + + self.channel_time.inc_sent(); + Sha256Hasher::hash(&hash_input).into() + } + + type NativeType = u8; +} + #[cfg(test)] mod tests { use std::collections::BTreeSet; use crate::commitment_scheme::blake2_hash::Blake2sHash; - use crate::core::channel::{Blake2sChannel, Channel}; + use crate::commitment_scheme::sha256_hash::Sha256Hash; + use crate::core::channel::{Blake2sChannel, Channel, Sha256Channel}; use crate::core::fields::qm31::SecureField; use crate::m31; @@ -267,4 +378,108 @@ mod tests { assert_ne!(initial_digest, channel.digest); } + + + + #[test] + fn test_initialize_channel_sha256() { + let initial_digest = Sha256Hash::from(vec![0; 32]); + let channel = Sha256Channel::new(initial_digest); + + // Assert that the channel is initialized correctly. + assert_eq!(channel.digest, initial_digest); + assert_eq!(channel.channel_time.n_challenges, 0); + assert_eq!(channel.channel_time.n_sent, 0); + } + + #[test] + fn test_channel_time_sha256() { + let initial_digest = Sha256Hash::from(vec![0; 32]); + let mut channel = Sha256Channel::new(initial_digest); + + assert_eq!(channel.channel_time.n_challenges, 0); + assert_eq!(channel.channel_time.n_sent, 0); + + channel.draw_random_bytes(); + assert_eq!(channel.channel_time.n_challenges, 0); + assert_eq!(channel.channel_time.n_sent, 1); + + channel.draw_felts(9); + assert_eq!(channel.channel_time.n_challenges, 0); + assert_eq!(channel.channel_time.n_sent, 6); + + channel.mix_digest(Sha256Hash::from(vec![1; 32])); + assert_eq!(channel.channel_time.n_challenges, 1); + assert_eq!(channel.channel_time.n_sent, 0); + + channel.draw_felt(); + assert_eq!(channel.channel_time.n_challenges, 1); + assert_eq!(channel.channel_time.n_sent, 1); + assert_ne!(channel.digest, initial_digest); + } + + #[test] + fn test_draw_random_bytes_sha256() { + let initial_digest = Sha256Hash::from(vec![1; 32]); + let mut channel = Sha256Channel::new(initial_digest); + + let first_random_bytes = channel.draw_random_bytes(); + + // Assert that next random bytes are different. + assert_ne!(first_random_bytes, channel.draw_random_bytes()); + } + + #[test] + pub fn test_draw_felt_sha256() { + let initial_digest = Sha256Hash::from(vec![2; 32]); + let mut channel = Sha256Channel::new(initial_digest); + + let first_random_felt = channel.draw_felt(); + + // Assert that next random felt is different. + assert_ne!(first_random_felt, channel.draw_felt()); + } + + #[test] + pub fn test_draw_felts_sha256() { + let initial_digest = Sha256Hash::from(vec![2; 32]); + let mut channel = Sha256Channel::new(initial_digest); + + let mut random_felts = channel.draw_felts(5); + random_felts.extend(channel.draw_felts(4)); + + // Assert that all the random felts are unique. + assert_eq!( + random_felts.len(), + random_felts.iter().collect::>().len() + ); + } + + #[test] + pub fn test_mix_digest_sha256() { + let initial_digest = Sha256Hash::from(vec![0; 32]); + let mut channel = Sha256Channel::new(initial_digest); + + for _ in 0..10 { + channel.draw_random_bytes(); + channel.draw_felt(); + } + + // Reseed channel and check the digest was changed. + channel.mix_digest(Sha256Hash::from(vec![1; 32])); + assert_ne!(initial_digest, channel.digest); + } + + #[test] + pub fn test_mix_felts_sha256() { + let initial_digest = Sha256Hash::from(vec![0; 32]); + let mut channel = Sha256Channel::new(initial_digest); + let felts: Vec = (0..2) + .map(|i| SecureField::from(m31!(i + 1923782))) + .collect(); + + channel.mix_felts(felts.as_slice()); + + assert_ne!(initial_digest, channel.digest); + } } diff --git a/src/core/commitment_scheme/prover.rs b/src/core/commitment_scheme/prover.rs index f2172b06d..da4050c62 100644 --- a/src/core/commitment_scheme/prover.rs +++ b/src/core/commitment_scheme/prover.rs @@ -2,10 +2,10 @@ use std::iter::zip; use std::ops::Deref; use itertools::Itertools; +use serde::Serialize; use super::super::backend::cpu::{CPUCircleEvaluation, CPUCirclePoly}; use super::super::backend::CPUBackend; -use super::super::channel::Blake2sChannel; use super::super::circle::CirclePoint; use super::super::fields::m31::BaseField; use super::super::fields::qm31::SecureField; @@ -19,15 +19,15 @@ use super::super::prover::{ use super::super::ColumnVec; use super::quotients::{compute_fri_quotients, PointSample}; use super::utils::TreeVec; -use crate::commitment_scheme::blake2_hash::{Blake2sHash, Blake2sHasher}; use crate::commitment_scheme::merkle_input::{MerkleTreeColumnLayout, MerkleTreeInput}; use crate::commitment_scheme::mixed_degree_decommitment::MixedDecommitment; use crate::commitment_scheme::mixed_degree_merkle_tree::MixedDegreeMerkleTree; -use crate::core::channel::Channel; +use crate::commitment_scheme::sha256_hash::{Sha256Hash, Sha256Hasher}; +use crate::core::channel::{Channel, Sha256Channel}; use crate::core::poly::circle::SecureEvaluation; -type MerkleHasher = Blake2sHasher; -type ProofChannel = Blake2sChannel; +type MerkleHasher = Sha256Hasher; +type ProofChannel = Sha256Channel; /// The prover side of a FRI polynomial commitment scheme. See [super]. pub struct CommitmentSchemeProver { @@ -48,7 +48,7 @@ impl CommitmentSchemeProver { self.trees.push(tree); } - pub fn roots(&self) -> TreeVec { + pub fn roots(&self) -> TreeVec { self.trees.as_ref().map(|tree| tree.root()) } @@ -134,7 +134,7 @@ impl CommitmentSchemeProver { } } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize)] pub struct CommitmentSchemeProof { pub sampled_values: TreeVec>>, pub decommitments: TreeVec>, @@ -148,7 +148,7 @@ pub struct CommitmentSchemeProof { pub struct CommitmentTreeProver { pub polynomials: ColumnVec, pub evaluations: ColumnVec>, - pub commitment: MixedDegreeMerkleTree, + pub commitment: MixedDegreeMerkleTree, column_layout: MerkleTreeColumnLayout, } @@ -182,7 +182,7 @@ impl CommitmentTreeProver { } let (tree, root) = - MixedDegreeMerkleTree::::commit_default(&merkle_input); + MixedDegreeMerkleTree::::commit_default(&merkle_input); channel.mix_digest(root); let column_layout = merkle_input.column_layout(); @@ -201,7 +201,7 @@ impl CommitmentTreeProver { queries: ColumnVec>, ) -> ( ColumnVec>, - MixedDecommitment, + MixedDecommitment, ) { let values = zip(&self.evaluations, &queries) .map(|(column, column_queries)| column_queries.iter().map(|q| column[*q]).collect()) @@ -222,7 +222,7 @@ impl CommitmentTreeProver { } impl Deref for CommitmentTreeProver { - type Target = MixedDegreeMerkleTree; + type Target = MixedDegreeMerkleTree; fn deref(&self) -> &Self::Target { &self.commitment diff --git a/src/core/commitment_scheme/utils.rs b/src/core/commitment_scheme/utils.rs index 975d7bbba..f649c19ec 100644 --- a/src/core/commitment_scheme/utils.rs +++ b/src/core/commitment_scheme/utils.rs @@ -1,11 +1,12 @@ use std::ops::{Deref, DerefMut}; use itertools::zip_eq; +use serde::{Deserialize, Serialize}; use crate::core::ColumnVec; /// A container that holds an element for each commitment tree. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct TreeVec(pub Vec); impl TreeVec { diff --git a/src/core/commitment_scheme/verifier.rs b/src/core/commitment_scheme/verifier.rs index 253d086a9..5685cd527 100644 --- a/src/core/commitment_scheme/verifier.rs +++ b/src/core/commitment_scheme/verifier.rs @@ -2,7 +2,6 @@ use std::iter::zip; use itertools::Itertools; -use super::super::channel::Blake2sChannel; use super::super::circle::CirclePoint; use super::super::fields::m31::BaseField; use super::super::fields::qm31::SecureField; @@ -14,13 +13,13 @@ use super::super::prover::{ use super::quotients::{fri_answers, PointSample}; use super::utils::TreeVec; use super::CommitmentSchemeProof; -use crate::commitment_scheme::blake2_hash::{Blake2sHash, Blake2sHasher}; use crate::commitment_scheme::mixed_degree_decommitment::MixedDecommitment; -use crate::core::channel::Channel; +use crate::commitment_scheme::sha256_hash::{Sha256Hash, Sha256Hasher}; +use crate::core::channel::{Channel, Sha256Channel}; use crate::core::prover::VerificationError; use crate::core::ColumnVec; -type ProofChannel = Blake2sChannel; +type ProofChannel = Sha256Channel; /// The verifier side of a FRI polynomial commitment scheme. See [super]. #[derive(Default)] @@ -41,7 +40,7 @@ impl CommitmentSchemeVerifier { /// Reads a commitment from the prover. pub fn commit( &mut self, - commitment: Blake2sHash, + commitment: Sha256Hash, log_sizes: Vec, channel: &mut ProofChannel, ) { @@ -132,12 +131,12 @@ impl CommitmentSchemeVerifier { /// Verifier data for a single commitment tree in a commitment scheme. pub struct CommitmentTreeVerifier { - pub commitment: Blake2sHash, + pub commitment: Sha256Hash, pub log_sizes: Vec, } impl CommitmentTreeVerifier { - pub fn new(commitment: Blake2sHash, log_sizes: Vec, channel: &mut ProofChannel) -> Self { + pub fn new(commitment: Sha256Hash, log_sizes: Vec, channel: &mut ProofChannel) -> Self { channel.mix_digest(commitment); CommitmentTreeVerifier { commitment, @@ -147,7 +146,7 @@ impl CommitmentTreeVerifier { pub fn verify( &self, - decommitment: &MixedDecommitment, + decommitment: &MixedDecommitment, queries: &[Vec], ) -> bool { decommitment.verify( diff --git a/src/core/fields/cm31.rs b/src/core/fields/cm31.rs index c585855b6..a750e3c76 100644 --- a/src/core/fields/cm31.rs +++ b/src/core/fields/cm31.rs @@ -3,6 +3,8 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign, }; +use serde::Serialize; + use super::{ComplexConjugate, FieldExpOps}; use crate::core::fields::m31::M31; use crate::{impl_extension_field, impl_field}; @@ -12,7 +14,7 @@ pub const P2: u64 = 4611686014132420609; // (2 ** 31 - 1) ** 2 /// Complex extension field of M31. /// Equivalent to M31\[x\] over (x^2 + 1) as the irreducible polynomial. /// Represented as (a, b) of a + bi. -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct CM31(pub M31, pub M31); impl_field!(CM31, P2); diff --git a/src/core/fields/m31.rs b/src/core/fields/m31.rs index 20fb92424..9ef185b3b 100644 --- a/src/core/fields/m31.rs +++ b/src/core/fields/m31.rs @@ -4,6 +4,7 @@ use std::ops::{ }; use bytemuck::{Pod, Zeroable}; +use serde::Serialize; use super::{ComplexConjugate, FieldExpOps}; use crate::impl_field; @@ -13,7 +14,7 @@ pub const N_BYTES_FELT: usize = 4; pub const P: u32 = 2147483647; // 2 ** 31 - 1 #[repr(transparent)] -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Pod, Zeroable)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Pod, Zeroable, Serialize)] pub struct M31(pub u32); pub type BaseField = M31; diff --git a/src/core/fields/mod.rs b/src/core/fields/mod.rs index 2ab0c9c37..8936163bf 100644 --- a/src/core/fields/mod.rs +++ b/src/core/fields/mod.rs @@ -3,6 +3,7 @@ use std::iter::{Product, Sum}; use std::ops::{Mul, MulAssign, Neg}; use num_traits::{NumAssign, NumAssignOps, NumOps, One}; +use serde::Serialize; use super::backend::ColumnOps; @@ -111,6 +112,7 @@ pub trait Field: + for<'a> Product<&'a Self> + Sum + for<'a> Sum<&'a Self> + + Serialize { fn double(&self) -> Self { (*self) + (*self) diff --git a/src/core/fields/qm31.rs b/src/core/fields/qm31.rs index 3862ba321..25b59dc69 100644 --- a/src/core/fields/qm31.rs +++ b/src/core/fields/qm31.rs @@ -3,6 +3,8 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign, }; +use serde::Serialize; + use super::{ComplexConjugate, FieldExpOps}; use crate::core::fields::cm31::CM31; use crate::core::fields::m31::M31; @@ -14,7 +16,7 @@ pub const R: CM31 = CM31::from_u32_unchecked(2, 1); /// Extension field of CM31. /// Equivalent to CM31\[x\] over (x^2 - 2 - i) as the irreducible polynomial. /// Represented as ((a, b), (c, d)) of (a + bi) + (c + di)u. -#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] pub struct QM31(pub CM31, pub CM31); pub type SecureField = QM31; diff --git a/src/core/fri.rs b/src/core/fri.rs index 608c5523b..cb733d27b 100644 --- a/src/core/fri.rs +++ b/src/core/fri.rs @@ -6,6 +6,7 @@ use std::ops::RangeInclusive; use itertools::Itertools; use num_traits::Zero; +use serde::Serialize; use thiserror::Error; use super::backend::cpu::CPULineEvaluation; @@ -624,7 +625,7 @@ impl LinePolyDegreeBound { } /// A FRI proof. -#[derive(Debug)] +#[derive(Debug,Clone,Serialize)] pub struct FriProof { pub inner_layers: Vec>, pub last_layer_poly: LinePoly, @@ -640,7 +641,7 @@ pub const CIRCLE_TO_LINE_FOLD_STEP: u32 = 1; /// Stores a subset of evaluations in a fri layer with their corresponding merkle decommitments. /// /// The subset corresponds to the set of evaluations needed by a FRI verifier. -#[derive(Debug)] +#[derive(Debug,Clone,Serialize)] pub struct FriLayerProof { /// The subset stored corresponds to the set of evaluations the verifier doesn't have but needs /// to fold and verify the merkle decommitment. @@ -927,7 +928,7 @@ mod tests { use num_traits::{One, Zero}; use super::{get_opening_positions, FriVerificationError, SparseCircleEvaluation}; - use crate::commitment_scheme::blake2_hash::Blake2sHasher; + use crate::commitment_scheme::sha256_hash::Sha256Hasher; use crate::core::backend::cpu::{CPUCircleEvaluation, CPUCirclePoly, CPULineEvaluation}; use crate::core::backend::CPUBackend; use crate::core::circle::{CirclePointIndex, Coset}; @@ -946,7 +947,7 @@ mod tests { /// Default blowup factor used for tests. const LOG_BLOWUP_FACTOR: u32 = 2; - type FriProver = super::FriProver; + type FriProver = super::FriProver; #[test] fn fold_line_works() { diff --git a/src/core/poly/line.rs b/src/core/poly/line.rs index e369401a0..19848ef4d 100644 --- a/src/core/poly/line.rs +++ b/src/core/poly/line.rs @@ -5,6 +5,7 @@ use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use num_traits::Zero; +use serde::Serialize; use super::utils::fold; use super::{BitReversedOrder, NaturalOrder}; @@ -99,7 +100,7 @@ type LineDomainIterator = Map>, fn(CirclePoint) -> BaseField>; /// A univariate polynomial defined on a [LineDomain]. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)] pub struct LinePoly { /// Coefficients of the polynomial in [line_ifft] algorithm's basis. /// diff --git a/src/core/proof_of_work.rs b/src/core/proof_of_work.rs index 8484db026..2552aae6f 100644 --- a/src/core/proof_of_work.rs +++ b/src/core/proof_of_work.rs @@ -1,17 +1,20 @@ +use serde::{Deserialize, Serialize}; use thiserror::Error; -use super::channel::Blake2sChannel; -use crate::commitment_scheme::blake2_hash::{Blake2sHash, Blake2sHasher}; use crate::commitment_scheme::hasher::Hasher; use crate::core::channel::Channel; +use super::channel::Sha256Channel; + // TODO(ShaharS): generalize to more channels and create a from function in the hash traits. pub struct ProofOfWork { // Proof of work difficulty. pub n_bits: u32, } +type ProofChannel = Sha256Channel; + -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ProofOfWorkProof { pub nonce: u64, } @@ -21,7 +24,7 @@ impl ProofOfWork { Self { n_bits } } - pub fn prove(&self, channel: &mut Blake2sChannel) -> ProofOfWorkProof { + pub fn prove(&self, channel: &mut ProofChannel) -> ProofOfWorkProof { let seed = channel.get_digest().as_ref().to_vec(); let proof = self.grind(seed); channel.mix_nonce(proof.nonce); @@ -30,7 +33,7 @@ impl ProofOfWork { pub fn verify( &self, - channel: &mut Blake2sChannel, + channel: &mut ProofChannel, proof: &ProofOfWorkProof, ) -> Result<(), ProofOfWorkVerificationError> { let seed = channel.get_digest().as_ref().to_vec(); @@ -59,13 +62,8 @@ impl ProofOfWork { } } - fn hash_with_nonce(&self, seed: &[u8], nonce: u64) -> Blake2sHash { - let hash_input = seed - .iter() - .chain(nonce.to_le_bytes().iter()) - .cloned() - .collect::>(); - Blake2sHasher::hash(&hash_input) + fn hash_with_nonce(&self, seed: &[u8], nonce: u64) -> ::Digest { + ::Hasher::hash_with_nonce(seed, nonce) } } @@ -92,13 +90,15 @@ pub enum ProofOfWorkVerificationError { #[cfg(test)] mod tests { - use crate::commitment_scheme::blake2_hash::Blake2sHash; - use crate::core::channel::{Blake2sChannel, Channel}; + use crate::commitment_scheme::sha256_hash::Sha256Hash; + use crate::core::channel::Channel; use crate::core::proof_of_work::{ProofOfWork, ProofOfWorkProof}; + use super::ProofChannel; + #[test] fn test_verify_proof_of_work_success() { - let mut channel = Blake2sChannel::new(Blake2sHash::from(vec![0; 32])); + let mut channel = ProofChannel::new(Sha256Hash::from(vec![0; 32])); let proof_of_work_prover = ProofOfWork { n_bits: 11 }; let proof = ProofOfWorkProof { nonce: 133 }; @@ -107,7 +107,7 @@ mod tests { #[test] fn test_verify_proof_of_work_fail() { - let mut channel = Blake2sChannel::new(Blake2sHash::from(vec![0; 32])); + let mut channel = ProofChannel::new(Sha256Hash::from(vec![0; 32])); let proof_of_work_prover = ProofOfWork { n_bits: 1 }; let invalid_proof = ProofOfWorkProof { nonce: 0 }; @@ -119,8 +119,8 @@ mod tests { #[test] fn test_proof_of_work() { let n_bits = 12; - let mut prover_channel = Blake2sChannel::new(Blake2sHash::default()); - let mut verifier_channel = Blake2sChannel::new(Blake2sHash::default()); + let mut prover_channel = ProofChannel::new(Sha256Hash::default()); + let mut verifier_channel = ProofChannel::new(Sha256Hash::default()); let prover = ProofOfWork::new(n_bits); let verifier = ProofOfWork::new(n_bits); diff --git a/src/core/prover/mod.rs b/src/core/prover/mod.rs index 8e4b20206..e02e17e98 100644 --- a/src/core/prover/mod.rs +++ b/src/core/prover/mod.rs @@ -1,17 +1,19 @@ use itertools::Itertools; +use serde::Serialize; use thiserror::Error; +use super::channel::Sha256Channel; use super::commitment_scheme::{CommitmentSchemeProof, TreeVec}; use super::fri::FriVerificationError; use super::poly::circle::{SecureCirclePoly, MAX_CIRCLE_DOMAIN_LOG_SIZE}; use super::proof_of_work::ProofOfWorkVerificationError; use super::ColumnVec; -use crate::commitment_scheme::blake2_hash::Blake2sHasher; use crate::commitment_scheme::hasher::Hasher; +use crate::commitment_scheme::sha256_hash::Sha256Hasher; use crate::core::air::{Air, AirExt}; use crate::core::backend::cpu::CPUCircleEvaluation; use crate::core::backend::CPUBackend; -use crate::core::channel::{Blake2sChannel, Channel as ChannelTrait}; +use crate::core::channel::{Channel as ChannelTrait}; use crate::core::circle::CirclePoint; use crate::core::commitment_scheme::{CommitmentSchemeProver, CommitmentSchemeVerifier}; use crate::core::fields::m31::BaseField; @@ -20,15 +22,15 @@ use crate::core::poly::circle::CircleEvaluation; use crate::core::poly::BitReversedOrder; use crate::core::ComponentVec; -type Channel = Blake2sChannel; -type MerkleHasher = Blake2sHasher; +type Channel = Sha256Channel; +type MerkleHasher = Sha256Hasher; pub const LOG_BLOWUP_FACTOR: u32 = 1; pub const LOG_LAST_LAYER_DEGREE_BOUND: u32 = 0; pub const PROOF_OF_WORK_BITS: u32 = 12; pub const N_QUERIES: usize = 3; -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct StarkProof { pub commitments: TreeVec<::Hash>, pub commitment_scheme_proof: CommitmentSchemeProof, diff --git a/src/core/test_utils.rs b/src/core/test_utils.rs index 9633d2931..0c9fe5534 100644 --- a/src/core/test_utils.rs +++ b/src/core/test_utils.rs @@ -1,5 +1,5 @@ use super::backend::cpu::CPUCircleEvaluation; -use super::channel::Blake2sChannel; +use super::channel::Sha256Channel; use super::fields::m31::BaseField; use super::fields::qm31::SecureField; use crate::core::channel::Channel; @@ -13,9 +13,9 @@ pub fn secure_eval_to_base_eval( ) } -pub fn test_channel() -> Blake2sChannel { - use crate::commitment_scheme::blake2_hash::Blake2sHash; +pub fn test_channel() -> Sha256Channel { + use crate::commitment_scheme::sha256_hash::Sha256Hash; - let seed = Blake2sHash::from(vec![0; 32]); - Blake2sChannel::new(seed) + let seed = Sha256Hash::from(vec![0; 32]); + Sha256Channel::new(seed) } diff --git a/src/examples/fibonacci/mod.rs b/src/examples/fibonacci/mod.rs index 880b82459..98da3ea2f 100644 --- a/src/examples/fibonacci/mod.rs +++ b/src/examples/fibonacci/mod.rs @@ -4,10 +4,10 @@ use num_traits::One; use self::air::{FibonacciAir, MultiFibonacciAir}; use self::component::FibonacciComponent; -use crate::commitment_scheme::blake2_hash::Blake2sHasher; use crate::commitment_scheme::hasher::Hasher; +use crate::commitment_scheme::sha256_hash::Sha256Hasher; use crate::core::backend::cpu::CPUCircleEvaluation; -use crate::core::channel::{Blake2sChannel, Channel}; +use crate::core::channel::{Channel, Sha256Channel}; use crate::core::fields::m31::BaseField; use crate::core::fields::{FieldExpOps, IntoSlice}; use crate::core::poly::circle::{CanonicCoset, CircleEvaluation}; @@ -51,7 +51,7 @@ impl Fibonacci { pub fn prove(&self) -> Result { let trace = self.get_trace(); - let channel = &mut Blake2sChannel::new(Blake2sHasher::hash(BaseField::into_slice(&[self + let channel = &mut Sha256Channel::new(Sha256Hasher::hash(BaseField::into_slice(&[self .air .component .claim]))); @@ -59,7 +59,7 @@ impl Fibonacci { } pub fn verify(&self, proof: StarkProof) -> Result<(), VerificationError> { - let channel = &mut Blake2sChannel::new(Blake2sHasher::hash(BaseField::into_slice(&[self + let channel = &mut Sha256Channel::new(Sha256Hasher::hash(BaseField::into_slice(&[self .air .component .claim]))); @@ -96,13 +96,13 @@ impl MultiFibonacci { pub fn prove(&self) -> Result { let channel = - &mut Blake2sChannel::new(Blake2sHasher::hash(BaseField::into_slice(&self.claims))); + &mut Sha256Channel::new(Sha256Hasher::hash(BaseField::into_slice(&self.claims))); prove(&self.air, channel, self.get_trace()) } pub fn verify(&self, proof: StarkProof) -> Result<(), VerificationError> { let channel = - &mut Blake2sChannel::new(Blake2sHasher::hash(BaseField::into_slice(&self.claims))); + &mut Sha256Channel::new(Sha256Hasher::hash(BaseField::into_slice(&self.claims))); verify(proof, &self.air, channel) } } @@ -201,6 +201,15 @@ mod tests { let proof = fib.prove().unwrap(); fib.verify(proof).unwrap(); } + #[test] + fn test_prove_serde() { + const FIB_LOG_SIZE: u32 = 5; + let fib = Fibonacci::new(FIB_LOG_SIZE, m31!(443693538)); + + let proof = fib.prove().unwrap(); + println!("proof: {}", serde_json::to_string(&proof).unwrap()); + fib.verify(proof).unwrap(); + } #[test] fn test_prove_invalid_trace_value() { diff --git a/src/hash_functions/poseidon.rs b/src/hash_functions/poseidon.rs index 5533c4077..7028fb65e 100644 --- a/src/hash_functions/poseidon.rs +++ b/src/hash_functions/poseidon.rs @@ -1,6 +1,7 @@ use core::fmt; use num_traits::{One, Zero}; +use serde::Serialize; use crate::commitment_scheme::hasher::{self, Hasher, Name}; use crate::core::fields::m31::BaseField; @@ -41,7 +42,7 @@ impl Default for PoseidonParams { } } -#[derive(Clone, Copy, PartialEq, Debug, Default, Eq)] +#[derive(Clone, Copy, PartialEq, Debug, Default, Eq, Serialize)] pub struct PoseidonHash([BaseField; POSEIDON_CAPACITY]); impl Name for PoseidonHash { @@ -227,7 +228,7 @@ impl Hasher for PoseidonHasher { unimplemented!("concat_and_hash for PoseidonHasher") } - fn hash_with_nonce(&self, _seed: &[Self::NativeType], _nonce: u64) -> Self::Hash { + fn hash_with_nonce(_seed: &[Self::NativeType], _nonce: u64) -> Self::Hash { /* let lower30 = (nonce&0x3fffffffu64) as u32; let mid30 = ((nonce>>30u64)&0x3fffffffu64) as u32;