warriors/trisha/cli/verify.rs

use std::path::PathBuf;
use std::process;

use clap::{Args, Subcommand};

use trident::runtime::Verifier;
use trisha_rs::Warrior;

use crate::batch;
use crate::error::TrishaError;

use super::load_proof_data;

#[derive(Args)]
#[command(args_conflicts_with_subcommands = true)]
pub struct VerifyArgs {
    #[command(subcommand)]
    pub mode: Option<VerifyMode>,

    pub proof: Option<PathBuf>,
    #[arg(long, default_value = "triton")]
    pub target: String,
}

#[derive(Subcommand)]
pub enum VerifyMode {
    Batch(VerifyBatchArgs),
}

#[derive(Args)]
pub struct VerifyBatchArgs {
    pub proofs: Vec<PathBuf>,
    #[arg(long, default_value = "triton")]
    pub target: String,
    #[arg(long, default_value = "4")]
    pub max_parallel: usize,
}

pub fn cmd_verify(args: VerifyArgs) {
    match args.mode {
        Some(VerifyMode::Batch(batch_args)) => cmd_verify_batch(batch_args),
        None => {
            let proof = match args.proof {
                Some(p) => p,
                None => {
                    eprintln!("error: no proof file specified");
                    process::exit(1);
                }
            };
            cmd_verify_single(proof);
        }
    }
}

fn cmd_verify_single(proof_path: PathBuf) {
    let proof_data = match load_proof_data(&proof_path) {
        Ok(p) => p,
        Err(e) => {
            eprintln!("error: {}", e);
            process::exit(1);
        }
    };
    let warrior = Warrior::new();
    match warrior.verify(&proof_data) {
        Ok(true) => println!("Verification: PASS"),
        Ok(false) => {
            println!("Verification: FAIL");
            process::exit(1);
        }
        Err(e) => {
            eprintln!("error: {}", e);
            process::exit(1);
        }
    }
}

fn cmd_verify_batch(args: VerifyBatchArgs) {
    if args.proofs.is_empty() {
        eprintln!("error: no proof files specified");
        process::exit(1);
    }
    let count = args.proofs.len();
    eprintln!(
        "Verifying {} proofs (max {} parallel)...",
        count, args.max_parallel
    );
    let results = batch::run_batch(args.proofs, args.max_parallel, |path| {
        let proof_data = load_proof_data(&path)?;
        let warrior = Warrior::new();
        let valid = warrior.verify(&proof_data).map_err(TrishaError::Verify)?;
        Ok::<(PathBuf, bool), TrishaError>((path, valid))
    });
    let mut failures = 0;
    for r in &results {
        match &r.result {
            Ok((path, true)) => {
                eprintln!("  {} PASS ({} ms)", path.display(), r.elapsed_ms);
            }
            Ok((path, false)) => {
                eprintln!("  {} FAIL", path.display());
                failures += 1;
            }
            Err(e) => {
                eprintln!("  [{}] ERROR: {}", r.index, e);
                failures += 1;
            }
        }
    }
    eprintln!("{}/{} verified", count - failures, count);
    if failures > 0 {
        process::exit(1);
    }
}

Homonyms

neural/trident/src/cli/verify.rs

Graph