use std::time::Duration;
use crate::Result;
use zisk_common::{ProgramVK, Proof, ProofKind, PublicValues};
use zisk_prover_backend::GuestProgram;
use crate::{
aggregate_proofs::{AggregateProofsRequest, AggregationInput},
execute::{ExecuteRequest, ExecuteResult},
hints::HintsSource,
input_source::InputSource,
job_handle::{JobHandle, SubscriberList},
lifecycle::{SetupTarget, UploadTarget},
prove::{ProveRequest, ProveResult},
recurser::Recurser,
setup::{SetupRequest, SetupResult},
upload::{UploadRequest, UploadResult},
wrap::WrapRequest,
Client, EmbeddedClient, ExecutorKind, RemoteClient,
};
#[derive(Clone)]
#[allow(clippy::large_enum_variant)]
enum Inner {
Embedded(EmbeddedClient),
Remote(RemoteClient),
}
#[derive(Clone)]
pub struct ZiskClient {
inner: Inner,
executor: ExecutorKind,
}
impl From<EmbeddedClient> for ZiskClient {
fn from(client: EmbeddedClient) -> Self {
let executor = client.executor();
Self { inner: Inner::Embedded(client), executor }
}
}
impl From<RemoteClient> for ZiskClient {
fn from(client: RemoteClient) -> Self {
Self { inner: Inner::Remote(client), executor: ExecutorKind::default() }
}
}
impl Client for ZiskClient {
fn run_upload(&self, program: &GuestProgram) -> Result<UploadResult> {
match &self.inner {
Inner::Embedded(c) => c.run_upload(program),
Inner::Remote(c) => c.run_upload(program),
}
}
fn run_setup(
&self,
program: &GuestProgram,
with_hints: bool,
emulator_only: bool,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<SetupResult>> {
match &self.inner {
Inner::Embedded(c) => c.run_setup(program, with_hints, emulator_only, timeout, subs),
Inner::Remote(c) => c.run_setup(program, with_hints, emulator_only, timeout, subs),
}
}
fn run_prove(
&self,
program: &GuestProgram,
stdin: InputSource,
hints: Option<HintsSource>,
executor: ExecutorKind,
proof_kind: ProofKind,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<ProveResult>> {
match &self.inner {
Inner::Embedded(c) => {
c.run_prove(program, stdin, hints, executor, proof_kind, timeout, subs)
}
Inner::Remote(c) => {
c.run_prove(program, stdin, hints, executor, proof_kind, timeout, subs)
}
}
}
fn run_execute(
&self,
program: &GuestProgram,
stdin: InputSource,
hints: Option<HintsSource>,
executor: ExecutorKind,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<ExecuteResult>> {
match &self.inner {
Inner::Embedded(c) => c.run_execute(program, stdin, hints, executor, timeout, subs),
Inner::Remote(c) => c.run_execute(program, stdin, hints, executor, timeout, subs),
}
}
fn run_wrap(
&self,
proof: &Proof,
proof_kind: ProofKind,
override_publics: Option<PublicValues>,
override_program_vk: Option<ProgramVK>,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<ProveResult>> {
match &self.inner {
Inner::Embedded(c) => {
c.run_wrap(proof, proof_kind, override_publics, override_program_vk, timeout, subs)
}
Inner::Remote(c) => {
c.run_wrap(proof, proof_kind, override_publics, override_program_vk, timeout, subs)
}
}
}
fn run_upload_aggregation_program(&self, agg: &Recurser) -> Result<UploadResult> {
match &self.inner {
Inner::Embedded(c) => c.run_upload_aggregation_program(agg),
Inner::Remote(c) => c.run_upload_aggregation_program(agg),
}
}
fn run_setup_aggregation_program(
&self,
agg: &Recurser,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<SetupResult>> {
match &self.inner {
Inner::Embedded(c) => c.run_setup_aggregation_program(agg, timeout, subs),
Inner::Remote(c) => c.run_setup_aggregation_program(agg, timeout, subs),
}
}
fn run_aggregate_proofs(
&self,
agg: &Recurser,
proof_a: &Proof,
proof_b: &Proof,
free_a: &[u64],
free_b: &[u64],
root_c_recurser_agg: Option<[u64; 4]>,
timeout: Option<Duration>,
subs: SubscriberList,
) -> Result<JobHandle<ProveResult>> {
match &self.inner {
Inner::Embedded(c) => c.run_aggregate_proofs(
agg,
proof_a,
proof_b,
free_a,
free_b,
root_c_recurser_agg,
timeout,
subs,
),
Inner::Remote(c) => c.run_aggregate_proofs(
agg,
proof_a,
proof_b,
free_a,
free_b,
root_c_recurser_agg,
timeout,
subs,
),
}
}
}
impl ZiskClient {
#[must_use]
pub fn embedded() -> crate::EmbeddedClientBuilder<Self> {
crate::EmbeddedClientBuilder::for_output()
}
#[must_use]
pub fn remote(url: impl Into<String>) -> crate::RemoteClientBuilder<Self> {
crate::RemoteClientBuilder::new(url)
}
#[must_use]
pub fn as_embedded(&self) -> Option<&EmbeddedClient> {
match &self.inner {
Inner::Embedded(c) => Some(c),
Inner::Remote(_) => None,
}
}
#[must_use]
pub fn as_remote(&self) -> Option<&RemoteClient> {
match &self.inner {
Inner::Remote(c) => Some(c),
Inner::Embedded(_) => None,
}
}
#[must_use]
pub fn prove<'a>(
&'a self,
program: &'a GuestProgram,
stdin: impl Into<InputSource>,
) -> ProveRequest<'a, Self> {
ProveRequest::new(self, program, stdin, self.executor)
}
#[must_use]
pub fn execute<'a>(
&'a self,
program: &'a GuestProgram,
stdin: impl Into<InputSource>,
) -> ExecuteRequest<'a, Self> {
ExecuteRequest::new(self, program, stdin, self.executor)
}
#[must_use]
pub fn setup<'a, T: Into<SetupTarget<'a>>>(&'a self, target: T) -> SetupRequest<'a, Self> {
SetupRequest::new(self, target.into())
}
#[must_use]
pub fn upload<'a, T: Into<UploadTarget<'a>>>(&'a self, target: T) -> UploadRequest<'a, Self> {
UploadRequest::new(self, target.into())
}
#[must_use]
pub fn wrap_proof<'a>(
&'a self,
proof: &'a Proof,
proof_kind: ProofKind,
) -> WrapRequest<'a, Self> {
WrapRequest::new(self, proof, proof_kind)
}
#[must_use]
pub fn aggregate_proofs<'a>(
&'a self,
agg: &'a Recurser,
input_a: impl Into<AggregationInput<'a>>,
input_b: impl Into<AggregationInput<'a>>,
) -> AggregateProofsRequest<'a, Self> {
AggregateProofsRequest::new(self, agg, input_a.into(), input_b.into())
}
}