diff --git a/src/bin/mint-classic.rs b/src/bin/mint-classic.rs index 367c40449..414c390eb 100644 --- a/src/bin/mint-classic.rs +++ b/src/bin/mint-classic.rs @@ -5,71 +5,7 @@ use bls12_381::Bls12; use ff::Field; use group::{Curve, Group, GroupEncoding}; -use sapvi::circuit::mint_contract::MintContract; - -struct MintRevealedValues { - value_commit: jubjub::SubgroupPoint, - coin: [u8; 32], -} - -impl MintRevealedValues { - fn compute( - value: u64, - randomness_value: &jubjub::Fr, - serial: &jubjub::Fr, - randomness_coin: &jubjub::Fr, - public: &jubjub::SubgroupPoint, - ) -> Self { - let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR - * jubjub::Fr::from(value)) - + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR - * randomness_value); - - let mut coin = [0; 32]; - coin.copy_from_slice( - Blake2sParams::new() - .hash_length(32) - .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION) - .to_state() - .update(&public.to_bytes()) - .update(&value.to_le_bytes()) - .update(&serial.to_bytes()) - .update(&randomness_coin.to_bytes()) - .finalize() - .as_bytes(), - ); - - MintRevealedValues { value_commit, coin } - } - - fn make_outputs(&self) -> [bls12_381::Scalar; 4] { - let mut public_input = [bls12_381::Scalar::zero(); 4]; - - { - let result = jubjub::ExtendedPoint::from(self.value_commit); - let affine = result.to_affine(); - //let (u, v) = (affine.get_u(), affine.get_v()); - let u = affine.get_u(); - let v = affine.get_v(); - public_input[0] = u; - public_input[1] = v; - } - - { - // Pack the hash as inputs for proof verification. - let hash = multipack::bytes_to_bits_le(&self.coin); - let hash = multipack::compute_multipacking(&hash); - - // There are 2 chunks for a blake hash - assert_eq!(hash.len(), 2); - - public_input[2] = hash[0]; - public_input[3] = hash[1]; - } - - public_input - } -} +use sapvi::crypto::{setup_mint_prover, create_mint_proof, verify_mint_proof}; fn main() { use rand::rngs::OsRng; @@ -83,80 +19,10 @@ fn main() { let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng); let randomness_coin: jubjub::Fr = jubjub::Fr::random(&mut OsRng); - let revealed = - MintRevealedValues::compute(value, &randomness_value, &serial, &randomness_coin, &public); + let (params, pvk) = setup_mint_prover(); - println!("Making random params..."); - let start = Instant::now(); - let params = { - let c = MintContract { - value: None, - randomness_value: None, - serial: None, - randomness_coin: None, - public: None, - }; - groth16::generate_random_parameters::(c, &mut OsRng).unwrap() - }; - let pvk = groth16::prepare_verifying_key(¶ms.vk); - println!("Setup: [{:?}]", start.elapsed()); + let (proof, revealed) = create_mint_proof(¶ms, value, randomness_value, serial, randomness_coin, + public); - let c = MintContract { - value: Some(value), - randomness_value: Some(randomness_value), - serial: Some(serial), - randomness_coin: Some(randomness_coin), - public: Some(public), - }; - - let start = Instant::now(); - let proof = groth16::create_random_proof(c, ¶ms, &mut OsRng).unwrap(); - println!("Prove: [{:?}]", start.elapsed()); - - /* - let mut public_input = [bls12_381::Scalar::zero(); 4]; - { - let result = jubjub::ExtendedPoint::from(public); - let affine = result.to_affine(); - //let (u, v) = (affine.get_u(), affine.get_v()); - let u = affine.get_u(); - let v = affine.get_v(); - public_input[0] = u; - public_input[1] = v; - } - - { - const CRH_IVK_PERSONALIZATION: &[u8; 8] = b"Zcashivk"; - let preimage = [42; 80]; - let hash_result = { - let mut hash = [0; 32]; - hash.copy_from_slice( - Blake2sParams::new() - .hash_length(32) - .personal(CRH_IVK_PERSONALIZATION) - .to_state() - .update(&ak.to_bytes()) - .finalize() - .as_bytes() - ); - hash - }; - - // Pack the hash as inputs for proof verification. - let hash = multipack::bytes_to_bits_le(&hash_result); - let hash = multipack::compute_multipacking(&hash); - - // There are 2 chunks for a blake hash - assert_eq!(hash.len(), 2); - - public_input[2] = hash[0]; - public_input[3] = hash[1]; - } - */ - - let public_input = revealed.make_outputs(); - - let start = Instant::now(); - assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok()); - println!("Verify: [{:?}]", start.elapsed()); + assert!(verify_mint_proof(&pvk, &proof, &revealed)); } diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs new file mode 100644 index 000000000..92bde2c15 --- /dev/null +++ b/src/crypto/mod.rs @@ -0,0 +1,4 @@ +pub mod payment_proof; + +pub use payment_proof::{setup_mint_prover, create_mint_proof, verify_mint_proof}; + diff --git a/src/crypto/payment_proof.rs b/src/crypto/payment_proof.rs new file mode 100644 index 000000000..a4796e06c --- /dev/null +++ b/src/crypto/payment_proof.rs @@ -0,0 +1,132 @@ +use rand::rngs::OsRng; +use std::time::Instant; +use bellman::gadgets::multipack; +use bellman::groth16; +use blake2s_simd::Params as Blake2sParams; +use bls12_381::Bls12; +use ff::Field; +use group::{Curve, Group, GroupEncoding}; + +use crate::circuit::mint_contract::MintContract; + +pub struct MintRevealedValues { + pub value_commit: jubjub::SubgroupPoint, + pub coin: [u8; 32], +} + +impl MintRevealedValues { + fn compute( + value: u64, + randomness_value: &jubjub::Fr, + serial: &jubjub::Fr, + randomness_coin: &jubjub::Fr, + public: &jubjub::SubgroupPoint, + ) -> Self { + let value_commit = (zcash_primitives::constants::VALUE_COMMITMENT_VALUE_GENERATOR + * jubjub::Fr::from(value)) + + (zcash_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR + * randomness_value); + + let mut coin = [0; 32]; + coin.copy_from_slice( + Blake2sParams::new() + .hash_length(32) + .personal(zcash_primitives::constants::CRH_IVK_PERSONALIZATION) + .to_state() + .update(&public.to_bytes()) + .update(&value.to_le_bytes()) + .update(&serial.to_bytes()) + .update(&randomness_coin.to_bytes()) + .finalize() + .as_bytes(), + ); + + MintRevealedValues { value_commit, coin } + } + + fn make_outputs(&self) -> [bls12_381::Scalar; 4] { + let mut public_input = [bls12_381::Scalar::zero(); 4]; + + { + let result = jubjub::ExtendedPoint::from(self.value_commit); + let affine = result.to_affine(); + //let (u, v) = (affine.get_u(), affine.get_v()); + let u = affine.get_u(); + let v = affine.get_v(); + public_input[0] = u; + public_input[1] = v; + } + + { + // Pack the hash as inputs for proof verification. + let hash = multipack::bytes_to_bits_le(&self.coin); + let hash = multipack::compute_multipacking(&hash); + + // There are 2 chunks for a blake hash + assert_eq!(hash.len(), 2); + + public_input[2] = hash[0]; + public_input[3] = hash[1]; + } + + public_input + } +} + +pub fn setup_mint_prover() -> (groth16::Parameters, groth16::PreparedVerifyingKey) { + println!("Making random params..."); + let start = Instant::now(); + let params = { + let c = MintContract { + value: None, + randomness_value: None, + serial: None, + randomness_coin: None, + public: None, + }; + groth16::generate_random_parameters::(c, &mut OsRng).unwrap() + }; + let pvk = groth16::prepare_verifying_key(¶ms.vk); + println!("Setup: [{:?}]", start.elapsed()); + (params, pvk) +} + +pub fn create_mint_proof( + params: &groth16::Parameters, + value: u64, + randomness_value: jubjub::Fr, + serial: jubjub::Fr, + randomness_coin: jubjub::Fr, + public: jubjub::SubgroupPoint + ) -> (groth16::Proof, MintRevealedValues) { + let revealed = + MintRevealedValues::compute(value, &randomness_value, &serial, &randomness_coin, &public); + + let c = MintContract { + value: Some(value), + randomness_value: Some(randomness_value), + serial: Some(serial), + randomness_coin: Some(randomness_coin), + public: Some(public), + }; + + let start = Instant::now(); + let proof = groth16::create_random_proof(c, params, &mut OsRng).unwrap(); + println!("Prove: [{:?}]", start.elapsed()); + + (proof, revealed) +} + +pub fn verify_mint_proof( + pvk: &groth16::PreparedVerifyingKey, + proof: &groth16::Proof, + revealed: &MintRevealedValues + ) -> bool { + let public_input = revealed.make_outputs(); + + let start = Instant::now(); + let result = groth16::verify_proof(pvk, proof, &public_input).is_ok(); + println!("Verify: [{:?}]", start.elapsed()); + result +} + diff --git a/src/lib.rs b/src/lib.rs index 5e889b8dc..528b28a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet}; pub mod async_serial; pub mod bls_extensions; pub mod circuit; +pub mod crypto; pub mod endian; pub mod error; pub mod gfx;