Skip to content

Commit 80f2e52

Browse files
committed
proof v2
1 parent f8fdd32 commit 80f2e52

31 files changed

+884
-477
lines changed

prover/src/aggregator/error.rs

+11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ pub enum BatchProverError {
1111
/// [`protocol`][snark_verifier::Protocol] did not match the expected protocols.
1212
#[error("SNARK protocol mismatch: index={0}, expected={1}, found={2}")]
1313
ChunkProtocolMismatch(usize, String, String),
14+
/// Indicates that after generating an EVM verifier contract, the proof itself could not be
15+
/// verified successfully, implying that this sanity check failed.
16+
#[error("EVM verifier contract could not verify proof")]
17+
SanityEVMVerifier,
18+
/// Error indicating that the verification of batch proof failed.
19+
#[error("proof verification failure")]
20+
Verification,
21+
/// Error indicating that in the final [`BundleProof`][crate::BundleProofV2] the number of
22+
/// instances found does not match the number of instances expected.
23+
#[error("number of instances in bundle proof mismatch! expected={0}, got={1}")]
24+
PublicInputsMismatch(usize, usize),
1425
/// This variant represents other errors.
1526
#[error("custom: {0}")]
1627
Custom(String),

prover/src/aggregator/prover.rs

+38-37
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use crate::{
1818
proof::BundleProof,
1919
types::BundleProvingTask,
2020
utils::{force_to_read, try_to_read},
21-
BatchProof, BatchProvingTask, ChunkKind, ChunkProof, ParamsMap,
21+
BatchProofV2, BatchProofV2Metadata, BatchProvingTask, ChunkKind, ChunkProof, ParamsMap,
22+
ProverError,
2223
};
2324

2425
/// Prover capable of generating [`BatchProof`] and [`BundleProof`].
@@ -129,15 +130,14 @@ impl<'params> Prover<'params> {
129130
batch: BatchProvingTask,
130131
name: Option<&str>,
131132
output_dir: Option<&str>,
132-
) -> Result<BatchProof, BatchProverError> {
133+
) -> Result<BatchProofV2, ProverError> {
133134
// Denotes the identifier for this batch proving task. Eventually a generated proof is
134135
// cached to disk using this identifier.
135136
let name = name.map_or_else(|| batch.identifier(), |name| name.to_string());
136137

137138
// Return early if the batch proof was found on disk.
138139
if let Some(output_dir) = output_dir {
139-
if let Ok(batch_proof) = BatchProof::from_json_file(output_dir, &name) {
140-
log::info!("batch proof found on disk! id={name}, path={output_dir}");
140+
if let Ok(batch_proof) = BatchProofV2::from_json(output_dir, &name) {
141141
return Ok(batch_proof);
142142
}
143143
}
@@ -157,7 +157,7 @@ impl<'params> Prover<'params> {
157157
layer3_snark,
158158
output_dir,
159159
)
160-
.map_err(|e| e.to_string())?;
160+
.map_err(|e| BatchProverError::Custom(e.to_string()))?;
161161
log::info!("Got batch compression thin proof (layer-4): {name}");
162162

163163
// Sanity check on the layer-4 verifying key.
@@ -167,18 +167,13 @@ impl<'params> Prover<'params> {
167167
let pk = self.prover_impl.pk(LayerId::Layer4.id());
168168

169169
// Build a wrapper around the layer-4 SNARK, aka batch proof.
170-
let batch_proof =
171-
BatchProof::new(layer4_snark, pk, batch_hash).map_err(|e| e.to_string())?;
170+
let batch_proof_metadata = BatchProofV2Metadata::new(&layer4_snark, batch_hash)?;
171+
let batch_proof = BatchProofV2::new(layer4_snark, pk, batch_proof_metadata)?;
172172

173173
// If an output directory was provided, write the generated batch proof and layer-4
174174
// verifying key to disk.
175175
if let Some(output_dir) = output_dir {
176-
batch_proof
177-
.dump_vk(output_dir, "agg")
178-
.map_err(|e| e.to_string())?;
179-
batch_proof
180-
.dump(output_dir, &name)
181-
.map_err(|e| e.to_string())?;
176+
batch_proof.dump(output_dir, &name)?;
182177
}
183178

184179
Ok(batch_proof)
@@ -196,7 +191,7 @@ impl<'params> Prover<'params> {
196191
bundle: BundleProvingTask,
197192
name: Option<&str>,
198193
output_dir: Option<&str>,
199-
) -> Result<BundleProof, BatchProverError> {
194+
) -> Result<BundleProof, ProverError> {
200195
// Denotes the identifier for this bundle proving task. Eventually a generated proof is
201196
// written to disk using this name.
202197
let name = name.map_or_else(|| bundle.identifier(), |name| name.to_string());
@@ -218,7 +213,7 @@ impl<'params> Prover<'params> {
218213
&bundle_snarks,
219214
output_dir,
220215
)
221-
.map_err(|e| e.to_string())?;
216+
.map_err(|e| BatchProverError::Custom(e.to_string()))?;
222217

223218
// Load from disk or generate a layer-6 Compression Circuit SNARK. Since we use a Keccak
224219
// hasher for the proof transcript at layer-6, the output proof is EVM-verifiable.
@@ -232,7 +227,7 @@ impl<'params> Prover<'params> {
232227
layer5_snark,
233228
output_dir,
234229
)
235-
.map_err(|e| e.to_string())?;
230+
.map_err(|e| BatchProverError::Custom(e.to_string()))?;
236231

237232
// Sanity check for the layer-6 verifying key.
238233
self.check_bundle_vk()?;
@@ -244,7 +239,7 @@ impl<'params> Prover<'params> {
244239
if let Some(output_dir) = output_dir {
245240
bundle_proof
246241
.dump(output_dir, "recursion")
247-
.map_err(|e| e.to_string())?;
242+
.map_err(|e| BatchProverError::Custom(e.to_string()))?;
248243
}
249244

250245
Ok(bundle_proof)
@@ -258,13 +253,14 @@ impl<'params> Prover<'params> {
258253
batch: BatchProvingTask,
259254
name: &str,
260255
output_dir: Option<&str>,
261-
) -> Result<(Snark, H256), BatchProverError> {
256+
) -> Result<(Snark, H256), ProverError> {
262257
// Early return with an error if the number of SNARKs to aggregate is not within limits.
263258
let num_chunks = batch.chunk_proofs.len();
264259
if !(1..=MAX_AGG_SNARKS).contains(&num_chunks) {
265260
return Err(BatchProverError::Custom(format!(
266261
"1 <= num_chunks <= MAX_AGG_SNARKS, found={num_chunks}"
267-
)));
262+
))
263+
.into());
268264
}
269265

270266
// Sanity check on the chunk proof's SNARK protocols.
@@ -311,28 +307,32 @@ impl<'params> Prover<'params> {
311307
return Err(BatchProverError::Custom(format!(
312308
"BatchHeader(sanity) data_hash mismatch! expected={}, got={}",
313309
batch.batch_header.data_hash, batch_header.data_hash
314-
)));
310+
))
311+
.into());
315312
}
316313
// Batch's random challenge point (z) must match.
317314
if batch_header.blob_data_proof[0] != batch.batch_header.blob_data_proof[0] {
318315
return Err(BatchProverError::Custom(format!(
319316
"BatchHeader(sanity) random challenge (z) mismatch! expected={}, got={}",
320317
batch.batch_header.blob_data_proof[0], batch_header.blob_data_proof[0],
321-
)));
318+
))
319+
.into());
322320
}
323321
// Batch's evaluation at z, i.e. y, must match.
324322
if batch_header.blob_data_proof[1] != batch.batch_header.blob_data_proof[1] {
325323
return Err(BatchProverError::Custom(format!(
326324
"BatchHeader(sanity) evaluation (y) mismatch! expected={}, got={}",
327325
batch.batch_header.blob_data_proof[1], batch_header.blob_data_proof[1],
328-
)));
326+
))
327+
.into());
329328
}
330329
// The versioned hash of the blob that encodes the batch must match.
331330
if batch_header.blob_versioned_hash != batch.batch_header.blob_versioned_hash {
332331
return Err(BatchProverError::Custom(format!(
333332
"BatchHeader(sanity) blob versioned_hash mismatch! expected={}, got={}",
334333
batch.batch_header.blob_versioned_hash, batch_header.blob_versioned_hash,
335-
)));
334+
))
335+
.into());
336336
}
337337

338338
// Build relevant types that are used for batch circuit witness assignments.
@@ -342,13 +342,14 @@ impl<'params> Prover<'params> {
342342

343343
// Sanity check: validate that conditionally decoded blob should match batch data.
344344
let batch_bytes = batch_data.get_batch_data_bytes();
345-
let decoded_blob_bytes = decode_blob(&batch.blob_bytes).map_err(|e| e.to_string())?;
345+
let decoded_blob_bytes =
346+
decode_blob(&batch.blob_bytes).map_err(|e| BatchProverError::Custom(e.to_string()))?;
346347
if batch_bytes != decoded_blob_bytes {
347348
return Err(BatchProverError::Custom(format!(
348349
"BatchProvingTask(sanity) decoded blob bytes do not match batch bytes! len(expected)={}, len(got)={}",
349350
decoded_blob_bytes.len(),
350351
batch_bytes.len(),
351-
)));
352+
)).into());
352353
}
353354

354355
// Load from disk or generate the layer-3 SNARK using the batch circuit.
@@ -364,18 +365,15 @@ impl<'params> Prover<'params> {
364365
&layer2_snarks,
365366
output_dir,
366367
)
367-
.map_err(|e| e.to_string())?;
368+
.map_err(|e| BatchProverError::Custom(e.to_string()))?;
368369

369370
Ok((layer3_snark, batch_hash))
370371
}
371372

372373
/// Sanity check: validate that the SNARK [`protocol`][snark_verifier::Protocol] for the SNARKs
373374
/// being aggregated by the [`BatchCircuit`][aggregator::BatchCircuit] match the expected SNARK
374375
/// protocols conditional to the chunk proof generation route utilised, i.e. halo2 or sp1.
375-
fn check_protocol_of_chunks(
376-
&self,
377-
chunk_proofs: &[ChunkProof],
378-
) -> Result<(), BatchProverError> {
376+
fn check_protocol_of_chunks(&self, chunk_proofs: &[ChunkProof]) -> Result<(), ProverError> {
379377
for (i, proof) in chunk_proofs.iter().enumerate() {
380378
let expected = match proof.chunk_kind {
381379
ChunkKind::Halo2 => &self.halo2_protocol,
@@ -394,7 +392,8 @@ impl<'params> Prover<'params> {
394392
i,
395393
expected_digest,
396394
found_digest,
397-
));
395+
)
396+
.into());
398397
}
399398
}
400399

@@ -404,7 +403,7 @@ impl<'params> Prover<'params> {
404403
/// Sanity check for the [`VerifyinKey`][halo2_proofs::plonk::VerifyingKey] used to generate
405404
/// Layer-4 SNARK that is wrapped inside the [`BatchProof`]. The prover generated VK is
406405
/// expected to match the VK used to initialise the prover.
407-
fn check_batch_vk(&self) -> Result<(), BatchProverError> {
406+
fn check_batch_vk(&self) -> Result<(), ProverError> {
408407
let layer = LayerId::Layer4;
409408
if let Some(expected_vk) = self.raw_vk_batch.as_ref() {
410409
let base64_exp_vk = base64::encode(expected_vk);
@@ -421,10 +420,11 @@ impl<'params> Prover<'params> {
421420
layer,
422421
base64_gen_vk,
423422
base64_exp_vk,
424-
));
423+
)
424+
.into());
425425
}
426426
} else {
427-
return Err(BatchProverError::VerifyingKeyNotFound(layer, base64_exp_vk));
427+
return Err(BatchProverError::VerifyingKeyNotFound(layer, base64_exp_vk).into());
428428
}
429429
}
430430

@@ -434,7 +434,7 @@ impl<'params> Prover<'params> {
434434
/// Sanity check for the [`VerifyinKey`][halo2_proofs::plonk::VerifyingKey] used to generate
435435
/// Layer-6 SNARK that is wrapped inside the [`BundleProof`]. The prover generated VK is
436436
/// expected to match the VK used to initialise the prover.
437-
fn check_bundle_vk(&self) -> Result<(), BatchProverError> {
437+
fn check_bundle_vk(&self) -> Result<(), ProverError> {
438438
let layer = LayerId::Layer6;
439439
if let Some(expected_vk) = self.raw_vk_bundle.as_ref() {
440440
let base64_exp_vk = base64::encode(expected_vk);
@@ -451,10 +451,11 @@ impl<'params> Prover<'params> {
451451
layer,
452452
base64_gen_vk,
453453
base64_exp_vk,
454-
));
454+
)
455+
.into());
455456
}
456457
} else {
457-
return Err(BatchProverError::VerifyingKeyNotFound(layer, base64_exp_vk));
458+
return Err(BatchProverError::VerifyingKeyNotFound(layer, base64_exp_vk).into());
458459
}
459460
}
460461

prover/src/aggregator/verifier.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ use halo2_proofs::{
66
plonk::VerifyingKey,
77
poly::kzg::commitment::ParamsKZG,
88
};
9-
use snark_verifier_sdk::Snark;
109

1110
use crate::{
1211
common,
1312
config::{LAYER4_CONFIG_PATH, LAYER4_DEGREE},
1413
consts::{batch_vk_filename, DEPLOYMENT_CODE_FILENAME},
1514
proof::BundleProof,
1615
utils::{deploy_and_call, force_to_read, try_to_read},
17-
ParamsMap,
16+
BatchProofV2, BatchProverError, ParamsMap, ProverError,
1817
};
1918

2019
/// Verifier capable of verifying both [`BatchProof`][crate::BatchProof] and [`BundleProof`].
@@ -72,8 +71,13 @@ impl<'params> Verifier<'params> {
7271
}
7372

7473
/// Verify a [`Layer-4`][crate::config::LayerId::Layer4] [`CompressionCircuit`] [`Snark`].
75-
pub fn verify_batch_proof<S: Into<Snark>>(&self, snark: S) -> bool {
76-
self.inner.verify_snark(snark.into())
74+
pub fn verify_batch_proof(&self, batch_proof: &BatchProofV2) -> Result<(), ProverError> {
75+
let snark = batch_proof.try_into()?;
76+
if self.inner.verify_snark(snark) {
77+
Ok(())
78+
} else {
79+
Err(BatchProverError::Verification.into())
80+
}
7781
}
7882

7983
/// Verify a [`Layer-6`][crate::config::LayerId::Layer6] EVM-verifiable

0 commit comments

Comments
 (0)