diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 32557ea1b..6b5a5e057 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: pull_token: ${{ secrets.PULL_TOKEN }} # If it's a nightly release, tag with the release time. If the tag is `main`, we want to use - # `latest` as the tag name. Else, use the tag name as is. + # `latest` as the tag name. else, use the tag name as is. - name: Compute release name and tag id: release_info run: | @@ -220,6 +220,8 @@ jobs: fi # Creates the release for this specific version + # If this is for latest, this will override the files there, but not change the commit to the current main. + # todo(n): change this to override the commit as well somehow. - name: Create release uses: softprops/action-gh-release@v2 with: @@ -272,7 +274,7 @@ jobs: - name: "Install SP1" env: - SP1UP_VERSION: ${{ github.ref_name }} + SP1UP_VERSION: ${{ github.ref_name == 'main' && 'latest' || github.ref_name }} run: | cd sp1up chmod +x sp1up diff --git a/.github/workflows/toolchain-ec2.yml b/.github/workflows/toolchain-ec2.yml index bbc4f6d11..75b6e2fd6 100644 --- a/.github/workflows/toolchain-ec2.yml +++ b/.github/workflows/toolchain-ec2.yml @@ -96,7 +96,7 @@ jobs: - name: "Install SP1" env: - SP1UP_VERSION: ${{ github.ref_name }} + SP1UP_VERSION: ${{ github.ref_name == 'main' && 'latest' || github.ref_name }} run: | cd sp1up chmod +x sp1up diff --git a/crates/core/executor/src/executor.rs b/crates/core/executor/src/executor.rs index 8b9584451..e1d3fb8d4 100644 --- a/crates/core/executor/src/executor.rs +++ b/crates/core/executor/src/executor.rs @@ -165,7 +165,8 @@ pub struct Executor<'a> { /// The costs of the program. pub costs: HashMap, - /// Skip deferred proof verification. + /// Skip deferred proof verification. This check is informational only, not related to circuit + /// correctness. pub deferred_proof_verification: DeferredProofVerification, /// The frequency to check the stopping condition. @@ -378,6 +379,9 @@ impl<'a> Executor<'a> { pub fn recover(program: Program, state: ExecutionState, opts: SP1CoreOpts) -> Self { let mut runtime = Self::new(program, opts); runtime.state = state; + // Disable deferred proof verification since we're recovering from a checkpoint, and the + // checkpoint creator already had a chance to check the proofs. + runtime.deferred_proof_verification = DeferredProofVerification::Disabled; runtime } @@ -1800,12 +1804,14 @@ impl<'a> Executor<'a> { self.executor_mode = ExecutorMode::Checkpoint; self.emit_global_memory_events = emit_global_memory_events; - // Clone self.state without memory and uninitialized_memory in it so it's faster. + // Clone self.state without memory, uninitialized_memory, proof_stream in it so it's faster. let memory = std::mem::take(&mut self.state.memory); let uninitialized_memory = std::mem::take(&mut self.state.uninitialized_memory); + let proof_stream = std::mem::take(&mut self.state.proof_stream); let mut checkpoint = tracing::debug_span!("clone").in_scope(|| self.state.clone()); self.state.memory = memory; self.state.uninitialized_memory = uninitialized_memory; + self.state.proof_stream = proof_stream; let done = tracing::debug_span!("execute").in_scope(|| self.execute())?; // Create a checkpoint using `memory_checkpoint`. Just include all memory if `done` since we diff --git a/crates/core/executor/src/syscalls/verify.rs b/crates/core/executor/src/syscalls/verify.rs index ad0882d2f..721612744 100644 --- a/crates/core/executor/src/syscalls/verify.rs +++ b/crates/core/executor/src/syscalls/verify.rs @@ -15,43 +15,39 @@ impl Syscall for VerifySyscall { ) -> Option { let rt = &mut ctx.rt; - // vkey_ptr is a pointer to [u32; 8] which contains the verification key. - assert_eq!(vkey_ptr % 4, 0, "vkey_ptr must be word-aligned"); - // pv_digest_ptr is a pointer to [u32; 8] which contains the public values digest. - assert_eq!(pv_digest_ptr % 4, 0, "pv_digest_ptr must be word-aligned"); - - let vkey = (0..8).map(|i| rt.word(vkey_ptr + i * 4)).collect::>(); + // Skip deferred proof verification if the corresponding runtime flag is set. + if rt.deferred_proof_verification == DeferredProofVerification::Enabled { + // vkey_ptr is a pointer to [u32; 8] which contains the verification key. + assert_eq!(vkey_ptr % 4, 0, "vkey_ptr must be word-aligned"); + // pv_digest_ptr is a pointer to [u32; 8] which contains the public values digest. + assert_eq!(pv_digest_ptr % 4, 0, "pv_digest_ptr must be word-aligned"); - let pv_digest = (0..8).map(|i| rt.word(pv_digest_ptr + i * 4)).collect::>(); + let vkey = (0..8).map(|i| rt.word(vkey_ptr + i * 4)).collect::>(); - let proof_index = rt.state.proof_stream_ptr; - if proof_index >= rt.state.proof_stream.len() { - panic!("Not enough proofs were written to the runtime."); - } - let (proof, proof_vk) = &rt.state.proof_stream[proof_index].clone(); - rt.state.proof_stream_ptr += 1; + let pv_digest = (0..8).map(|i| rt.word(pv_digest_ptr + i * 4)).collect::>(); - let vkey_bytes: [u32; 8] = vkey.try_into().unwrap(); - let pv_digest_bytes: [u32; 8] = pv_digest.try_into().unwrap(); - - // Skip deferred proof verification if the corresponding runtime flag is set. - match rt.deferred_proof_verification { - DeferredProofVerification::Enabled => { - if let Some(verifier) = rt.subproof_verifier { - 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 - ) - }); - } else if rt.state.proof_stream_ptr == 1 { - tracing::info!("Not verifying sub proof during runtime"); - }; + let proof_index = rt.state.proof_stream_ptr; + if proof_index >= rt.state.proof_stream.len() { + panic!("Not enough proofs were written to the runtime."); } - DeferredProofVerification::Disabled => {} + let (proof, proof_vk) = &rt.state.proof_stream[proof_index].clone(); + rt.state.proof_stream_ptr += 1; + + let vkey_bytes: [u32; 8] = vkey.try_into().unwrap(); + let pv_digest_bytes: [u32; 8] = pv_digest.try_into().unwrap(); + if let Some(verifier) = rt.subproof_verifier { + 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 + ) + }); + } else if rt.state.proof_stream_ptr == 1 { + tracing::info!("Not verifying sub proof during runtime"); + }; } None