diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 1909afa..4a2c349 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -1024,15 +1024,15 @@ pub extern "system" fn librustzcash_sapling_output_proof( diversifier: diversifier, }; - // Initialize secure RNG - let mut rng = OsRng::new().expect("should be able to construct RNG"); - // The caller provides the commitment randomness for the output note let rcm = match Fs::from_repr(read_fs(&(unsafe { &*rcm })[..])) { Ok(p) => p, Err(_) => return false, }; + // Initialize secure RNG + let mut rng = OsRng::new().expect("should be able to construct RNG"); + // We construct ephemeral randomness for the value commitment. This // randomness is not given back to the caller, but the synthetic // blinding factor `bsk` is accumulated in the context. @@ -1070,11 +1070,6 @@ pub extern "system" fn librustzcash_sapling_output_proof( &mut rng, ).expect("proving should not fail"); - // Write the proof out to the caller - proof - .write(&mut (unsafe { &mut *zkproof })[..]) - .expect("should be able to serialize a proof"); - // Compute the value commitment let value_commitment: edwards::Point = value_commitment.cm(&JUBJUB).into(); @@ -1088,6 +1083,11 @@ pub extern "system" fn librustzcash_sapling_output_proof( unsafe { &mut *ctx }.bvk = tmp; } + // Write the proof out to the caller + proof + .write(&mut (unsafe { &mut *zkproof })[..]) + .expect("should be able to serialize a proof"); + // Write the value commitment to the caller value_commitment .write(&mut (unsafe { &mut *cv })[..]) @@ -1152,6 +1152,9 @@ pub extern "system" fn librustzcash_sapling_binding_sig( sighash: *const [c_uchar; 32], result: *mut [c_uchar; 64], ) -> bool { + // Initialize secure RNG + let mut rng = OsRng::new().expect("should be able to construct RNG"); + // Grab the current `bsk` from the context let bsk = redjubjub::PrivateKey::(unsafe { &*ctx }.bsk); @@ -1191,7 +1194,6 @@ pub extern "system" fn librustzcash_sapling_binding_sig( (&mut data_to_be_signed[32..64]).copy_from_slice(&(unsafe { &*sighash })[..]); // Sign - let mut rng = OsRng::new().expect("should be able to construct RNG"); let sig = bsk.sign( &data_to_be_signed, &mut rng, @@ -1221,26 +1223,6 @@ pub extern "system" fn librustzcash_sapling_spend_proof( rk_out: *mut [c_uchar; 32], zkproof: *mut [c_uchar; GROTH_PROOF_SIZE], ) -> bool { - let mut rng = OsRng::new().expect("should be able to construct RNG"); - - // We create the randomness of the value commitment - let rcv = Fs::rand(&mut rng); - - // Accumulate the value commitment randomness in the context - { - let mut tmp = rcv.clone(); - tmp.add_assign(&unsafe { &*ctx }.bsk); - - // Update the context - unsafe { &mut *ctx }.bsk = tmp; - } - - // Construct the value commitment - let value_commitment = ValueCommitment:: { - value: value, - randomness: rcv, - }; - // Grab `ak` from the caller, which should be a point. let ak = match edwards::Point::::read(&(unsafe { &*ak })[..], &JUBJUB) { Ok(p) => p, @@ -1265,18 +1247,9 @@ pub extern "system" fn librustzcash_sapling_spend_proof( nsk, }; - // Construct the viewing key - let viewing_key = proof_generation_key.into_viewing_key(&JUBJUB); - // Grab the diversifier from the caller let diversifier = sapling_crypto::primitives::Diversifier(unsafe { *diversifier }); - // Construct the payment address with the viewing key / diversifier - let payment_address = match viewing_key.into_payment_address(diversifier, &JUBJUB) { - Some(p) => p, - None => return false, - }; - // The caller chooses the note randomness let rcm = match Fs::from_repr(read_fs(&(unsafe { &*rcm })[..])) { Ok(p) => p, @@ -1289,6 +1262,36 @@ pub extern "system" fn librustzcash_sapling_spend_proof( Err(_) => return false, }; + // Initialize secure RNG + let mut rng = OsRng::new().expect("should be able to construct RNG"); + + // We create the randomness of the value commitment + let rcv = Fs::rand(&mut rng); + + // Accumulate the value commitment randomness in the context + { + let mut tmp = rcv.clone(); + tmp.add_assign(&unsafe { &*ctx }.bsk); + + // Update the context + unsafe { &mut *ctx }.bsk = tmp; + } + + // Construct the value commitment + let value_commitment = ValueCommitment:: { + value: value, + randomness: rcv, + }; + + // Construct the viewing key + let viewing_key = proof_generation_key.into_viewing_key(&JUBJUB); + + // Construct the payment address with the viewing key / diversifier + let payment_address = match viewing_key.into_payment_address(diversifier, &JUBJUB) { + Some(p) => p, + None => return false, + }; + // This is the result of the re-randomization, we compute it for the caller let rk = redjubjub::PublicKey::(ak.into()).randomize( ar, @@ -1296,10 +1299,6 @@ pub extern "system" fn librustzcash_sapling_spend_proof( &JUBJUB, ); - // Write out `rk` to the caller - rk.write(&mut unsafe { &mut *rk_out }[..]) - .expect("should be able to write to rk_out"); - // We need to compute the anchor of the Spend. let anchor = match Fr::from_repr(read_le(unsafe { &(&*anchor)[..] })) { Ok(p) => p, @@ -1453,6 +1452,10 @@ pub extern "system" fn librustzcash_sapling_spend_proof( .write(&mut (unsafe { &mut *zkproof })[..]) .expect("should be able to serialize a proof"); + // Write out `rk` to the caller + rk.write(&mut unsafe { &mut *rk_out }[..]) + .expect("should be able to write to rk_out"); + true }