pub fn decrypt<E: Engine>(
    ct: &SaverCiphertext<E>,
    params: &Parameters<E>,
    secret_key: &SaverSecretKey<E>,
    verification_key: &SaverVerificationKey<E>,
) -> Result<SaverPlaintext<E>, ()>
where
    E::Gt: Group<Scalar = E::Fr>,
{
    // Determine the discrete log of a certain value `result`, and base `base`.
    fn discrete_log<E: Engine>(base: E::Gt, result: E::Gt) -> Result<E::Fr, ()> {
        if result == E::Gt::identity() {
            return Ok(E::Fr::zero());
        } else if result == base {
            return Ok(E::Fr::one());
        }
        let mut cur_guess = base;
        for exponent in 2..2_u64.pow(SAVER_BLOCK_SIZE) {
            cur_guess += &base;
            if result == cur_guess {
                return Ok(<E::Fr as From<u64>>::from(exponent));
            }
        }
        Err(())
    }

    let mut threads = vec![];
    let rho = secret_key.rho;
    let ct0 = ct.ct0;
    for (((&cti, &vi_one), &vi_two), &gi) in ct
        .ctis
        .iter()
        .zip(verification_key.vis_one.iter())
        .zip(verification_key.vis_two.iter())
        .zip(params.vk.ic.iter().skip(1))
    {
        threads.push(thread::spawn(move || {
            let result = E::pairing(&cti, &vi_two) - (E::pairing(&ct0, &vi_one) * rho);
            discrete_log::<E>(E::pairing(&gi, &vi_two), result)
        }))
    }
    let mut mis = vec![];
    for thread in threads {
        mis.push(thread.join().unwrap()?)
    }

    Ok(SaverPlaintext {
        mis,
        nu: (ct.ct0 * secret_key.rho).to_affine(),
    })
}
/// Decrypt a SAVER ciphertext `ct` to the original plaintext and a decryption proof. Makes use of
/// the Groth16 CRS `params`, SAVER secret key `secret_key` and verification key `verification_key`.
Decrypt a SAVER ciphertext `ct` to the original plaintext and a decryption proof.
Decrypt a SAVER ciphertext ` ct ` to the original plaintext and a decryption proof .
pub fn decrypt<E: Engine>(
    ct: &SaverCiphertext<E>,
    params: &Parameters<E>,
    secret_key: &SaverSecretKey<E>,
    verification_key: &SaverVerificationKey<E>,
) -> Result<SaverPlaintext<E>, ()>
where
    E::Gt: Group<Scalar = E::Fr>,
{
    // Determine the discrete log of a certain value `result`, and base `base`.
    fn discrete_log<E: Engine>(base: E::Gt, result: E::Gt) -> Result<E::Fr, ()> {
        if result == E::Gt::identity() {
            return Ok(E::Fr::zero());
        } else if result == base {
            return Ok(E::Fr::one());
        }
        let mut cur_guess = base;
        for exponent in 2..2_u64.pow(SAVER_BLOCK_SIZE) {
            cur_guess += &base;
            if result == cur_guess {
                return Ok(<E::Fr as From<u64>>::from(exponent));
            }
        }
        Err(())
    }
    let mut threads = vec![];
    let rho = secret_key.rho;
    let ct0 = ct.ct0;
    for (((&cti, &vi_one), &vi_two), &gi) in ct
        .ctis
        .iter()
        .zip(verification_key.vis_one.iter())
        .zip(verification_key.vis_two.iter())
        .zip(params.vk.ic.iter().skip(1))
    {
        threads.push(thread::spawn(move || {
            let result = E::pairing(&cti, &vi_two) - (E::pairing(&ct0, &vi_one) * rho);
            discrete_log::<E>(E::pairing(&gi, &vi_two), result)
        }))
    }
    let mut mis = vec![];
    for thread in threads {
        mis.push(thread.join().unwrap()?)
    }
    Ok(SaverPlaintext {
        mis,
        nu: (ct.ct0 * secret_key.rho).to_affine(),
    })
}
pub fn decrypt < E : Engine > ( ct : & SaverCiphertext < E > , params : & Parameters < E > , secret_key : & SaverSecretKey < E > , verification_key : & SaverVerificationKey < E > , ) -> Result < SaverPlaintext < E > , ( ) > where E :: Gt : Group < Scalar = E :: Fr > , { // Determine the discrete log of a certain value `result`, and base `base`. fn discrete_log < E : Engine > ( base : E :: Gt , result : E :: Gt ) -> Result < E :: Fr , ( ) > { if result == E :: Gt :: identity ( ) { return Ok ( E :: Fr :: zero ( ) ) ; } else if result == base { return Ok ( E :: Fr :: one ( ) ) ; } let mut cur_guess = base ; for exponent in 2 .. 2_u64 . pow ( SAVER_BLOCK_SIZE ) { cur_guess += & base ; if result == cur_guess { return Ok ( < E :: Fr as From < u64 > > :: from ( exponent ) ) ; } } Err ( ( ) ) } let mut threads = vec ! [ ] ; let rho = secret_key . rho ; let ct0 = ct . ct0 ; for ( ( ( & cti , & vi_one ) , & vi_two ) , & gi ) in ct . ctis . iter ( ) . zip ( verification_key . vis_one . iter ( ) ) . zip ( verification_key . vis_two . iter ( ) ) . zip ( params . vk . ic . iter ( ) . skip ( 1 ) ) { threads . push ( thread :: spawn ( move | | { let result = E :: pairing ( & cti , & vi_two ) - ( E :: pairing ( & ct0 , & vi_one ) * rho ) ; discrete_log :: < E > ( E :: pairing ( & gi , & vi_two ) , result ) } ) ) } let mut mis = vec ! [ ] ; for thread in threads { mis . push ( thread . join ( ) . unwrap ( ) ? ) } Ok ( SaverPlaintext { mis , nu : ( ct . ct0 * secret_key . rho ) . to_affine ( ) , } ) }
Decrypt a SAVER ciphertext `ct` to the original plaintext and a decryption proof.
Decrypt a SAVER ciphertext ` ct ` to the original plaintext and a decryption proof .
ct
&SaverCiphertext<E>
params
&Parameters<E>
secret_key
&SaverSecretKey<E>
verification_key
&SaverVerificationKey<E>
ct
&SaverCiphertext<E>
params
&Parameters<E>
secret_key
&SaverSecretKey<E>
verification_key
&SaverVerificationKey<E>