diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 72efea7ee..87fac95c1 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -8,12 +8,13 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lambdaworks-math = { workspace = true, features = ["alloc"] } +lambdaworks-math = { workspace = true, features = ["alloc", "lambdaworks-serde-binary"] } sha3 = { version = "0.10", default-features = false } sha2 = { version = "0.10", default-features = false } # Optional serde = { version = "1.0", default-features = false, features = ["derive", "alloc"], optional = true } +bincode = { version = "2.0.0-rc.2", tag = "v2.0.0-rc.2", git = "https://github.com/bincode-org/bincode.git", features = ['serde'] } rayon = { version = "1.8.0", optional = true } [dev-dependencies] diff --git a/crypto/src/merkle_tree/backends/field_element.rs b/crypto/src/merkle_tree/backends/field_element.rs index 68fed0b6d..cc9a2dc64 100644 --- a/crypto/src/merkle_tree/backends/field_element.rs +++ b/crypto/src/merkle_tree/backends/field_element.rs @@ -91,9 +91,9 @@ mod tests { #[test] fn hash_data_field_element_backend_works_with_keccak_256() { let values: Vec = (1..6).map(FE::from).collect(); - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -104,9 +104,8 @@ mod tests { #[test] fn hash_data_field_element_backend_works_with_sha3_256() { let values: Vec = (1..6).map(FE::from).collect(); - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -117,9 +116,8 @@ mod tests { #[test] fn hash_data_field_element_backend_works_with_keccak_512() { let values: Vec = (1..6).map(FE::from).collect(); - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -130,9 +128,8 @@ mod tests { #[test] fn hash_data_field_element_backend_works_with_sha3_512() { let values: Vec = (1..6).map(FE::from).collect(); - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, diff --git a/crypto/src/merkle_tree/backends/field_element_vector.rs b/crypto/src/merkle_tree/backends/field_element_vector.rs index 8d5f132dd..42cd0db2b 100644 --- a/crypto/src/merkle_tree/backends/field_element_vector.rs +++ b/crypto/src/merkle_tree/backends/field_element_vector.rs @@ -111,9 +111,8 @@ mod tests { vec![FE::from(8u64), FE::from(19u64)], vec![FE::from(9u64), FE::from(21u64)], ]; - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -133,9 +132,8 @@ mod tests { vec![FE::from(8u64), FE::from(19u64)], vec![FE::from(9u64), FE::from(21u64)], ]; - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -155,9 +153,8 @@ mod tests { vec![FE::from(8u64), FE::from(19u64)], vec![FE::from(9u64), FE::from(21u64)], ]; - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -177,9 +174,8 @@ mod tests { vec![FE::from(8u64), FE::from(19u64)], vec![FE::from(9u64), FE::from(21u64)], ]; - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, @@ -199,9 +195,8 @@ mod tests { vec![FE::from(8u64), FE::from(19u64)], vec![FE::from(9u64), FE::from(21u64)], ]; - let merkle_tree = - MerkleTree::>::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(0).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = merkle_tree.get_proof(0).unwrap(); assert!(proof.verify::>( &merkle_tree.root, 0, diff --git a/crypto/src/merkle_tree/batch_proof.rs b/crypto/src/merkle_tree/batch_proof.rs new file mode 100644 index 000000000..95f825666 --- /dev/null +++ b/crypto/src/merkle_tree/batch_proof.rs @@ -0,0 +1,241 @@ +use super::{ + traits::IsMerkleTreeBackend, + utils::{get_parent_pos, get_sibling_pos}, +}; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; +extern crate std; +use std::collections::HashMap; + +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BatchProof +where + T: PartialEq + Eq, +{ + pub auth: HashMap, +} + +#[cfg(feature = "serde")] +impl BatchProof +where + T: PartialEq + Eq + Serialize + for<'a> Deserialize<'a>, +{ + pub fn serialize(&self) -> Vec { + bincode::serde::encode_to_vec(self, bincode::config::standard()).unwrap() + } + + pub fn deserialize(bytes: &[u8]) -> Self { + let (decoded, _): (BatchProof, usize) = + bincode::serde::decode_from_slice(bytes, bincode::config::standard()).unwrap(); + decoded + } +} + +impl BatchProof +where + T: PartialEq + Eq, +{ + pub fn verify(&self, root_hash: B::Node, hashed_leaves: HashMap) -> bool + where + B: IsMerkleTreeBackend, + { + let root_pos = 0; + + // Iterate the levels starting from the leaves, and build the upper level only using + // the provided leaves and the auth map. + // Return true if the constructed root matches the given one. + let mut current_level = hashed_leaves; + loop { + let mut parent_level = HashMap::::new(); + + for (pos, node) in current_level.iter() { + // Levels are expected to have tuples of nodes. If the first one was + // already processed and parent was set, skip the sibling. + let parent_pos = get_parent_pos(*pos); + if parent_level.contains_key(&parent_pos) { + continue; + } + + // Get the sibling node from the current level. + // If doesn't exist, then it must have been provided in the batch auth. + // If neither, then verification fails. + let sibling_pos = get_sibling_pos(*pos); + let sibling_node = if current_level.contains_key(&sibling_pos) { + current_level.get(&sibling_pos).unwrap() + } else if self.auth.contains_key(&sibling_pos) { + self.auth.get(&sibling_pos).unwrap() + } else { + panic!("Leaf with position {pos} has sibling {sibling_pos}, but it's not included in the auth map. "); + }; + + let parent_node = B::hash_new_parent(node, sibling_node); + + // Root must match the provided root hash. + if parent_pos == root_pos { + return parent_node == root_hash; + } + + // Create a new element for the next, upper level + parent_level.insert(parent_pos, parent_node); + } + + // We didn't create any parents, and we didn't reach the root neither. Verification fails. + if parent_level.is_empty() { + return false; + } + + // Issue the next level in the next iteration + current_level = parent_level; + } + } +} + +#[cfg(test)] +mod tests { + + // #[cfg(feature = "alloc")] + use crate::merkle_tree::{merkle::MerkleTree, test_merkle::TestBackend as TB}; + use alloc::vec::Vec; + use lambdaworks_math::field::{element::*, fields::u64_prime_field::U64PrimeField}; + extern crate std; + use std::collections::HashMap; + + /// Goldilocks + pub type Ecgfp5 = U64PrimeField<0xFFFF_FFFF_0000_0001_u64>; + pub type Ecgfp5FE = FieldElement; + pub type TestBackend = TB; + pub type TestMerkleTreeEcgfp = MerkleTree; + + // + // 20 + // / \ + // 6 14 + // / \ / \ + // 2 4 6 8 + // + // Proves inclusion of leaves whose indices are passed into 'proven_leaf_indices' + // array. These leaf indices start from 0 for the first leaf, 2 in the example above. + // If leaf_indices is [0, 3], then the test will create proof and verify inclusion + // of leaves with indices 0 and 3, that are, 2 and 8. + #[test] + fn batch_proof_pen_and_paper_example() { + let leaves_values: Vec = (1..u64::pow(2, 2) + 1).map(Ecgfp5FE::new).collect(); + let merkle_tree: MerkleTree = TestMerkleTreeEcgfp::build(&leaves_values); + + let proven_leaves_indices = [0, 3]; + let first_leaf_pos = merkle_tree.nodes_len() / 2; + let proven_leaves_positions: Vec = proven_leaves_indices + .iter() + .map(|leaf_index| leaf_index + first_leaf_pos) + .collect(); + + let batch_proof = merkle_tree + .get_batch_proof(&proven_leaves_positions) + .unwrap(); + + let proven_leaves_values_hashed: HashMap = proven_leaves_positions + .iter() + .map(|pos| (*pos, merkle_tree.get_leaf(*pos - first_leaf_pos))) + .collect(); + + assert!(batch_proof.verify::(merkle_tree.root, proven_leaves_values_hashed)); + } + + #[test] + fn batch_proof_big_tree_one_leaf() { + let leaves_values: Vec = (1..u64::pow(2, 16) + 1).map(Ecgfp5FE::new).collect(); + let merkle_tree: MerkleTree = TestMerkleTreeEcgfp::build(&leaves_values); + + let proven_leaves_indices = [76]; // Only prove one of the leaves + let first_leaf_pos = merkle_tree.nodes_len() / 2; + let proven_leaves_positions: Vec = proven_leaves_indices + .iter() + .map(|leaf_index| leaf_index + first_leaf_pos) + .collect(); + + let batch_proof = merkle_tree + .get_batch_proof(&proven_leaves_positions) + .unwrap(); + + let proven_leaves_values_hashed: HashMap = proven_leaves_positions + .iter() + .map(|pos| (*pos, merkle_tree.get_leaf(*pos - first_leaf_pos))) + .collect(); + + assert!(batch_proof.verify::(merkle_tree.root, proven_leaves_values_hashed)); + } + + #[test] + fn batch_proof_big_tree_many_leaves() { + // Just add -18 to make the test case a little more complex + let all_leaves_values: Vec = + (1..u64::pow(2, 16) - 18).map(Ecgfp5FE::new).collect(); + let merkle_tree: MerkleTree = TestMerkleTreeEcgfp::build(&all_leaves_values); + + let proven_leaves_indices = usize::pow(2, 4) + 5..(usize::pow(2, 13) + 7); + let first_leaf_pos = merkle_tree.nodes_len() / 2; + let proven_leaves_positions: Vec = proven_leaves_indices + .map(|leaf_index| leaf_index + first_leaf_pos) + .collect(); + + let batch_proof = merkle_tree + .get_batch_proof(&proven_leaves_positions) + .unwrap(); + + let proven_leaves_values_hashed: HashMap = proven_leaves_positions + .iter() + .map(|pos| (*pos, merkle_tree.get_leaf(*pos - first_leaf_pos))) + .collect(); + + assert!(batch_proof.verify::(merkle_tree.root, proven_leaves_values_hashed)); + } + + #[test] + fn create_a_merkle_tree_with_10000_elements_and_verify_that_a_series_of_elements_belong_to_it() + { + let all_leaves_values: Vec = (1..10000).map(Ecgfp5FE::new).collect(); + let merkle_tree = TestMerkleTreeEcgfp::build(&all_leaves_values); + + let proven_leaves_indices = [0].iter(); + let first_leaf_pos = merkle_tree.nodes_len() / 2; + let proven_leaves_positions: Vec = proven_leaves_indices + .clone() + .map(|leaf_index| leaf_index + first_leaf_pos) + .collect(); + + let batch_proof = merkle_tree + .get_batch_proof(&proven_leaves_positions) + .unwrap(); + + let proven_leaves_values_hashed: HashMap = proven_leaves_positions + .iter() + .map(|pos| (*pos, merkle_tree.get_leaf(*pos - first_leaf_pos))) + .collect(); + + assert!(batch_proof.verify::(merkle_tree.root, proven_leaves_values_hashed)); + } + + #[cfg(feature = "serde")] + #[test] + fn proof_is_same_after_serde() { + let all_leaves_values: Vec = (1..10000).map(Ecgfp5FE::new).collect(); + let merkle_tree = TestMerkleTreeEcgfp::build(&all_leaves_values); + + let proven_leaves_indices = [0].iter(); + let first_leaf_pos = merkle_tree.nodes_len() / 2; + let proven_leaves_positions: Vec = proven_leaves_indices + .clone() + .map(|leaf_index| leaf_index + first_leaf_pos) + .collect(); + + let batch_proof = merkle_tree + .get_batch_proof(&proven_leaves_positions) + .unwrap(); + + let serialized = batch_proof.serialize(); + let batch_proof_2 = super::BatchProof::::deserialize(&serialized); + + assert_eq!(batch_proof, batch_proof_2); + } +} diff --git a/crypto/src/merkle_tree/merkle.rs b/crypto/src/merkle_tree/merkle.rs index bbfe89bf7..103d3d147 100644 --- a/crypto/src/merkle_tree/merkle.rs +++ b/crypto/src/merkle_tree/merkle.rs @@ -1,8 +1,13 @@ use core::fmt::Display; +extern crate std; +use std::collections::HashSet; + use alloc::vec::Vec; -use super::{proof::Proof, traits::IsMerkleTreeBackend, utils::*}; +use super::{batch_proof::BatchProof, proof::Proof, traits::IsMerkleTreeBackend, utils::*}; + +const ROOT: usize = 0; #[derive(Debug)] pub enum Error { @@ -24,8 +29,6 @@ pub struct MerkleTree { nodes: Vec, } -const ROOT: usize = 0; - impl MerkleTree where B: IsMerkleTreeBackend, @@ -49,41 +52,121 @@ where //Build the inner nodes of the tree build::(&mut nodes, leaves_len); + // #[cfg(test)] + // print_positions(nodes.len(), HashSet::new()); + Some(MerkleTree { root: nodes[ROOT].clone(), nodes, }) } - pub fn get_proof_by_pos(&self, pos: usize) -> Option> { - let pos = pos + self.nodes.len() / 2; + /// Returns the leaf at the given index. + /// leaf_index starts from 0 for the first leaf. + pub fn get_leaf(&self, leaf_index: usize) -> B::Node { + let first_leaf_pos = self.nodes_len() / 2; + self.nodes[leaf_index + first_leaf_pos].clone() + } + + pub fn get_proof(&self, pos: usize) -> Option> { + let first_leaf_index = self.nodes_len() / 2; + let pos = pos + first_leaf_index; let Ok(merkle_path) = self.build_merkle_path(pos) else { return None; }; - self.create_proof(merkle_path) + Some(Proof { merkle_path }) } - fn create_proof(&self, merkle_path: Vec) -> Option> { - Some(Proof { merkle_path }) + /// Builds and returns a batch proof for when a Merkle tree is used to prove inclusion of multiple leaves. + /// + /// pos_list is a list of leaf positions (within all tree) to create a batch inclusion proof for. + /// pos_list need not be continuous, but the resulting proof becomes the smallest when so. + pub fn get_batch_proof(&self, pos_list: &[usize]) -> Option> { + let batch_auth_path_positions = self.get_batch_auth_path_positions(pos_list); + + let batch_auth_path_nodes_iter = batch_auth_path_positions + .iter() + .map(|pos| (*pos, self.nodes[*pos].clone()).clone()); + + Some(BatchProof:: { + auth: batch_auth_path_nodes_iter.collect(), + }) + } + + pub fn nodes_len(&self) -> usize { + self.nodes.len() } + /// Builds and returns a proof of inclusion for the leaf whose position is passed as an argument. + /// + /// pos parameter is the index in overall Merkle tree, including the inner nodes fn build_merkle_path(&self, pos: usize) -> Result, Error> { let mut merkle_path = Vec::new(); let mut pos = pos; while pos != ROOT { - let Some(node) = self.nodes.get(sibling_index(pos)) else { + let Some(node) = self.nodes.get(get_sibling_pos(pos)) else { // out of bounds, exit returning the current merkle_path return Err(Error::OutOfBounds); }; merkle_path.push(node.clone()); - pos = parent_index(pos); + pos = get_parent_pos(pos); } Ok(merkle_path) } + + /// Batch Merkle proofs require multiple authentication paths to be computed, and some nodes in these paths + /// can be obtained from the leaves that are subject to the batch Merkle proof. + /// This function returns a set of node positions that are supposedly just enough to satisfy all authentication + /// paths in the batch Merkle proof. + /// + /// See the following Merkle tree, where we build a batch authentication path for leaves [15,24] inclusively. + /// We'd only need nodes (12) and (6), because all the other nodes that would be needed in the authentication + /// path of any leaf can be obtained from just the leaves (which are public input). + /// If we were to build a batch authentication path for leaves [15,26] inclusively, then we'd need (6) alone, + /// because we could use nodes (25) and (26) to build (12), to be combined with (11) to obtain (5). + /// + /// 0 + /// 1 2 + /// 3 4 5 6 + /// 7 8 9 10 11 12 13 14 + /// 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + /// + /// leaf_positions is a list of leaves to create a batch inclusion proof for. + /// For the example above, it would be [15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + /// leaf_positions need not be continuous, but the resulting auth_set becomes the smallest when so. + fn get_batch_auth_path_positions(&self, leaf_positions: &[usize]) -> Vec { + let mut auth_set = HashSet::::new(); + // Add all the leaves to the set of obtainable nodes, because we already have them. + let mut obtainable_nodes_by_level: HashSet = + leaf_positions.iter().cloned().collect(); + + // Iterate levels starting from the leaves up to the root + for _ in (1..self.levels()).rev() { + let mut parent_level_obtainable_positions = HashSet::new(); + for pos in &obtainable_nodes_by_level { + let sibling_pos = get_sibling_pos(*pos); + + let sibling_is_obtainable = obtainable_nodes_by_level.contains(&sibling_pos) + || auth_set.contains(&sibling_pos); + if !sibling_is_obtainable { + auth_set.insert(sibling_pos); + } + parent_level_obtainable_positions.insert(get_parent_pos(*pos)); + } + + obtainable_nodes_by_level = parent_level_obtainable_positions; + } + + auth_set.into_iter().collect() + } + + fn levels(&self) -> usize { + (self.nodes_len() as f32).log2().ceil() as usize + } } #[cfg(test)] mod tests { @@ -95,12 +178,13 @@ mod tests { const MODULUS: u64 = 13; type U64PF = U64PrimeField; type FE = FieldElement; + type TestTree = MerkleTree>; #[test] fn build_merkle_tree_from_a_power_of_two_list_of_values() { let values: Vec = (1..5).map(FE::new).collect(); - let merkle_tree = MerkleTree::>::build(&values).unwrap(); - assert_eq!(merkle_tree.root, FE::new(7)); // Adjusted expected value + let merkle_tree = TestTree::build(&values); + assert_eq!(merkle_tree.root, FE::new(20)); } #[test] @@ -111,8 +195,9 @@ mod tests { type FE = FieldElement; let values: Vec = (1..6).map(FE::new).collect(); - let merkle_tree = MerkleTree::>::build(&values).unwrap(); - assert_eq!(merkle_tree.root, FE::new(8)); // Adjusted expected value + + let merkle_tree = TestTree::build(&values); + assert_eq!(merkle_tree.root, FE::new(8)); } #[test] diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index 5fee9b7c8..8f2f57773 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -1,4 +1,5 @@ pub mod backends; +pub mod batch_proof; pub mod merkle; pub mod proof; #[cfg(test)] diff --git a/crypto/src/merkle_tree/proof.rs b/crypto/src/merkle_tree/proof.rs index 65e37555a..488bf55e3 100644 --- a/crypto/src/merkle_tree/proof.rs +++ b/crypto/src/merkle_tree/proof.rs @@ -122,8 +122,8 @@ mod tests { fn create_a_proof_over_value_that_belongs_to_a_given_merkle_tree_when_given_the_leaf_position() { let values: Vec = (1..6).map(FE::new).collect(); - let merkle_tree = MerkleTree::>::build(&values).unwrap(); - let proof = &merkle_tree.get_proof_by_pos(1).unwrap(); + let merkle_tree = MerkleTree::>::build(&values); + let proof = &merkle_tree.get_proof(1).unwrap(); assert_merkle_path(&proof.merkle_path, &[FE::new(2), FE::new(1), FE::new(1)]); assert!(proof.verify::>(&merkle_tree.root, 1, &FE::new(2))); } @@ -142,8 +142,8 @@ mod tests { #[test] fn create_a_merkle_tree_with_10000_elements_and_verify_that_an_element_is_part_of_it() { let values: Vec = (1..10000).map(Ecgfp5FE::new).collect(); - let merkle_tree = TestMerkleTreeEcgfp::build(&values).unwrap(); - let proof = merkle_tree.get_proof_by_pos(9349).unwrap(); + let merkle_tree = TestMerkleTreeEcgfp::build(&values); + let proof = merkle_tree.get_proof(9349).unwrap(); assert!(proof.verify::>(&merkle_tree.root, 9349, &Ecgfp5FE::new(9350))); } diff --git a/crypto/src/merkle_tree/utils.rs b/crypto/src/merkle_tree/utils.rs index 1a32d205a..b1d47db62 100644 --- a/crypto/src/merkle_tree/utils.rs +++ b/crypto/src/merkle_tree/utils.rs @@ -4,19 +4,22 @@ use super::traits::IsMerkleTreeBackend; #[cfg(feature = "parallel")] use rayon::prelude::*; -pub fn sibling_index(node_index: usize) -> usize { - if node_index % 2 == 0 { - node_index - 1 +pub fn get_sibling_pos(node_pos: usize) -> usize { + if node_pos % 2 == 0 { + if node_pos == 0 { + return node_pos; + } + node_pos - 1 } else { - node_index + 1 + node_pos + 1 } } -pub fn parent_index(node_index: usize) -> usize { - if node_index % 2 == 0 { - (node_index - 1) / 2 +pub fn get_parent_pos(node_pos: usize) -> usize { + if node_pos % 2 == 0 { + (node_pos - 1) / 2 } else { - node_index / 2 + node_pos / 2 } } diff --git a/examples/merkle-tree-cli/src/main.rs b/examples/merkle-tree-cli/src/main.rs index 8b62eba00..8e89639a1 100644 --- a/examples/merkle-tree-cli/src/main.rs +++ b/examples/merkle-tree-cli/src/main.rs @@ -49,7 +49,7 @@ fn generate_merkle_proof(tree_path: String, pos: usize) -> Result<(), io::Error> let merkle_tree = MerkleTree::>::build(&values) .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "requested empty tree"))?; - let Some(proof) = merkle_tree.get_proof_by_pos(pos) else { + let Some(proof) = merkle_tree.get_proof(pos) else { return Err(io::Error::new(io::ErrorKind::Other, "Index out of bounds")); }; diff --git a/math/src/field/fields/u64_goldilocks_field.rs b/math/src/field/fields/u64_goldilocks_field.rs index 5c1a29d3c..1d9f5b93d 100644 --- a/math/src/field/fields/u64_goldilocks_field.rs +++ b/math/src/field/fields/u64_goldilocks_field.rs @@ -26,26 +26,30 @@ impl Goldilocks64Field { impl ByteConversion for u64 { #[cfg(feature = "alloc")] fn to_bytes_be(&self) -> alloc::vec::Vec { - unimplemented!() + self.to_be_bytes().to_vec() } #[cfg(feature = "alloc")] fn to_bytes_le(&self) -> alloc::vec::Vec { - unimplemented!() + self.to_le_bytes().to_vec() } fn from_bytes_be(_bytes: &[u8]) -> Result where Self: Sized, { - unimplemented!() + Ok(u64::from_be_bytes(_bytes.try_into().expect( + "Tried to create a u64 from the byte array but its size was not 8", + ))) } fn from_bytes_le(_bytes: &[u8]) -> Result where Self: Sized, { - unimplemented!() + Ok(u64::from_le_bytes(_bytes.try_into().expect( + "Tried to create a u64 from the byte array but its size was not 8", + ))) } } diff --git a/provers/stark/src/fri/mod.rs b/provers/stark/src/fri/mod.rs index b0b102319..694d18929 100644 --- a/provers/stark/src/fri/mod.rs +++ b/provers/stark/src/fri/mod.rs @@ -92,7 +92,7 @@ where for layer in fri_layers { // symmetric element let evaluation_sym = layer.evaluation[index ^ 1].clone(); - let auth_path_sym = layer.merkle_tree.get_proof_by_pos(index >> 1).unwrap(); + let auth_path_sym = layer.merkle_tree.get_proof(index >> 1).unwrap(); layers_evaluations_sym.push(evaluation_sym); layers_auth_paths_sym.push(auth_path_sym); diff --git a/provers/stark/src/prover.rs b/provers/stark/src/prover.rs index 49ed326ce..4b0445c7e 100644 --- a/provers/stark/src/prover.rs +++ b/provers/stark/src/prover.rs @@ -679,9 +679,7 @@ pub trait IsStarkProver { FieldElement: AsBytes + Sync + Send, FieldElement: AsBytes + Sync + Send, { - let proof = composition_poly_merkle_tree - .get_proof_by_pos(index) - .unwrap(); + let proof = composition_poly_merkle_tree.get_proof(index).unwrap(); let lde_composition_poly_parts_evaluation: Vec<_> = lde_composition_poly_evaluations .iter() @@ -729,8 +727,8 @@ pub trait IsStarkProver { let index = challenge * 2; let index_sym = challenge * 2 + 1; PolynomialOpenings { - proof: tree.get_proof_by_pos(index).unwrap(), - proof_sym: tree.get_proof_by_pos(index_sym).unwrap(), + proof: tree.get_proof(index).unwrap(), + proof_sym: tree.get_proof(index_sym).unwrap(), evaluations: lde_trace .get_row(reverse_index(index, domain_size as u64)) .to_vec(),