mod mimc;
use std::fs::{remove_file, File};
use std::io::{BufReader, BufWriter};
use std::path::Path;
use bellperson::groth16::{create_random_proof, prepare_verifying_key, verify_proof};
use ff::Field;
use bellperson::bls::{Bls12, Fr};
use phase21::small::{read_small_params_from_large_file, verify_contribution_small, MPCSmall};
use phase21::{verify_contribution, MPCParameters};
use rand::{thread_rng, SeedableRng};
use rand_chacha::ChaChaRng;
use mimc::{mimc as mimc_hash, MiMCDemo, MIMC_ROUNDS};
#[test]
#[ignore]
fn test_mimc_small_params() {
assert!(
Path::new("./phase1radix2m10").exists(),
"the phase1 file `phase1radix2m10` must be in the crate's top level directory"
);
let constants = (0..MIMC_ROUNDS)
.map(|_| Fr::random(&mut thread_rng()))
.collect::<Vec<_>>();
let circuit = MiMCDemo::<Bls12> {
xl: None,
xr: None,
constants: &constants,
};
let mut rng_large = ChaChaRng::from_seed([0u8; 32]);
let mut rng_small = ChaChaRng::from_seed([0u8; 32]);
let initial_large = MPCParameters::new(circuit).unwrap();
let initial_small = initial_large.copy_small();
let mut large_added = initial_large.copy();
let (first_large, first_large_contrib) = {
let mut params = initial_large.copy();
let contrib = params.contribute(&mut rng_large);
(params, contrib)
};
let (first_small, first_small_contrib) = {
let mut params = initial_small.clone();
let contrib = params.contribute(&mut rng_small);
(params, contrib)
};
assert_eq!(
&first_small_contrib[..],
&first_large_contrib[..],
"first small and large contributions are not equal"
);
let verified_large = verify_contribution(&initial_large, &first_large)
.expect("first large verify_contribution() failed");
assert_eq!(
&first_large_contrib[..],
&verified_large[..],
"first large contribution does not match verified contribution"
);
let verified_small = verify_contribution_small(&initial_small, &first_small)
.expect("first small verify_contribution_small() failed");
assert_eq!(
&first_small_contrib[..],
&verified_small[..],
"first small contribution does not match verified contribution"
);
assert!(first_large.has_last_contrib(&first_small));
large_added.add_contrib(first_small.clone());
assert_eq!(large_added, first_large);
let (second_large, second_large_contrib) = {
let mut params = first_large.copy();
let contrib = params.contribute(&mut rng_large);
(params, contrib)
};
let (second_small, second_small_contrib) = {
let mut params = first_small.clone();
let contrib = params.contribute(&mut rng_small);
(params, contrib)
};
assert_eq!(
&second_small_contrib[..],
&second_large_contrib[..],
"second small and large contributions are not equal"
);
let verified_large = verify_contribution(&first_large, &second_large)
.expect("second large verify_contribution() failed");
assert_eq!(
&second_large_contrib[..],
&verified_large[..],
"second large contribution does not match verified contribution"
);
let verified_small = verify_contribution_small(&first_small, &second_small)
.expect("second small verify_contribution_small() failed");
assert_eq!(
&second_small_contrib[..],
&verified_small[..],
"second small contribution does not match verified contribution"
);
assert!(second_large.has_last_contrib(&second_small));
large_added.add_contrib(second_small.clone());
assert_eq!(large_added, second_large);
let all_contributions = large_added
.verify(MiMCDemo::<Bls12> {
xl: None,
xr: None,
constants: &constants,
})
.unwrap();
assert_eq!(all_contributions.len(), 2);
assert_eq!(&all_contributions[0][..], &first_large_contrib[..]);
assert_eq!(&all_contributions[1][..], &second_large_contrib[..]);
let groth_params = large_added.get_params();
let pvk = prepare_verifying_key(&groth_params.vk);
let xl = Fr::random(&mut thread_rng());
let xr = Fr::random(&mut thread_rng());
let image = mimc_hash::<Bls12>(xl, xr, &constants);
let circuit = MiMCDemo {
xl: Some(xl),
xr: Some(xr),
constants: &constants,
};
let proof = create_random_proof(circuit, groth_params, &mut thread_rng())
.expect("failed to create Groth16 proof using MPC params");
assert!(verify_proof(&pvk, &proof, &[image]).unwrap());
}
#[test]
#[ignore]
fn test_small_file_io() {
const LARGE_PATH: &str = "./tests/large_params";
const SMALL_PATH: &str = "./tests/small_params";
struct TestCleanup;
impl Drop for TestCleanup {
fn drop(&mut self) {
remove_file(LARGE_PATH).unwrap();
remove_file(SMALL_PATH).unwrap();
}
}
let _cleanup = TestCleanup;
assert!(
Path::new("./phase1radix2m10").exists(),
"the phase1 file `phase1radix2m10` must be in the crate's top level directory"
);
let constants = (0..MIMC_ROUNDS)
.map(|_| Fr::random(&mut thread_rng()))
.collect::<Vec<_>>();
let circuit = MiMCDemo::<Bls12> {
xl: None,
xr: None,
constants: &constants,
};
let large_params = MPCParameters::new(circuit).unwrap();
let small_params = large_params.copy_small();
{
let file = File::create(LARGE_PATH).unwrap();
let mut writer = BufWriter::with_capacity(1024 * 1024, file);
large_params.write(&mut writer).unwrap();
}
{
let file = File::create(SMALL_PATH).unwrap();
let mut writer = BufWriter::with_capacity(1024 * 1024, file);
small_params.write(&mut writer).unwrap();
}
{
let file = File::open(SMALL_PATH).unwrap();
let mut reader = BufReader::with_capacity(1024 * 1024, file);
let small_read = MPCSmall::read(&mut reader, false, false).unwrap();
assert_eq!(small_read, small_params);
assert!(large_params.has_last_contrib(&small_read));
};
{
let small_read = read_small_params_from_large_file(LARGE_PATH).unwrap();
assert_eq!(small_read, small_params);
}
}