Skip to content

Commit ed6509e

Browse files
committed
catch verification panics
1 parent 9e83560 commit ed6509e

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

crates/core/executor/src/executor.rs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,20 @@ pub enum ExecutionError {
262262
/// The actual number of deferred proofs that were verified.
263263
actual: usize,
264264
},
265+
266+
/// Insufficient deferred proofs were provided.
267+
#[error("insufficient deferred proofs: unable to verify proof at index {index}")]
268+
InsufficientDeferredProofs {
269+
/// The index of the proof that was requested.
270+
index: usize,
271+
},
272+
273+
/// Deferred proof verification failed.
274+
#[error("deferred proof verification failed: {reason}")]
275+
DeferredProofVerificationFailed {
276+
/// The reason for the verification failure.
277+
reason: String,
278+
},
265279
}
266280

267281
impl<'a> Executor<'a> {
@@ -1623,7 +1637,51 @@ impl<'a> Executor<'a> {
16231637
// Executing a syscall optionally returns a value to write to the t0
16241638
// register. If it returns None, we just keep the
16251639
// syscall_id in t0.
1626-
let res = syscall_impl.execute(&mut precompile_rt, syscall, b, c);
1640+
let res = if syscall == SyscallCode::VERIFY_SP1_PROOF {
1641+
// Catch panics for VERIFY_SP1_PROOF to provide better error messages.
1642+
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1643+
syscall_impl.execute(&mut precompile_rt, syscall, b, c)
1644+
})) {
1645+
Ok(result) => result,
1646+
Err(panic_payload) => {
1647+
// Extract the panic message.
1648+
let msg = panic_payload
1649+
.downcast_ref::<String>()
1650+
.map(String::as_str)
1651+
.or_else(|| panic_payload.downcast_ref::<&str>().copied());
1652+
1653+
if let Some(msg) = msg {
1654+
let index = precompile_rt.rt.state.proof_stream_ptr;
1655+
let available = precompile_rt.rt.state.proof_stream.len();
1656+
1657+
if msg.contains("Not enough proofs") {
1658+
tracing::error!(
1659+
"Insufficient deferred proofs: unable to verify proof \
1660+
at index {index} because only {available} proofs were \
1661+
provided. \
1662+
Make sure you're passing the correct number of proofs \
1663+
and that you're calling verify_sp1_proof for all proofs."
1664+
);
1665+
return Err(ExecutionError::InsufficientDeferredProofs {
1666+
index,
1667+
});
1668+
} else if msg.contains("Failed to verify proof") {
1669+
tracing::error!(
1670+
"Failed to verify deferred proof at index {index}."
1671+
);
1672+
return Err(ExecutionError::DeferredProofVerificationFailed {
1673+
reason: msg.to_string(),
1674+
});
1675+
}
1676+
}
1677+
1678+
// Resume default behavior for unknown panics.
1679+
std::panic::resume_unwind(panic_payload);
1680+
}
1681+
}
1682+
} else {
1683+
syscall_impl.execute(&mut precompile_rt, syscall, b, c)
1684+
};
16271685
let a = if let Some(val) = res { val } else { syscall_id };
16281686

16291687
// If the syscall is `HALT` and the exit code is non-zero, return an error.
@@ -2137,8 +2195,9 @@ impl<'a> Executor<'a> {
21372195
if self.state.proof_stream_ptr != self.state.proof_stream.len() {
21382196
tracing::error!(
21392197
"Not all proofs were verified. \
2140-
Make sure you are passing the correct number of proofs \
2141-
and that you are calling verify_sp1_proof for all proofs."
2198+
Expected to verify {expected} proofs, but only {actual} were verified. \
2199+
Make sure you're passing the correct number of proofs \
2200+
and that you're calling verify_sp1_proof for all proofs."
21422201
);
21432202
return Err(ExecutionError::UnverifiedDeferredProofs {
21442203
expected: self.state.proof_stream.len(),

0 commit comments

Comments
 (0)