Skip to content

Commit 704a1d6

Browse files
committed
feat: add the execute path to the Prover trait and sp1 prover
1 parent b064ba0 commit 704a1d6

4 files changed

Lines changed: 51 additions & 8 deletions

File tree

crates/prover/core/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ pub trait StfProver {
3838

3939
/// Verify a proof and return the public values it commits to.
4040
async fn verify(&self, proof: &Proof) -> Result<StfPublicValues, ProverError>;
41+
42+
/// Execute the guest program, without generating the proof.
43+
async fn execute(&self, input: &StfInput) -> Result<StfPublicValues, ProverError>;
4144
}
4245

4346
/// Errors raised while proving or verifying a state transition.
@@ -52,4 +55,7 @@ pub enum ProverError {
5255
/// A proof or its public values could not be (de)serialized.
5356
#[error("proof (de)serialization failed: {0}")]
5457
Serialization(String),
58+
/// The execution of the guest program failed.
59+
#[error("execution failed: {0}")]
60+
Execute(String),
5561
}

crates/prover/sp1/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ bincode = "1.3"
1818

1919
[build-dependencies]
2020
sp1-build = "6.3.1"
21+
22+
[dev-dependencies]
23+
# Build valid `(state, block)` inputs for tests and cross-check the guest's
24+
# committed roots against a host-side run of the same transition.
25+
ethlambda-state-transition = { path = "../../blockchain/state_transition" }
26+
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

crates/prover/sp1/build.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
use sp1_build::{BuildArgs, build_program_with_args};
2+
13
fn main() {
24
// Compile the RISC-V guest program so `include_elf!("zkvm_guest_sp1")` can
35
// embed its ELF. Path is relative to this crate's manifest directory.
4-
sp1_build::build_program("../../guest-program/sp1");
6+
//
7+
// `ignore_rust_version` removes the compatibility issues with the toolchain
8+
// being used for ethlambda and the sp1 toolchain
9+
let args = BuildArgs {
10+
ignore_rust_version: true,
11+
..Default::default()
12+
};
13+
build_program_with_args("../../guest-program/sp1", args);
514
}

crates/prover/sp1/src/lib.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use ethlambda_prover_core::{Proof, ProverError, StfInput, StfProver, StfPublicValues};
22
use sp1_sdk::{
3-
MockProver, Prover, SP1ProofWithPublicValues, SP1ProvingKey, SP1Stdin, SP1VerifyingKey,
4-
include_elf,
3+
Elf, MockProver, ProveRequest, Prover, ProvingKey, SP1ProofWithPublicValues, SP1ProvingKey,
4+
SP1Stdin, SP1VerifyingKey, include_elf,
55
};
66

7-
8-
const STATE_TRANSITION_ELF: &[u8] = include_elf!("zkvm_guest_sp1");
7+
const STATE_TRANSITION_ELF: Elf = include_elf!("zkvm_guest_sp1");
98
const CYCLE_LIMIT: u64 = 10_000_000;
109

1110
/// SP1 prover: proves the STF guest and verifies its proofs.
@@ -25,7 +24,13 @@ impl Sp1Prover {
2524
pub async fn new() -> Self {
2625
let client = MockProver::new().await;
2726
// let client = ProverClient::builder().cpu().await;
28-
let (pk, vk) = client.setup(STATE_TRANSITION_ELF).await;
27+
// `setup` returns only the proving key (fallible); the verifying key is
28+
// derived from it.
29+
let pk = client
30+
.setup(STATE_TRANSITION_ELF)
31+
.await
32+
.expect("failed to set up SP1 proving key");
33+
let vk = pk.verifying_key().clone();
2934
Self { client, pk, vk }
3035
}
3136
}
@@ -56,12 +61,29 @@ impl StfProver for Sp1Prover {
5661
let mut sp1_proof: SP1ProofWithPublicValues = bincode::deserialize(proof.as_bytes())
5762
.map_err(|err| ProverError::Serialization(err.to_string()))?;
5863

64+
// `verify` is synchronous in this SDK and takes an optional status code.
5965
self.client
60-
.verify(&sp1_proof, &self.vk)
61-
.await
66+
.verify(&sp1_proof, &self.vk, None)
6267
.map_err(|err| ProverError::Verify(err.to_string()))?;
6368

6469
// The guest committed `StfPublicValues` via `io::commit`; read it back.
6570
Ok(sp1_proof.public_values.read::<StfPublicValues>())
6671
}
72+
73+
async fn execute(&self, input: &StfInput) -> Result<StfPublicValues, ProverError> {
74+
let mut stdin = SP1Stdin::new();
75+
stdin.write(input);
76+
77+
// Runs the guest in the SP1 executor without proving; the future yields
78+
// `(SP1PublicValues, ExecutionReport)`. We ignore the report for now.
79+
let (mut public_values, _report) = self
80+
.client
81+
.execute(STATE_TRANSITION_ELF, stdin)
82+
.cycle_limit(CYCLE_LIMIT)
83+
.await
84+
.map_err(|err| ProverError::Execute(err.to_string()))?;
85+
86+
// The guest committed `StfPublicValues` via `io::commit`; read it back.
87+
Ok(public_values.read::<StfPublicValues>())
88+
}
6789
}

0 commit comments

Comments
 (0)