Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add skip_deferred_proof_verification + refactor skip_simulation #1760

Draft
wants to merge 11 commits into
base: dev
Choose a base branch
from
21 changes: 19 additions & 2 deletions crates/core/executor/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub struct SP1Context<'a> {

/// The maximum number of cpu cycles to use for execution.
pub max_cycles: Option<u64>,

/// Whether to skip deferred proof verification.
pub skip_deferred_proof_verification: bool,
}

/// A builder for [`SP1Context`].
Expand All @@ -30,6 +33,7 @@ pub struct SP1ContextBuilder<'a> {
hook_registry_entries: Vec<(u32, BoxedHook<'a>)>,
subproof_verifier: Option<Arc<dyn SubproofVerifier + 'a>>,
max_cycles: Option<u64>,
skip_deferred_proof_verification: bool,
}

impl<'a> SP1Context<'a> {
Expand Down Expand Up @@ -68,7 +72,14 @@ impl<'a> SP1ContextBuilder<'a> {
});
let subproof_verifier = take(&mut self.subproof_verifier);
let cycle_limit = take(&mut self.max_cycles);
SP1Context { hook_registry, subproof_verifier, max_cycles: cycle_limit }
let skip_deferred_proof_verification =
take(&mut self.skip_deferred_proof_verification);
SP1Context {
hook_registry,
subproof_verifier,
max_cycles: cycle_limit,
skip_deferred_proof_verification,
}
}

/// Add a runtime [Hook](super::Hook) into the context.
Expand Down Expand Up @@ -110,6 +121,12 @@ impl<'a> SP1ContextBuilder<'a> {
self.max_cycles = Some(max_cycles);
self
}

/// Set whether to skip deferred proof verification.
pub fn set_skip_deferred_proof_verification(&mut self, skip: bool) -> &mut Self {
self.skip_deferred_proof_verification = skip;
self
}
}

#[cfg(test)]
Expand All @@ -120,7 +137,7 @@ mod tests {

#[test]
fn defaults() {
let SP1Context { hook_registry, subproof_verifier, max_cycles: cycle_limit } =
let SP1Context { hook_registry, subproof_verifier, max_cycles: cycle_limit, .. } =
SP1Context::builder().build();
assert!(hook_registry.is_none());
assert!(subproof_verifier.is_none());
Expand Down
4 changes: 4 additions & 0 deletions crates/core/executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub struct Executor<'a> {
/// The maximum number of cpu cycles to use for execution.
pub max_cycles: Option<u64>,

/// Whether to skip deferred proof verification.
pub skip_deferred_proof_verification: bool,

/// The state of the execution.
pub state: ExecutionState,

Expand Down Expand Up @@ -231,6 +234,7 @@ impl<'a> Executor<'a> {
hook_registry,
opts,
max_cycles: context.max_cycles,
skip_deferred_proof_verification: context.skip_deferred_proof_verification,
memory_checkpoint: PagedMemory::new_preallocated(),
uninitialized_memory_checkpoint: PagedMemory::new_preallocated(),
local_memory_access: HashMap::new(),
Expand Down
23 changes: 13 additions & 10 deletions crates/core/executor/src/syscalls/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@ impl Syscall for VerifySyscall {
let vkey_bytes: [u32; 8] = vkey.try_into().unwrap();
let pv_digest_bytes: [u32; 8] = pv_digest.try_into().unwrap();

ctx.rt
.subproof_verifier
.verify_deferred_proof(proof, proof_vk, vkey_bytes, pv_digest_bytes)
.unwrap_or_else(|e| {
panic!(
"Failed to verify proof {proof_index} with digest {}: {}",
hex::encode(bytemuck::cast_slice(&pv_digest_bytes)),
e
)
});
// Only verify deferred proofs if the runtime is not skipping deferred proof verification.
if !ctx.rt.skip_deferred_proof_verification {
ctx.rt
.subproof_verifier
.verify_deferred_proof(proof, proof_vk, vkey_bytes, pv_digest_bytes)
.unwrap_or_else(|e| {
panic!(
"Failed to verify proof {proof_index} with digest {}: {}",
hex::encode(bytemuck::cast_slice(&pv_digest_bytes)),
e
)
});
}

None
}
Expand Down
16 changes: 16 additions & 0 deletions crates/sdk/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ impl<'a> Execute<'a> {
self.context_builder.max_cycles(max_cycles);
self
}

/// Set whether to skip deferred proof verification.
pub fn set_skip_deferred_proof_verification(mut self, value: bool) -> Self {
self.context_builder.set_skip_deferred_proof_verification(value);
self
}
}

/// Builder to prepare and configure proving execution of a program on an input.
Expand All @@ -82,6 +88,7 @@ pub struct Prove<'a> {
core_opts: SP1CoreOpts,
recursion_opts: SP1CoreOpts,
timeout: Option<Duration>,
skip_deferred_proof_verification: bool,
}

impl<'a> Prove<'a> {
Expand All @@ -103,6 +110,7 @@ impl<'a> Prove<'a> {
core_opts: SP1CoreOpts::default(),
recursion_opts: SP1CoreOpts::recursion(),
timeout: None,
skip_deferred_proof_verification: false,
}
}

Expand All @@ -117,9 +125,11 @@ impl<'a> Prove<'a> {
core_opts,
recursion_opts,
timeout,
skip_deferred_proof_verification,
} = self;
let opts = SP1ProverOpts { core_opts, recursion_opts };
let proof_opts = ProofOpts { sp1_prover_opts: opts, timeout };
context_builder.set_skip_deferred_proof_verification(skip_deferred_proof_verification);
let context = context_builder.build();

// Dump the program and stdin to files for debugging if `SP1_DUMP` is set.
Expand Down Expand Up @@ -217,4 +227,10 @@ impl<'a> Prove<'a> {
self.timeout = Some(timeout);
self
}

/// Set whether to skip deferred proof verification.
pub fn set_skip_deferred_proof_verification(mut self, value: bool) -> Self {
self.skip_deferred_proof_verification = value;
self
}
}
1 change: 1 addition & 0 deletions crates/sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@
let mut stdin = SP1Stdin::new();
stdin.write(&10usize);
client.execute(elf, stdin).max_cycles(1).run().unwrap();
client.execute(elf, stdin).skip_deferred_proof_verification().run().unwrap();

Check failure on line 356 in crates/sdk/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test (ARM)

no method named `skip_deferred_proof_verification` found for struct `Execute` in the current scope

Check failure on line 356 in crates/sdk/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test (x86-64)

no method named `skip_deferred_proof_verification` found for struct `Execute` in the current scope
}

#[test]
Expand Down
11 changes: 8 additions & 3 deletions crates/sdk/src/network-v2/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const DEFAULT_CYCLE_LIMIT: u64 = 100_000_000;
pub struct NetworkProver {
client: NetworkClient,
local_prover: CpuProver,
skip_simulation: bool,
}

impl NetworkProver {
Expand All @@ -40,13 +41,18 @@ impl NetworkProver {
Self::new_from_key(&private_key)
}

/// Skip simulation when running `prove`.
pub fn set_skip_simulation(&mut self, skip: bool) {
self.skip_simulation = skip;
}

/// Creates a new [NetworkProver] with the given private key.
pub fn new_from_key(private_key: &str) -> Self {
let version = SP1_CIRCUIT_VERSION;
log::info!("Client circuit version: {}", version);
let local_prover = CpuProver::new();
let client = NetworkClient::new(private_key);
Self { client, local_prover }
Self { client, local_prover, skip_simulation: false }
}

/// Requests a proof from the prover network, returning the request ID.
Expand All @@ -58,8 +64,7 @@ impl NetworkProver {
timeout: Option<Duration>,
) -> Result<Vec<u8>> {
// Simulate and get the cycle limit.
let skip_simulation = env::var("SKIP_SIMULATION").map(|val| val == "true").unwrap_or(false);
let cycle_limit = if !skip_simulation {
let cycle_limit = if !self.skip_simulation {
let (_, report) =
self.local_prover.sp1_prover().execute(elf, &stdin, Default::default())?;
let cycles = report.total_instruction_count();
Expand Down
16 changes: 9 additions & 7 deletions crates/sdk/src/network/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const MAX_CONSECUTIVE_ERRORS: usize = 10;
pub struct NetworkProver {
client: NetworkClient,
local_prover: CpuProver,
skip_simulation: bool,
}

impl NetworkProver {
Expand All @@ -42,7 +43,12 @@ impl NetworkProver {
log::info!("Client circuit version: {}", version);

let local_prover = CpuProver::new();
Self { client: NetworkClient::new(private_key), local_prover }
Self { client: NetworkClient::new(private_key), local_prover, skip_simulation: false }
}

/// Skip simulation when running `prove`.
pub fn set_skip_simulation(&mut self, skip: bool) {
self.skip_simulation = skip;
}

/// Requests a proof from the prover network, returning the proof ID.
Expand All @@ -52,19 +58,15 @@ impl NetworkProver {
stdin: SP1Stdin,
mode: ProofMode,
) -> Result<String> {
let client = &self.client;

let skip_simulation = env::var("SKIP_SIMULATION").map(|val| val == "true").unwrap_or(false);

if !skip_simulation {
if !self.skip_simulation {
let (_, report) =
self.local_prover.sp1_prover().execute(elf, &stdin, Default::default())?;
log::info!("Simulation complete, cycles: {}", report.total_instruction_count());
} else {
log::info!("Skipping simulation");
}

let proof_id = client.create_proof(elf, &stdin, mode, SP1_CIRCUIT_VERSION).await?;
let proof_id = self.client.create_proof(elf, &stdin, mode, SP1_CIRCUIT_VERSION).await?;
log::info!("Created {}", proof_id);

if NetworkClient::rpc_url() == DEFAULT_PROVER_NETWORK_RPC {
Expand Down
2 changes: 2 additions & 0 deletions crates/sdk/src/provers/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ impl Prover<DefaultProverComponents> for MockProver {
})
}
SP1ProofKind::Groth16 => {
// TODO: The issue is that .prove() invokes execution in the Groth16 case, which
// will attempt to verify the proof according to the stdin.
let (public_values, _) = self.prover.execute(&pk.elf, &stdin, context)?;
Ok(SP1ProofWithPublicValues {
proof: SP1Proof::Groth16(Groth16Bn254Proof {
Expand Down
3 changes: 3 additions & 0 deletions crates/stark/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ impl<SC: StarkGenericConfig, A: MachineAir<Val<SC>>> StarkMachine<SC, A> {
if contains_global_bus {
challenger.observe(shard_proof.commitment.global_main_commit.clone());
}
// TODO: In mock mode, the public values of the compressed proof is vec![]
// This causes a panic because it's trying to index into the slice past the slice's length.
// What's the best way to turn off this check in the veriifer.
challenger.observe_slice(&shard_proof.public_values[0..self.num_pv_elts()]);
});
});
Expand Down
Loading