Skip to main content

mina_tree/verifier/
mod.rs

1use 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
27// TODO: Move this into `Verifier` struct above
28pub static VERIFIER_INDEX: Lazy<Arc<VerifierIndex<Fq>>> = Lazy::new(|| {
29    TransactionVerifier::get()
30        .expect("verifier index not initialized")
31        .into()
32});
33
34/// Returns the Structured Reference String (SRS) for proof verification.
35/// Lazily created and cached globally. Immutable version for verifiers.
36///
37/// TODO: Use directly from proof-systems (<https://github.com/o1-labs/mina-rust/issues/1749>)
38pub 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
48/// Returns the SRS on the other curve (Mutex-wrapped version for prover).
49///
50/// TODO: Use directly from proof-systems (<https://github.com/o1-labs/mina-rust/issues/1749>)
51pub 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
61/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/transaction_snark/transaction_snark.ml#L3492>
62fn 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/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/verifier/dummy.ml#L59C1-L75C81>
86#[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
100/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/verifier/verifier_intf.ml#L10C1-L36C29>
101pub type VerifyCommandsResult = Result<valid::UserCommand, VerifierError>;
102
103#[derive(Debug, thiserror::Error)]
104pub enum VerifierError {
105    // TODO(adonagy): print something here as well?
106    #[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        // Implement verification later
136        //
137        // <https://github.com/MinaProtocol/mina/blob/05c2f73d0f6e4f1341286843814ce02dcb3919e0/src/lib/pickles/pickles.ml#L1122>
138        // <https://viable-systems.slack.com/archives/D01SVA87PQC/p1671715846448749>
139        Ok(Ok(()))
140    }
141
142    /// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/verifier/prod.ml#L138>
143    #[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;