mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-11-15 18:47:01 +00:00
Squashed 'bellman/' changes from 4272cfa..2279da4
2279da4 Merge pull request #38 from debris/docs 2e57190 Remove documentation entry from Cargo.toml 346d540 bellman 0.2.0 8d79665 Merge pull request #93 from defuse/qed-it-lrz f50079f Crate docs 701cb2b Update READMEs ccf1ee9 CI: Check intra-doc links ddd390a Add READMEs to Cargo.toml files 54d3122 Add missing cs.is_satisfied() to bellman test 52bf23c Fix build warnings 581ad35 boolean: adds tests for alloc_conditionally 0403396 blake2s: adds test vectors from go-jubjub 9f24e47 Fix blake2s test data length assertion. 42d5b3b Add blake2s test vectors for varying sizes from go-jubjub b2597de pedersen_hash: removes debug prints c903fad pedersen hashes: example of size limit bug bc697c1 bellman: Fix compile errors without multicore feature a4e5df9 Upgrade to hex-literal 0.2 c063509 Migrate bellman to crossbeam 0.7 1775843 Take self directly in into_* functions 614d784 Rename into_ -> to_ where &self is used. 08664b1 Address various clippy warnings/errors in bellman bb11ef2 cargo fmt cff2e2f cargo fix --edition-idioms for bellman dc2a280 Add edition = 2018 1a2bc19 cargo fmt ad37878 cargo fix --edition for bellman e73d1a2 cargo fmt bellman dfb86fc Move generic circuit gadgets into bellman 9b3d766 Migrate to rand 0.7 055280f Migrate ff, group, pairing, and bellman to rand 0.6 533d586 Migrate bellman to rand 0.5 bfa9aaf Merge pull request #61 from rex4539/fix-typos 3dd8490 Place bellman multicore operations behind a (default) feature flag 955e679 Merge pull request #46 from str4d/ff-traits d4ddaa9 Fix typos 12f93f2 Add ff and group crates to Cargo workspace 2e35a32 Update sapling-crypto crate to use ff crate 2019e63 Update workspace after pulling in external crates git-subtree-dir: bellman git-subtree-split: 2279da422ca9d7b83e84cb85018c713976b873e5
This commit is contained in:
229
tests/mimc.rs
Normal file
229
tests/mimc.rs
Normal file
@@ -0,0 +1,229 @@
|
||||
// For randomness (during paramgen and proof generation)
|
||||
use rand::thread_rng;
|
||||
|
||||
// For benchmarking
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
// Bring in some tools for using pairing-friendly curves
|
||||
use ff::{Field, ScalarEngine};
|
||||
use pairing::Engine;
|
||||
|
||||
// We're going to use the BLS12-381 pairing-friendly elliptic curve.
|
||||
use pairing::bls12_381::Bls12;
|
||||
|
||||
// We'll use these interfaces to construct our circuit.
|
||||
use bellman::{Circuit, ConstraintSystem, SynthesisError};
|
||||
|
||||
// We're going to use the Groth16 proving system.
|
||||
use bellman::groth16::{
|
||||
create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Proof,
|
||||
};
|
||||
|
||||
const MIMC_ROUNDS: usize = 322;
|
||||
|
||||
/// This is an implementation of MiMC, specifically a
|
||||
/// variant named `LongsightF322p3` for BLS12-381.
|
||||
/// See http://eprint.iacr.org/2016/492 for more
|
||||
/// information about this construction.
|
||||
///
|
||||
/// ```
|
||||
/// function LongsightF322p3(xL ⦂ Fp, xR ⦂ Fp) {
|
||||
/// for i from 0 up to 321 {
|
||||
/// xL, xR := xR + (xL + Ci)^3, xL
|
||||
/// }
|
||||
/// return xL
|
||||
/// }
|
||||
/// ```
|
||||
fn mimc<E: Engine>(mut xl: E::Fr, mut xr: E::Fr, constants: &[E::Fr]) -> E::Fr {
|
||||
assert_eq!(constants.len(), MIMC_ROUNDS);
|
||||
|
||||
for i in 0..MIMC_ROUNDS {
|
||||
let mut tmp1 = xl;
|
||||
tmp1.add_assign(&constants[i]);
|
||||
let mut tmp2 = tmp1;
|
||||
tmp2.square();
|
||||
tmp2.mul_assign(&tmp1);
|
||||
tmp2.add_assign(&xr);
|
||||
xr = xl;
|
||||
xl = tmp2;
|
||||
}
|
||||
|
||||
xl
|
||||
}
|
||||
|
||||
/// This is our demo circuit for proving knowledge of the
|
||||
/// preimage of a MiMC hash invocation.
|
||||
struct MiMCDemo<'a, E: Engine> {
|
||||
xl: Option<E::Fr>,
|
||||
xr: Option<E::Fr>,
|
||||
constants: &'a [E::Fr],
|
||||
}
|
||||
|
||||
/// Our demo circuit implements this `Circuit` trait which
|
||||
/// is used during paramgen and proving in order to
|
||||
/// synthesize the constraint system.
|
||||
impl<'a, E: Engine> Circuit<E> for MiMCDemo<'a, E> {
|
||||
fn synthesize<CS: ConstraintSystem<E>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
|
||||
assert_eq!(self.constants.len(), MIMC_ROUNDS);
|
||||
|
||||
// Allocate the first component of the preimage.
|
||||
let mut xl_value = self.xl;
|
||||
let mut xl = cs.alloc(
|
||||
|| "preimage xl",
|
||||
|| xl_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
// Allocate the second component of the preimage.
|
||||
let mut xr_value = self.xr;
|
||||
let mut xr = cs.alloc(
|
||||
|| "preimage xr",
|
||||
|| xr_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
for i in 0..MIMC_ROUNDS {
|
||||
// xL, xR := xR + (xL + Ci)^3, xL
|
||||
let cs = &mut cs.namespace(|| format!("round {}", i));
|
||||
|
||||
// tmp = (xL + Ci)^2
|
||||
let tmp_value = xl_value.map(|mut e| {
|
||||
e.add_assign(&self.constants[i]);
|
||||
e.square();
|
||||
e
|
||||
});
|
||||
let tmp = cs.alloc(
|
||||
|| "tmp",
|
||||
|| tmp_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "tmp = (xL + Ci)^2",
|
||||
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||
|lc| lc + tmp,
|
||||
);
|
||||
|
||||
// new_xL = xR + (xL + Ci)^3
|
||||
// new_xL = xR + tmp * (xL + Ci)
|
||||
// new_xL - xR = tmp * (xL + Ci)
|
||||
let new_xl_value = xl_value.map(|mut e| {
|
||||
e.add_assign(&self.constants[i]);
|
||||
e.mul_assign(&tmp_value.unwrap());
|
||||
e.add_assign(&xr_value.unwrap());
|
||||
e
|
||||
});
|
||||
|
||||
let new_xl = if i == (MIMC_ROUNDS - 1) {
|
||||
// This is the last round, xL is our image and so
|
||||
// we allocate a public input.
|
||||
cs.alloc_input(
|
||||
|| "image",
|
||||
|| new_xl_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?
|
||||
} else {
|
||||
cs.alloc(
|
||||
|| "new_xl",
|
||||
|| new_xl_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?
|
||||
};
|
||||
|
||||
cs.enforce(
|
||||
|| "new_xL = xR + (xL + Ci)^3",
|
||||
|lc| lc + tmp,
|
||||
|lc| lc + xl + (self.constants[i], CS::one()),
|
||||
|lc| lc + new_xl - xr,
|
||||
);
|
||||
|
||||
// xR = xL
|
||||
xr = xl;
|
||||
xr_value = xl_value;
|
||||
|
||||
// xL = new_xL
|
||||
xl = new_xl;
|
||||
xl_value = new_xl_value;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mimc() {
|
||||
// This may not be cryptographically safe, use
|
||||
// `OsRng` (for example) in production software.
|
||||
let rng = &mut thread_rng();
|
||||
|
||||
// Generate the MiMC round constants
|
||||
let constants = (0..MIMC_ROUNDS)
|
||||
.map(|_| <Bls12 as ScalarEngine>::Fr::random(rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!("Creating parameters...");
|
||||
|
||||
// Create parameters for our circuit
|
||||
let params = {
|
||||
let c = MiMCDemo::<Bls12> {
|
||||
xl: None,
|
||||
xr: None,
|
||||
constants: &constants,
|
||||
};
|
||||
|
||||
generate_random_parameters(c, rng).unwrap()
|
||||
};
|
||||
|
||||
// Prepare the verification key (for proof verification)
|
||||
let pvk = prepare_verifying_key(¶ms.vk);
|
||||
|
||||
println!("Creating proofs...");
|
||||
|
||||
// Let's benchmark stuff!
|
||||
const SAMPLES: u32 = 50;
|
||||
let mut total_proving = Duration::new(0, 0);
|
||||
let mut total_verifying = Duration::new(0, 0);
|
||||
|
||||
// Just a place to put the proof data, so we can
|
||||
// benchmark deserialization.
|
||||
let mut proof_vec = vec![];
|
||||
|
||||
for _ in 0..SAMPLES {
|
||||
// Generate a random preimage and compute the image
|
||||
let xl = <Bls12 as ScalarEngine>::Fr::random(rng);
|
||||
let xr = <Bls12 as ScalarEngine>::Fr::random(rng);
|
||||
let image = mimc::<Bls12>(xl, xr, &constants);
|
||||
|
||||
proof_vec.truncate(0);
|
||||
|
||||
let start = Instant::now();
|
||||
{
|
||||
// Create an instance of our circuit (with the
|
||||
// witness)
|
||||
let c = MiMCDemo {
|
||||
xl: Some(xl),
|
||||
xr: Some(xr),
|
||||
constants: &constants,
|
||||
};
|
||||
|
||||
// Create a groth16 proof with our parameters.
|
||||
let proof = create_random_proof(c, ¶ms, rng).unwrap();
|
||||
|
||||
proof.write(&mut proof_vec).unwrap();
|
||||
}
|
||||
|
||||
total_proving += start.elapsed();
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = Proof::read(&proof_vec[..]).unwrap();
|
||||
// Check the proof
|
||||
assert!(verify_proof(&pvk, &proof, &[image]).unwrap());
|
||||
total_verifying += start.elapsed();
|
||||
}
|
||||
let proving_avg = total_proving / SAMPLES;
|
||||
let proving_avg =
|
||||
proving_avg.subsec_nanos() as f64 / 1_000_000_000f64 + (proving_avg.as_secs() as f64);
|
||||
|
||||
let verifying_avg = total_verifying / SAMPLES;
|
||||
let verifying_avg =
|
||||
verifying_avg.subsec_nanos() as f64 / 1_000_000_000f64 + (verifying_avg.as_secs() as f64);
|
||||
|
||||
println!("Average proving time: {:?} seconds", proving_avg);
|
||||
println!("Average verifying time: {:?} seconds", verifying_avg);
|
||||
}
|
||||
Reference in New Issue
Block a user