@@ -12,6 +12,8 @@ use sp1_recursion_core::{
1212use sp1_stark:: { baby_bear_poseidon2:: BabyBearPoseidon2 , * } ;
1313use thiserror:: Error ;
1414
15+ use crate :: { blake3_hash, hash_public_inputs, hash_public_inputs_with_fn} ;
16+
1517// NOTE: that all these constants and types are checked by sp1_prover::tests::sp1_verifier_valid.
1618// If you add a new proof, you MUST add to the test in that crate.
1719//
@@ -47,15 +49,18 @@ pub const RECURSION_VK_SET: &[[u32; 8]] = &[
4749
4850/// A reason why the verifier rejects a given proof.
4951#[ derive( Debug , Error ) ]
52+ #[ non_exhaustive]
5053pub enum CompressedError {
51- #[ error( "failed to deserialize proof" ) ]
54+ #[ error( "failed to deserialize proof: {0} " ) ]
5255 DeserializeProof ( Box < bincode:: ErrorKind > ) ,
53- #[ error( "failed to deserialize vkey hash" ) ]
56+ #[ error( "failed to deserialize vkey hash: {0} " ) ]
5457 DeserializeVkeyHash ( Box < bincode:: ErrorKind > ) ,
55- #[ error( "failed to verify proof" ) ]
58+ #[ error( "failed to verify proof: {0} " ) ]
5659 ProofRejected ( #[ from] MachineVerificationError < SC > ) ,
5760 #[ error( "single-shard proofs are currently unsupported by this verifier" ) ]
5861 SingleShard ,
62+ #[ error( "given public values do not match the commitment in the proof" ) ]
63+ PublicValuesMismatch ,
5964}
6065
6166/// A verifier for SP1 "compressed" proofs.
@@ -86,13 +91,17 @@ impl CompressedVerifier {
8691 /// _ => unreachable!("expected compressed proof"),
8792 /// };
8893 /// ```
89- pub fn verify ( proof : & [ u8 ] , sp1_vkey_hash : & [ u8 ] ) -> Result < ( ) , CompressedError > {
94+ pub fn verify (
95+ proof : & [ u8 ] ,
96+ sp1_public_inputs : & [ u8 ] ,
97+ sp1_vkey_hash : & [ u8 ] ,
98+ ) -> Result < ( ) , CompressedError > {
9099 let reduce_proof: Box < SP1ReduceProof < SC > > =
91100 bincode:: deserialize ( proof) . map_err ( CompressedError :: DeserializeProof ) ?;
92101 let vkey_hash: [ F ; 8 ] =
93102 bincode:: deserialize ( sp1_vkey_hash) . map_err ( CompressedError :: DeserializeVkeyHash ) ?;
94103
95- verify_compressed ( & reduce_proof, & vkey_hash) ?;
104+ verify_compressed ( & reduce_proof, sp1_public_inputs , & vkey_hash) ?;
96105
97106 Ok ( ( ) )
98107 }
@@ -103,6 +112,7 @@ impl CompressedVerifier {
103112/// Verify a compressed proof.
104113fn verify_compressed (
105114 proof : & SP1ReduceProof < SC > ,
115+ sp1_public_inputs : & [ u8 ] ,
106116 vkey_hash : & [ BabyBear ; 8 ] ,
107117) -> Result < ( ) , CompressedError > {
108118 let SP1ReduceProof { vk : compress_vk, proof } = proof;
@@ -120,7 +130,21 @@ fn verify_compressed(
120130 let machine_proof = MachineProof { shard_proofs : vec ! [ proof. clone( ) ] } ;
121131 compress_machine. verify ( compress_vk, & machine_proof, & mut challenger) ?;
122132
123- // Validate public values
133+ // Validate the SP1 public values against the committed digest.
134+ let committed_value_digest_bytes = public_values
135+ . committed_value_digest
136+ . iter ( )
137+ . flat_map ( |w| w. 0 . iter ( ) . map ( |x| x. as_canonical_u32 ( ) as u8 ) )
138+ . collect :: < Vec < _ > > ( ) ;
139+
140+ if committed_value_digest_bytes. as_slice ( ) != hash_public_inputs ( sp1_public_inputs) . as_slice ( ) &&
141+ committed_value_digest_bytes. as_slice ( ) !=
142+ hash_public_inputs_with_fn ( sp1_public_inputs, blake3_hash)
143+ {
144+ return Err ( CompressedError :: PublicValuesMismatch ) ;
145+ }
146+
147+ // Validate recursion's public values.
124148 if !is_recursion_public_values_valid ( compress_machine. config ( ) , public_values) {
125149 return Err ( MachineVerificationError :: InvalidPublicValues (
126150 "recursion public values are invalid" ,
0 commit comments