1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "std")]
6extern crate std;
7
8use alloc::vec::Vec;
9
10use miden_air::{ProcessorAir, PublicInputs, config};
11use miden_crypto::stark;
12
13mod exports {
16 pub use miden_core::{
17 Word,
18 precompile::{
19 PrecompileTranscriptDigest, PrecompileTranscriptState, PrecompileVerificationError,
20 PrecompileVerifierRegistry,
21 },
22 program::{Kernel, ProgramInfo, StackInputs, StackOutputs},
23 proof::{ExecutionProof, HashFunction},
24 };
25 pub mod math {
26 pub use miden_core::Felt;
27 }
28}
29pub use exports::*;
30
31pub fn verify(
57 program_info: ProgramInfo,
58 stack_inputs: StackInputs,
59 stack_outputs: StackOutputs,
60 proof: ExecutionProof,
61) -> Result<u32, VerificationError> {
62 let (security_level, _commitment) = verify_with_precompiles(
63 program_info,
64 stack_inputs,
65 stack_outputs,
66 proof,
67 &PrecompileVerifierRegistry::new(),
68 )?;
69 Ok(security_level)
70}
71
72#[tracing::instrument("verify_program", skip_all)]
87pub fn verify_with_precompiles(
88 program_info: ProgramInfo,
89 stack_inputs: StackInputs,
90 stack_outputs: StackOutputs,
91 proof: ExecutionProof,
92 precompile_verifiers: &PrecompileVerifierRegistry,
93) -> Result<(u32, PrecompileTranscriptDigest), VerificationError> {
94 let security_level = proof.security_level();
95
96 let (hash_fn, proof_bytes, precompile_requests) = proof.into_parts();
97
98 let recomputed_transcript = precompile_verifiers
103 .requests_transcript(&precompile_requests)
104 .map_err(VerificationError::PrecompileVerificationError)?;
105 let pc_transcript_state = recomputed_transcript.state();
106
107 verify_stark(
109 program_info,
110 stack_inputs,
111 stack_outputs,
112 pc_transcript_state,
113 hash_fn,
114 proof_bytes,
115 )?;
116
117 let digest = recomputed_transcript.finalize();
119 Ok((security_level, digest))
120}
121
122fn verify_stark(
126 program_info: ProgramInfo,
127 stack_inputs: StackInputs,
128 stack_outputs: StackOutputs,
129 pc_transcript_state: PrecompileTranscriptState,
130 hash_fn: HashFunction,
131 proof_bytes: Vec<u8>,
132) -> Result<(), VerificationError> {
133 let program_hash = *program_info.program_hash();
134 let pub_inputs =
135 PublicInputs::new(program_info, stack_inputs, stack_outputs, pc_transcript_state);
136 let public_values = pub_inputs.to_elements();
137 let air = ProcessorAir::new();
138
139 match hash_fn {
140 HashFunction::Blake3_256 => {
141 let config = config::create_blake3_256_config();
142 let proof = bincode::deserialize(&proof_bytes)
143 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))?;
144 stark::verify(&config, &air, &proof, &public_values, &[])
145 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))
146 },
147 HashFunction::Rpo256 => {
148 let config = config::create_rpo_config();
149 let proof = bincode::deserialize(&proof_bytes)
150 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))?;
151 stark::verify(&config, &air, &proof, &public_values, &[])
152 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))
153 },
154 HashFunction::Rpx256 => {
155 let config = config::create_rpx_config();
156 let proof = bincode::deserialize(&proof_bytes)
157 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))?;
158 stark::verify(&config, &air, &proof, &public_values, &[])
159 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))
160 },
161 HashFunction::Poseidon2 => {
162 let config = config::create_poseidon2_config();
163 let proof = bincode::deserialize(&proof_bytes)
164 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))?;
165 stark::verify(&config, &air, &proof, &public_values, &[])
166 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))
167 },
168 HashFunction::Keccak => {
169 let config = config::create_keccak_config();
170 let proof = bincode::deserialize(&proof_bytes)
171 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))?;
172 stark::verify(&config, &air, &proof, &public_values, &[])
173 .map_err(|_| VerificationError::ProgramVerificationError(program_hash))
174 },
175 }?;
176
177 Ok(())
178}
179
180#[derive(Debug, thiserror::Error)]
185pub enum VerificationError {
186 #[error("failed to verify proof for program with hash {0}")]
187 ProgramVerificationError(Word),
188 #[error("failed to verify precompile calls")]
189 PrecompileVerificationError(#[source] PrecompileVerificationError),
190}