use std::fmt;
use std::sync::Arc;
use tasm_lib::triton_vm::prelude::Program;
use tasm_lib::triton_vm::proof::Claim;
use tasm_lib::triton_vm::vm::NonDeterminism;
use crate::proof_abstractions::error::CreateProofError;
use crate::proof_abstractions::error::ProofRequirement;
use crate::proof_abstractions::tasm::program::prove_triton_program;
use crate::proof_abstractions::tasm::program::TritonVmProofJobOptions;
use crate::proof_abstractions::triton_vm_job_queue::vm_job_queue;
use crate::proof_abstractions::triton_vm_job_queue::TritonVmJobQueue;
use crate::transaction::validity::neptune_proof::Proof;
#[derive(Default)]
pub struct ProofBuilder<'a> {
program: Option<Program>,
claim: Option<Claim>,
nondeterminism_callback: Option<Box<dyn FnOnce() -> NonDeterminism + Send + Sync + 'a>>,
job_queue: Option<Arc<TritonVmJobQueue>>,
proof_job_options: Option<TritonVmProofJobOptions>,
valid_mock: Option<bool>,
}
impl fmt::Debug for ProofBuilder<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ProofBuilder")
.field("program", &self.program)
.field("claim", &self.claim)
.field("job_queue", &self.job_queue)
.field("proof_job_options", &self.proof_job_options)
.field("valid_mock", &self.valid_mock)
.finish()
}
}
impl<'a> ProofBuilder<'a> {
pub fn new() -> Self {
Default::default()
}
pub fn program(mut self, program: Program) -> Self {
self.program = Some(program);
self
}
pub fn claim(mut self, claim: Claim) -> Self {
self.claim = Some(claim);
self
}
pub fn nondeterminism<F>(mut self, callback: F) -> Self
where
F: FnOnce() -> NonDeterminism + Send + Sync + 'a,
{
self.nondeterminism_callback = Some(Box::new(callback));
self
}
pub fn job_queue(mut self, job_queue: Arc<TritonVmJobQueue>) -> Self {
self.job_queue = Some(job_queue);
self
}
pub fn proof_job_options(mut self, proof_job_options: TritonVmProofJobOptions) -> Self {
self.proof_job_options = Some(proof_job_options);
self
}
pub fn valid_mock(mut self, valid_mock: bool) -> Self {
self.valid_mock = Some(valid_mock);
self
}
pub async fn build(self) -> Result<Proof, CreateProofError> {
let Self {
program,
claim,
nondeterminism_callback,
job_queue,
proof_job_options,
valid_mock,
} = self;
let program = program.ok_or(ProofRequirement::Program)?;
let claim = claim.ok_or(ProofRequirement::Claim)?;
let nondeterminism_callback =
nondeterminism_callback.ok_or(ProofRequirement::NonDeterminism)?;
let proof_job_options = proof_job_options.ok_or(ProofRequirement::ProofJobOptions)?;
if proof_job_options.job_settings.network.use_mock_proof() {
let proof = Proof::mock(valid_mock.unwrap_or(true));
return Ok(proof);
}
let nondeterminism = nondeterminism_callback();
let proof_type = proof_job_options.job_settings.proof_type;
let capability = proof_job_options.job_settings.tx_proving_capability;
if !capability.can_prove(proof_type) {
return Err(CreateProofError::TooWeak {
proof_type,
capability,
});
}
if !proof_type.executes_in_vm() {
return Err(CreateProofError::NotVmProof(proof_type));
}
let job_queue = job_queue.unwrap_or_else(vm_job_queue);
prove_triton_program(program, claim, nondeterminism, job_queue, proof_job_options).await
}
}