Refactor Sapling verification checks

This commit is contained in:
Jack Grigg 2018-11-30 23:50:50 +00:00
parent 8be50c9531
commit eb2db2e667
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829

View File

@ -690,10 +690,39 @@ pub extern "system" fn librustzcash_sapling_check_spend(
Err(_) => return false,
};
// Deserialize the anchor, which should be an element
// of Fr.
let anchor = match Fr::from_repr(read_le(&(unsafe { &*anchor })[..])) {
Ok(a) => a,
Err(_) => return false,
};
// Deserialize rk
let rk = match redjubjub::PublicKey::<Bls12>::read(&(unsafe { &*rk })[..], &JUBJUB) {
Ok(p) => p,
Err(_) => return false,
};
// Deserialize the signature
let spend_auth_sig = match Signature::read(&(unsafe { &*spend_auth_sig })[..]) {
Ok(sig) => sig,
Err(_) => return false,
};
// Deserialize the proof
let zkproof = match Proof::<Bls12>::read(&(unsafe { &*zkproof })[..]) {
Ok(p) => p,
Err(_) => return false,
};
if is_small_order(&cv) {
return false;
}
if is_small_order(&rk.0) {
return false;
}
// Accumulate the value commitment in the context
{
let mut tmp = cv.clone();
@ -703,37 +732,15 @@ pub extern "system" fn librustzcash_sapling_check_spend(
unsafe { &mut *ctx }.bvk = tmp;
}
// Deserialize the anchor, which should be an element
// of Fr.
let anchor = match Fr::from_repr(read_le(&(unsafe { &*anchor })[..])) {
Ok(a) => a,
Err(_) => return false,
};
// Grab the nullifier as a sequence of bytes
let nullifier = &unsafe { &*nullifier }[..];
// Compute the signature's message for rk/spend_auth_sig
let mut data_to_be_signed = [0u8; 64];
(&mut data_to_be_signed[0..32]).copy_from_slice(&(unsafe { &*rk })[..]);
rk.0.write(&mut data_to_be_signed[0..32])
.expect("message buffer should be 32 bytes");
(&mut data_to_be_signed[32..64]).copy_from_slice(&(unsafe { &*sighash_value })[..]);
// Deserialize rk
let rk = match redjubjub::PublicKey::<Bls12>::read(&(unsafe { &*rk })[..], &JUBJUB) {
Ok(p) => p,
Err(_) => return false,
};
if is_small_order(&rk.0) {
return false;
}
// Deserialize the signature
let spend_auth_sig = match Signature::read(&(unsafe { &*spend_auth_sig })[..]) {
Ok(sig) => sig,
Err(_) => return false,
};
// Verify the spend_auth_sig
if !rk.verify(
&data_to_be_signed,
@ -769,12 +776,6 @@ pub extern "system" fn librustzcash_sapling_check_spend(
public_input[6] = nullifier[1];
}
// Deserialize the proof
let zkproof = match Proof::<Bls12>::read(&(unsafe { &*zkproof })[..]) {
Ok(p) => p,
Err(_) => return false,
};
// Verify the proof
match verify_proof(
unsafe { SAPLING_SPEND_VK.as_ref() }.unwrap(),
@ -803,20 +804,6 @@ pub extern "system" fn librustzcash_sapling_check_output(
Err(_) => return false,
};
if is_small_order(&cv) {
return false;
}
// Accumulate the value commitment in the context
{
let mut tmp = cv.clone();
tmp = tmp.negate(); // Outputs subtract from the total.
tmp = tmp.add(&unsafe { &*ctx }.bvk, &JUBJUB);
// Update the context
unsafe { &mut *ctx }.bvk = tmp;
}
// Deserialize the commitment, which should be an element
// of Fr.
let cm = match Fr::from_repr(read_le(&(unsafe { &*cm })[..])) {
@ -830,10 +817,30 @@ pub extern "system" fn librustzcash_sapling_check_output(
Err(_) => return false,
};
// Deserialize the proof
let zkproof = match Proof::<Bls12>::read(&(unsafe { &*zkproof })[..]) {
Ok(p) => p,
Err(_) => return false,
};
if is_small_order(&cv) {
return false;
}
if is_small_order(&epk) {
return false;
}
// Accumulate the value commitment in the context
{
let mut tmp = cv.clone();
tmp = tmp.negate(); // Outputs subtract from the total.
tmp = tmp.add(&unsafe { &*ctx }.bvk, &JUBJUB);
// Update the context
unsafe { &mut *ctx }.bvk = tmp;
}
// Construct public input for circuit
let mut public_input = [Fr::zero(); 5];
{
@ -848,12 +855,6 @@ pub extern "system" fn librustzcash_sapling_check_output(
}
public_input[4] = cm;
// Deserialize the proof
let zkproof = match Proof::<Bls12>::read(&(unsafe { &*zkproof })[..]) {
Ok(p) => p,
Err(_) => return false,
};
// Verify the proof
match verify_proof(
unsafe { SAPLING_OUTPUT_VK.as_ref() }.unwrap(),
@ -901,6 +902,12 @@ pub extern "system" fn librustzcash_sapling_final_check(
binding_sig: *const [c_uchar; 64],
sighash_value: *const [c_uchar; 32],
) -> bool {
// Deserialize the signature
let binding_sig = match Signature::read(&(unsafe { &*binding_sig })[..]) {
Ok(sig) => sig,
Err(_) => return false,
};
// Obtain current bvk from the context
let mut bvk = redjubjub::PublicKey(unsafe { &*ctx }.bvk.clone());
@ -921,12 +928,6 @@ pub extern "system" fn librustzcash_sapling_final_check(
.expect("bvk is 32 bytes");
(&mut data_to_be_signed[32..64]).copy_from_slice(&(unsafe { &*sighash_value })[..]);
// Deserialize the signature
let binding_sig = match Signature::read(&(unsafe { &*binding_sig })[..]) {
Ok(sig) => sig,
Err(_) => return false,
};
// Verify the binding_sig
if !bvk.verify(
&data_to_be_signed,