use std::ops::Deref;
use std::time::Duration;
use crate::Result;
use zisk_prover_backend::{GuestProgram, VerifyConstraintsOutput};
use crate::hints::HintsSource;
use crate::job_handle::{new_subscriber_list, JobHandle, JobId, SubscriberList};
use crate::{ExecutorKind, ZiskStdin};
pub struct VerifyConstraintsResult {
job_id: Option<JobId>,
output: VerifyConstraintsOutput,
}
impl VerifyConstraintsResult {
pub fn new(output: VerifyConstraintsOutput, job_id: Option<JobId>) -> Self {
Self { output, job_id }
}
pub fn job_id(&self) -> Option<&JobId> {
self.job_id.as_ref()
}
}
impl Deref for VerifyConstraintsResult {
type Target = VerifyConstraintsOutput;
fn deref(&self) -> &Self::Target {
&self.output
}
}
impl From<VerifyConstraintsOutput> for VerifyConstraintsResult {
fn from(output: VerifyConstraintsOutput) -> Self {
Self { output, job_id: None }
}
}
pub(crate) trait RunVerifyConstraints {
#[allow(clippy::too_many_arguments)]
fn run_verify_constraints(
&self,
program: &GuestProgram,
stdin: ZiskStdin,
hints: Option<HintsSource>,
debug_info: Option<Option<String>>,
executor: Option<ExecutorKind>,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<VerifyConstraintsResult>>;
}
pub struct VerifyConstraintsRequest<'a, C> {
client: &'a C,
program: &'a GuestProgram,
stdin: ZiskStdin,
hints: Option<HintsSource>,
debug_info: Option<Option<String>>,
executor: Option<ExecutorKind>,
timeout: Option<Duration>,
}
impl<'a, C> VerifyConstraintsRequest<'a, C> {
pub(crate) fn new(client: &'a C, program: &'a GuestProgram, stdin: ZiskStdin) -> Self {
Self {
client,
program,
stdin,
hints: None,
debug_info: None,
executor: None,
timeout: None,
}
}
#[must_use]
pub fn executor(mut self, executor: ExecutorKind) -> Self {
self.executor = Some(executor);
self
}
#[must_use]
pub fn hints(mut self, hints: impl Into<HintsSource>) -> Self {
self.hints = Some(hints.into());
self
}
#[must_use]
pub fn debug_info(mut self, path: impl Into<Option<String>>) -> Self {
self.debug_info = Some(path.into());
self
}
#[must_use]
pub fn timeout(mut self, duration: Duration) -> Self {
self.timeout = Some(duration);
self
}
}
#[allow(private_bounds)]
impl<'a, C: RunVerifyConstraints> VerifyConstraintsRequest<'a, C> {
pub fn run(self) -> Result<JobHandle<VerifyConstraintsResult>> {
let subs = new_subscriber_list();
self.client.run_verify_constraints(
self.program,
self.stdin,
self.hints,
self.debug_info,
self.executor,
self.timeout,
subs,
)
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` does not support verify_constraints",
note = "verify_constraints is only available on `EmbeddedClient` — \
`RemoteClient` cannot run this operation because the coordinator \
does not yet have a VerifyConstraints job kind",
label = "consider using `EmbeddedClientBuilder::new().build()` instead"
)]
#[allow(private_bounds)]
pub trait VerifyConstraintsExtension: RunVerifyConstraints + Sized {
fn verify_constraints<'a>(
&'a self,
program: &'a GuestProgram,
stdin: ZiskStdin,
) -> VerifyConstraintsRequest<'a, Self> {
VerifyConstraintsRequest::new(self, program, stdin)
}
}