mina_tree/verifier/
mod.rs1use self::common::CheckResult;
2use crate::{
3 proofs::{
4 self, field::FieldWitness, verification, verifiers::TransactionVerifier, VerifierIndex,
5 },
6 scan_state::{
7 scan_state::transaction_snark::{
8 LedgerProof, LedgerProofWithSokMessage, SokMessage, TransactionSnark,
9 },
10 transaction_logic::{valid, verifiable, zkapp_statement::ZkappStatement, WithStatus},
11 },
12 staged_ledger::staged_ledger::SkipVerification,
13 VerificationKey,
14};
15use mina_curves::pasta::{Fp, Fq};
16use mina_p2p_messages::v2::{
17 PicklesProofProofsVerified2ReprStableV2, PicklesProofProofsVerifiedMaxStableV2,
18};
19use mina_signer::CompressedPubKey;
20use once_cell::sync::Lazy;
21use poly_commitment::{ipa::SRS, SRS as _};
22use std::sync::{Arc, Mutex};
23
24#[derive(Debug, Clone)]
25pub struct Verifier;
26
27pub static VERIFIER_INDEX: Lazy<Arc<VerifierIndex<Fq>>> = Lazy::new(|| {
29 TransactionVerifier::get()
30 .expect("verifier index not initialized")
31 .into()
32});
33
34pub fn get_srs<F: FieldWitness>() -> Arc<SRS<F::OtherCurve>> {
39 cache! {
40 Arc<SRS<F::OtherCurve>>,
41 {
42 let srs = SRS::<F::OtherCurve>::create(<F as proofs::field::FieldWitness>::Scalar::SRS_DEPTH);
43 Arc::new(srs)
44 }
45 }
46}
47
48pub fn get_srs_mut<F: FieldWitness>() -> Arc<Mutex<SRS<F::OtherCurve>>> {
52 cache! {
53 Arc<Mutex<SRS<F::OtherCurve>>>,
54 {
55 let srs = SRS::<F::OtherCurve>::create(<F as proofs::field::FieldWitness>::Scalar::SRS_DEPTH);
56 Arc::new(Mutex::new(srs))
57 }
58 }
59}
60
61fn verify(ts: Vec<(LedgerProof, SokMessage)>) -> Result<(), String> {
63 let srs = get_srs::<Fp>();
64
65 if ts.iter().all(|(proof, msg)| {
66 let LedgerProof(TransactionSnark { statement, .. }) = proof;
67 statement.sok_digest == msg.digest()
68 }) {
69 let verifier_index = VERIFIER_INDEX.as_ref();
70
71 let proofs = ts.iter().map(|(proof, _)| {
72 let LedgerProof(TransactionSnark { statement, proof }) = proof;
73 (statement, &**proof)
74 });
75
76 if !crate::proofs::verification::verify_transaction(proofs, verifier_index, &srs) {
77 return Err("Transaction_snark.verify: verification failed".into());
78 }
79 Ok(())
80 } else {
81 Err("Transaction_snark.verify: Mismatched sok_message".into())
82 }
83}
84
85#[cfg(test)]
87fn verify_digest_only(ts: Vec<(LedgerProof, SokMessage)>) -> Result<(), String> {
88 use crate::scan_state::scan_state::transaction_snark::SokDigest;
89
90 if ts.iter().all(|(proof, msg)| {
91 let LedgerProof(TransactionSnark { statement, .. }) = proof;
92 statement.sok_digest == SokDigest::default() || statement.sok_digest == msg.digest()
93 }) {
94 Ok(())
95 } else {
96 Err("Transaction_snark.verify: Mismatched sok_message".into())
97 }
98}
99
100pub type VerifyCommandsResult = Result<valid::UserCommand, VerifierError>;
102
103#[derive(Debug, thiserror::Error)]
104pub enum VerifierError {
105 #[error("Batch verification failed")]
107 ValidAssuming(
108 Vec<(
109 VerificationKey,
110 ZkappStatement,
111 Arc<PicklesProofProofsVerifiedMaxStableV2>,
112 )>,
113 ),
114 #[error("Invalid keys: {0:?}")]
115 InvalidKeys(Vec<CompressedPubKey>),
116 #[error("Invalid signature: {0:?}")]
117 InvalidSignature(Vec<CompressedPubKey>),
118 #[error("Invalid proof: {0}")]
119 InvalidProof(String),
120 #[error("Missing verification key: {0:?}")]
121 MissingVerificationKey(Vec<CompressedPubKey>),
122 #[error("Unexpected verification key: {0:?}")]
123 UnexpectedVerificationKey(Vec<CompressedPubKey>),
124 #[error("Mismatched verification key: {0:?}")]
125 MismatchedVerificationKey(Vec<CompressedPubKey>),
126 #[error("Authorization kind does not match the authorization - Keys {0:?}")]
127 MismatchedAuthorizationKind(Vec<CompressedPubKey>),
128}
129
130impl Verifier {
131 pub fn verify(
132 &self,
133 _proofs: &[Arc<LedgerProofWithSokMessage>],
134 ) -> Result<Result<(), ()>, String> {
135 Ok(Ok(()))
140 }
141
142 #[allow(unreachable_code)]
144 pub fn verify_transaction_snarks(
145 &self,
146 ts: Vec<(LedgerProof, SokMessage)>,
147 ) -> Result<(), String> {
148 #[cfg(test)]
149 return verify_digest_only(ts);
150
151 verify(ts)
152 }
153
154 pub fn verify_commands(
155 &self,
156 cmds: Vec<WithStatus<verifiable::UserCommand>>,
157 skip_verification: Option<SkipVerification>,
158 ) -> Vec<VerifyCommandsResult> {
159 let cs: Vec<_> = cmds.into_iter().map(common::check).collect();
160
161 let mut to_verify = cs
162 .iter()
163 .filter_map(|c| match c {
164 CheckResult::Valid(_) => None,
165 CheckResult::ValidAssuming((_, xs)) => Some(xs),
166 _ => None,
167 })
168 .flatten();
169
170 let all_verified = if skip_verification.is_some() {
171 true
172 } else {
173 let srs = get_srs::<Fp>();
174
175 to_verify.all(|(vk, zkapp_statement, proof)| {
176 let proof: PicklesProofProofsVerified2ReprStableV2 = (&**proof).into();
177 verification::verify_zkapp(vk, zkapp_statement, &proof, &srs)
178 })
179 };
180
181 cs.into_iter()
182 .map(|c| match c {
183 CheckResult::Valid(c) => Ok(c),
184 CheckResult::ValidAssuming((c, xs)) => {
185 if all_verified {
186 Ok(c)
187 } else {
188 Err(VerifierError::ValidAssuming(xs))
189 }
190 }
191 CheckResult::InvalidKeys(keys) => Err(VerifierError::InvalidKeys(keys)),
192 CheckResult::InvalidSignature(keys) => Err(VerifierError::InvalidSignature(keys)),
193 CheckResult::InvalidProof(s) => Err(VerifierError::InvalidProof(s)),
194 CheckResult::MissingVerificationKey(keys) => {
195 Err(VerifierError::MissingVerificationKey(keys))
196 }
197 CheckResult::UnexpectedVerificationKey(keys) => {
198 Err(VerifierError::UnexpectedVerificationKey(keys))
199 }
200 CheckResult::MismatchedAuthorizationKind(keys) => {
201 Err(VerifierError::MismatchedAuthorizationKind(keys))
202 }
203 })
204 .collect()
205 }
206}
207
208pub mod common;