/// Verifies multiple aggregated rangeproofs with a single multiexponentiation
Verifies multiple aggregated rangeproofs with a single multiexponentiation
Verifies multiple aggregated rangeproofs with a single multiexponentiation
pub fn batch_verify<T: RngCore + CryptoRng>(
        rng: &mut T,
        proofs: &[&RangeProof],
        transcripts: &mut [Transcript],
        value_commitments: &[&[CompressedRistretto]],
        bp_gens: &BulletproofGens,
        pc_gens: &PedersenGens,
        n: usize,
    ) -> Result<(), ProofError> {
        let mut all_scalars = vec![];
        let mut random_scalars = vec![];
        let mut max_m = 0;
        for ((proof, transcript), value_commitment) in proofs
            .iter()
            .zip(transcripts.iter_mut())
            .zip(value_commitments.iter())
        {
            let instance_scalars = proof.compute_verification_scalars_with_rng(
                bp_gens,
                transcript,
                value_commitment,
                n,
                rng,
            )?;
            let mut rng = transcript.build_rng().finalize(&mut thread_rng());
            random_scalars.push(Scalar::random(&mut rng));
            all_scalars.push((instance_scalars, value_commitment.len()));
        }
        let mut all_scaled_scalars = vec![];
        for ((scalars, m_i), rand_scalar) in all_scalars.iter().zip(random_scalars.iter()) {
            let scaled_scalars: Vec<Scalar> = scalars.iter().map(|s| s * rand_scalar).collect();
            all_scaled_scalars.push((scaled_scalars, *m_i));
            if *m_i > max_m {
                max_m = *m_i;
            }
        }
        let grouped_scalars = Self::group_scalars(all_scaled_scalars.as_slice(), n, max_m);
        let mut elems = vec![];
        for (proof, value_commitments) in proofs.iter().zip(value_commitments) {
            elems.push(proof.A.decompress());
            elems.push(proof.S.decompress());
            elems.push(proof.T_1.decompress());
            elems.push(proof.T_2.decompress());
            for L in proof.ipp_proof.L_vec.iter() {
                elems.push(L.decompress());
            }
            for R in proof.ipp_proof.R_vec.iter() {
                elems.push(R.decompress());
            }
            for V in value_commitments.iter() {
                elems.push(V.decompress())
            }
        }
        elems.push(Some(pc_gens.B_blinding));
        elems.push(Some(pc_gens.B));
        for G in bp_gens.G(n, max_m) {
            elems.push(Some(*G));
        }
        for H in bp_gens.H(n, max_m) {
            elems.push(Some(*H));
        }
        let mega_check = RistrettoPoint::optional_multiscalar_mul(grouped_scalars, elems)
            .ok_or_else(|| ProofError::VerificationError)?;
        if !mega_check.is_identity() {
            return Err(ProofError::VerificationError);
        }
        Ok(())
    }
pub fn batch_verify < T : RngCore + CryptoRng > ( rng : & mut T , proofs : & [ & RangeProof ] , transcripts : & mut [ Transcript ] , value_commitments : & [ & [ CompressedRistretto ] ] , bp_gens : & BulletproofGens , pc_gens : & PedersenGens , n : usize , ) -> Result < ( ) , ProofError > { let mut all_scalars = vec ! [ ] ; let mut random_scalars = vec ! [ ] ; let mut max_m = 0 ; for ( ( proof , transcript ) , value_commitment ) in proofs . iter ( ) . zip ( transcripts . iter_mut ( ) ) . zip ( value_commitments . iter ( ) ) { let instance_scalars = proof . compute_verification_scalars_with_rng ( bp_gens , transcript , value_commitment , n , rng , ) ? ; let mut rng = transcript . build_rng ( ) . finalize ( & mut thread_rng ( ) ) ; random_scalars . push ( Scalar :: random ( & mut rng ) ) ; all_scalars . push ( ( instance_scalars , value_commitment . len ( ) ) ) ; } let mut all_scaled_scalars = vec ! [ ] ; for ( ( scalars , m_i ) , rand_scalar ) in all_scalars . iter ( ) . zip ( random_scalars . iter ( ) ) { let scaled_scalars : Vec < Scalar > = scalars . iter ( ) . map ( | s | s * rand_scalar ) . collect ( ) ; all_scaled_scalars . push ( ( scaled_scalars , * m_i ) ) ; if * m_i > max_m { max_m = * m_i ; } } let grouped_scalars = Self :: group_scalars ( all_scaled_scalars . as_slice ( ) , n , max_m ) ; let mut elems = vec ! [ ] ; for ( proof , value_commitments ) in proofs . iter ( ) . zip ( value_commitments ) { elems . push ( proof . A . decompress ( ) ) ; elems . push ( proof . S . decompress ( ) ) ; elems . push ( proof . T_1 . decompress ( ) ) ; elems . push ( proof . T_2 . decompress ( ) ) ; for L in proof . ipp_proof . L_vec . iter ( ) { elems . push ( L . decompress ( ) ) ; } for R in proof . ipp_proof . R_vec . iter ( ) { elems . push ( R . decompress ( ) ) ; } for V in value_commitments . iter ( ) { elems . push ( V . decompress ( ) ) } } elems . push ( Some ( pc_gens . B_blinding ) ) ; elems . push ( Some ( pc_gens . B ) ) ; for G in bp_gens . G ( n , max_m ) { elems . push ( Some ( * G ) ) ; } for H in bp_gens . H ( n , max_m ) { elems . push ( Some ( * H ) ) ; } let mega_check = RistrettoPoint :: optional_multiscalar_mul ( grouped_scalars , elems ) . ok_or_else ( | | ProofError :: VerificationError ) ? ; if ! mega_check . is_identity ( ) { return Err ( ProofError :: VerificationError ) ; } Ok ( ( ) ) }
Verifies multiple aggregated rangeproofs with a single multiexponentiation
Verifies multiple aggregated rangeproofs with a single multiexponentiation
rng
&mut T
proofs
&[&RangeProof]
transcripts
&mut [Transcript]
value_commitments
&[&[CompressedRistretto]]
bp_gens
&BulletproofGens
pc_gens
&PedersenGens
n
usize