diff --git a/src/rustzcash.rs b/src/rustzcash.rs index ca3ca39c2..21ce3c1a4 100644 --- a/src/rustzcash.rs +++ b/src/rustzcash.rs @@ -42,6 +42,12 @@ static mut SAPLING_SPEND_PARAMS: Option> = None; static mut SAPLING_OUTPUT_PARAMS: Option> = None; static mut SPROUT_GROTH16_PARAMS_PATH: Option = None; +fn is_small_order( + p: &edwards::Point +) -> bool { + p.double(&JUBJUB).double(&JUBJUB).double(&JUBJUB) == edwards::Point::zero() +} + /// Writes an FrRepr to [u8] of length 32 fn write_le(mut f: FrRepr, to: &mut [u8]) { assert_eq!(to.len(), 32); @@ -243,6 +249,10 @@ pub extern "system" fn librustzcash_sapling_check_spend( Err(_) => return false, }; + if is_small_order(&cv) { + return false; + } + // Accumulate the value commitment in the context { let mut tmp = cv.clone(); @@ -273,6 +283,10 @@ pub extern "system" fn librustzcash_sapling_check_spend( 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, @@ -348,6 +362,10 @@ 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(); @@ -371,6 +389,10 @@ pub extern "system" fn librustzcash_sapling_check_output( Err(_) => return false, }; + if is_small_order(&epk) { + return false; + } + // Construct public input for circuit let mut public_input = [Fr::zero(); 5]; {