Skip to content

Commit

Permalink
Support for deferred assumptions (risc0#2288)
Browse files Browse the repository at this point in the history
This change defers the processing of on-demand ZKR proofs so that they
occur later in the pipeline rather than inline during the execution
phase. The benefit of this approach is that proving services can
distribute the ZKR proof workload out to a worker pool.

A `CoprocessorCallback` can be configured on the `ExecutorEnv` which
allows users to receive a notification when a ZKR proof needs to be
produced. The ZKR proof can happen asynchronously and does not need to
block the executor. However, the assumption receipt needs to be produced
by the time `resolve` is called to resolve any outstanding assumptions.
  • Loading branch information
flaub authored Sep 7, 2024
1 parent 1938061 commit fcde654
Show file tree
Hide file tree
Showing 53 changed files with 1,138 additions and 535 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,10 @@ jobs:
run: cargo test --locked -F $FEATURE --no-run
working-directory: examples
- name: test in dev mode
run: RISC0_DEV_MODE=1 cargo test --locked -F $FEATURE --workspace --exclude prover
run: RISC0_DEV_MODE=1 cargo test --locked -F $FEATURE --workspace --exclude prover-example
working-directory: examples
- name: test prover example
run: cargo test --locked -F $FEATURE -p prover
run: cargo test --locked -F $FEATURE -p prover-example
working-directory: examples
- run: cargo run --locked -F $FEATURE
env:
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ metal = "0.29"
risc0-binfmt = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/binfmt" }
risc0-build = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/build" }
risc0-build-kernel = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/build_kernel" }
risc0-circuit-bigint = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/circuit/bigint" }
risc0-circuit-recursion = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/circuit/recursion" }
risc0-circuit-recursion-sys = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/circuit/recursion-sys" }
risc0-circuit-rv32im = { version = "1.2.0-alpha.1", default-features = false, path = "risc0/circuit/rv32im" }
Expand Down
107 changes: 35 additions & 72 deletions examples/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions examples/prover/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
[package]
name = "prover"
name = "prover-example"
version = "0.1.0"
edition = "2021"

[dependencies]
risc0-zkvm = { path = "../../risc0/zkvm" }
risc0-zkvm-methods = { path = "../../risc0/zkvm/methods" }
anyhow = "1.0"
num-bigint = { version = "0.4", features = ["serde"] }
risc0-circuit-bigint = { path = "../../risc0/circuit/bigint" }
risc0-circuit-bigint-test-methods = { path = "../../risc0/circuit/bigint/methods" }
risc0-zkvm = { path = "../../risc0/zkvm", features = ["unstable"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
workerpool = "1.2"

[features]
Expand Down
7 changes: 7 additions & 0 deletions examples/prover/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- cargo-rdme start -->

This is an example of how the public 1.0 API can be used to build a proving service.
It's not meant to be used in production since it doesn't handle failures.
This is also not an optimal implementation; many performance improvements could be made.

<!-- cargo-rdme end -->
91 changes: 81 additions & 10 deletions examples/prover/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,63 @@ mod plan;
mod task_mgr;
mod worker;

use risc0_zkvm::{ApiClient, Asset, AssetRequest, ExecutorEnv, InnerReceipt, Receipt};
use risc0_zkvm_methods::{FIB_ELF, FIB_ID};
use std::{cell::RefCell, collections::HashMap, rc::Rc};

use anyhow::Result;
use num_bigint::BigUint;
use risc0_circuit_bigint_test_methods::{RSA_ELF, RSA_ID};
use risc0_zkvm::{
sha::Digest, ApiClient, Asset, AssetRequest, CoprocessorCallback, ExecutorEnv, InnerReceipt,
ProveZkrRequest, ProverOpts, Receipt, SuccinctReceipt, Unknown,
};

use self::{plan::Planner, task_mgr::TaskManager};

fn main() {
prover_example();
}

struct Coprocessor {
pub(crate) receipts: HashMap<Digest, SuccinctReceipt<Unknown>>,
}

impl Coprocessor {
fn new() -> Self {
Self {
receipts: HashMap::new(),
}
}
}

impl CoprocessorCallback for Coprocessor {
fn prove_zkr(&mut self, proof_request: ProveZkrRequest) -> Result<()> {
let client = ApiClient::from_env().unwrap();
let claim_digest = proof_request.claim_digest;
let receipt = client.prove_zkr(proof_request, AssetRequest::Inline)?;
self.receipts.insert(claim_digest, receipt);
Ok(())
}
}

fn prover_example() {
println!("Submitting proof request...");

let mut task_manager = TaskManager::new();
let mut planner = Planner::default();

let iterations = 100;
// Parameters for a message `m` with signature `s` under the RSA public key modulus `n`.
let n = from_hex(b"9c98f9aacfc0b73c916a824db9afe39673dcb56c42dffe9de5b86d5748aca4d5");
let s = from_hex(b"de67116c809a5cc876cebb5e8c72d998f983a4d61b499dd9ae23b789a7183677");
let m = from_hex(b"1fb897fac8aa8870b936631d3af1a17930c8af0ca4376b3056677ded52adf5aa");
let claims = vec![[n, s, m]];

let coprocessor = Rc::new(RefCell::new(Coprocessor::new()));
let env = ExecutorEnv::builder()
.write_slice(&[iterations])
.coprocessor_callback(coprocessor.clone())
.write(&claims)
.unwrap()
// Use a low segment size to generate more jobs in this example.
.segment_limit_po2(15)
.segment_limit_po2(17)
.build()
.unwrap();

Expand All @@ -48,9 +85,10 @@ fn prover_example() {
let session = client
.execute(
&env,
Asset::Inline(FIB_ELF.into()),
Asset::Inline(RSA_ELF.into()),
AssetRequest::Inline,
|_info, segment| {
|info, segment| {
println!("{info:?}");
planner.enqueue_segment(segment_idx).unwrap();
task_manager.add_segment(segment_idx, segment);
while let Some(task) = planner.next_task() {
Expand All @@ -71,15 +109,48 @@ fn prover_example() {
task_manager.add_task(task.clone());
}

let root_receipt = task_manager.run();
let conditional_receipt = task_manager.run();

let output = conditional_receipt
.claim
.as_value()
.unwrap()
.output
.as_value()
.unwrap()
.as_ref()
.unwrap();
let assumptions = output.assumptions.as_value().unwrap();

let coprocessor = RefCell::borrow(&coprocessor);
let mut succinct_receipt = conditional_receipt.clone();
for assumption in assumptions.iter() {
let assumption = assumption.as_value().unwrap();
println!("{assumption:?}");
let assumption_receipt = coprocessor.receipts.get(&assumption.claim).unwrap().clone();
let opts = ProverOpts::default();
succinct_receipt = client
.resolve(
&opts,
succinct_receipt.try_into().unwrap(),
assumption_receipt.try_into().unwrap(),
AssetRequest::Inline,
)
.unwrap();
}

let receipt = Receipt::new(
InnerReceipt::Succinct(root_receipt),
InnerReceipt::Succinct(succinct_receipt),
session.journal.bytes.clone(),
);
receipt.verify(FIB_ID).unwrap();
receipt.verify(RSA_ID).unwrap();
println!("Receipt verified!");
}

fn from_hex(bytes: &[u8]) -> BigUint {
BigUint::parse_bytes(bytes, 16).expect("Unable to parse hex value")
}

#[test]
fn smoke_test() {
prover_example();
Expand Down
3 changes: 2 additions & 1 deletion risc0/build/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::path::PathBuf;

use cargo_metadata::Package;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// Options for configuring a docker build environment.
#[derive(Clone, Serialize, Deserialize)]
Expand Down
Loading

0 comments on commit fcde654

Please sign in to comment.