From e18cc13eee5769903077ca19e6cc8af75766b8b5 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 8 Apr 2024 15:32:36 -0700 Subject: [PATCH 1/6] feat: e2e verifier --- core/src/stark/machine.rs | 57 ++++++---- core/src/stark/verifier.rs | 2 - eval/src/main.rs | 2 + examples/fibonacci/program/Cargo.lock | 14 +-- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 86124 -> 102152 bytes examples/fibonacci/script/Cargo.lock | 99 +++++++++++------- 6 files changed, 103 insertions(+), 71 deletions(-) diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index eda62809b9..5c5fdfd340 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -242,31 +242,46 @@ impl>> MachineStark { { // Observe the preprocessed commitment. challenger.observe(vk.commit.clone()); - // TODO: Observe the challenges in a tree-like structure for easily verifiable reconstruction - // in a map-reduce recursion setting. - tracing::debug_span!("observe challenges for all shards").in_scope(|| { - proof.shard_proofs.iter().for_each(|proof| { - challenger.observe(proof.commitment.main_commit.clone()); - let public_values = - PublicValues::>, Val>::new(proof.public_values); - challenger.observe_slice(&public_values.to_vec()); - }); + + // Observe the challenges. + proof.shard_proofs.iter().for_each(|proof| { + challenger.observe(proof.commitment.main_commit.clone()); + let public_values = PublicValues::>, Val>::new(proof.public_values); + challenger.observe_slice(&public_values.to_vec()); }); - // Verify the segment proofs. - tracing::info!("verifying shard proofs"); - for (i, proof) in proof.shard_proofs.iter().enumerate() { - tracing::debug_span!("verifying shard", segment = i).in_scope(|| { - let chips = self - .shard_chips_ordered(&proof.chip_ordering) - .collect::>(); - Verifier::verify_shard(&self.config, vk, &chips, &mut challenger.clone(), proof) - .map_err(ProgramVerificationError::InvalidSegmentProof) - })?; + // Verify the shards. + for proof in proof.shard_proofs.iter() { + let chips = self + .shard_chips_ordered(&proof.chip_ordering) + .collect::>(); + Verifier::verify_shard(&self.config, vk, &chips, &mut challenger.clone(), proof) + .map_err(ProgramVerificationError::InvalidSegmentProof)?; + } + + // Verify the public values for each shard. + for i in 0..proof.shard_proofs.len() { + let curr = &proof.shard_proofs[i]; + + // Assert that the shard number is correct. + assert_eq!(curr.public_values.shard, (i + 1) as u32); + } + + // Verify the public values between shards. + for i in 1..proof.shard_proofs.len() { + let curr = &proof.shard_proofs[i]; + let prev = &proof.shard_proofs[i - 1]; + + // Assert that the program counter is carried over correctly. + assert_eq!(prev.public_values.next_pc, curr.public_values.start_pc); + + // Assert that the public values digest is the same. + assert_eq!( + prev.public_values.committed_value_digest, + curr.public_values.committed_value_digest + ); } - tracing::info!("verifying individual shards succeeded"); - tracing::info!("verifying cumulative sum is 0"); // Verify the cumulative sum is 0. let mut sum = SC::Challenge::zero(); for proof in proof.shard_proofs.iter() { diff --git a/core/src/stark/verifier.rs b/core/src/stark/verifier.rs index 86ce7a7afa..886efa7364 100644 --- a/core/src/stark/verifier.rs +++ b/core/src/stark/verifier.rs @@ -169,8 +169,6 @@ impl>> Verifier { ) .map_err(|_| VerificationError::InvalidopeningArgument)?; - // Verify the constrtaint evaluations. - for (chip, trace_domain, qc_domains, values) in izip!( chips.iter(), trace_domains, diff --git a/eval/src/main.rs b/eval/src/main.rs index fa93dcd1a1..c2b6e24d20 100644 --- a/eval/src/main.rs +++ b/eval/src/main.rs @@ -1,3 +1,5 @@ +#![feature(generic_const_exprs)] + use clap::{command, Parser}; use csv::WriterBuilder; use serde::Serialize; diff --git a/examples/fibonacci/program/Cargo.lock b/examples/fibonacci/program/Cargo.lock index 5be5074d04..395fc3fde0 100644 --- a/examples/fibonacci/program/Cargo.lock +++ b/examples/fibonacci/program/Cargo.lock @@ -347,7 +347,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2", "signature", ] @@ -535,16 +535,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha2" -version = "0.10.8" -source = "git+https://github.com/sp1-patches/RustCrypto-hashes.git?branch=patch-v0.10.8#3d692aa90b91513886d757d01f8fc2d51c0ec0d7" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "signature" version = "2.2.0" @@ -588,7 +578,7 @@ dependencies = [ "once_cell", "rand", "serde", - "sha2 0.10.8 (git+https://github.com/sp1-patches/RustCrypto-hashes.git?branch=patch-v0.10.8)", + "sha2", "sp1-precompiles", ] diff --git a/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf b/examples/fibonacci/program/elf/riscv32im-succinct-zkvm-elf index bb9b2b657d9ddae69e25df1498970107b8586ae7..406a930e4e23010afea65cd34761058110dfcd23 100755 GIT binary patch delta 38669 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 delta 22214 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 Date: Mon, 8 Apr 2024 15:34:28 -0700 Subject: [PATCH 2/6] rust verifier --- core/src/stark/machine.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index 5c5fdfd340..102afe700e 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -282,6 +282,10 @@ impl>> MachineStark { ); } + // Verify the public values of the last shard. + let last = &proof.shard_proofs[proof.shard_proofs.len() - 1]; + assert_eq!(last.public_values.exit_code, 0); + // Verify the cumulative sum is 0. let mut sum = SC::Challenge::zero(); for proof in proof.shard_proofs.iter() { From 34c5047fff3eedcda2f3aff841013083bdb46772 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 8 Apr 2024 16:05:45 -0700 Subject: [PATCH 3/6] small changes --- core/src/air/public_values.rs | 19 +++++++++++++------ core/src/air/word.rs | 14 ++++++++++++++ core/src/cpu/air/mod.rs | 4 ++-- core/src/lookup/builder.rs | 4 ++-- core/src/runtime/record.rs | 4 ++-- core/src/stark/debug.rs | 4 ++-- core/src/stark/machine.rs | 14 ++++++++------ core/src/stark/prover.rs | 9 ++++----- core/src/stark/quotient.rs | 4 ++-- core/src/stark/record.rs | 2 +- core/src/stark/types.rs | 6 +++--- core/src/stark/verifier.rs | 8 ++++---- core/src/syscall/commit.rs | 7 +++++-- core/src/utils/prove.rs | 6 +++--- recursion/circuit/src/constraints.rs | 11 ++++------- recursion/circuit/src/stark.rs | 4 ++-- recursion/core/src/runtime/record.rs | 2 +- recursion/program/src/compress.rs | 6 ++---- recursion/program/src/constraints.rs | 20 ++++++++++---------- recursion/program/src/hints.rs | 15 ++++++++------- recursion/program/src/stark.rs | 9 +++------ recursion/program/src/types.rs | 14 +++++++------- 22 files changed, 102 insertions(+), 84 deletions(-) diff --git a/core/src/air/public_values.rs b/core/src/air/public_values.rs index 91132b50b2..4cb8de18f0 100644 --- a/core/src/air/public_values.rs +++ b/core/src/air/public_values.rs @@ -10,9 +10,9 @@ pub const PV_DIGEST_NUM_WORDS: usize = 8; /// The PublicValues struct is used to store all of a shard proof's public values. #[derive(Serialize, Deserialize, Clone, Copy, Default, Debug)] -pub struct PublicValues { +pub struct PublicValues { /// The hash of all the bytes that the guest program has written to public values. - pub committed_value_digest: [W; PV_DIGEST_NUM_WORDS], + pub committed_value_digest: [Word; PV_DIGEST_NUM_WORDS], /// The shard number. pub shard: T, @@ -27,8 +27,8 @@ pub struct PublicValues { pub exit_code: T, } -impl PublicValues, F> { - pub fn new(other: PublicValues) -> Self { +impl PublicValues { + pub fn from_u32(other: PublicValues) -> Self { let PublicValues { committed_value_digest, shard, @@ -37,7 +37,14 @@ impl PublicValues, F> { exit_code, } = other; Self { - committed_value_digest: committed_value_digest.map(Word::from), + committed_value_digest: committed_value_digest.map(|w| { + Word([ + F::from_canonical_u32(w.0[0]), + F::from_canonical_u32(w.0[1]), + F::from_canonical_u32(w.0[2]), + F::from_canonical_u32(w.0[3]), + ]) + }), shard: F::from_canonical_u32(shard), start_pc: F::from_canonical_u32(first_row_pc), next_pc: F::from_canonical_u32(last_row_next_pc), @@ -46,7 +53,7 @@ impl PublicValues, F> { } } -impl PublicValues, T> { +impl PublicValues { pub fn to_vec(&self) -> Vec { self.committed_value_digest .iter() diff --git a/core/src/air/word.rs b/core/src/air/word.rs index 0c896dc56b..09c526a996 100644 --- a/core/src/air/word.rs +++ b/core/src/air/word.rs @@ -131,3 +131,17 @@ impl FromIterator for Word { Word(elements) } } + +impl Word { + pub fn from_u32(value: u32) -> Self { + Word( + value + .to_le_bytes() + .into_iter() + .map(u32::from) + .collect::>() + .try_into() + .unwrap(), + ) + } +} diff --git a/core/src/cpu/air/mod.rs b/core/src/cpu/air/mod.rs index 75b71683b2..c62210b8ca 100644 --- a/core/src/cpu/air/mod.rs +++ b/core/src/cpu/air/mod.rs @@ -33,7 +33,7 @@ where let local: &CpuCols = main.row_slice(0).borrow(); let next: &CpuCols = main.row_slice(1).borrow(); - let public_values = PublicValues::, AB::Expr>::from_vec( + let public_values = PublicValues::::from_vec( builder .public_values() .iter() @@ -547,7 +547,7 @@ impl CpuChip { builder: &mut AB, local: &CpuCols, next: &CpuCols, - public_values: &PublicValues, AB::Expr>, + public_values: &PublicValues, ) { // Verify the public value's shard. builder diff --git a/core/src/lookup/builder.rs b/core/src/lookup/builder.rs index d1ab0291a4..ce75a5c26e 100644 --- a/core/src/lookup/builder.rs +++ b/core/src/lookup/builder.rs @@ -1,4 +1,4 @@ -use crate::air::{AirInteraction, MessageBuilder, PublicValues, Word}; +use crate::air::{AirInteraction, MessageBuilder, PublicValues}; use p3_air::{AirBuilder, AirBuilderWithPublicValues, PairBuilder, PairCol, VirtualPairCol}; use p3_field::Field; use p3_matrix::dense::RowMajorMatrix; @@ -36,7 +36,7 @@ impl InteractionBuilder { }) .collect(); - let public_values = PublicValues::, F>::default().to_vec(); + let public_values = PublicValues::::default().to_vec(); Self { preprocessed: RowMajorMatrix::new(prep_values, preprocessed_width), diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index 917a1346a5..13d1e46a50 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -92,7 +92,7 @@ pub struct ExecutionRecord { pub program_memory_events: Vec, /// The public values. - pub public_values: PublicValues, + pub public_values: PublicValues, } pub struct ShardingConfig { @@ -473,7 +473,7 @@ impl MachineRecord for ExecutionRecord { /// Retrieves the public values. This method is needed for the `MachineRecord` trait, since /// the public values digest is used by the prover. - fn public_values(&self) -> PublicValues { + fn public_values(&self) -> PublicValues { self.public_values } } diff --git a/core/src/stark/debug.rs b/core/src/stark/debug.rs index b38999f031..4cdc81c3a2 100644 --- a/core/src/stark/debug.rs +++ b/core/src/stark/debug.rs @@ -9,7 +9,7 @@ use p3_field::{AbstractField, PrimeField32}; use p3_field::{ExtensionField, Field}; use p3_matrix::{dense::RowMajorMatrix, Matrix, MatrixRowSlices}; -use crate::air::{EmptyMessageBuilder, MachineAir, MultiTableAirBuilder, PublicValues, Word}; +use crate::air::{EmptyMessageBuilder, MachineAir, MultiTableAirBuilder, PublicValues}; use super::{MachineChip, StarkGenericConfig, Val}; @@ -22,7 +22,7 @@ pub fn debug_constraints( main: &RowMajorMatrix>, perm: &RowMajorMatrix, perm_challenges: &[SC::Challenge], - public_values: PublicValues>, Val>, + public_values: PublicValues>, ) where SC: StarkGenericConfig, Val: PrimeField32, diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index 102afe700e..9ddc68376e 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use super::debug_constraints; use super::Dom; -use crate::air::{MachineAir, PublicValues, Word}; +use crate::air::{MachineAir, PublicValues}; use crate::lookup::debug_interactions_with_all_chips; use crate::lookup::InteractionBuilder; use crate::lookup::InteractionKind; @@ -246,8 +246,7 @@ impl>> MachineStark { // Observe the challenges. proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit.clone()); - let public_values = PublicValues::>, Val>::new(proof.public_values); - challenger.observe_slice(&public_values.to_vec()); + challenger.observe_slice(&proof.public_values.to_vec()); }); // Verify the shards. @@ -264,7 +263,10 @@ impl>> MachineStark { let curr = &proof.shard_proofs[i]; // Assert that the shard number is correct. - assert_eq!(curr.public_values.shard, (i + 1) as u32); + assert_eq!( + curr.public_values.shard, + Val::::from_canonical_usize(i + 1) + ); } // Verify the public values between shards. @@ -284,7 +286,7 @@ impl>> MachineStark { // Verify the public values of the last shard. let last = &proof.shard_proofs[proof.shard_proofs.len() - 1]; - assert_eq!(last.public_values.exit_code, 0); + assert_eq!(last.public_values.exit_code, Val::::zero()); // Verify the cumulative sum is 0. let mut sum = SC::Challenge::zero(); @@ -390,7 +392,7 @@ impl>> MachineStark { &traces[i].0, &permutation_traces[i], &permutation_challenges, - PublicValues::>, Val>::new(shard.public_values()), + PublicValues::>::from_u32(shard.public_values()), ); } }); diff --git a/core/src/stark/prover.rs b/core/src/stark/prover.rs index 78bfa19c0c..3165e408ce 100644 --- a/core/src/stark/prover.rs +++ b/core/src/stark/prover.rs @@ -30,7 +30,7 @@ use crate::stark::MachineChip; use crate::stark::PackedChallenge; use crate::stark::ProverConstraintFolder; -use crate::air::{MachineAir, PublicValues, Word}; +use crate::air::{MachineAir, PublicValues}; use crate::utils::env; fn chunk_vec(mut vec: Vec, chunk_size: usize) -> Vec> { @@ -90,8 +90,7 @@ where .zip(shards.iter()) .for_each(|(commitment, shard)| { challenger.observe(commitment); - let public_values = - PublicValues::>, Val>::new(shard.public_values()); + let public_values = PublicValues::>::from_u32(shard.public_values()); challenger.observe_slice(&public_values.to_vec()); }); }); @@ -219,7 +218,7 @@ where main_data, chip_ordering, index, - public_values: shard.public_values(), + public_values: PublicValues::>::from_u32(shard.public_values()), } } @@ -375,7 +374,7 @@ where permutation_trace_on_quotient_domains, &packed_perm_challenges, alpha, - PublicValues::>, Val>::new(shard_data.public_values), + shard_data.public_values, ) }) .collect::>() diff --git a/core/src/stark/quotient.rs b/core/src/stark/quotient.rs index 5da3eb9430..45143f0249 100644 --- a/core/src/stark/quotient.rs +++ b/core/src/stark/quotient.rs @@ -1,4 +1,4 @@ -use crate::air::{PublicValues, Word}; +use crate::air::PublicValues; use super::folder::ProverConstraintFolder; use super::Chip; @@ -29,7 +29,7 @@ pub fn quotient_values( permutation_trace_on_quotient_domain: Mat, perm_challenges: &[PackedChallenge], alpha: SC::Challenge, - public_values: PublicValues>, Val>, + public_values: PublicValues>, ) -> Vec where A: for<'a> Air>, diff --git a/core/src/stark/record.rs b/core/src/stark/record.rs index 098984bbfd..c3dc065e78 100644 --- a/core/src/stark/record.rs +++ b/core/src/stark/record.rs @@ -15,5 +15,5 @@ pub trait MachineRecord: Default + Sized + Send + Sync { fn shard(self, config: &Self::Config) -> Vec; - fn public_values(&self) -> PublicValues; + fn public_values(&self) -> PublicValues; } diff --git a/core/src/stark/types.rs b/core/src/stark/types.rs index e4f90b915b..0741dd3471 100644 --- a/core/src/stark/types.rs +++ b/core/src/stark/types.rs @@ -27,7 +27,7 @@ pub struct ShardMainData { pub main_data: PcsProverData, pub chip_ordering: HashMap, pub index: usize, - pub public_values: PublicValues, + pub public_values: PublicValues>, } impl ShardMainData { @@ -37,7 +37,7 @@ impl ShardMainData { main_data: PcsProverData, chip_ordering: HashMap, index: usize, - public_values: PublicValues, + public_values: PublicValues>, ) -> Self { Self { traces, @@ -130,7 +130,7 @@ pub struct ShardProof { pub opened_values: ShardOpenedValues>, pub opening_proof: OpeningProof, pub chip_ordering: HashMap, - pub public_values: PublicValues, + pub public_values: PublicValues>, } impl AirOpenedValues { diff --git a/core/src/stark/verifier.rs b/core/src/stark/verifier.rs index 886efa7364..87896c8158 100644 --- a/core/src/stark/verifier.rs +++ b/core/src/stark/verifier.rs @@ -1,5 +1,5 @@ use super::Domain; -use crate::air::{MachineAir, PublicValues, Word}; +use crate::air::{MachineAir, PublicValues}; use crate::stark::MachineChip; use itertools::Itertools; use p3_air::Air; @@ -183,7 +183,7 @@ impl>> Verifier { zeta, alpha, &permutation_challenges, - PublicValues::>, Val>::new(proof.public_values), + proof.public_values, ) .map_err(|_| VerificationError::OodEvaluationMismatch(chip.name()))?; } @@ -199,7 +199,7 @@ impl>> Verifier { zeta: SC::Challenge, alpha: SC::Challenge, permutation_challenges: &[SC::Challenge], - public_values: PublicValues>, Val>, + public_values: PublicValues>, ) -> Result<(), OodEvaluationMismatch> where A: for<'a> Air>, @@ -230,7 +230,7 @@ impl>> Verifier { selectors: &LagrangeSelectors, alpha: SC::Challenge, permutation_challenges: &[SC::Challenge], - public_values: PublicValues>, Val>, + public_values: PublicValues>, ) -> SC::Challenge where A: for<'a> Air>, diff --git a/core/src/syscall/commit.rs b/core/src/syscall/commit.rs index 960dc1d6de..87b501f643 100644 --- a/core/src/syscall/commit.rs +++ b/core/src/syscall/commit.rs @@ -1,4 +1,7 @@ -use crate::runtime::{Syscall, SyscallContext}; +use crate::{ + air::Word, + runtime::{Syscall, SyscallContext}, +}; pub struct SyscallCommit; @@ -18,7 +21,7 @@ impl Syscall for SyscallCommit { let rt = &mut ctx.rt; rt.record.public_values.committed_value_digest[word_idx as usize] = - public_values_digest_word; + Word::::from_u32(public_values_digest_word); None } diff --git a/core/src/utils/prove.rs b/core/src/utils/prove.rs index 47e1ced50a..71345fcb63 100644 --- a/core/src/utils/prove.rs +++ b/core/src/utils/prove.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::{Seek, Write}; use std::time::Instant; -use crate::air::{PublicValues, Word}; +use crate::air::PublicValues; use crate::runtime::{ExecutionRecord, ShardingConfig}; use crate::stark::MachineRecord; use crate::stark::{Com, PcsProverData, RiscvAir, ShardProof, UniConfig}; @@ -150,7 +150,7 @@ where let mut cycles = 0; let mut prove_time = 0; let mut checkpoints = Vec::new(); - let mut public_values: PublicValues = Default::default(); + let mut public_values: PublicValues = Default::default(); let public_values_stream = tracing::info_span!("runtime.state").in_scope(|| loop { // Get checkpoint + move to next checkpoint, then save checkpoint to temp file let (state, done) = runtime.execute_state(); @@ -195,7 +195,7 @@ where for (commitment, shard) in commitments.into_iter().zip(shards.iter()) { challenger.observe(commitment); - let public_values = PublicValues::, SC::Val>::new(shard.public_values()); + let public_values = PublicValues::::from_u32(shard.public_values()); challenger.observe_slice(&public_values.to_vec()); } } diff --git a/recursion/circuit/src/constraints.rs b/recursion/circuit/src/constraints.rs index 1acb9d66aa..43ce153545 100644 --- a/recursion/circuit/src/constraints.rs +++ b/recursion/circuit/src/constraints.rs @@ -164,12 +164,9 @@ mod tests { use p3_commit::{Pcs, PolynomialSpace}; use serde::{de::DeserializeOwned, Serialize}; use serial_test::serial; - use sp1_core::{ - air::{PublicValues, Word}, - stark::{ - Chip, Com, Dom, LocalProver, MachineStark, OpeningProof, PcsProverData, - ShardCommitment, ShardMainData, ShardProof, StarkGenericConfig, - }, + use sp1_core::stark::{ + Chip, Com, Dom, LocalProver, MachineStark, OpeningProof, PcsProverData, ShardCommitment, + ShardMainData, ShardProof, StarkGenericConfig, }; use sp1_recursion_compiler::{ constraints::{gnark_ffi, ConstraintBackend}, @@ -300,7 +297,7 @@ mod tests { challenger.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_value_field = PublicValues::, F>::new(proof.public_values); + let public_value_field = proof.public_values; challenger.observe_slice(&public_value_field.to_vec()); }); diff --git a/recursion/circuit/src/stark.rs b/recursion/circuit/src/stark.rs index ee1671d37d..8160d1e340 100644 --- a/recursion/circuit/src/stark.rs +++ b/recursion/circuit/src/stark.rs @@ -238,7 +238,7 @@ pub(crate) mod tests { use p3_field::PrimeField32; use serial_test::serial; use sp1_core::{ - air::{MachineAir, PublicValues, Word}, + air::MachineAir, stark::{LocalProver, MachineStark, ShardCommitment, ShardProof, StarkGenericConfig}, }; use sp1_recursion_compiler::{ @@ -379,7 +379,7 @@ pub(crate) mod tests { challenger_val.observe(vk.commit); proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger_val.observe_slice(&public_values_field.to_vec()); }); diff --git a/recursion/core/src/runtime/record.rs b/recursion/core/src/runtime/record.rs index 024f8f3ca6..141e816703 100644 --- a/recursion/core/src/runtime/record.rs +++ b/recursion/core/src/runtime/record.rs @@ -46,7 +46,7 @@ impl MachineRecord for ExecutionRecord { vec![self] } - fn public_values(&self) -> PublicValues { + fn public_values(&self) -> PublicValues { PublicValues::default() } } diff --git a/recursion/program/src/compress.rs b/recursion/program/src/compress.rs index 3de001c593..77858789e8 100644 --- a/recursion/program/src/compress.rs +++ b/recursion/program/src/compress.rs @@ -24,8 +24,6 @@ use p3_poseidon2::Poseidon2; use p3_poseidon2::Poseidon2ExternalMatrixGeneral; use p3_symmetric::PaddingFreeSponge; use p3_symmetric::TruncatedPermutation; -use sp1_core::air::PublicValues; -use sp1_core::air::Word; use sp1_core::stark::Proof; use sp1_core::stark::ShardProof; use sp1_core::stark::VerifyingKey; @@ -96,7 +94,7 @@ pub fn build_compress( challenger_val.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -135,7 +133,7 @@ pub fn build_compress( }); let ShardCommitmentVariable { main_commit, .. } = &proof.commitment; challenger.observe(&mut builder, main_commit.clone()); - let public_values_field = PublicValues::, F>::new(proof_val.public_values); + let public_values_field = proof_val.public_values; let public_values_felt: Vec> = public_values_field .to_vec() .iter() diff --git a/recursion/program/src/constraints.rs b/recursion/program/src/constraints.rs index 5b5ef6c402..984cef43c6 100644 --- a/recursion/program/src/constraints.rs +++ b/recursion/program/src/constraints.rs @@ -158,7 +158,7 @@ mod tests { use itertools::{izip, Itertools}; use serde::{de::DeserializeOwned, Serialize}; use sp1_core::{ - air::{PublicValues, Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, + air::{Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, runtime::Program, stark::{ Chip, Com, Dom, MachineStark, OpeningProof, PcsProverData, RiscvAir, ShardCommitment, @@ -170,7 +170,7 @@ mod tests { use sp1_sdk::{SP1Prover, SP1Stdin, SP1Verifier}; use p3_challenger::{CanObserve, FieldChallenger}; - use p3_field::{AbstractField, PrimeField32}; + use p3_field::PrimeField32; use sp1_recursion_compiler::{asm::VmBuilder, ir::Felt, prelude::ExtConst}; use p3_commit::{Pcs, PolynomialSpace}; @@ -297,7 +297,7 @@ mod tests { challenger.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger.observe_slice(&public_values_field.to_vec()); }); @@ -315,13 +315,13 @@ mod tests { ) = get_shard_data(&machine, &proof, &mut challenger); // Set up the public values. - let pv_shard = builder.eval(F::from_canonical_u32(proof.public_values.shard)); - let pv_start_pc = builder.eval(F::from_canonical_u32(proof.public_values.start_pc)); - let pv_next_pc = builder.eval(F::from_canonical_u32(proof.public_values.next_pc)); - let pv_exit_code = builder.eval(F::from_canonical_u32(proof.public_values.exit_code)); + let pv_shard = builder.eval(proof.public_values.shard); + let pv_start_pc = builder.eval(proof.public_values.start_pc); + let pv_next_pc = builder.eval(proof.public_values.next_pc); + let pv_exit_code = builder.eval(proof.public_values.exit_code); let mut pv_committed_value_digest = builder.dyn_array(PV_DIGEST_NUM_WORDS * WORD_SIZE); for i in 0..PV_DIGEST_NUM_WORDS { - let word_val: Word = Word::from(proof.public_values.committed_value_digest[i]); + let word_val: Word = proof.public_values.committed_value_digest[i]; for j in 0..WORD_SIZE { let word_val: Felt<_> = builder.eval(word_val[j]); builder.set(&mut pv_committed_value_digest, i * WORD_SIZE + j, word_val); @@ -349,7 +349,7 @@ mod tests { &sels_val, alpha_val, &permutation_challenges, - PublicValues::, F>::new(proof.public_values), + proof.public_values, ); // Compute the folded constraints value in the DSL. @@ -441,7 +441,7 @@ mod tests { proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger.observe_slice(&public_values_field.to_vec()); }); diff --git a/recursion/program/src/hints.rs b/recursion/program/src/hints.rs index de243ccae5..ca6c0a41a8 100644 --- a/recursion/program/src/hints.rs +++ b/recursion/program/src/hints.rs @@ -1,6 +1,7 @@ +use p3_baby_bear::BabyBear; use p3_field::{AbstractExtensionField, AbstractField}; use sp1_core::{ - air::{PublicValues, Word}, + air::PublicValues, stark::{AirOpenedValues, ChipOpenedValues, ShardCommitment, ShardOpenedValues, ShardProof}, }; use sp1_recursion_compiler::{ @@ -252,7 +253,7 @@ impl Hintable for ShardCommitment { } } -impl Hintable for PublicValues { +impl Hintable for PublicValues { type HintVariable = PublicValuesVariable; fn read(builder: &mut Builder) -> Self::HintVariable { @@ -277,14 +278,14 @@ impl Hintable for PublicValues { stream.extend( self.committed_value_digest .into_iter() - .flat_map(|x| Word::from(x).0) + .flat_map(|x| x.0) .collect::>() .write(), ); - stream.extend(F::from_canonical_u32(self.shard).write()); - stream.extend(F::from_canonical_u32(self.start_pc).write()); - stream.extend(F::from_canonical_u32(self.next_pc).write()); - stream.extend(F::from_canonical_u32(self.exit_code).write()); + stream.extend(self.shard.write()); + stream.extend(self.start_pc.write()); + stream.extend(self.next_pc.write()); + stream.extend(self.exit_code.write()); stream } } diff --git a/recursion/program/src/stark.rs b/recursion/program/src/stark.rs index c6ae9b0950..0f4d2b49b9 100644 --- a/recursion/program/src/stark.rs +++ b/recursion/program/src/stark.rs @@ -263,7 +263,6 @@ pub(crate) mod tests { use p3_challenger::{CanObserve, FieldChallenger}; use p3_field::AbstractField; use rand::Rng; - use sp1_core::air::PublicValues; use sp1_core::runtime::Program; use sp1_core::{ stark::{RiscvAir, ShardProof, StarkGenericConfig}, @@ -282,8 +281,6 @@ pub(crate) mod tests { use sp1_recursion_core::stark::config::InnerVal; use sp1_sdk::{SP1Prover, SP1Stdin}; - use sp1_core::air::Word; - use crate::{ challenger::DuplexChallengerVariable, fri::{const_fri_config, TwoAdicFriPcsVariable}, @@ -320,7 +317,7 @@ pub(crate) mod tests { proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -393,7 +390,7 @@ pub(crate) mod tests { challenger_val.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = PublicValues::, F>::new(proof.public_values); + let public_values_field = proof.public_values; challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -432,7 +429,7 @@ pub(crate) mod tests { }); let ShardCommitmentVariable { main_commit, .. } = &proof.commitment; challenger.observe(&mut builder, main_commit.clone()); - let public_values_field = PublicValues::, F>::new(proof_val.public_values); + let public_values_field = proof_val.public_values; let public_values_felt: Vec> = public_values_field .to_vec() .iter() diff --git a/recursion/program/src/types.rs b/recursion/program/src/types.rs index 5f69a753fb..2f6be86d49 100644 --- a/recursion/program/src/types.rs +++ b/recursion/program/src/types.rs @@ -1,7 +1,7 @@ use p3_air::BaseAir; use p3_field::{AbstractExtensionField, AbstractField}; use sp1_core::{ - air::{MachineAir, PublicValues, Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, + air::{MachineAir, PublicValues, PV_DIGEST_NUM_WORDS, WORD_SIZE}, stark::{AirOpenedValues, Chip, ChipOpenedValues}, }; use sp1_recursion_compiler::prelude::*; @@ -40,16 +40,16 @@ impl PublicValuesVariable { } impl FromConstant for PublicValuesVariable { - type Constant = PublicValues; + type Constant = PublicValues; fn eval_const(value: Self::Constant, builder: &mut Builder) -> Self { - let pv_shard = builder.eval(C::F::from_canonical_u32(value.shard)); - let pv_start_pc = builder.eval(C::F::from_canonical_u32(value.start_pc)); - let pv_next_pc = builder.eval(C::F::from_canonical_u32(value.next_pc)); - let pv_exit_code = builder.eval(C::F::from_canonical_u32(value.exit_code)); + let pv_shard = builder.eval(value.shard); + let pv_start_pc = builder.eval(value.start_pc); + let pv_next_pc = builder.eval(value.next_pc); + let pv_exit_code = builder.eval(value.exit_code); let mut pv_committed_value_digest = Vec::new(); for i in 0..PV_DIGEST_NUM_WORDS { - let word_val: Word = Word::from(value.committed_value_digest[i]); + let word_val = value.committed_value_digest[i]; for j in 0..WORD_SIZE { let word_val: Felt<_> = builder.eval(word_val[j]); pv_committed_value_digest.push(word_val); From 6d90a7a0876bec94f28f62cee7e392fab9a5dd7e Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 8 Apr 2024 16:15:11 -0700 Subject: [PATCH 4/6] things --- core/src/stark/config.rs | 4 +- core/src/stark/types.rs | 12 ++++ .../program/elf/riscv32im-succinct-zkvm-elf | Bin 121924 -> 121924 bytes examples/fibonacci-io/script/Cargo.lock | 57 ++++++++++-------- examples/fibonacci-io/script/Cargo.toml | 1 - examples/fibonacci-io/script/src/main.rs | 8 +-- 6 files changed, 47 insertions(+), 35 deletions(-) diff --git a/core/src/stark/config.rs b/core/src/stark/config.rs index 2caf8c2e7f..7350c49907 100644 --- a/core/src/stark/config.rs +++ b/core/src/stark/config.rs @@ -1,6 +1,6 @@ use p3_challenger::{CanObserve, CanSample, FieldChallenger}; use p3_commit::{Pcs, PolynomialSpace}; -use p3_field::{ExtensionField, Field, PrimeField}; +use p3_field::{ExtensionField, Field, PrimeField32}; use serde::{de::DeserializeOwned, Serialize}; pub type Domain = <::Pcs as Pcs< @@ -47,7 +47,7 @@ pub type Challenge = ::Challenge; pub type Challenger = ::Challenger; pub trait StarkGenericConfig: Send + Sync + Serialize + DeserializeOwned + Clone { - type Val: PrimeField; + type Val: PrimeField32; type Domain: PolynomialSpace + Sync; diff --git a/core/src/stark/types.rs b/core/src/stark/types.rs index 0741dd3471..e9f87310bc 100644 --- a/core/src/stark/types.rs +++ b/core/src/stark/types.rs @@ -6,6 +6,7 @@ use std::{ use bincode::{deserialize_from, Error}; use p3_air::TwoRowMatrixView; +use p3_field::PrimeField32; use p3_matrix::dense::RowMajorMatrix; use size::Size; @@ -154,3 +155,14 @@ impl ShardProof { pub struct Proof { pub shard_proofs: Vec>, } + +impl Proof { + pub fn commited_values_digest(&self) -> Vec { + self.shard_proofs[0] + .public_values + .committed_value_digest + .iter() + .flat_map(|w| w.0.map(|x| x.as_canonical_u32() as u8)) + .collect() + } +} diff --git a/examples/fibonacci-io/program/elf/riscv32im-succinct-zkvm-elf b/examples/fibonacci-io/program/elf/riscv32im-succinct-zkvm-elf index 4aad3973b1a325c581af0e2470f1b6f18e8c479a..8220d99a796faf7e3303a7fb94a7c10bd3276e15 100755 GIT binary patch delta 17688 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 KM6n#_;r|!8{2v|w diff --git a/examples/fibonacci-io/script/Cargo.lock b/examples/fibonacci-io/script/Cargo.lock index fce1feb876..77ee7f5371 100644 --- a/examples/fibonacci-io/script/Cargo.lock +++ b/examples/fibonacci-io/script/Cargo.lock @@ -535,9 +535,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", @@ -760,15 +760,14 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.1.20" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" [[package]] name = "fibonacci-io-script" version = "0.1.0" dependencies = [ - "itertools 0.12.1", "sha2", "sp1-helper", "sp1-sdk", @@ -915,6 +914,12 @@ dependencies = [ "slab", ] +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + [[package]] name = "generic-array" version = "0.14.7" @@ -1757,7 +1762,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p3-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-field", "p3-matrix", @@ -1766,7 +1771,7 @@ dependencies = [ [[package]] name = "p3-baby-bear" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "num-bigint", "p3-field", @@ -1780,7 +1785,7 @@ dependencies = [ [[package]] name = "p3-blake3" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "blake3", "p3-symmetric", @@ -1789,7 +1794,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-field", "p3-maybe-rayon", @@ -1801,7 +1806,7 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -1814,7 +1819,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-field", "p3-matrix", @@ -1826,7 +1831,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "num-bigint", @@ -1839,7 +1844,7 @@ dependencies = [ [[package]] name = "p3-fri" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-challenger", @@ -1857,7 +1862,7 @@ dependencies = [ [[package]] name = "p3-goldilocks" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "num-bigint", "p3-dft", @@ -1873,7 +1878,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-field", "p3-matrix", @@ -1883,7 +1888,7 @@ dependencies = [ [[package]] name = "p3-keccak" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-symmetric", "tiny-keccak", @@ -1892,7 +1897,7 @@ dependencies = [ [[package]] name = "p3-keccak-air" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "p3-air", "p3-field", @@ -1904,7 +1909,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-field", @@ -1918,7 +1923,7 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "rayon", ] @@ -1926,7 +1931,7 @@ dependencies = [ [[package]] name = "p3-mds" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.11.0", "p3-dft", @@ -1940,7 +1945,7 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-commit", @@ -1956,9 +1961,11 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ + "gcd", "p3-field", + "p3-mds", "p3-symmetric", "rand", ] @@ -1966,7 +1973,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-field", @@ -1976,7 +1983,7 @@ dependencies = [ [[package]] name = "p3-uni-stark" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "itertools 0.12.1", "p3-air", @@ -1994,7 +2001,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.1.0" -source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#7e4f7afedeffbc49c9c123e21f29e0eb1a9b2227" +source = "git+https://github.com/Plonky3/Plonky3.git#cbbcbe1c1353f742782323676af55e59b4318d94" dependencies = [ "serde", ] diff --git a/examples/fibonacci-io/script/Cargo.toml b/examples/fibonacci-io/script/Cargo.toml index f81c791563..dacc74336d 100644 --- a/examples/fibonacci-io/script/Cargo.toml +++ b/examples/fibonacci-io/script/Cargo.toml @@ -5,7 +5,6 @@ name = "fibonacci-io-script" edition = "2021" [dependencies] -itertools = "0.12.1" sp1-sdk = { path = "../../../sdk" } sha2 = "0.10.8" diff --git a/examples/fibonacci-io/script/src/main.rs b/examples/fibonacci-io/script/src/main.rs index ef4b9803a5..c6a53cedd8 100644 --- a/examples/fibonacci-io/script/src/main.rs +++ b/examples/fibonacci-io/script/src/main.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use sha2::{Digest, Sha256}; use sp1_sdk::{utils, SP1Prover, SP1Stdin, SP1Verifier}; @@ -43,12 +42,7 @@ fn main() { pv_hasher.update(expected_b.to_le_bytes()); let expected_pv_digest: &[u8] = &pv_hasher.finalize(); - let proof_pv_bytes: Vec = proof.proof.shard_proofs[0] - .public_values - .committed_value_digest - .iter() - .flat_map(|w| w.to_le_bytes()) - .collect_vec(); + let proof_pv_bytes = proof.proof.commited_values_digest(); assert_eq!(proof_pv_bytes.as_slice(), expected_pv_digest); // Save the proof. From d73cb7523880a81def37099fbb73658a8cdeacba Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 8 Apr 2024 17:24:18 -0700 Subject: [PATCH 5/6] Revert "things" This reverts commit 6d90a7a0876bec94f28f62cee7e392fab9a5dd7e. --- core/src/stark/config.rs | 4 +- core/src/stark/types.rs | 12 ---- .../program/elf/riscv32im-succinct-zkvm-elf | Bin 121924 -> 121924 bytes examples/fibonacci-io/script/Cargo.lock | 57 ++++++++---------- examples/fibonacci-io/script/Cargo.toml | 1 + examples/fibonacci-io/script/src/main.rs | 8 ++- 6 files changed, 35 insertions(+), 47 deletions(-) diff --git a/core/src/stark/config.rs b/core/src/stark/config.rs index 7350c49907..2caf8c2e7f 100644 --- a/core/src/stark/config.rs +++ b/core/src/stark/config.rs @@ -1,6 +1,6 @@ use p3_challenger::{CanObserve, CanSample, FieldChallenger}; use p3_commit::{Pcs, PolynomialSpace}; -use p3_field::{ExtensionField, Field, PrimeField32}; +use p3_field::{ExtensionField, Field, PrimeField}; use serde::{de::DeserializeOwned, Serialize}; pub type Domain = <::Pcs as Pcs< @@ -47,7 +47,7 @@ pub type Challenge = ::Challenge; pub type Challenger = ::Challenger; pub trait StarkGenericConfig: Send + Sync + Serialize + DeserializeOwned + Clone { - type Val: PrimeField32; + type Val: PrimeField; type Domain: PolynomialSpace + Sync; diff --git a/core/src/stark/types.rs b/core/src/stark/types.rs index e9f87310bc..0741dd3471 100644 --- a/core/src/stark/types.rs +++ b/core/src/stark/types.rs @@ -6,7 +6,6 @@ use std::{ use bincode::{deserialize_from, Error}; use p3_air::TwoRowMatrixView; -use p3_field::PrimeField32; use p3_matrix::dense::RowMajorMatrix; use size::Size; @@ -155,14 +154,3 @@ impl ShardProof { pub struct Proof { pub shard_proofs: Vec>, } - -impl Proof { - pub fn commited_values_digest(&self) -> Vec { - self.shard_proofs[0] - .public_values - .committed_value_digest - .iter() - .flat_map(|w| w.0.map(|x| x.as_canonical_u32() as u8)) - .collect() - } -} diff --git a/examples/fibonacci-io/program/elf/riscv32im-succinct-zkvm-elf b/examples/fibonacci-io/program/elf/riscv32im-succinct-zkvm-elf index 8220d99a796faf7e3303a7fb94a7c10bd3276e15..4aad3973b1a325c581af0e2470f1b6f18e8c479a 100755 GIT binary patch delta 17642 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 KM6n#_;r|!8{2v|w delta 17688 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 e2Kgk3@lU;RXsL)h*Kvcs!yt~o44UhB^#23cmp$ = proof.proof.shard_proofs[0] + .public_values + .committed_value_digest + .iter() + .flat_map(|w| w.to_le_bytes()) + .collect_vec(); assert_eq!(proof_pv_bytes.as_slice(), expected_pv_digest); // Save the proof. From 9f3361fdf259d1d79cde41cd423c513d9cee3a27 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 8 Apr 2024 17:24:28 -0700 Subject: [PATCH 6/6] Revert "small changes" This reverts commit 34c5047fff3eedcda2f3aff841013083bdb46772. --- core/src/air/public_values.rs | 19 ++++++------------- core/src/air/word.rs | 14 -------------- core/src/cpu/air/mod.rs | 4 ++-- core/src/lookup/builder.rs | 4 ++-- core/src/runtime/record.rs | 4 ++-- core/src/stark/debug.rs | 4 ++-- core/src/stark/machine.rs | 14 ++++++-------- core/src/stark/prover.rs | 9 +++++---- core/src/stark/quotient.rs | 4 ++-- core/src/stark/record.rs | 2 +- core/src/stark/types.rs | 6 +++--- core/src/stark/verifier.rs | 8 ++++---- core/src/syscall/commit.rs | 7 ++----- core/src/utils/prove.rs | 6 +++--- recursion/circuit/src/constraints.rs | 11 +++++++---- recursion/circuit/src/stark.rs | 4 ++-- recursion/core/src/runtime/record.rs | 2 +- recursion/program/src/compress.rs | 6 ++++-- recursion/program/src/constraints.rs | 20 ++++++++++---------- recursion/program/src/hints.rs | 15 +++++++-------- recursion/program/src/stark.rs | 9 ++++++--- recursion/program/src/types.rs | 14 +++++++------- 22 files changed, 84 insertions(+), 102 deletions(-) diff --git a/core/src/air/public_values.rs b/core/src/air/public_values.rs index 4cb8de18f0..91132b50b2 100644 --- a/core/src/air/public_values.rs +++ b/core/src/air/public_values.rs @@ -10,9 +10,9 @@ pub const PV_DIGEST_NUM_WORDS: usize = 8; /// The PublicValues struct is used to store all of a shard proof's public values. #[derive(Serialize, Deserialize, Clone, Copy, Default, Debug)] -pub struct PublicValues { +pub struct PublicValues { /// The hash of all the bytes that the guest program has written to public values. - pub committed_value_digest: [Word; PV_DIGEST_NUM_WORDS], + pub committed_value_digest: [W; PV_DIGEST_NUM_WORDS], /// The shard number. pub shard: T, @@ -27,8 +27,8 @@ pub struct PublicValues { pub exit_code: T, } -impl PublicValues { - pub fn from_u32(other: PublicValues) -> Self { +impl PublicValues, F> { + pub fn new(other: PublicValues) -> Self { let PublicValues { committed_value_digest, shard, @@ -37,14 +37,7 @@ impl PublicValues { exit_code, } = other; Self { - committed_value_digest: committed_value_digest.map(|w| { - Word([ - F::from_canonical_u32(w.0[0]), - F::from_canonical_u32(w.0[1]), - F::from_canonical_u32(w.0[2]), - F::from_canonical_u32(w.0[3]), - ]) - }), + committed_value_digest: committed_value_digest.map(Word::from), shard: F::from_canonical_u32(shard), start_pc: F::from_canonical_u32(first_row_pc), next_pc: F::from_canonical_u32(last_row_next_pc), @@ -53,7 +46,7 @@ impl PublicValues { } } -impl PublicValues { +impl PublicValues, T> { pub fn to_vec(&self) -> Vec { self.committed_value_digest .iter() diff --git a/core/src/air/word.rs b/core/src/air/word.rs index 09c526a996..0c896dc56b 100644 --- a/core/src/air/word.rs +++ b/core/src/air/word.rs @@ -131,17 +131,3 @@ impl FromIterator for Word { Word(elements) } } - -impl Word { - pub fn from_u32(value: u32) -> Self { - Word( - value - .to_le_bytes() - .into_iter() - .map(u32::from) - .collect::>() - .try_into() - .unwrap(), - ) - } -} diff --git a/core/src/cpu/air/mod.rs b/core/src/cpu/air/mod.rs index c62210b8ca..75b71683b2 100644 --- a/core/src/cpu/air/mod.rs +++ b/core/src/cpu/air/mod.rs @@ -33,7 +33,7 @@ where let local: &CpuCols = main.row_slice(0).borrow(); let next: &CpuCols = main.row_slice(1).borrow(); - let public_values = PublicValues::::from_vec( + let public_values = PublicValues::, AB::Expr>::from_vec( builder .public_values() .iter() @@ -547,7 +547,7 @@ impl CpuChip { builder: &mut AB, local: &CpuCols, next: &CpuCols, - public_values: &PublicValues, + public_values: &PublicValues, AB::Expr>, ) { // Verify the public value's shard. builder diff --git a/core/src/lookup/builder.rs b/core/src/lookup/builder.rs index ce75a5c26e..d1ab0291a4 100644 --- a/core/src/lookup/builder.rs +++ b/core/src/lookup/builder.rs @@ -1,4 +1,4 @@ -use crate::air::{AirInteraction, MessageBuilder, PublicValues}; +use crate::air::{AirInteraction, MessageBuilder, PublicValues, Word}; use p3_air::{AirBuilder, AirBuilderWithPublicValues, PairBuilder, PairCol, VirtualPairCol}; use p3_field::Field; use p3_matrix::dense::RowMajorMatrix; @@ -36,7 +36,7 @@ impl InteractionBuilder { }) .collect(); - let public_values = PublicValues::::default().to_vec(); + let public_values = PublicValues::, F>::default().to_vec(); Self { preprocessed: RowMajorMatrix::new(prep_values, preprocessed_width), diff --git a/core/src/runtime/record.rs b/core/src/runtime/record.rs index 13d1e46a50..917a1346a5 100644 --- a/core/src/runtime/record.rs +++ b/core/src/runtime/record.rs @@ -92,7 +92,7 @@ pub struct ExecutionRecord { pub program_memory_events: Vec, /// The public values. - pub public_values: PublicValues, + pub public_values: PublicValues, } pub struct ShardingConfig { @@ -473,7 +473,7 @@ impl MachineRecord for ExecutionRecord { /// Retrieves the public values. This method is needed for the `MachineRecord` trait, since /// the public values digest is used by the prover. - fn public_values(&self) -> PublicValues { + fn public_values(&self) -> PublicValues { self.public_values } } diff --git a/core/src/stark/debug.rs b/core/src/stark/debug.rs index 4cdc81c3a2..b38999f031 100644 --- a/core/src/stark/debug.rs +++ b/core/src/stark/debug.rs @@ -9,7 +9,7 @@ use p3_field::{AbstractField, PrimeField32}; use p3_field::{ExtensionField, Field}; use p3_matrix::{dense::RowMajorMatrix, Matrix, MatrixRowSlices}; -use crate::air::{EmptyMessageBuilder, MachineAir, MultiTableAirBuilder, PublicValues}; +use crate::air::{EmptyMessageBuilder, MachineAir, MultiTableAirBuilder, PublicValues, Word}; use super::{MachineChip, StarkGenericConfig, Val}; @@ -22,7 +22,7 @@ pub fn debug_constraints( main: &RowMajorMatrix>, perm: &RowMajorMatrix, perm_challenges: &[SC::Challenge], - public_values: PublicValues>, + public_values: PublicValues>, Val>, ) where SC: StarkGenericConfig, Val: PrimeField32, diff --git a/core/src/stark/machine.rs b/core/src/stark/machine.rs index 9ddc68376e..102afe700e 100644 --- a/core/src/stark/machine.rs +++ b/core/src/stark/machine.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use super::debug_constraints; use super::Dom; -use crate::air::{MachineAir, PublicValues}; +use crate::air::{MachineAir, PublicValues, Word}; use crate::lookup::debug_interactions_with_all_chips; use crate::lookup::InteractionBuilder; use crate::lookup::InteractionKind; @@ -246,7 +246,8 @@ impl>> MachineStark { // Observe the challenges. proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit.clone()); - challenger.observe_slice(&proof.public_values.to_vec()); + let public_values = PublicValues::>, Val>::new(proof.public_values); + challenger.observe_slice(&public_values.to_vec()); }); // Verify the shards. @@ -263,10 +264,7 @@ impl>> MachineStark { let curr = &proof.shard_proofs[i]; // Assert that the shard number is correct. - assert_eq!( - curr.public_values.shard, - Val::::from_canonical_usize(i + 1) - ); + assert_eq!(curr.public_values.shard, (i + 1) as u32); } // Verify the public values between shards. @@ -286,7 +284,7 @@ impl>> MachineStark { // Verify the public values of the last shard. let last = &proof.shard_proofs[proof.shard_proofs.len() - 1]; - assert_eq!(last.public_values.exit_code, Val::::zero()); + assert_eq!(last.public_values.exit_code, 0); // Verify the cumulative sum is 0. let mut sum = SC::Challenge::zero(); @@ -392,7 +390,7 @@ impl>> MachineStark { &traces[i].0, &permutation_traces[i], &permutation_challenges, - PublicValues::>::from_u32(shard.public_values()), + PublicValues::>, Val>::new(shard.public_values()), ); } }); diff --git a/core/src/stark/prover.rs b/core/src/stark/prover.rs index 3165e408ce..78bfa19c0c 100644 --- a/core/src/stark/prover.rs +++ b/core/src/stark/prover.rs @@ -30,7 +30,7 @@ use crate::stark::MachineChip; use crate::stark::PackedChallenge; use crate::stark::ProverConstraintFolder; -use crate::air::{MachineAir, PublicValues}; +use crate::air::{MachineAir, PublicValues, Word}; use crate::utils::env; fn chunk_vec(mut vec: Vec, chunk_size: usize) -> Vec> { @@ -90,7 +90,8 @@ where .zip(shards.iter()) .for_each(|(commitment, shard)| { challenger.observe(commitment); - let public_values = PublicValues::>::from_u32(shard.public_values()); + let public_values = + PublicValues::>, Val>::new(shard.public_values()); challenger.observe_slice(&public_values.to_vec()); }); }); @@ -218,7 +219,7 @@ where main_data, chip_ordering, index, - public_values: PublicValues::>::from_u32(shard.public_values()), + public_values: shard.public_values(), } } @@ -374,7 +375,7 @@ where permutation_trace_on_quotient_domains, &packed_perm_challenges, alpha, - shard_data.public_values, + PublicValues::>, Val>::new(shard_data.public_values), ) }) .collect::>() diff --git a/core/src/stark/quotient.rs b/core/src/stark/quotient.rs index 45143f0249..5da3eb9430 100644 --- a/core/src/stark/quotient.rs +++ b/core/src/stark/quotient.rs @@ -1,4 +1,4 @@ -use crate::air::PublicValues; +use crate::air::{PublicValues, Word}; use super::folder::ProverConstraintFolder; use super::Chip; @@ -29,7 +29,7 @@ pub fn quotient_values( permutation_trace_on_quotient_domain: Mat, perm_challenges: &[PackedChallenge], alpha: SC::Challenge, - public_values: PublicValues>, + public_values: PublicValues>, Val>, ) -> Vec where A: for<'a> Air>, diff --git a/core/src/stark/record.rs b/core/src/stark/record.rs index c3dc065e78..098984bbfd 100644 --- a/core/src/stark/record.rs +++ b/core/src/stark/record.rs @@ -15,5 +15,5 @@ pub trait MachineRecord: Default + Sized + Send + Sync { fn shard(self, config: &Self::Config) -> Vec; - fn public_values(&self) -> PublicValues; + fn public_values(&self) -> PublicValues; } diff --git a/core/src/stark/types.rs b/core/src/stark/types.rs index 0741dd3471..e4f90b915b 100644 --- a/core/src/stark/types.rs +++ b/core/src/stark/types.rs @@ -27,7 +27,7 @@ pub struct ShardMainData { pub main_data: PcsProverData, pub chip_ordering: HashMap, pub index: usize, - pub public_values: PublicValues>, + pub public_values: PublicValues, } impl ShardMainData { @@ -37,7 +37,7 @@ impl ShardMainData { main_data: PcsProverData, chip_ordering: HashMap, index: usize, - public_values: PublicValues>, + public_values: PublicValues, ) -> Self { Self { traces, @@ -130,7 +130,7 @@ pub struct ShardProof { pub opened_values: ShardOpenedValues>, pub opening_proof: OpeningProof, pub chip_ordering: HashMap, - pub public_values: PublicValues>, + pub public_values: PublicValues, } impl AirOpenedValues { diff --git a/core/src/stark/verifier.rs b/core/src/stark/verifier.rs index 87896c8158..886efa7364 100644 --- a/core/src/stark/verifier.rs +++ b/core/src/stark/verifier.rs @@ -1,5 +1,5 @@ use super::Domain; -use crate::air::{MachineAir, PublicValues}; +use crate::air::{MachineAir, PublicValues, Word}; use crate::stark::MachineChip; use itertools::Itertools; use p3_air::Air; @@ -183,7 +183,7 @@ impl>> Verifier { zeta, alpha, &permutation_challenges, - proof.public_values, + PublicValues::>, Val>::new(proof.public_values), ) .map_err(|_| VerificationError::OodEvaluationMismatch(chip.name()))?; } @@ -199,7 +199,7 @@ impl>> Verifier { zeta: SC::Challenge, alpha: SC::Challenge, permutation_challenges: &[SC::Challenge], - public_values: PublicValues>, + public_values: PublicValues>, Val>, ) -> Result<(), OodEvaluationMismatch> where A: for<'a> Air>, @@ -230,7 +230,7 @@ impl>> Verifier { selectors: &LagrangeSelectors, alpha: SC::Challenge, permutation_challenges: &[SC::Challenge], - public_values: PublicValues>, + public_values: PublicValues>, Val>, ) -> SC::Challenge where A: for<'a> Air>, diff --git a/core/src/syscall/commit.rs b/core/src/syscall/commit.rs index 87b501f643..960dc1d6de 100644 --- a/core/src/syscall/commit.rs +++ b/core/src/syscall/commit.rs @@ -1,7 +1,4 @@ -use crate::{ - air::Word, - runtime::{Syscall, SyscallContext}, -}; +use crate::runtime::{Syscall, SyscallContext}; pub struct SyscallCommit; @@ -21,7 +18,7 @@ impl Syscall for SyscallCommit { let rt = &mut ctx.rt; rt.record.public_values.committed_value_digest[word_idx as usize] = - Word::::from_u32(public_values_digest_word); + public_values_digest_word; None } diff --git a/core/src/utils/prove.rs b/core/src/utils/prove.rs index 71345fcb63..47e1ced50a 100644 --- a/core/src/utils/prove.rs +++ b/core/src/utils/prove.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::{Seek, Write}; use std::time::Instant; -use crate::air::PublicValues; +use crate::air::{PublicValues, Word}; use crate::runtime::{ExecutionRecord, ShardingConfig}; use crate::stark::MachineRecord; use crate::stark::{Com, PcsProverData, RiscvAir, ShardProof, UniConfig}; @@ -150,7 +150,7 @@ where let mut cycles = 0; let mut prove_time = 0; let mut checkpoints = Vec::new(); - let mut public_values: PublicValues = Default::default(); + let mut public_values: PublicValues = Default::default(); let public_values_stream = tracing::info_span!("runtime.state").in_scope(|| loop { // Get checkpoint + move to next checkpoint, then save checkpoint to temp file let (state, done) = runtime.execute_state(); @@ -195,7 +195,7 @@ where for (commitment, shard) in commitments.into_iter().zip(shards.iter()) { challenger.observe(commitment); - let public_values = PublicValues::::from_u32(shard.public_values()); + let public_values = PublicValues::, SC::Val>::new(shard.public_values()); challenger.observe_slice(&public_values.to_vec()); } } diff --git a/recursion/circuit/src/constraints.rs b/recursion/circuit/src/constraints.rs index 43ce153545..1acb9d66aa 100644 --- a/recursion/circuit/src/constraints.rs +++ b/recursion/circuit/src/constraints.rs @@ -164,9 +164,12 @@ mod tests { use p3_commit::{Pcs, PolynomialSpace}; use serde::{de::DeserializeOwned, Serialize}; use serial_test::serial; - use sp1_core::stark::{ - Chip, Com, Dom, LocalProver, MachineStark, OpeningProof, PcsProverData, ShardCommitment, - ShardMainData, ShardProof, StarkGenericConfig, + use sp1_core::{ + air::{PublicValues, Word}, + stark::{ + Chip, Com, Dom, LocalProver, MachineStark, OpeningProof, PcsProverData, + ShardCommitment, ShardMainData, ShardProof, StarkGenericConfig, + }, }; use sp1_recursion_compiler::{ constraints::{gnark_ffi, ConstraintBackend}, @@ -297,7 +300,7 @@ mod tests { challenger.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_value_field = proof.public_values; + let public_value_field = PublicValues::, F>::new(proof.public_values); challenger.observe_slice(&public_value_field.to_vec()); }); diff --git a/recursion/circuit/src/stark.rs b/recursion/circuit/src/stark.rs index 8160d1e340..ee1671d37d 100644 --- a/recursion/circuit/src/stark.rs +++ b/recursion/circuit/src/stark.rs @@ -238,7 +238,7 @@ pub(crate) mod tests { use p3_field::PrimeField32; use serial_test::serial; use sp1_core::{ - air::MachineAir, + air::{MachineAir, PublicValues, Word}, stark::{LocalProver, MachineStark, ShardCommitment, ShardProof, StarkGenericConfig}, }; use sp1_recursion_compiler::{ @@ -379,7 +379,7 @@ pub(crate) mod tests { challenger_val.observe(vk.commit); proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger_val.observe_slice(&public_values_field.to_vec()); }); diff --git a/recursion/core/src/runtime/record.rs b/recursion/core/src/runtime/record.rs index 141e816703..024f8f3ca6 100644 --- a/recursion/core/src/runtime/record.rs +++ b/recursion/core/src/runtime/record.rs @@ -46,7 +46,7 @@ impl MachineRecord for ExecutionRecord { vec![self] } - fn public_values(&self) -> PublicValues { + fn public_values(&self) -> PublicValues { PublicValues::default() } } diff --git a/recursion/program/src/compress.rs b/recursion/program/src/compress.rs index 77858789e8..3de001c593 100644 --- a/recursion/program/src/compress.rs +++ b/recursion/program/src/compress.rs @@ -24,6 +24,8 @@ use p3_poseidon2::Poseidon2; use p3_poseidon2::Poseidon2ExternalMatrixGeneral; use p3_symmetric::PaddingFreeSponge; use p3_symmetric::TruncatedPermutation; +use sp1_core::air::PublicValues; +use sp1_core::air::Word; use sp1_core::stark::Proof; use sp1_core::stark::ShardProof; use sp1_core::stark::VerifyingKey; @@ -94,7 +96,7 @@ pub fn build_compress( challenger_val.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -133,7 +135,7 @@ pub fn build_compress( }); let ShardCommitmentVariable { main_commit, .. } = &proof.commitment; challenger.observe(&mut builder, main_commit.clone()); - let public_values_field = proof_val.public_values; + let public_values_field = PublicValues::, F>::new(proof_val.public_values); let public_values_felt: Vec> = public_values_field .to_vec() .iter() diff --git a/recursion/program/src/constraints.rs b/recursion/program/src/constraints.rs index 984cef43c6..5b5ef6c402 100644 --- a/recursion/program/src/constraints.rs +++ b/recursion/program/src/constraints.rs @@ -158,7 +158,7 @@ mod tests { use itertools::{izip, Itertools}; use serde::{de::DeserializeOwned, Serialize}; use sp1_core::{ - air::{Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, + air::{PublicValues, Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, runtime::Program, stark::{ Chip, Com, Dom, MachineStark, OpeningProof, PcsProverData, RiscvAir, ShardCommitment, @@ -170,7 +170,7 @@ mod tests { use sp1_sdk::{SP1Prover, SP1Stdin, SP1Verifier}; use p3_challenger::{CanObserve, FieldChallenger}; - use p3_field::PrimeField32; + use p3_field::{AbstractField, PrimeField32}; use sp1_recursion_compiler::{asm::VmBuilder, ir::Felt, prelude::ExtConst}; use p3_commit::{Pcs, PolynomialSpace}; @@ -297,7 +297,7 @@ mod tests { challenger.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger.observe_slice(&public_values_field.to_vec()); }); @@ -315,13 +315,13 @@ mod tests { ) = get_shard_data(&machine, &proof, &mut challenger); // Set up the public values. - let pv_shard = builder.eval(proof.public_values.shard); - let pv_start_pc = builder.eval(proof.public_values.start_pc); - let pv_next_pc = builder.eval(proof.public_values.next_pc); - let pv_exit_code = builder.eval(proof.public_values.exit_code); + let pv_shard = builder.eval(F::from_canonical_u32(proof.public_values.shard)); + let pv_start_pc = builder.eval(F::from_canonical_u32(proof.public_values.start_pc)); + let pv_next_pc = builder.eval(F::from_canonical_u32(proof.public_values.next_pc)); + let pv_exit_code = builder.eval(F::from_canonical_u32(proof.public_values.exit_code)); let mut pv_committed_value_digest = builder.dyn_array(PV_DIGEST_NUM_WORDS * WORD_SIZE); for i in 0..PV_DIGEST_NUM_WORDS { - let word_val: Word = proof.public_values.committed_value_digest[i]; + let word_val: Word = Word::from(proof.public_values.committed_value_digest[i]); for j in 0..WORD_SIZE { let word_val: Felt<_> = builder.eval(word_val[j]); builder.set(&mut pv_committed_value_digest, i * WORD_SIZE + j, word_val); @@ -349,7 +349,7 @@ mod tests { &sels_val, alpha_val, &permutation_challenges, - proof.public_values, + PublicValues::, F>::new(proof.public_values), ); // Compute the folded constraints value in the DSL. @@ -441,7 +441,7 @@ mod tests { proof.shard_proofs.iter().for_each(|proof| { challenger.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger.observe_slice(&public_values_field.to_vec()); }); diff --git a/recursion/program/src/hints.rs b/recursion/program/src/hints.rs index ca6c0a41a8..de243ccae5 100644 --- a/recursion/program/src/hints.rs +++ b/recursion/program/src/hints.rs @@ -1,7 +1,6 @@ -use p3_baby_bear::BabyBear; use p3_field::{AbstractExtensionField, AbstractField}; use sp1_core::{ - air::PublicValues, + air::{PublicValues, Word}, stark::{AirOpenedValues, ChipOpenedValues, ShardCommitment, ShardOpenedValues, ShardProof}, }; use sp1_recursion_compiler::{ @@ -253,7 +252,7 @@ impl Hintable for ShardCommitment { } } -impl Hintable for PublicValues { +impl Hintable for PublicValues { type HintVariable = PublicValuesVariable; fn read(builder: &mut Builder) -> Self::HintVariable { @@ -278,14 +277,14 @@ impl Hintable for PublicValues { stream.extend( self.committed_value_digest .into_iter() - .flat_map(|x| x.0) + .flat_map(|x| Word::from(x).0) .collect::>() .write(), ); - stream.extend(self.shard.write()); - stream.extend(self.start_pc.write()); - stream.extend(self.next_pc.write()); - stream.extend(self.exit_code.write()); + stream.extend(F::from_canonical_u32(self.shard).write()); + stream.extend(F::from_canonical_u32(self.start_pc).write()); + stream.extend(F::from_canonical_u32(self.next_pc).write()); + stream.extend(F::from_canonical_u32(self.exit_code).write()); stream } } diff --git a/recursion/program/src/stark.rs b/recursion/program/src/stark.rs index 0f4d2b49b9..c6ae9b0950 100644 --- a/recursion/program/src/stark.rs +++ b/recursion/program/src/stark.rs @@ -263,6 +263,7 @@ pub(crate) mod tests { use p3_challenger::{CanObserve, FieldChallenger}; use p3_field::AbstractField; use rand::Rng; + use sp1_core::air::PublicValues; use sp1_core::runtime::Program; use sp1_core::{ stark::{RiscvAir, ShardProof, StarkGenericConfig}, @@ -281,6 +282,8 @@ pub(crate) mod tests { use sp1_recursion_core::stark::config::InnerVal; use sp1_sdk::{SP1Prover, SP1Stdin}; + use sp1_core::air::Word; + use crate::{ challenger::DuplexChallengerVariable, fri::{const_fri_config, TwoAdicFriPcsVariable}, @@ -317,7 +320,7 @@ pub(crate) mod tests { proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -390,7 +393,7 @@ pub(crate) mod tests { challenger_val.observe(vk.commit); proof.shard_proofs.iter().for_each(|proof| { challenger_val.observe(proof.commitment.main_commit); - let public_values_field = proof.public_values; + let public_values_field = PublicValues::, F>::new(proof.public_values); challenger_val.observe_slice(&public_values_field.to_vec()); }); @@ -429,7 +432,7 @@ pub(crate) mod tests { }); let ShardCommitmentVariable { main_commit, .. } = &proof.commitment; challenger.observe(&mut builder, main_commit.clone()); - let public_values_field = proof_val.public_values; + let public_values_field = PublicValues::, F>::new(proof_val.public_values); let public_values_felt: Vec> = public_values_field .to_vec() .iter() diff --git a/recursion/program/src/types.rs b/recursion/program/src/types.rs index 2f6be86d49..5f69a753fb 100644 --- a/recursion/program/src/types.rs +++ b/recursion/program/src/types.rs @@ -1,7 +1,7 @@ use p3_air::BaseAir; use p3_field::{AbstractExtensionField, AbstractField}; use sp1_core::{ - air::{MachineAir, PublicValues, PV_DIGEST_NUM_WORDS, WORD_SIZE}, + air::{MachineAir, PublicValues, Word, PV_DIGEST_NUM_WORDS, WORD_SIZE}, stark::{AirOpenedValues, Chip, ChipOpenedValues}, }; use sp1_recursion_compiler::prelude::*; @@ -40,16 +40,16 @@ impl PublicValuesVariable { } impl FromConstant for PublicValuesVariable { - type Constant = PublicValues; + type Constant = PublicValues; fn eval_const(value: Self::Constant, builder: &mut Builder) -> Self { - let pv_shard = builder.eval(value.shard); - let pv_start_pc = builder.eval(value.start_pc); - let pv_next_pc = builder.eval(value.next_pc); - let pv_exit_code = builder.eval(value.exit_code); + let pv_shard = builder.eval(C::F::from_canonical_u32(value.shard)); + let pv_start_pc = builder.eval(C::F::from_canonical_u32(value.start_pc)); + let pv_next_pc = builder.eval(C::F::from_canonical_u32(value.next_pc)); + let pv_exit_code = builder.eval(C::F::from_canonical_u32(value.exit_code)); let mut pv_committed_value_digest = Vec::new(); for i in 0..PV_DIGEST_NUM_WORDS { - let word_val = value.committed_value_digest[i]; + let word_val: Word = Word::from(value.committed_value_digest[i]); for j in 0..WORD_SIZE { let word_val: Felt<_> = builder.eval(word_val[j]); pv_committed_value_digest.push(word_val);