diff --git a/crates/verifier/src/compressed/internal.rs b/crates/verifier/src/compressed/internal.rs index eccfaa2d1..04b922722 100644 --- a/crates/verifier/src/compressed/internal.rs +++ b/crates/verifier/src/compressed/internal.rs @@ -57,13 +57,12 @@ pub const RECURSION_VK_SET: &[[u32; 8]] = &[ /// Then, calls [`verify_sp1_reduce_proof`] and returns the result. pub fn verify_sp1_proof( sp1_proof: &SP1Proof, - sp1_public_inputs: &[u8], vkey_hash: &[BabyBear; 8], ) -> Result<(), CompressedError> { let SP1Proof::Compressed(reduce_proof) = sp1_proof else { return Err(CompressedError::Mode(sp1_proof.into())); }; - verify_sp1_reduce_proof(reduce_proof.as_ref(), sp1_public_inputs, vkey_hash) + verify_sp1_reduce_proof(reduce_proof.as_ref(), vkey_hash) } // The rest of the functions in this file have been copied from elsewhere with slight modifications. @@ -71,7 +70,6 @@ pub fn verify_sp1_proof( /// Verify a compressed proof. pub fn verify_sp1_reduce_proof( reduce_proof: &SP1ReduceProof, - sp1_public_inputs: &[u8], vkey_hash: &[BabyBear; 8], ) -> Result<(), CompressedError> { let SP1ReduceProof { vk: compress_vk, proof } = reduce_proof; @@ -89,20 +87,6 @@ pub fn verify_sp1_reduce_proof( let machine_proof = MachineProof { shard_proofs: vec![proof.clone()] }; compress_machine.verify(compress_vk, &machine_proof, &mut challenger)?; - // Validate the SP1 public values against the committed digest. - let committed_value_digest_bytes = public_values - .committed_value_digest - .iter() - .flat_map(|w| w.0.iter().map(|x| x.as_canonical_u32() as u8)) - .collect::>(); - - if committed_value_digest_bytes.as_slice() != hash_public_inputs(sp1_public_inputs).as_slice() && - committed_value_digest_bytes.as_slice() != - hash_public_inputs_with_fn(sp1_public_inputs, blake3_hash) - { - return Err(CompressedError::PublicValuesMismatch); - } - // Validate recursion's public values. if !is_recursion_public_values_valid(compress_machine.config(), public_values) { return Err(MachineVerificationError::InvalidPublicValues( @@ -134,6 +118,55 @@ pub fn verify_sp1_reduce_proof( Ok(()) } +/// Verify a compressed proof. +pub fn verify_sp1_public_values( + reduce_proof: &SP1ReduceProof, + sp1_public_inputs: &[u8], +) -> Result<(), CompressedError> { + let SP1ReduceProof { proof, .. } = reduce_proof; + + let public_values: &RecursionPublicValues<_> = proof.public_values.as_slice().borrow(); + // Validate the SP1 public values against the committed digest. + let committed_value_digest_bytes = public_values + .committed_value_digest + .iter() + .flat_map(|w| w.0.iter().map(|x| x.as_canonical_u32() as u8)) + .collect::>(); + + if committed_value_digest_bytes.as_slice() != hash_public_inputs(sp1_public_inputs).as_slice() + && committed_value_digest_bytes.as_slice() + != hash_public_inputs_with_fn(sp1_public_inputs, blake3_hash) + { + return Err(CompressedError::PublicValuesMismatch); + } + + Ok(()) +} + +/// Verify a compressed proof with public values. +pub fn verify_sp1_proof_with_public_values( + sp1_proof: &SP1Proof, + sp1_public_inputs: &[u8], + vkey_hash: &[BabyBear; 8], +) -> Result<(), CompressedError> { + let SP1Proof::Compressed(reduce_proof) = sp1_proof else { + return Err(CompressedError::Mode(sp1_proof.into())); + }; + verify_sp1_reduce_proof_with_public_values(reduce_proof, sp1_public_inputs, vkey_hash) +} + +/// Verify a compressed proof. +pub fn verify_sp1_reduce_proof_with_public_values( + reduce_proof: &SP1ReduceProof, + sp1_public_inputs: &[u8], + vkey_hash: &[BabyBear; 8], +) -> Result<(), CompressedError> { + // Verify the proof + verify_sp1_reduce_proof(reduce_proof, vkey_hash)?; + // Verify the public values against the committed digest + verify_sp1_public_values(reduce_proof, sp1_public_inputs) +} + /// Compute the digest of the public values. fn recursion_public_values_digest( config: &SC, diff --git a/crates/verifier/src/compressed/mod.rs b/crates/verifier/src/compressed/mod.rs index 4a462a866..4c5412269 100644 --- a/crates/verifier/src/compressed/mod.rs +++ b/crates/verifier/src/compressed/mod.rs @@ -6,7 +6,10 @@ use thiserror::Error; pub mod internal; -use internal::{verify_sp1_proof, verify_sp1_reduce_proof, F, SC}; +use internal::{ + verify_sp1_proof, verify_sp1_proof_with_public_values, verify_sp1_reduce_proof, + verify_sp1_reduce_proof_with_public_values, F, SC, +}; /// A reason why the verifier rejects a given proof. #[derive(Debug, Error)] @@ -51,7 +54,17 @@ impl CompressedVerifier { /// let sp1_vkey_hash = bincode::serialize(&vk.hash_babybear()).unwrap(); /// let proof: SP1Proof = match client.prove(&pk, &stdin).compressed().run().unwrap().proof; /// ``` - pub fn verify_sp1_proof( + pub fn verify_sp1_proof(sp1_proof: &[u8], sp1_vkey_hash: &[u8]) -> Result<(), CompressedError> { + let sp1_proof: SP1Proof = + bincode::deserialize(sp1_proof).map_err(CompressedError::DeserializeProof)?; + let vkey_hash: [F; 8] = deserialize_vkey(sp1_vkey_hash)?; + + verify_sp1_proof(&sp1_proof, &vkey_hash)?; + + Ok(()) + } + + pub fn verify_sp1_proof_with_public_values( sp1_proof: &[u8], sp1_public_inputs: &[u8], sp1_vkey_hash: &[u8], @@ -59,21 +72,37 @@ impl CompressedVerifier { let sp1_proof: SP1Proof = bincode::deserialize(sp1_proof).map_err(CompressedError::DeserializeProof)?; let vkey_hash: [F; 8] = deserialize_vkey(sp1_vkey_hash)?; - - verify_sp1_proof(&sp1_proof, sp1_public_inputs, &vkey_hash)?; + verify_sp1_proof_with_public_values(&sp1_proof, sp1_public_inputs, &vkey_hash)?; Ok(()) } + pub fn verify_sp1_reduce_proof( sp1_reduce_proof: &[u8], - sp1_public_inputs: &[u8], sp1_vkey_hash: &[u8], ) -> Result<(), CompressedError> { let reduce_proof: Box> = bincode::deserialize(sp1_reduce_proof).map_err(CompressedError::DeserializeProof)?; let vkey_hash: [F; 8] = deserialize_vkey(sp1_vkey_hash)?; - verify_sp1_reduce_proof(reduce_proof.as_ref(), sp1_public_inputs, &vkey_hash)?; + verify_sp1_reduce_proof(reduce_proof.as_ref(), &vkey_hash)?; + + Ok(()) + } + + pub fn verify_sp1_reduce_proof_with_public_values( + sp1_reduce_proof: &[u8], + sp1_public_inputs: &[u8], + sp1_vkey_hash: &[u8], + ) -> Result<(), CompressedError> { + let reduce_proof: Box> = + bincode::deserialize(sp1_reduce_proof).map_err(CompressedError::DeserializeProof)?; + let vkey_hash: [F; 8] = deserialize_vkey(sp1_vkey_hash)?; + verify_sp1_reduce_proof_with_public_values( + reduce_proof.as_ref(), + sp1_public_inputs, + &vkey_hash, + )?; Ok(()) }