Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1ef5db0
feat: Add initial function stubs and main function structure
Jun 17, 2024
ca7064a
feat: Add generate_data
Jun 17, 2024
a70d1c2
feat: Add a test for generate_data
Jun 17, 2024
6d8fa26
feat: Add commit
Jun 17, 2024
0234c9a
feat: Add a test for commit
Jun 17, 2024
5e59f6e
chore: Refactor fri_options to fri_options_path
Jun 19, 2024
0d971ad
feat: Change default value location to command
Jun 19, 2024
96e6efc
Merge branch 'main' into feature/cli
Jun 25, 2024
520695c
feat: Add serialization for Commitment
Jun 25, 2024
dbee966
feat: Implement Serializable to Commitment
Jun 27, 2024
d1893cb
feat: Add open command
Jun 30, 2024
ed85773
feat: Initialize prover in the main
Jul 1, 2024
145f427
feat: Complete CLI implementation
Jul 1, 2024
9df2757
refactor: Refactor CLI codes
Jul 15, 2024
c73129a
Merge branch 'main' of github.com:NethermindEth/Frida-poc into featur…
Jul 15, 2024
56a3f5c
fix: Fix errors caused by change in commitment struct
Jul 15, 2024
83e22d4
refactor: Refactor handle_* functions
Jul 17, 2024
820e93a
refactor: Add CleanupFiles struct and use Path types
Jul 17, 2024
6edefee
refactor: Change deserialization of FriOptions with BP
Jul 17, 2024
97bfe52
fix: Use .display() instead of {:?}
Jul 22, 2024
bde35bb
refactor: Refactor error handling
Jul 22, 2024
b0adee7
refactor: Change to unwrap prover on an outer level
Jul 22, 2024
bc249c7
Fix conflicts with main branch
ali-rezai Sep 2, 2024
85e6d63
fix
ali-rezai Sep 2, 2024
41c015f
Fix main CLI
ali-rezai Sep 2, 2024
4fd065a
Fix cli sub command issue
ali-rezai Sep 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
target
data

# IDEs
.vscode
.idea

target
data
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ required-features = ["bench"]
clap = { version = "4.5", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
shlex = "1.3.0"
winter-crypto = "0.9.0"
winter-fri = "0.9.0"
winter-math = "0.9.0"
Expand Down
80 changes: 58 additions & 22 deletions src/commands/commit.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,85 @@
use frida_poc::{
frida_data::encoded_data_element_count,
frida_prover::{traits::BaseFriProver, FridaProver},
use crate::{
frida_prover::{Commitment, FridaProver},
frida_prover_channel::FridaProverChannel,
frida_random::FridaRandom,
utils::{read_file_to_vec, write_to_file},
};
use winter_crypto::hashers::Blake3_256;
use winter_fri::FriOptions;
use winter_math::fields::f128::BaseElement;
use winter_utils::{Deserializable, Serializable};

type Blake3 = Blake3_256<BaseElement>;
type FridaChannel =
FridaProverChannel<BaseElement, Blake3, Blake3, FridaRandom<Blake3, Blake3, BaseElement>>;
type FridaProverType = FridaProver<BaseElement, BaseElement, FridaChannel, Blake3>;

pub fn run(data_path: &str, num_queries: usize, options: FriOptions) {
let data = std::fs::read(data_path).expect("Unable to read data file");
let mut prover: FridaProverType = FridaProver::new(options.clone());
/// Runs the commitment process, saving the commitment to a file.
pub fn run(
prover: &mut FridaProverType,
num_queries: usize,
data_path: &str,
commitment_path: &str,
) -> Result<Commitment<Blake3>, Box<dyn std::error::Error>> {
// Read data from file
let data = read_file_to_vec(data_path)?;

let encoded_element_count =
encoded_data_element_count::<BaseElement>(data.len()).next_power_of_two();
// Create commitment from data
let (commitment, _) =
prover
.commit(data, num_queries)
.map_err(|e| -> Box<dyn std::error::Error> {
format!("Prover commit error: {}", e).into()
})?;

let (commitment, _) = prover.commit(data.clone(), num_queries).unwrap();
// TODO: Save commitment to file
// Write commitment to file
let commitment_bytes = commitment.to_bytes();
write_to_file(commitment_path, &commitment_bytes)?;

println!(
"Data committed with commitment: {:?} and encoded element count: {}",
commitment, encoded_element_count
);
println!("Commitment created and saved to {}", commitment_path);
Ok(commitment)
}

/// Reads the commitment from a file.
pub fn read_commitment_from_file(
file_path: &str,
) -> Result<Commitment<Blake3>, Box<dyn std::error::Error>> {
let commitment_bytes = read_file_to_vec(file_path)?;
let commitment = Commitment::<Blake3>::read_from_bytes(&commitment_bytes).map_err(
|e| -> Box<dyn std::error::Error> { format!("Deserialization error: {}", e).into() },
)?;
Ok(commitment)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::commands::generate_data;
use crate::frida_prover::traits::BaseFriProver;
use std::fs;
use winter_fri::FriOptions;

#[test]
fn test_commit() {
let data_path = "data/data.bin";
assert!(
std::path::Path::new(data_path).exists(),
"Test data file does not exist"
);
let commitment_path = "data/commitment.bin";

if !std::path::Path::new(data_path).exists() {
generate_data::run(200, data_path).unwrap();
}

let mut prover = FridaProverType::new(FriOptions::new(8, 2, 7));

// Run the commitment process
let commitment = run(&mut prover, 31, data_path, commitment_path).unwrap();

// Read the commitment from the file
let commitment_file = read_commitment_from_file(commitment_path).unwrap();

let options = FriOptions::new(8, 2, 7);
run(data_path, 31, options);
// Verify the commitment
assert_eq!(commitment, commitment_file, "Commitment does not match.");

// TODO: Check if the commitment file is correct
// Cleanup
fs::remove_file(data_path).unwrap();
fs::remove_file(commitment_path).unwrap();
Comment thread
frozenspider marked this conversation as resolved.
Outdated
}
}
75 changes: 64 additions & 11 deletions src/commands/generate_data.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,79 @@
use std::fs::File;
use std::io::Write;
use crate::utils::write_to_file;
use std::fs;
use std::io;
use winter_rand_utils::rand_vector;

pub fn run(size: usize, file_path: &str) {
pub fn run(size: usize, file_path: &str) -> Result<Vec<u8>, GenerateDataError> {
// Generate random data
let data = rand_vector::<u8>(size);
let mut file = File::create(file_path).expect("Unable to create file");
file.write_all(&data).expect("Unable to write data");

// Ensure directory exists
if let Some(parent) = std::path::Path::new(file_path).parent() {
fs::create_dir_all(parent).map_err(GenerateDataError::IoError)?;
}

// Write data to file
write_to_file(file_path, &data).map_err(GenerateDataError::IoError)?;

// Print success message
println!("Generated data of size {} and saved to {}", size, file_path);

Ok(data)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::utils::read_file_to_vec;
use std::fs;

#[test]
fn test_generate_data() {
fn test_generate_data() -> Result<(), GenerateDataError> {
let size = 200;
let file_path = "data/data.bin";
run(size, file_path);
let metadata = fs::metadata(file_path).expect("Unable to read metadata");
assert!(metadata.is_file());
assert_eq!(metadata.len(), size as u64);
let file_path = "data/test_data.bin";

// Generate data and write to file
let data = run(size, file_path)?;

// Read data from file
let file_data = read_file_to_vec(file_path).map_err(GenerateDataError::IoError)?;

// Verify data
assert_eq!(data, file_data);

// Clean up
fs::remove_file(file_path).map_err(GenerateDataError::IoError)?;

Ok(())
}
}

#[derive(Debug)]
pub enum GenerateDataError {
IoError(io::Error),
CustomError(String),
}

impl std::fmt::Display for GenerateDataError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
GenerateDataError::IoError(ref err) => write!(f, "IO error: {}", err),
GenerateDataError::CustomError(ref err) => write!(f, "Custom error: {}", err),
}
}
}

impl std::error::Error for GenerateDataError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
GenerateDataError::IoError(ref err) => Some(err),
GenerateDataError::CustomError(_) => None,
}
}
}

impl From<io::Error> for GenerateDataError {
fn from(err: io::Error) -> GenerateDataError {
GenerateDataError::IoError(err)
}
}
144 changes: 142 additions & 2 deletions src/commands/open.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,143 @@
use winter_fri::FriOptions;
use crate::{
frida_data::{build_evaluations_from_data, encoded_data_element_count},
frida_prover::{proof::FridaProof, traits::BaseFriProver, FridaProver},
frida_prover_channel::FridaProverChannel,
frida_random::FridaRandom,
utils::{read_file_to_vec, write_to_file},
};

pub fn run(proof_path: &str, position: usize, options: FriOptions) {}
use winter_crypto::hashers::Blake3_256;
use winter_math::fields::f128::BaseElement;
use winter_utils::{Deserializable, Serializable};

type Blake3 = Blake3_256<BaseElement>;
type FridaChannel =
FridaProverChannel<BaseElement, Blake3, Blake3, FridaRandom<Blake3, Blake3, BaseElement>>;
type FridaProverType = FridaProver<BaseElement, BaseElement, FridaChannel, Blake3>;

pub fn run(
prover: &mut FridaProverType,
positions: &[usize],
positions_path: &str,
evaluations_path: &str,
proof_path: &str,
) -> Result<(Vec<usize>, Vec<BaseElement>, FridaProof), Box<dyn std::error::Error>> {
let options = prover.options().clone();

// Read data from file
let data = read_file_to_vec("data/data.bin")?;

let encoded_element_count =
encoded_data_element_count::<BaseElement>(data.len()).next_power_of_two();

// Create proof
let proof = prover.open(positions);

let domain_size = (encoded_element_count - 1).next_power_of_two() * options.blowup_factor();
let evaluations = build_evaluations_from_data(&data, domain_size, options.blowup_factor())
.map_err(|e| -> Box<dyn std::error::Error> {
format!("Failed to build evaluations: {}", e).into()
})?;

let queried_evaluations: Vec<BaseElement> = positions.iter().map(|&p| evaluations[p]).collect();

// Write positions, evaluations, and proof to files
write_to_file(positions_path, &positions.to_bytes())?;
write_to_file(evaluations_path, &queried_evaluations.to_bytes())?;
write_to_file(proof_path, &proof.to_bytes())?;

Ok((positions.to_vec(), queried_evaluations, proof))
}

pub fn read_and_deserialize_proof(
positions_path: &str,
evaluations_path: &str,
proof_path: &str,
) -> Result<(Vec<usize>, Vec<BaseElement>, FridaProof), Box<dyn std::error::Error>> {
// Read and deserialize positions
let positions_bytes = read_file_to_vec(positions_path)?;
let positions = Vec::<usize>::read_from_bytes(&positions_bytes).map_err(
|e| -> Box<dyn std::error::Error> { format!("Deserialization error: {}", e).into() },
)?;

// Read and deserialize evaluations
let queried_evaluations_bytes = read_file_to_vec(evaluations_path)?;
let queried_evaluations = Vec::<BaseElement>::read_from_bytes(&queried_evaluations_bytes)
.map_err(|e| -> Box<dyn std::error::Error> {
format!("Deserialization error: {}", e).into()
})?;

// Read and deserialize proof
let proof_bytes = read_file_to_vec(proof_path)?;
let proof =
FridaProof::read_from_bytes(&proof_bytes).map_err(|e| -> Box<dyn std::error::Error> {
format!("Deserialization error: {}", e).into()
})?;

Ok((positions, queried_evaluations, proof))
}

#[cfg(test)]
mod tests {
use super::*;
use crate::commands::generate_data;
use std::fs;
use winter_fri::FriOptions;

#[test]
fn test_open() {
let data_path = "data/data.bin";
let positions_path = "data/positions.bin";
let evaluations_path = "data/evaluations.bin";
let proof_path = "data/proof.bin";

if !std::path::Path::new(data_path).exists() {
generate_data::run(200, data_path).unwrap();
}

let data = fs::read(data_path).unwrap();
let num_queries = 31;

let mut prover = FridaProverType::new(FriOptions::new(8, 2, 7));
prover.commit(data, num_queries).unwrap();

let positions = vec![0, 5, 10];

let result = run(
&mut prover,
&positions,
positions_path,
evaluations_path,
proof_path,
);
assert!(result.is_ok(), "Failed to generate proof and evaluations.");

let (positions, queried_evaluations, proof) = result.unwrap();

let deserialized_result =
read_and_deserialize_proof(positions_path, evaluations_path, proof_path);
assert!(
deserialized_result.is_ok(),
"Failed to deserialize proof and evaluations."
);

let (deserialized_positions, deserialized_evaluations, deserialized_proof) =
deserialized_result.unwrap();

assert_eq!(positions, deserialized_positions, "Positions do not match.");
assert_eq!(
queried_evaluations, deserialized_evaluations,
"Queried evaluations do not match."
);
assert_eq!(
proof.to_bytes(),
deserialized_proof.to_bytes(),
"Proof does not match."
);

fs::remove_file(data_path).unwrap();
fs::remove_file(proof_path).unwrap();
fs::remove_file(positions_path).unwrap();
fs::remove_file(evaluations_path).unwrap();
}
}
Loading