bellman: add VerificationError (#254)
* bellman: add VerificationError This adds a distinct VerificationError type to the crate and changes `verify_proof` to return `Result<(), VerificationError>` rather than `Result<bool, SynthesisError>`. This is significantly safer, because it avoids the need to mix pattern-matching logic with boolean logic (the cause of RUSTSEC-2019-0004). * Rename VerificationError variants per review comments. * Add missing Clone impl to VerificationError.
This commit is contained in:
parent
701e6cfa1b
commit
e534f36ec4
|
@ -560,8 +560,8 @@ mod test_with_bls12_381 {
|
|||
let de_proof = Proof::read(&v[..]).unwrap();
|
||||
assert!(proof == de_proof);
|
||||
|
||||
assert!(verify_proof(&pvk, &proof, &[c]).unwrap());
|
||||
assert!(!verify_proof(&pvk, &proof, &[a]).unwrap());
|
||||
assert!(verify_proof(&pvk, &proof, &[c]).is_ok());
|
||||
assert!(verify_proof(&pvk, &proof, &[a]).is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,5 +377,5 @@ fn test_xordemo() {
|
|||
assert_eq!(expected_c, proof.c);
|
||||
}
|
||||
|
||||
assert!(verify_proof(&pvk, &proof, &[Fr::one()]).unwrap());
|
||||
assert!(verify_proof(&pvk, &proof, &[Fr::one()]).is_ok());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::ops::{AddAssign, Neg};
|
|||
|
||||
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||
|
||||
use crate::SynthesisError;
|
||||
use crate::VerificationError;
|
||||
|
||||
pub fn prepare_verifying_key<E: MultiMillerLoop>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
||||
let gamma = vk.gamma_g2.neg();
|
||||
|
@ -22,9 +22,9 @@ pub fn verify_proof<'a, E: MultiMillerLoop>(
|
|||
pvk: &'a PreparedVerifyingKey<E>,
|
||||
proof: &Proof<E>,
|
||||
public_inputs: &[E::Fr],
|
||||
) -> Result<bool, SynthesisError> {
|
||||
) -> Result<(), VerificationError> {
|
||||
if (public_inputs.len() + 1) != pvk.ic.len() {
|
||||
return Err(SynthesisError::MalformedVerifyingKey);
|
||||
return Err(VerificationError::InvalidVerifyingKey);
|
||||
}
|
||||
|
||||
let mut acc = pvk.ic[0].to_curve();
|
||||
|
@ -41,11 +41,16 @@ pub fn verify_proof<'a, E: MultiMillerLoop>(
|
|||
// A * B + inputs * (-gamma) + C * (-delta) = alpha * beta
|
||||
// which allows us to do a single final exponentiation.
|
||||
|
||||
Ok(E::multi_miller_loop(&[
|
||||
(&proof.a, &proof.b.into()),
|
||||
(&acc.to_affine(), &pvk.neg_gamma_g2),
|
||||
(&proof.c, &pvk.neg_delta_g2),
|
||||
])
|
||||
.final_exponentiation()
|
||||
== pvk.alpha_g1_beta_g2)
|
||||
if pvk.alpha_g1_beta_g2
|
||||
== E::multi_miller_loop(&[
|
||||
(&proof.a, &proof.b.into()),
|
||||
(&acc.to_affine(), &pvk.neg_gamma_g2),
|
||||
(&proof.c, &pvk.neg_delta_g2),
|
||||
])
|
||||
.final_exponentiation()
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(VerificationError::InvalidProof)
|
||||
}
|
||||
}
|
||||
|
|
31
src/lib.rs
31
src/lib.rs
|
@ -122,7 +122,7 @@
|
|||
//! let inputs = multipack::compute_multipacking(&hash_bits);
|
||||
//!
|
||||
//! // Check the proof!
|
||||
//! assert!(groth16::verify_proof(&pvk, &proof, &inputs).unwrap());
|
||||
//! assert!(groth16::verify_proof(&pvk, &proof, &inputs).is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! # Roadmap
|
||||
|
@ -314,7 +314,7 @@ impl<'a, Scalar: PrimeField> Sub<(Scalar, &'a LinearCombination<Scalar>)>
|
|||
}
|
||||
|
||||
/// This is an error that could occur during circuit synthesis contexts,
|
||||
/// such as CRS generation, proving or verification.
|
||||
/// such as CRS generation or proving.
|
||||
#[derive(Debug)]
|
||||
pub enum SynthesisError {
|
||||
/// During synthesis, we lacked knowledge of a variable assignment.
|
||||
|
@ -329,8 +329,6 @@ pub enum SynthesisError {
|
|||
UnexpectedIdentity,
|
||||
/// During proof generation, we encountered an I/O error with the CRS
|
||||
IoError(io::Error),
|
||||
/// During verification, our verifying key was malformed.
|
||||
MalformedVerifyingKey,
|
||||
/// During CRS generation, we observed an unconstrained auxiliary variable
|
||||
UnconstrainedVariable,
|
||||
}
|
||||
|
@ -352,7 +350,6 @@ impl Error for SynthesisError {
|
|||
SynthesisError::PolynomialDegreeTooLarge => "polynomial degree is too large",
|
||||
SynthesisError::UnexpectedIdentity => "encountered an identity element in the CRS",
|
||||
SynthesisError::IoError(_) => "encountered an I/O error",
|
||||
SynthesisError::MalformedVerifyingKey => "malformed verifying key",
|
||||
SynthesisError::UnconstrainedVariable => "auxiliary variable was unconstrained",
|
||||
}
|
||||
}
|
||||
|
@ -369,6 +366,30 @@ impl fmt::Display for SynthesisError {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error during verification.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VerificationError {
|
||||
/// Verification was attempted with a malformed verifying key.
|
||||
InvalidVerifyingKey,
|
||||
/// Proof verification failed.
|
||||
InvalidProof,
|
||||
}
|
||||
|
||||
impl Error for VerificationError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
VerificationError::InvalidVerifyingKey => "malformed verifying key",
|
||||
VerificationError::InvalidProof => "proof verification failed",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VerificationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a constraint system which can have new variables
|
||||
/// allocated and constrains between them formed.
|
||||
pub trait ConstraintSystem<Scalar: PrimeField>: Sized {
|
||||
|
|
|
@ -210,7 +210,7 @@ fn test_mimc() {
|
|||
let start = Instant::now();
|
||||
let proof = Proof::read(&proof_vec[..]).unwrap();
|
||||
// Check the proof
|
||||
assert!(verify_proof(&pvk, &proof, &[image]).unwrap());
|
||||
assert!(verify_proof(&pvk, &proof, &[image]).is_ok());
|
||||
total_verifying += start.elapsed();
|
||||
}
|
||||
let proving_avg = total_proving / SAMPLES;
|
||||
|
|
Loading…
Reference in New Issue