diff --git a/storage-proofs/core/src/multi_proof.rs b/storage-proofs/core/src/multi_proof.rs index 7c14d6eed6..0f4360539c 100644 --- a/storage-proofs/core/src/multi_proof.rs +++ b/storage-proofs/core/src/multi_proof.rs @@ -1,8 +1,9 @@ use bellperson::groth16; use crate::error::Result; -use anyhow::Context; +use anyhow::{ensure, Context}; use paired::bls12_381::Bls12; +use rayon::prelude::*; use std::io::{self, Read, Write}; pub struct MultiProof<'a> { @@ -10,6 +11,8 @@ pub struct MultiProof<'a> { pub verifying_key: &'a groth16::VerifyingKey, } +const GROTH_PROOF_SIZE: usize = 192; + impl<'a> MultiProof<'a> { pub fn new( groth_proofs: Vec>, @@ -26,14 +29,35 @@ impl<'a> MultiProof<'a> { mut reader: R, verifying_key: &'a groth16::VerifyingKey, ) -> Result { - let num_proofs = match partitions { - Some(n) => n, - None => 1, - }; - let proofs = (0..num_proofs) - .map(|_| groth16::Proof::read(&mut reader)) + let num_proofs = partitions.unwrap_or(1); + + let mut proof_vec: Vec = Vec::with_capacity(num_proofs * GROTH_PROOF_SIZE); + reader.read_to_end(&mut proof_vec)?; + + Self::new_from_bytes(partitions, &proof_vec, verifying_key) + } + + // Parallelizing reduces deserialization time for 10 proofs from 13ms to 2ms. + pub fn new_from_bytes( + partitions: Option, + proof_bytes: &[u8], + verifying_key: &'a groth16::VerifyingKey, + ) -> Result { + let num_proofs = partitions.unwrap_or(1); + + let proofs = proof_bytes + .par_chunks(GROTH_PROOF_SIZE) + .take(num_proofs) + .map(groth16::Proof::read) .collect::>>()?; + ensure!( + num_proofs == proofs.len(), + "expected {} proofs but found only {}", + num_proofs, + proofs.len() + ); + Ok(Self::new(proofs, verifying_key)) }