Skip to content

Commit

Permalink
refactor: Add wrapper for triton_vm::verify
Browse files Browse the repository at this point in the history
The purpose of this method is two-fold:
 - First, it guarantees that `triton_vm::verify` is always called
   in the right way -- *i.e.*, with the right `Stark` parameters
   and in a new tokio task.
 - Second, when the test flag is set it can bypass the verify call
   when the claim is present in the cache, enabling tests involving
   verification to avoid producing proofs.
  • Loading branch information
aszepieniec authored and Sword-Smith committed Jan 20, 2025
1 parent 2dd639c commit 85a79d5
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/models/proof_abstractions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use triton_vm::prelude::PublicInput;
pub mod mast_hash;
pub mod tasm;
pub mod timestamp;
pub mod verifier;

/// A `SecretWitness` is data that makes a `ConsensusProgram` halt gracefully, but
/// that should be hidden behind a zero-knowledge proof.
Expand Down
76 changes: 76 additions & 0 deletions src/models/proof_abstractions/verifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use tasm_lib::triton_vm;
use tasm_lib::triton_vm::proof::Claim;
use tasm_lib::triton_vm::proof::Proof;
use tasm_lib::triton_vm::stark::Stark;
use tokio::task;

#[cfg(test)]
static CLAIMS_CACHE: std::sync::LazyLock<tokio::sync::Mutex<std::collections::HashSet<Claim>>> =
std::sync::LazyLock::new(|| tokio::sync::Mutex::new(std::collections::HashSet::new()));

/// Verify a Triton VM (claim,proof) pair for default STARK parameters.
///
/// When the test flag is set, this function checks whether the claim is present
/// in the `CLAIMS_CACHE` and if so returns true early (*i.e.*, without running
/// the verifier). When the test flag is set and the cache does not contain the
/// claim and verification succeeds, the claim is added to the cache. The only
/// other way to populate the cache is through method [`cache_true_claim`].
pub(crate) async fn verify(claim: Claim, proof: Proof) -> bool {
#[cfg(test)]
if CLAIMS_CACHE.lock().await.contains(&claim) {
return true;
}

let claim_clone = claim.clone();
let verdict =
task::spawn_blocking(move || triton_vm::verify(Stark::default(), &claim_clone, &proof))
.await
.expect("should be able to verify proof in new tokio task");

#[cfg(test)]
if verdict {
cache_true_claim(claim).await;
}

verdict
}

/// Add a claim to the `CLAIMS_CACHE`.
#[cfg(test)]
pub(crate) async fn cache_true_claim(claim: Claim) {
CLAIMS_CACHE.lock().await.insert(claim);
}

#[cfg(test)]
pub(crate) mod test {
use itertools::Itertools;
use rand::{thread_rng, Rng};

use tasm_lib::prelude::Tip5;
use triton_vm::prelude::BFieldCodec;

use super::*;

pub(crate) fn bogus_proof(claim: &Claim) -> Proof {
Proof(Tip5::hash_varlen(&claim.encode()).values().to_vec())
}

#[tokio::test]
async fn test_claims_cache() {
// generate random claim and bogus proof
let mut rng = thread_rng();
let some_claim = Claim::new(rng.gen())
.with_input((0..10).map(|_| rng.gen()).collect_vec())
.with_output((0..10).map(|_| rng.gen()).collect_vec());
let some_proof = bogus_proof(&some_claim);

// verification must fail
assert!(!verify(some_claim.clone(), some_proof.clone()).await);

// put claim into cache
cache_true_claim(some_claim.clone()).await;

// verification must succeed
assert!(verify(some_claim, some_proof).await);
}
}

0 comments on commit 85a79d5

Please sign in to comment.