Skip to content

Commit

Permalink
Prover: Switch receipt kind based on ProverOpts (risc0#1688)
Browse files Browse the repository at this point in the history
This change adds a way to switch receipt formats using the `ProverOpts`.
There's a new field called `ReceiptFormat` that is used to specify the
desired receipt format generated from the prove function. Fake receipts
were not included as a part of this because `DevMode` has a separate
`ProverServer` implementation. This implements a way to configure
`Prover::prove` to return either composite or succinct receipts. In the
near future, an implementation for `CompactReceipts` will be implemented
for x86-linux as well as a way to configure the receipt types for
`Prover::Compress`.

Closes: risc0#1689

---------

Co-authored-by: Frank Laub <[email protected]>
  • Loading branch information
SchmErik and flaub authored Apr 24, 2024
1 parent 90961af commit dcf25f8
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 14 deletions.
19 changes: 19 additions & 0 deletions risc0/r0vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ struct Cli {
/// to read it.
#[arg(long, env = "RISC0_PPROF_OUT")]
pprof_out: Option<PathBuf>,

/// The receipt kind produced by the r0vm prover
#[arg(long, value_enum, default_value_t = ReceiptKind::Composite)]
receipt_kind: ReceiptKind,
}

#[derive(Args)]
Expand All @@ -88,6 +92,16 @@ enum HashFn {
Poseidon2,
}

#[derive(Clone, PartialEq, ValueEnum)]
enum ReceiptKind {
#[value(name = "composite")]
Composite,
#[value(name = "succinct")]
Succinct,
#[value(name = "compact")]
Compact,
}

pub fn main() {
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
Expand Down Expand Up @@ -163,6 +177,11 @@ impl Cli {
let opts = ProverOpts {
hashfn: hashfn.to_string(),
prove_guest_errors: self.prove_guest_errors,
receipt_kind: match self.receipt_kind {
ReceiptKind::Composite => risc0_zkvm::ReceiptKind::Composite,
ReceiptKind::Succinct => risc0_zkvm::ReceiptKind::Succinct,
ReceiptKind::Compact => risc0_zkvm::ReceiptKind::Compact,
},
};

get_prover_server(&opts).unwrap()
Expand Down
4 changes: 3 additions & 1 deletion risc0/zkvm/benches/fib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

use hotbench::{benchmark_group, benchmark_main, BenchGroup};
use risc0_zkvm::{
get_prover_server, ExecutorEnv, ExecutorImpl, ProverOpts, VerifierContext, RECURSION_PO2,
get_prover_server, ExecutorEnv, ExecutorImpl, ProverOpts, ReceiptKind, VerifierContext,
RECURSION_PO2,
};
use risc0_zkvm_methods::FIB_ELF;

Expand Down Expand Up @@ -60,6 +61,7 @@ fn prove_segment(group: &mut BenchGroup, hashfn: &str) {
let opts = ProverOpts {
hashfn: hashfn.to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
};
let prover = get_prover_server(&opts).unwrap();
let ctx = VerifierContext::default();
Expand Down
9 changes: 8 additions & 1 deletion risc0/zkvm/src/host/api/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
recursion::SuccinctReceipt,
},
Assumptions, ExitCode, Journal, MaybePruned, Output, ProveInfo, ProverOpts, Receipt,
ReceiptClaim, SessionStats, TraceEvent,
ReceiptClaim, ReceiptKind, SessionStats, TraceEvent,
};

mod ver {
Expand Down Expand Up @@ -200,6 +200,12 @@ impl From<pb::api::ProverOpts> for ProverOpts {
Self {
hashfn: opts.hashfn,
prove_guest_errors: opts.prove_guest_errors,
receipt_kind: match opts.receipt_kind {
0 => ReceiptKind::Composite,
1 => ReceiptKind::Succinct,
2 => ReceiptKind::Compact,
value => panic!("Unknown receipt kind number: {value}"),
},
}
}
}
Expand All @@ -209,6 +215,7 @@ impl From<ProverOpts> for pb::api::ProverOpts {
Self {
hashfn: opts.hashfn,
prove_guest_errors: opts.prove_guest_errors,
receipt_kind: opts.receipt_kind as i32,
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions risc0/zkvm/src/host/client/prove/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ pub struct ProverOpts {
// moment if there is a better place. At some point before 1.0, this option should be moved or
// dropped.
pub prove_guest_errors: bool,
/// The kind of receipt to be generated.
pub receipt_kind: ReceiptKind,
}

/// This enum represents the various receipt kinds that can be generated.
#[derive(Clone, Serialize, Deserialize, PartialEq)]
pub enum ReceiptKind {
/// Composite Receipts resulting from proving a session
Composite,
/// Succinct Receipts resulting from applying the lift and join programgs so Composite receipts
Succinct,
/// Compact Receipts resulting from stark2snark on the Succinct receipts
Compact,
}

impl Default for ProverOpts {
Expand All @@ -129,6 +142,7 @@ impl Default for ProverOpts {
Self {
hashfn: "poseidon2".to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
}
}
}
Expand All @@ -139,6 +153,25 @@ impl ProverOpts {
Self {
hashfn: "sha-256".to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
}
}

/// Choose the prover that enables succinct receipts.
pub fn succinct() -> Self {
Self {
hashfn: "poseidon2".to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Succinct,
}
}

/// Choose the prover that enables compact, snark receipts, only supported for x86_64 linux
pub fn compact() -> Self {
Self {
hashfn: "poseidon2".to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Compact,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions risc0/zkvm/src/host/protos/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ message Assumption {
message ProverOpts {
string hashfn = 1;
bool prove_guest_errors = 2;
ReceiptKind receipt_kind = 3;
}

enum ReceiptKind {
COMPOSITE = 0;
SUCCINCT = 1;
COMPACT = 2;
}

message SessionInfo {
Expand Down
5 changes: 3 additions & 2 deletions risc0/zkvm/src/host/recursion/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use super::{
ProverOpts as RecursionProverOpts,
};
use crate::{
default_prover, get_prover_server, ExecutorEnv, ExecutorImpl, InnerReceipt, ProverOpts,
Receipt, SegmentReceipt, Session, VerifierContext, ALLOWED_IDS_ROOT,
default_prover, get_prover_server, host::client::prove::ReceiptKind, ExecutorEnv, ExecutorImpl,
InnerReceipt, ProverOpts, Receipt, SegmentReceipt, Session, VerifierContext, ALLOWED_IDS_ROOT,
};

// Failure on older mac minis in the lab with Intel UHD 630 graphics:
Expand Down Expand Up @@ -142,6 +142,7 @@ fn generate_busy_loop_segments(hashfn: &str) -> (Session, Vec<SegmentReceipt>) {
let opts = ProverOpts {
hashfn: hashfn.to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
};
let prover = get_prover_server(&opts).unwrap();

Expand Down
10 changes: 9 additions & 1 deletion risc0/zkvm/src/host/server/prove/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ mod cuda {
Ok(Rc::new(ProverImpl::new(
"cuda",
HalPair { hal, circuit_hal },
opts.receipt_kind.clone(),
)))
}
"poseidon2" => {
Expand All @@ -176,6 +177,7 @@ mod cuda {
Ok(Rc::new(ProverImpl::new(
"cuda",
HalPair { hal, circuit_hal },
opts.receipt_kind.clone(),
)))
}
_ => bail!("Unsupported hashfn: {}", opts.hashfn),
Expand Down Expand Up @@ -204,6 +206,7 @@ mod metal {
Ok(Rc::new(ProverImpl::new(
"metal",
HalPair { hal, circuit_hal },
opts.receipt_kind.clone(),
)))
}
"poseidon2" => {
Expand All @@ -212,6 +215,7 @@ mod metal {
Ok(Rc::new(ProverImpl::new(
"metal",
HalPair { hal, circuit_hal },
opts.receipt_kind.clone(),
)))
}
_ => bail!("Unsupported hashfn: {}", opts.hashfn),
Expand Down Expand Up @@ -242,7 +246,11 @@ mod cpu {
let hal = Rc::new(CpuHal::new(suite));
let circuit_hal = Rc::new(CpuCircuitHal::new());
let hal_pair = HalPair { hal, circuit_hal };
Ok(Rc::new(ProverImpl::new("cpu", hal_pair)))
Ok(Rc::new(ProverImpl::new(
"cpu",
hal_pair,
opts.receipt_kind.clone(),
)))
}
}

Expand Down
25 changes: 20 additions & 5 deletions risc0/zkvm/src/host/server/prove/prover_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use risc0_zkp::hal::{CircuitHal, Hal};
use super::{HalPair, ProverServer};
use crate::{
host::{
client::prove::ReceiptKind,
prove_info::ProveInfo,
receipt::{CompositeReceipt, InnerReceipt, SegmentReceipt, SuccinctReceipt},
recursion::{identity_p254, join, lift, resolve},
Expand All @@ -35,6 +36,7 @@ where
{
name: String,
hal_pair: HalPair<H, C>,
receipt_kind: ReceiptKind,
}

impl<H, C> ProverImpl<H, C>
Expand All @@ -43,10 +45,11 @@ where
C: CircuitHal<H>,
{
/// Construct a [ProverImpl] with the given name and [HalPair].
pub fn new(name: &str, hal_pair: HalPair<H, C>) -> Self {
pub fn new(name: &str, hal_pair: HalPair<H, C>, receipt_kind: ReceiptKind) -> Self {
Self {
name: name.to_string(),
hal_pair,
receipt_kind,
}
}
}
Expand Down Expand Up @@ -103,10 +106,22 @@ where
);
}

let receipt = Receipt::new(
InnerReceipt::Composite(composite_receipt),
session.journal.clone().unwrap_or_default().bytes,
);
let receipt = match self.receipt_kind {
ReceiptKind::Composite => Receipt::new(
InnerReceipt::Composite(composite_receipt),
session.journal.clone().unwrap_or_default().bytes,
),
ReceiptKind::Succinct => {
let succinct_receipt = self.compress(&composite_receipt)?;
Receipt::new(
InnerReceipt::Succinct(succinct_receipt),
session.journal.clone().unwrap_or_default().bytes,
)
}
ReceiptKind::Compact => {
todo!("this will be implemented in the near future")
}
};

// Verify the receipt to catch if something is broken in the proving process.
receipt.verify_integrity_with_context(ctx)?;
Expand Down
28 changes: 25 additions & 3 deletions risc0/zkvm/src/host/server/prove/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ use super::{get_prover_server, HalPair, ProverImpl};
use crate::{
host::server::testutils,
serde::{from_slice, to_vec},
ExecutorEnv, ExecutorImpl, ExitCode, ProveInfo, ProverOpts, ProverServer, Receipt, Session,
VerifierContext,
ExecutorEnv, ExecutorImpl, ExitCode, ProveInfo, ProverOpts, ProverServer, Receipt, ReceiptKind,
Session, VerifierContext,
};

fn prover_opts_fast() -> ProverOpts {
ProverOpts {
hashfn: "sha-256".to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
}
}

Expand All @@ -59,10 +60,29 @@ fn prove_nothing(hashfn: &str) -> Result<ProveInfo> {
let opts = ProverOpts {
hashfn: hashfn.to_string(),
prove_guest_errors: false,
receipt_kind: ReceiptKind::Composite,
};
get_prover_server(&opts).unwrap().prove(env, MULTI_TEST_ELF)
}

#[test]
fn prove_nothing_succinct() {
let env = ExecutorEnv::builder()
.write(&MultiTestSpec::DoNothing)
.unwrap()
.build()
.unwrap();
let opts = ProverOpts::succinct();
get_prover_server(&opts)
.unwrap()
.prove(env, MULTI_TEST_ELF)
.unwrap()
.receipt
.inner
.succinct()
.unwrap(); // ensure that we got a succinct receipt.
}

#[test]
#[cfg_attr(feature = "cuda", serial)]
fn hashfn_poseidon2() {
Expand All @@ -80,7 +100,7 @@ fn hashfn_blake2b() {
.unwrap()
.build()
.unwrap();
let prover = ProverImpl::new("cpu:blake2b", hal_pair);
let prover = ProverImpl::new("cpu:blake2b", hal_pair, ReceiptKind::Composite);
prover.prove(env, MULTI_TEST_ELF).unwrap();
}

Expand Down Expand Up @@ -533,6 +553,7 @@ mod docker {
}

mod sys_verify {
use crate::ReceiptKind;
use risc0_zkvm_methods::{
multi_test::MultiTestSpec, HELLO_COMMIT_ELF, HELLO_COMMIT_ID, MULTI_TEST_ELF, MULTI_TEST_ID,
};
Expand Down Expand Up @@ -560,6 +581,7 @@ mod sys_verify {
let opts = ProverOpts {
hashfn: "sha-256".to_string(),
prove_guest_errors: true,
receipt_kind: ReceiptKind::Composite,
};

let env = ExecutorEnvBuilder::default()
Expand Down
2 changes: 1 addition & 1 deletion risc0/zkvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub use {
env::{ExecutorEnv, ExecutorEnvBuilder},
prove::{
bonsai::BonsaiProver, default_executor, default_prover, external::ExternalProver,
Executor, Prover, ProverOpts,
Executor, Prover, ProverOpts, ReceiptKind,
},
},
},
Expand Down

0 comments on commit dcf25f8

Please sign in to comment.