diff --git a/Cargo.lock b/Cargo.lock index acbaec969e..98a40f9fb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3556,6 +3556,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "oorandom" version = "11.1.5" @@ -3661,21 +3673,6 @@ dependencies = [ "serde", ] -[[package]] -name = "p3-bn254-fr" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0dd4d095d254783098bd09fc5fdf33fd781a1be54608ab93cb3ed4bd723da54" -dependencies = [ - "ff 0.13.1", - "num-bigint 0.4.6", - "p3-field", - "p3-poseidon2", - "p3-symmetric", - "rand 0.8.5", - "serde", -] - [[package]] name = "p3-challenger" version = "0.2.3-succinct" @@ -3731,6 +3728,17 @@ dependencies = [ "serde", ] +[[package]] +name = "p3-field-testing" +version = "0.2.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb80c3a5f65481a39aa7ce9190e02f03ce49236d2dc9e630159edd2c54bf9f6" +dependencies = [ + "criterion", + "p3-field", + "rand 0.8.5", +] + [[package]] name = "p3-fri" version = "0.2.3-succinct" @@ -3845,6 +3853,25 @@ dependencies = [ "serde", ] +[[package]] +name = "p3-sect-fr" +version = "5.0.0" +dependencies = [ + "ark-ff 0.4.2", + "ff 0.13.1", + "lazy_static", + "num-bigint 0.4.6", + "num-traits", + "p3-field", + "p3-field-testing", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.5", + "serde", + "serde_json", + "zkhash", +] + [[package]] name = "p3-symmetric" version = "0.2.3-succinct" @@ -5543,7 +5570,6 @@ version = "5.0.0" dependencies = [ "bincode", "ctrlc", - "once_cell", "prost", "prost-build", "serde", @@ -5708,11 +5734,11 @@ dependencies = [ "lru", "num-bigint 0.4.6", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-field", "p3-matrix", + "p3-sect-fr", "p3-symmetric", "p3-util", "rayon", @@ -5745,7 +5771,6 @@ dependencies = [ "num-traits", "p3-air", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-dft", @@ -5754,6 +5779,7 @@ dependencies = [ "p3-matrix", "p3-merkle-tree", "p3-poseidon2", + "p3-sect-fr", "p3-symmetric", "p3-uni-stark", "p3-util", @@ -5781,11 +5807,11 @@ dependencies = [ "criterion", "itertools 0.13.0", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-dft", "p3-field", "p3-merkle-tree", + "p3-sect-fr", "p3-symmetric", "rand 0.8.5", "serde", @@ -5813,7 +5839,6 @@ dependencies = [ "num_cpus", "p3-air", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-dft", @@ -5823,6 +5848,7 @@ dependencies = [ "p3-maybe-rayon", "p3-merkle-tree", "p3-poseidon2", + "p3-sect-fr", "p3-symmetric", "p3-util", "pathdiff", diff --git a/Cargo.toml b/Cargo.toml index 298220ad3d..787ceadd64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ members = [ "crates/stark", "crates/zkvm/*", "crates/test-artifacts", + "crates/p3-sect-fr", ] exclude = ["examples/target"] resolver = "2" @@ -69,6 +70,7 @@ sp1-cuda = { path = "crates/cuda", version = "5.0.0" } sp1-stark = { path = "crates/stark", version = "5.0.0" } sp1-lib = { path = "crates/zkvm/lib", version = "5.0.0", default-features = false } sp1-zkvm = { path = "crates/zkvm/entrypoint", version = "5.0.0", default-features = false } +p3-sect-fr = { path = "crates/p3-sect-fr" } # For testing. test-artifacts = { path = "crates/test-artifacts" } diff --git a/README.md b/README.md index 70cdfdc3ca..b40e839ede 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,62 @@ -# SP1 +# SP1 Fork -![SP1](./assets/sp1.png) +This fork of SP1 includes changes to generate R1CS and satisfying witness of a stark-proof-verifier program over sect233k1. This way you can write arbitrary program in rust and have it validated by `dv-pari`. -SP1 is the fastest, most-feature complete zero-knowledge virtual machine (zkVM) that can prove the execution of arbitrary Rust (or any LLVM-compiled language) programs. SP1 makes ZK accessible to *any developer*, by making it easy to write ZKP programs in normal Rust code. +SP1 generates Inner Proof (core proof and compressed proof), wraps it over a scalar field (e.g bn254) and then generates snark proof (e.g. groth16). Here wrapping means you represent stark-proof-verifier in R1CS constraints over scalar field. Generating SNARK means you use this R1CS representation and stark-proof (Inner Proof) as an input to generate a succinct proof using systems like groth16. -**[Install](https://docs.succinct.xyz/docs/sp1/getting-started/install)** -| [Docs](https://docs.succinct.xyz/docs/sp1/introduction) -| [Examples](https://github.com/succinctlabs/sp1/tree/main/examples) -| [Telegram Chat](https://t.me/+AzG4ws-kD24yMGYx) +Our changes is reserved to wrapping the same R1CS constraints over a prime scalar field of sect233k1. Instead of generating SNARK, we dump R1CS and a satisfying witness (which includes stark proof) to a file. These files are taken as input by the `dv-pari` system. -## Getting Started +Changes include +1. Poseidon2 over sect233k1 +2. Fit public input hash and verification key hash in scalar field +3. Generate and dump r1cs constraints to a file +4. Generate satisfying witness to a file +5. Update `gnark` and `gnark-crypto` to be able to handle sect233k1 -Today, developers can write programs, including complex, large programs like a ZK Tendermint light client or type-1 zkEVM using Reth, in Rust (with std support), generate proofs and verify them. Most Rust crates should be supported and can be used seamlessly by your program. Example programs can be found in the [examples](https://github.com/succinctlabs/sp1/tree/main/examples) folder. +## General Info -To get started, make sure you have [Rust](https://www.rust-lang.org/tools/install) installed. Then follow the [installation](https://docs.succinct.xyz/docs/sp1/getting-started/install) guide in the SP1 book and read the [getting started](https://docs.succinct.xyz/docs/sp1/getting-started/quickstart) section. +### Running over cluster and then locally +Because SP1 cluster does not handle forked code, we run the expensive InnerProof (core and compressed proof) generation in SP1 Cluster and run the cheaper constant time OuterProof (wrap over sect233k1 scalar field and dump r1cs witness) locally. -## Security +Check `test_generate_sect_proof_single_step` to understand how both of the Outer and Inner proofs can be generated on the same machine. This approach is same as it used to be previously. -SP1 has undergone audits from [Veridise](https://www.veridise.com/), [Cantina](https://cantina.xyz/), -and [KALOS](https://kalos.xyz/) and is recommended for production use. The audit reports are available [here](./audits). +Check `test_generate_sect_proof_step_wise` to understand how Outer and Inner proofs are handled over different machines. In short -- compressed proof generated by SP1 cluster is fed as input through `SP1Stdin` by marking `prove(..).groth16_with_compressed().run()` instead of the usual `prove(..).groth16().run`. -## Supported Rust Versions (MSRV) +### Naming convention preserved to reduce code changes +Note: There are instances like the ones above where the underlying functionality has been changed to adapt for dv-pari repository (i.e generate r1cs, witness over sect233k1) but the name of functions being called appears as a misnomer (e.g. `groth16_with_compressed().run()`). You will find function names and variables whose names haven't been substituted to something like `dv` from `groth16`. This is to reduce the amount of code that do not impact functionality. -The current MSRV (minimum supported Rust version) is 1.79. +### Support for Groth16 +As we have substituted groth16 with functionality that fit our purpose, tests which assume `groth16` will fail. -## For Contributors +### Support in dv-pari +`dv-pari` library directly takes `r1cs_to_dvsnark` and `witness_to_dvsnark` as input and proceeds with the expected set of steps. +`dv-pari-demo` library handles the entire set of steps from sp1 to `dv-pari` and `dv-pari-circuit` end to end. -Open-source is a core part of SP1's ethos and key to its advantages. We wish to cultivate a vibrant community of open-source contributors that span individuals, teams and geographies. If you want to contribute, or follow along with contributor discussion, you can use our main Telegram to chat with us. Our contributor guidelines can be found in [CONTRIBUTING.md](./CONTRIBUTING.md). A quick overview of development tips can be found in [DEVELOPMENT.md](./DEVELOPMENT.md). +## Getting Started +1. Build Custom sp1-gnark -We are always looking for contributors interested in tasks big and small, including minor chores across the codebase, optimizing performance, adding precompiles for commonly used cryptographic operations, adding documentation, creating new example programs and more. Please reach out in the Telegram chat if interested! +```bash +docker build -t sp1-gnark -f ./Dockerfile.gnark-ffi . +``` -## Acknowledgements +2. Generate R1CS and satisying witness -We would like to acknowledge the projects below whose previous work has been instrumental in making this project a reality. +```bash +RUST_LOG=info cargo test --release --package sp1-sdk --lib -- tests::test_generate_sect_proof_single_step --exact --show-output --ignored --nocapture +``` -- [Plonky3](https://github.com/Plonky3/Plonky3): The SP1's prover is powered by the Plonky3 toolkit. -- [Valida](https://github.com/valida-xyz/valida): The SP1 cross-table lookups, prover, borrow macro, and chip design, including constraints, are inspired by Valida. -- [RISC0](https://github.com/risc0/risc0): The SP1 rust toolchain, install/build scripts, and our RISCV runtime borrow code from RISC0. -- [Cairo](https://docs.cairo-lang.org/how_cairo_works/builtins.html): Cairo introduced the idea of "builtins" which allow zkVMs to accelerate certain operations. However, the complexity of "builtins" was embedded in the CPU, limiting their complexity. SP1 extends this idea by executing on a vision of easily extensible "precompiles" that can be added as additional tables alongside the CPU. +This should generate R1CS and witness in file `~/.sp1/circuits/r1cs_to_dvsnark` and `~/.sp1/circuits/witness_to_dvsnark` respectively + +Recurring calls to generate proof will only generate proof and reuse pregenerated r1cs cached in the file `~/.sp1/circuits/r1cs_cached` + +## System Requirements + +Generating R1CS Constraints requires around 30 GB of docker memory. Ensure docker isn't constrained to a lower limit, else container crashes midway. R1CS only has to be generated once. SP1's main fork assumes these artifacts are directly downloaded from a trusted source, we can also opt for a similar approach where pre-generated r1cs of around 1.2 GB can be directly downloaded, its shasum validated and used. + +Generating proof requires around 8 GB of docker memory. + +## Versioning + +SP1 Fork is forked off of v5.0.0 fork from main branch. + +Our main branch is `alpen_dev`. \ No newline at end of file diff --git a/crates/core/machine/src/riscv/mod.rs b/crates/core/machine/src/riscv/mod.rs index 95a8005dd4..6d98350127 100644 --- a/crates/core/machine/src/riscv/mod.rs +++ b/crates/core/machine/src/riscv/mod.rs @@ -571,7 +571,6 @@ impl From for RiscvAirId { #[cfg(test)] #[allow(non_snake_case)] -#[allow(clippy::print_stdout)] pub mod tests { use crate::{ @@ -612,7 +611,7 @@ pub mod tests { #[ignore] fn write_core_air_costs() { let costs = RiscvAir::::costs(); - println!("{:?}", costs); + tracing::info!("{:?}", costs); // write to file // Create directory if it doesn't exist let dir = std::path::Path::new("../executor/src/artifacts"); diff --git a/crates/p3-sect-fr/Cargo.toml b/crates/p3-sect-fr/Cargo.toml new file mode 100644 index 0000000000..c587e5ee00 --- /dev/null +++ b/crates/p3-sect-fr/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "p3-sect-fr" +version.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true +categories.workspace = true +include.workspace = true + +[dependencies] +p3-poseidon2.workspace = true +p3-field.workspace = true +p3-symmetric.workspace = true +serde.workspace = true +serde_json.workspace = true +ark-ff = "0.4" +lazy_static = "1.5.0" + +rand = "0.8" +num-bigint = "0.4" +ff = { version = "0.13", features = [ + "derive", + "derive_bits", +] } +num-traits = "0.2" +zkhash = "0.2" + +[dev-dependencies] +p3-field-testing = "=0.2.3-succinct" + + +[lints] +workspace = true diff --git a/crates/p3-sect-fr/src/lib.rs b/crates/p3-sect-fr/src/lib.rs new file mode 100644 index 0000000000..cdb33cb7d2 --- /dev/null +++ b/crates/p3-sect-fr/src/lib.rs @@ -0,0 +1,379 @@ +/// This library references p3-bn254-fr 0.2.2-succinct +/// https://docs.rs/crate/p3-bn254-fr/0.2.3-succinct/source/src/lib.rs +/// +/// Changes in this file is reserved to sect233k1 parameters like field modulus +pub mod params; +mod poseidon2; + +use core::{ + fmt, + fmt::{Debug, Display, Formatter}, + hash::{Hash, Hasher}, + iter::{Product, Sum}, + ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}, +}; + +use ff::{Field as FFField, PrimeField as FFPrimeField, PrimeFieldBits}; +use num_bigint::BigUint; +use p3_field::{AbstractField, Field, Packable, PrimeField}; +pub use poseidon2::DiffusionMatrixSECT; +use rand::{ + distributions::{Distribution, Standard}, + Rng, +}; +use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize}; + +#[derive(FFPrimeField)] +#[PrimeFieldModulus = "3450873173395281893717377931138512760570940988862252126328087024741343"] +#[PrimeFieldGenerator = "3"] +#[PrimeFieldReprEndianness = "little"] +pub struct FFSectFr([u64; 4]); + +/// The SECT curve scalar field prime, defined as `F_r` where `r = +/// 3450873173395281893717377931138512760570940988862252126328087024741343`. +#[derive(Copy, Clone, Default, Eq, PartialEq)] +pub struct SectFr { + pub value: FFSectFr, +} + +impl SectFr { + pub(crate) const fn new(value: FFSectFr) -> Self { + Self { value } + } +} + +impl Serialize for SectFr { + fn serialize(&self, serializer: S) -> Result { + let repr = self.value.to_repr(); + let bytes = repr.as_ref(); + + let mut seq = serializer.serialize_seq(Some(bytes.len()))?; + for e in bytes { + seq.serialize_element(&e)?; + } + seq.end() + } +} + +impl<'de> Deserialize<'de> for SectFr { + fn deserialize>(d: D) -> Result { + let bytes: Vec = Deserialize::deserialize(d)?; + + let mut res = ::Repr::default(); + + for (i, digit) in res.0.as_mut().iter_mut().enumerate() { + *digit = bytes[i]; + } + + let value = FFSectFr::from_repr(res); + + if value.is_some().into() { + Ok(Self { value: value.unwrap() }) + } else { + Err(serde::de::Error::custom("Invalid field element")) + } + } +} + +impl Packable for SectFr {} + +impl Hash for SectFr { + fn hash(&self, state: &mut H) { + for byte in self.value.to_repr().as_ref().iter() { + state.write_u8(*byte); + } + } +} + +impl Ord for SectFr { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.value.cmp(&other.value) + } +} + +impl PartialOrd for SectFr { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Display for SectFr { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + ::fmt(&self.value, f) + } +} + +impl Debug for SectFr { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.value, f) + } +} + +impl AbstractField for SectFr { + type F = Self; + + fn zero() -> Self { + Self::new(FFSectFr::ZERO) + } + fn one() -> Self { + Self::new(FFSectFr::ONE) + } + fn two() -> Self { + Self::new(FFSectFr::from(2u64)) + } + + fn neg_one() -> Self { + Self::new(FFSectFr::ZERO - FFSectFr::ONE) + } + + #[inline] + fn from_f(f: Self::F) -> Self { + f + } + + fn from_bool(b: bool) -> Self { + Self::new(FFSectFr::from(b as u64)) + } + + fn from_canonical_u8(n: u8) -> Self { + Self::new(FFSectFr::from(n as u64)) + } + + fn from_canonical_u16(n: u16) -> Self { + Self::new(FFSectFr::from(n as u64)) + } + + fn from_canonical_u32(n: u32) -> Self { + Self::new(FFSectFr::from(n as u64)) + } + + fn from_canonical_u64(n: u64) -> Self { + Self::new(FFSectFr::from(n)) + } + + fn from_canonical_usize(n: usize) -> Self { + Self::new(FFSectFr::from(n as u64)) + } + + fn from_wrapped_u32(n: u32) -> Self { + Self::new(FFSectFr::from(n as u64)) + } + + fn from_wrapped_u64(n: u64) -> Self { + Self::new(FFSectFr::from(n)) + } + + fn generator() -> Self { + Self::new(FFSectFr::from(3u64)) + } +} + +impl Field for SectFr { + type Packing = Self; + + fn is_zero(&self) -> bool { + self.value.is_zero().into() + } + + fn try_inverse(&self) -> Option { + let inverse = self.value.invert(); + + if inverse.is_some().into() { + Some(Self::new(inverse.unwrap())) + } else { + None + } + } + + fn order() -> BigUint { + let bytes = FFSectFr::char_le_bits(); + BigUint::from_bytes_le(bytes.as_raw_slice()) + } +} + +impl PrimeField for SectFr { + fn as_canonical_biguint(&self) -> BigUint { + let repr = self.value.to_repr(); + let le_bytes = repr.as_ref(); + BigUint::from_bytes_le(le_bytes) + } +} + +impl Add for SectFr { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Self::new(self.value + rhs.value) + } +} + +impl AddAssign for SectFr { + fn add_assign(&mut self, rhs: Self) { + self.value += rhs.value; + } +} + +impl Sum for SectFr { + fn sum>(iter: I) -> Self { + iter.reduce(|x, y| x + y).unwrap_or(Self::zero()) + } +} + +impl Sub for SectFr { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + Self::new(self.value.sub(rhs.value)) + } +} + +impl SubAssign for SectFr { + fn sub_assign(&mut self, rhs: Self) { + self.value -= rhs.value; + } +} + +impl Neg for SectFr { + type Output = Self; + + fn neg(self) -> Self::Output { + self * Self::neg_one() + } +} + +impl Mul for SectFr { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + Self::new(self.value * rhs.value) + } +} + +impl MulAssign for SectFr { + fn mul_assign(&mut self, rhs: Self) { + self.value *= rhs.value; + } +} + +impl Product for SectFr { + fn product>(iter: I) -> Self { + iter.reduce(|x, y| x * y).unwrap_or(Self::one()) + } +} + +impl Div for SectFr { + type Output = Self; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn div(self, rhs: Self) -> Self { + self * rhs.inverse() + } +} + +impl Distribution for Standard { + #[inline] + fn sample(&self, rng: &mut R) -> SectFr { + SectFr::new(FFSectFr::random(rng)) + } +} + +use ark_ff::fields::{Fp256, MontBackend, MontConfig}; +use std::convert::TryInto; +#[derive(MontConfig)] +#[modulus = "3450873173395281893717377931138512760570940988862252126328087024741343"] +#[generator = "3"] +pub struct FqConfig; +pub type FpSECT = Fp256>; + +#[cfg(test)] +mod tests { + use super::*; + use num_traits::One; + + type F = SectFr; + + #[test] + fn test_sectfr() { + let f = F::new(FFSectFr::from_u128(100)); + assert_eq!(f.as_canonical_biguint(), BigUint::new(vec![100])); + + let f = F::from_canonical_u64(0); + assert!(f.is_zero()); + + let f = F::new(FFSectFr::from_str_vartime(&F::order().to_str_radix(10)).unwrap()); + assert!(f.is_zero()); + + assert_eq!(F::generator().as_canonical_biguint(), BigUint::new(vec![3])); + + let f_1 = F::new(FFSectFr::from_u128(1)); + let f_1_copy = F::new(FFSectFr::from_u128(1)); + + let expected_result = F::zero(); + assert_eq!(f_1 - f_1_copy, expected_result); + + let expected_result = F::new(FFSectFr::from_u128(2)); + assert_eq!(f_1 + f_1_copy, expected_result); + + let f_2 = F::new(FFSectFr::from_u128(2)); + let expected_result = F::new(FFSectFr::from_u128(3)); + assert_eq!(f_1 + f_1_copy * f_2, expected_result); + + let expected_result = F::new(FFSectFr::from_u128(5)); + assert_eq!(f_1 + f_2 * f_2, expected_result); + + let f_r_minus_1 = F::new( + FFSectFr::from_str_vartime(&(F::order() - BigUint::one()).to_str_radix(10)).unwrap(), + ); + let expected_result = F::zero(); + assert_eq!(f_1 + f_r_minus_1, expected_result); + + let f_r_minus_2 = F::new( + FFSectFr::from_str_vartime(&(F::order() - BigUint::new(vec![2])).to_str_radix(10)) + .unwrap(), + ); + let expected_result = F::new( + FFSectFr::from_str_vartime(&(F::order() - BigUint::new(vec![3])).to_str_radix(10)) + .unwrap(), + ); + assert_eq!(f_r_minus_1 + f_r_minus_2, expected_result); + + let expected_result = F::new(FFSectFr::from_u128(1)); + assert_eq!(f_r_minus_1 - f_r_minus_2, expected_result); + + let expected_result = f_r_minus_1; + assert_eq!(f_r_minus_2 - f_r_minus_1, expected_result); + + let expected_result = f_r_minus_2; + assert_eq!(f_r_minus_1 - f_1, expected_result); + + let expected_result = F::new(FFSectFr::from_u128(3)); + assert_eq!(f_2 * f_2 - f_1, expected_result); + + // Generator check + let expected_multiplicative_group_generator = F::new(FFSectFr::from_u128(3)); + assert_eq!(F::generator(), expected_multiplicative_group_generator); + + let f_serialized = serde_json::to_string(&f).unwrap(); + let f_deserialized: F = serde_json::from_str(&f_serialized).unwrap(); + assert_eq!(f, f_deserialized); + + let f_1_serialized = serde_json::to_string(&f_1).unwrap(); + let f_1_deserialized: F = serde_json::from_str(&f_1_serialized).unwrap(); + let f_1_serialized_again = serde_json::to_string(&f_1_deserialized).unwrap(); + let f_1_deserialized_again: F = serde_json::from_str(&f_1_serialized_again).unwrap(); + assert_eq!(f_1, f_1_deserialized); + assert_eq!(f_1, f_1_deserialized_again); + + let f_2_serialized = serde_json::to_string(&f_2).unwrap(); + let f_2_deserialized: F = serde_json::from_str(&f_2_serialized).unwrap(); + assert_eq!(f_2, f_2_deserialized); + + let f_r_minus_1_serialized = serde_json::to_string(&f_r_minus_1).unwrap(); + let f_r_minus_1_deserialized: F = serde_json::from_str(&f_r_minus_1_serialized).unwrap(); + assert_eq!(f_r_minus_1, f_r_minus_1_deserialized); + + let f_r_minus_2_serialized = serde_json::to_string(&f_r_minus_2).unwrap(); + let f_r_minus_2_deserialized: F = serde_json::from_str(&f_r_minus_2_serialized).unwrap(); + assert_eq!(f_r_minus_2, f_r_minus_2_deserialized); + } +} diff --git a/crates/p3-sect-fr/src/params.rs b/crates/p3-sect-fr/src/params.rs new file mode 100644 index 0000000000..ff3143d069 --- /dev/null +++ b/crates/p3-sect-fr/src/params.rs @@ -0,0 +1,369 @@ +//! Poseidon params are referenced from bn254 poseidon parameters below: +//! https://github.com/HorizenLabs/poseidon2/blob/main/plain_implementations/src/poseidon2/poseidon2_instance_bn256.rs +//! +//! Round constants given below are exactly the ones provided for bn254 above, except that these +//! values are truncated to fit the field size. `Poseidon2Params` like state-width, round sizes, +//! s-box size are the same between bn254 and sect233k1. +//! +//! we should generate round constants through the procedure noted in Poseidon paper, +//! which suggests hashing the above poseidon parameters + scalar field to generate these constants. +//! The values generated this way are deterministic and transparent +//! but truncation adds bias and as such does not preserve uniformity. +//! TODO: @manishbista28, @AaronFeickert + +use std::sync::Arc; + +use crate::FpSECT; +use lazy_static::lazy_static; +use zkhash::{fields::utils::from_hex, poseidon2::poseidon2_params::Poseidon2Params}; +type Scalar = FpSECT; + +lazy_static! { + pub static ref MAT_DIAG3_M_1: Vec = vec![ + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000002"), + ]; + pub static ref MAT_INTERNAL3: Vec> = vec![ + vec![ + from_hex("0x0000000000000000000000000000000000000000000000000000000002"), + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + ], + vec![ + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000002"), + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + ], + vec![ + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000001"), + from_hex("0x0000000000000000000000000000000000000000000000000000000003"), + ], + ]; + pub static ref RC3: Vec> = vec![ + vec![ + from_hex("0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97"), + from_hex("0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d3"), + from_hex("0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0"), + ], + vec![ + from_hex("0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded8"), + from_hex("0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595"), + from_hex("0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c90"), + ], + vec![ + from_hex("0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae150"), + from_hex("0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd6551561"), + from_hex("0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8"), + ], + vec![ + from_hex("0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a"), + from_hex("0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d81"), + from_hex("0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ff"), + ], + vec![ + from_hex("0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f235"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd3838313"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e6"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a53"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945db"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a9"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb1"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829b"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f694"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b460682"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef68522"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2f"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f77"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f752601"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7e"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706c"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f1037"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a58"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17d"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438d"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea1"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6e"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d8"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311b"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde22999"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + from_hex("0x0000000000000000000000000000000000000000000000000000000000"), + ], + vec![ + from_hex("0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8"), + from_hex("0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a"), + from_hex("0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b"), + ], + vec![ + from_hex("0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224"), + from_hex("0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28"), + from_hex("0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9"), + ], + vec![ + from_hex("0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb"), + from_hex("0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b"), + from_hex("0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af"), + ], + vec![ + from_hex("0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961"), + from_hex("0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e"), + from_hex("0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c"), + ], + ]; + // as mentioned above, params are same in value as for bn254 (except RC3 is truncated to fit scalar field size) + pub static ref POSEIDON2_SECT_PARAMS: Arc> = + Arc::new(Poseidon2Params::new(3, 5, 8, 56, &MAT_DIAG3_M_1, &MAT_INTERNAL3, &RC3)); +} diff --git a/crates/p3-sect-fr/src/poseidon2.rs b/crates/p3-sect-fr/src/poseidon2.rs new file mode 100644 index 0000000000..add395d278 --- /dev/null +++ b/crates/p3-sect-fr/src/poseidon2.rs @@ -0,0 +1,134 @@ +//! Diffusion matrix for SECT +//! +//! Reference: https://github.com/HorizenLabs/poseidon2/blob/main/plain_implementations/src/poseidon2/poseidon2_instance_bn256.rs + +use std::sync::OnceLock; + +use p3_field::AbstractField; +use p3_poseidon2::{matmul_internal, DiffusionPermutation}; +use p3_symmetric::Permutation; +use serde::{Deserialize, Serialize}; + +use crate::SectFr; + +#[inline] +fn get_diffusion_matrix_3() -> &'static [SectFr; 3] { + static MAT_DIAG3_M_1: OnceLock<[SectFr; 3]> = OnceLock::new(); + MAT_DIAG3_M_1.get_or_init(|| [SectFr::one(), SectFr::one(), SectFr::two()]) +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct DiffusionMatrixSECT; + +impl> Permutation<[AF; 3]> for DiffusionMatrixSECT { + fn permute_mut(&self, state: &mut [AF; 3]) { + matmul_internal::(state, *get_diffusion_matrix_3()); + } +} + +impl> DiffusionPermutation for DiffusionMatrixSECT {} + +#[cfg(test)] +mod tests { + use crate::{ + params::{POSEIDON2_SECT_PARAMS, RC3}, + FpSECT as ark_FpBN256, + }; + use ff::PrimeField; + use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixHL}; + use rand::Rng; + use zkhash::{ + ark_ff::{BigInteger, PrimeField as ark_PrimeField}, + poseidon2::poseidon2::Poseidon2 as Poseidon2Ref, + }; + + use super::*; + use crate::FFSectFr; + + fn sect_from_ark_ff(input: ark_FpBN256) -> SectFr { + let bytes = input.into_bigint().to_bytes_le(); + + let mut res = ::Repr::default(); + + for (i, digit) in res.0.as_mut().iter_mut().enumerate() { + *digit = bytes[i]; + } + + let value = FFSectFr::from_repr(res); + + if value.is_some().into() { + SectFr { value: value.unwrap() } + } else { + panic!("Invalid field element") + } + } + + /// external_round_constants and internal_round_constants are the generated values used in RC3 + #[test] + fn test_poseidon2_sect() { + const WIDTH: usize = 3; + const D: u64 = 5; + const ROUNDS_F: usize = 8; + const ROUNDS_P: usize = 56; + + type F = SectFr; + + let mut rng = rand::thread_rng(); + + // Poiseidon2 reference implementation from zkhash repo. + let poseidon2_ref = Poseidon2Ref::new(&POSEIDON2_SECT_PARAMS); + + // Copy over round constants from zkhash. + let mut round_constants: Vec<[F; WIDTH]> = RC3 + .iter() + .map(|vec| { + vec.iter().cloned().map(sect_from_ark_ff).collect::>().try_into().unwrap() + }) + .collect(); + + let internal_start = ROUNDS_F / 2; + let internal_end = (ROUNDS_F / 2) + ROUNDS_P; + let internal_round_constants = round_constants + .drain(internal_start..internal_end) + .map(|vec| vec[0]) + .collect::>(); + let external_round_constants = round_constants; + // Our Poseidon2 implementation. + let poseidon2: Poseidon2 = + Poseidon2::new( + ROUNDS_F, + external_round_constants, + Poseidon2ExternalMatrixHL, + ROUNDS_P, + internal_round_constants, + DiffusionMatrixSECT, + ); + + // Generate random input and convert to both Goldilocks field formats. + let input_ark_ff = rng.gen::<[ark_FpBN256; WIDTH]>(); + let input: [SectFr; 3] = input_ark_ff + .iter() + .cloned() + .map(sect_from_ark_ff) + .collect::>() + .try_into() + .unwrap(); + + // Run reference implementation. + let output_ref = poseidon2_ref.permutation(&input_ark_ff); + + let expected: [F; WIDTH] = output_ref + .iter() + .cloned() + .map(sect_from_ark_ff) + .collect::>() + .try_into() + .unwrap(); + + // Run our implementation. + let mut output = input; + poseidon2.permute_mut(&mut output); + + assert_eq!(output, expected); + } +} diff --git a/crates/prover/Cargo.toml b/crates/prover/Cargo.toml index 60680d6728..2e9455f671 100644 --- a/crates/prover/Cargo.toml +++ b/crates/prover/Cargo.toml @@ -25,7 +25,7 @@ sp1-primitives = { workspace = true } p3-field = { workspace = true } p3-challenger = { workspace = true } p3-baby-bear = { workspace = true } -p3-bn254-fr = { workspace = true } +p3-sect-fr = { workspace = true } p3-commit = { workspace = true } p3-util = { workspace = true } bincode = "1.3.3" diff --git a/crates/prover/src/build.rs b/crates/prover/src/build.rs index b6a25c6077..0cd89f8bcf 100644 --- a/crates/prover/src/build.rs +++ b/crates/prover/src/build.rs @@ -1,6 +1,6 @@ #![allow(clippy::print_stdout)] // okay to print to stdout: this is a build script -use std::{borrow::Borrow, path::PathBuf}; +use std::{borrow::Borrow, fs::metadata, path::PathBuf}; use p3_baby_bear::BabyBear; use sp1_core_executor::SP1Context; @@ -43,6 +43,37 @@ pub fn try_build_groth16_bn254_artifacts_dev( template_proof: &ShardProof, ) -> PathBuf { let build_dir = groth16_bn254_artifacts_dev_dir(); + + let home = std::env::home_dir().expect("Failed to find the home directory."); + let circuits_dir = home.join(".sp1/circuits"); + let r1cs_to_dvsnark_path = circuits_dir.join("r1cs_to_dvsnark"); // r1cs dump in gnark format + let r1cs_cached_path = circuits_dir.join("r1cs_cached"); // r1cs dump to export over to dvsnark + + let mut r1cs_to_dvsnark_content_exist = false; + if r1cs_to_dvsnark_path.exists() { + let md = metadata(r1cs_to_dvsnark_path).unwrap(); + let filesize = md.len(); + // ensure it is not empty, arbitrary threshold 1024, could have been set to 0 + if filesize > 1024 { + r1cs_to_dvsnark_content_exist = true + } + } + + let mut r1cs_cached_content_exist = false; + if r1cs_cached_path.exists() { + let md = metadata(r1cs_cached_path).unwrap(); + let filesize = md.len(); + // ensure it is not empty + if filesize > 1024 { + r1cs_cached_content_exist = true + } + } + + if r1cs_cached_content_exist && r1cs_to_dvsnark_content_exist { + println!("[sp1] build dir contains cached r1cs"); + return build_dir; // early return if content already exist + } + println!("[sp1] building groth16 bn254 artifacts in development mode"); build_groth16_bn254_artifacts(template_vk, template_proof, &build_dir); build_dir @@ -137,6 +168,8 @@ pub fn build_constraints_and_witness( words_to_bytes(&pv.committed_value_digest).try_into().unwrap(); let committed_values_digest = babybear_bytes_to_bn254(&committed_values_digest_bytes); + println!("SP1 VERIIFCATION KEY: {:?}", vkey_hash); + tracing::warn!("committed values digest {:?}", committed_values_digest); tracing::info!("building template witness"); let mut witness = OuterWitness::default(); template_input.write(&mut witness); diff --git a/crates/prover/src/lib.rs b/crates/prover/src/lib.rs index 3a291f0873..ca08e53f39 100644 --- a/crates/prover/src/lib.rs +++ b/crates/prover/src/lib.rs @@ -80,7 +80,10 @@ use sp1_recursion_core::{ RecursionProgram, Runtime as RecursionRuntime, }; pub use sp1_recursion_gnark_ffi::proof::{Groth16Bn254Proof, PlonkBn254Proof}; -use sp1_recursion_gnark_ffi::{groth16_bn254::Groth16Bn254Prover, plonk_bn254::PlonkBn254Prover}; +use sp1_recursion_gnark_ffi::{ + groth16_bn254::Groth16Bn254Prover, plonk_bn254::PlonkBn254Prover, SectWitness, + SectWitnessGenerator, +}; use sp1_stark::{ baby_bear_poseidon2::BabyBearPoseidon2, shape::{OrderedShape, Shape}, @@ -1043,6 +1046,38 @@ impl SP1Prover { proof } + /// Wrap the STARK proven over sect + /// Takes STARK proof and dumps witness satisfying the R1CS representing stark verifier in + /// file `~/.sp1/circuits/r1cs_to_dvsnark` + #[instrument(name = "wrap_sect", level = "info", skip_all)] + pub fn wrap_sect(&self, proof: SP1ReduceProof, build_dir: &Path) -> SectWitness { + let input = SP1CompressWitnessValues { + vks_and_proofs: vec![(proof.vk.clone(), proof.proof.clone())], + is_complete: true, + }; + let vkey_hash = sp1_vkey_digest_bn254(&proof); + let committed_values_digest = sp1_committed_values_digest_bn254(&proof); + + let mut witness = Witness::default(); + input.write(&mut witness); + witness.write_committed_values_digest(committed_values_digest); + witness.write_vkey_hash(vkey_hash); + + tracing::info!("vkey_hash {:?}", vkey_hash); + tracing::info!("committed_values_digest {:?}", committed_values_digest); + let prover = SectWitnessGenerator {}; + prover.prove(witness, build_dir.to_path_buf()) + + // omit verifying as we haven't generated proof + // Verify the proof. + // prover.verify( + // &proof, + // &vkey_hash.as_canonical_biguint(), + // &committed_values_digest.as_canonical_biguint(), + // build_dir, + // ); + } + pub fn recursion_program( &self, input: &SP1RecursionWitnessValues, @@ -1577,7 +1612,9 @@ pub mod tests { let mut bytes = Vec::new(); file.read_to_end(&mut bytes).unwrap(); - let wrapped_bn254_proof = bincode::deserialize(&bytes).unwrap(); + let wrapped_bn254_proof: SP1ReduceProof = + bincode::deserialize(&bytes).unwrap(); + let _ = prover.wrap_vk.set(wrapped_bn254_proof.clone().vk); if verify { tracing::info!("verify wrap bn254"); @@ -1596,6 +1633,7 @@ pub mod tests { let vk_digest_bn254 = sp1_vkey_digest_bn254(&wrapped_bn254_proof); assert_eq!(vk_digest_bn254, vk.hash_bn254()); + tracing::warn!("vk_digest_bn254 {:?}", vk_digest_bn254); tracing::info!("Test the outer Plonk circuit"); let (constraints, witness) = build_constraints_and_witness(&wrapped_bn254_proof.vk, &wrapped_bn254_proof.proof); diff --git a/crates/prover/src/types.rs b/crates/prover/src/types.rs index 34e81d9f53..55f9a25c99 100644 --- a/crates/prover/src/types.rs +++ b/crates/prover/src/types.rs @@ -3,9 +3,9 @@ use std::{fs::File, path::Path}; use anyhow::Result; use clap::ValueEnum; use p3_baby_bear::BabyBear; -use p3_bn254_fr::Bn254Fr; use p3_commit::{Pcs, TwoAdicMultiplicativeCoset}; use p3_field::{AbstractField, PrimeField, PrimeField32, TwoAdicField}; +use p3_sect_fr::SectFr; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sp1_core_machine::{io::SP1Stdin, reduce::SP1ReduceProof}; use sp1_primitives::{io::SP1PublicValues, poseidon2_hash}; @@ -47,8 +47,8 @@ pub trait HashableKey { /// Hash the key into a digest of u32 elements. fn hash_u32(&self) -> [u32; DIGEST_SIZE]; - /// Hash the key into a Bn254Fr element. - fn hash_bn254(&self) -> Bn254Fr { + /// Hash the key into a SectFr element. + fn hash_bn254(&self) -> SectFr { babybears_to_bn254(&self.hash_babybear()) } diff --git a/crates/prover/src/utils.rs b/crates/prover/src/utils.rs index 4667a6f3af..483064cb6f 100644 --- a/crates/prover/src/utils.rs +++ b/crates/prover/src/utils.rs @@ -7,8 +7,8 @@ use std::{ use itertools::Itertools; use p3_baby_bear::BabyBear; -use p3_bn254_fr::Bn254Fr; use p3_field::{AbstractField, PrimeField32}; +use p3_sect_fr::SectFr; use p3_symmetric::CryptographicHasher; use sp1_core_executor::{Executor, Program}; use sp1_core_machine::{io::SP1Stdin, reduce::SP1ReduceProof}; @@ -29,7 +29,7 @@ pub fn sp1_vkey_digest_babybear(proof: &SP1ReduceProof) } /// Get the SP1 vkey Bn Poseidon2 digest this reduce proof is representing. -pub fn sp1_vkey_digest_bn254(proof: &SP1ReduceProof) -> Bn254Fr { +pub fn sp1_vkey_digest_bn254(proof: &SP1ReduceProof) -> SectFr { babybears_to_bn254(&sp1_vkey_digest_babybear(proof)) } @@ -87,9 +87,7 @@ pub fn is_recursion_public_values_valid( } /// Get the committed values Bn Poseidon2 digest this reduce proof is representing. -pub fn sp1_committed_values_digest_bn254( - proof: &SP1ReduceProof, -) -> Bn254Fr { +pub fn sp1_committed_values_digest_bn254(proof: &SP1ReduceProof) -> SectFr { let proof = &proof.proof; let pv: &RecursionPublicValues = proof.public_values.as_slice().borrow(); let committed_values_digest_bytes: [BabyBear; 32] = @@ -125,32 +123,34 @@ pub fn words_to_bytes(words: &[Word]) -> Vec { words.iter().flat_map(|word| word.0).collect() } -/// Convert 8 BabyBear words into a Bn254Fr field element by shifting by 31 bits each time. The last -/// word becomes the least significant bits. -pub fn babybears_to_bn254(digest: &[BabyBear; 8]) -> Bn254Fr { - let mut result = Bn254Fr::zero(); - for word in digest.iter() { - // Since BabyBear prime is less than 2^31, we can shift by 31 bits each time and still be - // within the Bn254Fr field, so we don't have to truncate the top 3 bits. - result *= Bn254Fr::from_canonical_u64(1 << 31); - result += Bn254Fr::from_canonical_u32(word.as_canonical_u32()); +/// Convert 8 BabyBear words into a SectFr field element. +/// First 32 bits are fully masked, this leaves 256-32=224 bits +/// which is now small enough to fit within the scalar field. +/// The last word becomes the least significant bits. +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. +pub fn babybears_to_bn254(digest: &[BabyBear; 8]) -> SectFr { + let mut result = SectFr::zero(); + for (idx, word) in digest.iter().enumerate() { + result *= SectFr::from_canonical_u64(1 << 32); + let masked_val_u32 = if idx == 0 { 0 } else { word.as_canonical_u32() }; + result += SectFr::from_canonical_u32(masked_val_u32); } result } -/// Convert 32 BabyBear bytes into a Bn254Fr field element. The first byte's most significant 3 bits -/// (which would become the 3 most significant bits) are truncated. -pub fn babybear_bytes_to_bn254(bytes: &[BabyBear; 32]) -> Bn254Fr { - let mut result = Bn254Fr::zero(); - for (i, byte) in bytes.iter().enumerate() { - debug_assert!(byte < &BabyBear::from_canonical_u32(256)); - if i == 0 { - // 32 bytes is more than Bn254 prime, so we need to truncate the top 3 bits. - result = Bn254Fr::from_canonical_u32(byte.as_canonical_u32() & 0x1f); - } else { - result *= Bn254Fr::from_canonical_u32(256); - result += Bn254Fr::from_canonical_u32(byte.as_canonical_u32()); - } +/// Convert 32 BabyBear bytes into a SectFr field element. +/// First 4 bytes (32 bits) is fully masked, this leaves 256-32=224 bits. +/// which is now small enough to fit within the scalar field. +/// The last word becomes the least significant bits. +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. +pub fn babybear_bytes_to_bn254(bytes: &[BabyBear; 32]) -> SectFr { + let mut result = SectFr::zero(); + for (idx, byte) in bytes.iter().enumerate() { + result *= SectFr::from_canonical_u32(256); // shift by 7 bits + let masked = if idx < 4 { 0 } else { byte.as_canonical_u32() }; + result += SectFr::from_canonical_u32(masked); // add 7-bit } result } diff --git a/crates/recursion/circuit/Cargo.toml b/crates/recursion/circuit/Cargo.toml index 8052632d7a..8bfd297baa 100644 --- a/crates/recursion/circuit/Cargo.toml +++ b/crates/recursion/circuit/Cargo.toml @@ -19,7 +19,7 @@ p3-util = { workspace = true } p3-symmetric = { workspace = true } p3-challenger = { workspace = true } p3-dft = { workspace = true } -p3-bn254-fr = { workspace = true } +p3-sect-fr = { workspace = true } p3-baby-bear = { workspace = true } p3-uni-stark = { workspace = true } diff --git a/crates/recursion/circuit/src/challenger.rs b/crates/recursion/circuit/src/challenger.rs index 4be9da49e2..a193f43d50 100644 --- a/crates/recursion/circuit/src/challenger.rs +++ b/crates/recursion/circuit/src/challenger.rs @@ -435,9 +435,9 @@ pub(crate) mod tests { utils::tests::run_test_recursion, }; use p3_baby_bear::BabyBear; - use p3_bn254_fr::Bn254Fr; use p3_challenger::{CanObserve, CanSample, CanSampleBits, FieldChallenger}; use p3_field::AbstractField; + use p3_sect_fr::SectFr; use p3_symmetric::{CryptographicHasher, Hash, PseudoCompressionFunction}; use sp1_recursion_compiler::{ circuit::{AsmBuilder, AsmConfig}, @@ -446,7 +446,7 @@ pub(crate) mod tests { ir::{Builder, Config, Ext, ExtConst, Felt, Var}, }; use sp1_recursion_core::stark::{outer_perm, BabyBearPoseidon2Outer, OuterCompress, OuterHash}; - use sp1_recursion_gnark_ffi::PlonkBn254Prover; + use sp1_recursion_gnark_ffi::{Groth16Bn254Prover, PlonkBn254Prover}; use sp1_stark::{baby_bear_poseidon2::BabyBearPoseidon2, StarkGenericConfig}; use crate::{ @@ -615,7 +615,7 @@ pub(crate) mod tests { let mut backend = ConstraintCompiler::::default(); let constraints = backend.emit(builder.into_operations()); - PlonkBn254Prover::test::(constraints.clone(), OuterWitness::default()); + Groth16Bn254Prover::test::(constraints.clone(), OuterWitness::default()); } #[test] @@ -624,8 +624,8 @@ pub(crate) mod tests { let perm = outer_perm(); let compressor = OuterCompress::new(perm.clone()); - let a: [Bn254Fr; 1] = [Bn254Fr::two()]; - let b: [Bn254Fr; 1] = [Bn254Fr::two()]; + let a: [SectFr; 1] = [SectFr::two()]; + let b: [SectFr; 1] = [SectFr::two()]; let gt = compressor.compress([a, b]); let mut builder = Builder::::default(); diff --git a/crates/recursion/circuit/src/hash.rs b/crates/recursion/circuit/src/hash.rs index 7aff6dc930..891457ffd3 100644 --- a/crates/recursion/circuit/src/hash.rs +++ b/crates/recursion/circuit/src/hash.rs @@ -7,7 +7,7 @@ use itertools::Itertools; use p3_baby_bear::BabyBear; use p3_field::{AbstractField, Field}; -use p3_bn254_fr::Bn254Fr; +use p3_sect_fr::SectFr; use p3_symmetric::Permutation; use sp1_recursion_compiler::{ circuit::CircuitV2Builder, @@ -159,22 +159,22 @@ impl>> FieldHasherVariable for BabyBearPoseidon2Outer { - type Digest = [Bn254Fr; BN254_DIGEST_SIZE]; + type Digest = [SectFr; BN254_DIGEST_SIZE]; fn constant_compress(input: [Self::Digest; 2]) -> Self::Digest { - let mut state = [input[0][0], input[1][0], Bn254Fr::zero()]; + let mut state = [input[0][0], input[1][0], SectFr::zero()]; outer_perm().permute_mut(&mut state); [state[0]; BN254_DIGEST_SIZE] } } -impl>> FieldHasherVariable +impl>> FieldHasherVariable for BabyBearPoseidon2Outer { - type DigestVariable = [Var; BN254_DIGEST_SIZE]; + type DigestVariable = [Var; BN254_DIGEST_SIZE]; fn hash(builder: &mut Builder, input: &[Felt<::F>]) -> Self::DigestVariable { - assert!(C::N::bits() == p3_bn254_fr::Bn254Fr::bits()); + assert!(C::N::bits() == p3_sect_fr::SectFr::bits()); assert!(C::F::bits() == p3_baby_bear::BabyBear::bits()); let num_f_elms = C::N::bits() / C::F::bits(); let mut state: [Var; OUTER_MULTI_FIELD_CHALLENGER_WIDTH] = diff --git a/crates/recursion/circuit/src/lib.rs b/crates/recursion/circuit/src/lib.rs index ec268151bc..fac4b6f9ae 100644 --- a/crates/recursion/circuit/src/lib.rs +++ b/crates/recursion/circuit/src/lib.rs @@ -6,9 +6,9 @@ use challenger::{ }; use hash::{FieldHasherVariable, Posedion2BabyBearHasherVariable}; use itertools::izip; -use p3_bn254_fr::Bn254Fr; use p3_field::AbstractField; use p3_matrix::dense::RowMajorMatrix; +use p3_sect_fr::SectFr; use sp1_recursion_compiler::{ circuit::CircuitV2Builder, config::{InnerConfig, OuterConfig}, @@ -627,7 +627,7 @@ impl>> BabyBearFriConfigVari } } -impl>> BabyBearFriConfigVariable +impl>> BabyBearFriConfigVariable for BabyBearPoseidon2Outer { type FriChallengerVariable = MultiField32ChallengerVariable; diff --git a/crates/recursion/circuit/src/utils.rs b/crates/recursion/circuit/src/utils.rs index d4211dcb97..f05dadc78a 100644 --- a/crates/recursion/circuit/src/utils.rs +++ b/crates/recursion/circuit/src/utils.rs @@ -1,63 +1,72 @@ use p3_baby_bear::BabyBear; -use p3_bn254_fr::Bn254Fr; use p3_field::{AbstractField, PrimeField32}; +use p3_sect_fr::SectFr; use sp1_recursion_compiler::ir::{Builder, Config, Felt, Var}; use sp1_recursion_core::DIGEST_SIZE; use sp1_stark::Word; -/// Convert 8 BabyBear words into a Bn254Fr field element by shifting by 31 bits each time. The last -/// word becomes the least significant bits. +/// Convert 8 BabyBear words into a SectFr field element. +/// First word (32 bit) is fully masked, this leaves 256-32=224 bits +/// which is now small enough to fit within the scalar field. +/// The last word becomes the least significant bits. +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. #[allow(dead_code)] -pub fn babybears_to_bn254(digest: &[BabyBear; 8]) -> Bn254Fr { - let mut result = Bn254Fr::zero(); - for word in digest.iter() { - // Since BabyBear prime is less than 2^31, we can shift by 31 bits each time and still be - // within the Bn254Fr field, so we don't have to truncate the top 3 bits. - result *= Bn254Fr::from_canonical_u64(1 << 31); - result += Bn254Fr::from_canonical_u32(word.as_canonical_u32()); +pub fn babybears_to_bn254(digest: &[BabyBear; 8]) -> SectFr { + let mut result = SectFr::zero(); + for (idx, word) in digest.iter().enumerate() { + result *= SectFr::from_canonical_u64(1 << 32); + let masked_val_u32 = if idx == 0 { 0 } else { word.as_canonical_u32() }; + result += SectFr::from_canonical_u32(masked_val_u32); } result } -/// Convert 32 BabyBear bytes into a Bn254Fr field element. The first byte's most significant 3 bits -/// (which would become the 3 most significant bits) are truncated. +/// Convert 32 BabyBear bytes into a SectFr field element. +/// First 4 bytes (32 bits) is fully masked, this leaves 256-32=224 bits. +/// which is now small enough to fit within the scalar field. +/// The last word becomes the least significant bits. +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. #[allow(dead_code)] -pub fn babybear_bytes_to_bn254(bytes: &[BabyBear; 32]) -> Bn254Fr { - let mut result = Bn254Fr::zero(); - for (i, byte) in bytes.iter().enumerate() { - debug_assert!(byte < &BabyBear::from_canonical_u32(256)); - if i == 0 { - // 32 bytes is more than Bn254 prime, so we need to truncate the top 3 bits. - result = Bn254Fr::from_canonical_u32(byte.as_canonical_u32() & 0x1f); - } else { - result *= Bn254Fr::from_canonical_u32(256); - result += Bn254Fr::from_canonical_u32(byte.as_canonical_u32()); - } +pub fn babybear_bytes_to_bn254(bytes: &[BabyBear; 32]) -> SectFr { + let mut result = SectFr::zero(); + for (idx, byte) in bytes.iter().enumerate() { + result *= SectFr::from_canonical_u32(256); // shift by 7 bits + let masked = if idx < 4 { 0 } else { byte.as_canonical_u32() }; + result += SectFr::from_canonical_u32(masked); // add 7-bit } result } -#[allow(dead_code)] +/// truncate top 32 bits like babybears_to_bn254 +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. pub fn felts_to_bn254_var( builder: &mut Builder, digest: &[Felt; DIGEST_SIZE], ) -> Var { - let var_2_31: Var<_> = builder.constant(C::N::from_canonical_u32(1 << 31)); + let var_2_32: Var<_> = builder.constant(C::N::from_canonical_u64(1 << 32)); let result = builder.constant(C::N::zero()); + let zero_var: Var<_> = builder.constant(C::N::zero()); + for (i, word) in digest.iter().enumerate() { - let word_var = builder.felt2var_circuit(*word); + let all_bits: Vec> = builder.num2bits_f_circuit(*word); + let word_var = if i == 0 { zero_var } else { builder.bits2num_v_circuit(&all_bits) }; if i == 0 { builder.assign(result, word_var); } else { - builder.assign(result, result * var_2_31 + word_var); + builder.assign(result, result * var_2_32 + word_var); } } result } -#[allow(dead_code)] +/// truncate top 32 bits like babybear_bytes_to_bn254 +/// Note: the function name bn254 here is a misnomer and actually refers sect233k1 curve. +/// Is kept here to reduce extensive code changes. pub fn felt_bytes_to_bn254_var( builder: &mut Builder, bytes: &[Felt; 32], @@ -67,16 +76,10 @@ pub fn felt_bytes_to_bn254_var( let result = builder.constant(C::N::zero()); for (i, byte) in bytes.iter().enumerate() { let byte_bits = builder.num2bits_f_circuit(*byte); + let byte_var = if i < 4 { zero_var } else { builder.bits2num_v_circuit(&byte_bits) }; if i == 0 { - // Since 32 bytes doesn't fit into Bn254, we need to truncate the top 3 bits. - // For first byte, zero out 3 most significant bits. - for i in 0..3 { - builder.assign(byte_bits[8 - i - 1], zero_var); - } - let byte_var = builder.bits2num_v_circuit(&byte_bits); builder.assign(result, byte_var); } else { - let byte_var = builder.bits2num_v_circuit(&byte_bits); builder.assign(result, result * var_256 + byte_var); } } diff --git a/crates/recursion/circuit/src/witness/outer.rs b/crates/recursion/circuit/src/witness/outer.rs index 66c49d520c..fbc6e81bde 100644 --- a/crates/recursion/circuit/src/witness/outer.rs +++ b/crates/recursion/circuit/src/witness/outer.rs @@ -1,7 +1,7 @@ use std::borrow::Borrow; -use p3_bn254_fr::Bn254Fr; use p3_field::AbstractField; +use p3_sect_fr::SectFr; use p3_fri::{CommitPhaseProofStep, QueryProof}; pub use sp1_recursion_compiler::ir::Witness as OuterWitness; @@ -23,10 +23,10 @@ use super::{WitnessWriter, Witnessable}; impl WitnessWriter for OuterWitness { fn write_bit(&mut self, value: bool) { - self.vars.push(Bn254Fr::from_bool(value)); + self.vars.push(SectFr::from_bool(value)); } - fn write_var(&mut self, value: Bn254Fr) { + fn write_var(&mut self, value: SectFr) { self.vars.push(value); } @@ -39,8 +39,8 @@ impl WitnessWriter for OuterWitness { } } -impl> Witnessable for Bn254Fr { - type WitnessVariable = Var; +impl> Witnessable for SectFr { + type WitnessVariable = Var; fn read(&self, builder: &mut Builder) -> Self::WitnessVariable { builder.witness_var() diff --git a/crates/recursion/compiler/Cargo.toml b/crates/recursion/compiler/Cargo.toml index bc3d476469..42f44cdb79 100644 --- a/crates/recursion/compiler/Cargo.toml +++ b/crates/recursion/compiler/Cargo.toml @@ -10,7 +10,7 @@ keywords = { workspace = true } categories = { workspace = true } [dependencies] -p3-bn254-fr = { workspace = true } +p3-sect-fr = { workspace = true } p3-baby-bear = { workspace = true } p3-field = { workspace = true } p3-symmetric = { workspace = true } diff --git a/crates/recursion/compiler/src/config.rs b/crates/recursion/compiler/src/config.rs index dbdfd40c5e..69b0616db3 100644 --- a/crates/recursion/compiler/src/config.rs +++ b/crates/recursion/compiler/src/config.rs @@ -1,6 +1,6 @@ use p3_baby_bear::BabyBear; -use p3_bn254_fr::Bn254Fr; use p3_field::extension::BinomialExtensionField; +use p3_sect_fr::SectFr; use sp1_stark::{InnerChallenge, InnerVal}; use crate::{circuit::AsmConfig, prelude::Config}; @@ -11,7 +11,7 @@ pub type InnerConfig = AsmConfig; pub struct OuterConfig; impl Config for OuterConfig { - type N = Bn254Fr; + type N = SectFr; type F = BabyBear; type EF = BinomialExtensionField; } diff --git a/crates/recursion/core/Cargo.toml b/crates/recursion/core/Cargo.toml index f549193201..47c7e9ef4c 100644 --- a/crates/recursion/core/Cargo.toml +++ b/crates/recursion/core/Cargo.toml @@ -26,7 +26,7 @@ sp1-core-machine = { workspace = true } sp1-stark = { workspace = true } hashbrown = { workspace = true, features = ["serde"] } itertools = { workspace = true } -p3-bn254-fr = { workspace = true } +p3-sect-fr = { workspace = true } p3-merkle-tree = { workspace = true } p3-commit = { workspace = true } p3-dft = { workspace = true } diff --git a/crates/recursion/core/src/stark/config.rs b/crates/recursion/core/src/stark/config.rs index 48e812146b..d8e55a8eda 100644 --- a/crates/recursion/core/src/stark/config.rs +++ b/crates/recursion/core/src/stark/config.rs @@ -1,5 +1,4 @@ use p3_baby_bear::BabyBear; -use p3_bn254_fr::{Bn254Fr, DiffusionMatrixBN254}; use p3_challenger::MultiField32Challenger; use p3_commit::ExtensionMmcs; use p3_dft::Radix2DitParallel; @@ -10,6 +9,7 @@ use p3_fri::{ }; use p3_merkle_tree::FieldMerkleTreeMmcs; use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixGeneral}; +use p3_sect_fr::{DiffusionMatrixSECT, SectFr}; use p3_symmetric::{Hash, MultiField32PaddingFreeSponge, TruncatedPermutation}; use serde::{Deserialize, Serialize}; use sp1_stark::{Com, StarkGenericConfig, ZeroCommitment}; @@ -25,18 +25,17 @@ pub const OUTER_MULTI_FIELD_CHALLENGER_DIGEST_SIZE: usize = 1; /// A configuration for outer recursion. pub type OuterVal = BabyBear; pub type OuterChallenge = BinomialExtensionField; -pub type OuterPerm = Poseidon2; -pub type OuterHash = - MultiField32PaddingFreeSponge; -pub type OuterDigestHash = Hash; -pub type OuterDigest = [Bn254Fr; DIGEST_SIZE]; +pub type OuterPerm = Poseidon2; +pub type OuterHash = MultiField32PaddingFreeSponge; +pub type OuterDigestHash = Hash; +pub type OuterDigest = [SectFr; DIGEST_SIZE]; pub type OuterCompress = TruncatedPermutation; -pub type OuterValMmcs = FieldMerkleTreeMmcs; +pub type OuterValMmcs = FieldMerkleTreeMmcs; pub type OuterChallengeMmcs = ExtensionMmcs; pub type OuterDft = Radix2DitParallel; pub type OuterChallenger = MultiField32Challenger< OuterVal, - Bn254Fr, + SectFr, OuterPerm, OUTER_MULTI_FIELD_CHALLENGER_WIDTH, OUTER_MULTI_FIELD_CHALLENGER_RATE, @@ -66,7 +65,7 @@ pub fn outer_perm() -> OuterPerm { Poseidon2ExternalMatrixGeneral, ROUNDS_P, internal_round_constants, - DiffusionMatrixBN254, + DiffusionMatrixSECT, ) } @@ -179,7 +178,7 @@ impl StarkGenericConfig for BabyBearPoseidon2Outer { impl ZeroCommitment for OuterPcs { fn zero_commitment(&self) -> Com { - OuterDigestHash::from([Bn254Fr::zero(); DIGEST_SIZE]) + OuterDigestHash::from([SectFr::zero(); DIGEST_SIZE]) } } diff --git a/crates/recursion/core/src/stark/poseidon2.rs b/crates/recursion/core/src/stark/poseidon2.rs index 4ffd872c39..bdcff2e9ac 100644 --- a/crates/recursion/core/src/stark/poseidon2.rs +++ b/crates/recursion/core/src/stark/poseidon2.rs @@ -1,30 +1,27 @@ use ff::PrimeField as FFPrimeField; -use p3_bn254_fr::{Bn254Fr, FFBn254Fr}; -use zkhash::{ - ark_ff::{BigInteger, PrimeField}, - fields::bn256::FpBN256 as ark_FpBN256, - poseidon2::poseidon2_instance_bn256::RC3, -}; - -fn bn254_from_ark_ff(input: ark_FpBN256) -> Bn254Fr { +use p3_sect_fr::{params::RC3, FFSectFr, FpSECT as ark_FpSECT, SectFr}; + +use zkhash::ark_ff::{BigInteger, PrimeField}; + +fn bn254_from_ark_ff(input: ark_FpSECT) -> SectFr { let bytes = input.into_bigint().to_bytes_le(); - let mut res = ::Repr::default(); + let mut res = ::Repr::default(); for (i, digit) in res.0.as_mut().iter_mut().enumerate() { *digit = bytes[i]; } - let value = FFBn254Fr::from_repr(res); + let value = FFSectFr::from_repr(res); if value.is_some().into() { - Bn254Fr { value: value.unwrap() } + SectFr { value: value.unwrap() } } else { panic!("Invalid field element") } } -pub fn bn254_poseidon2_rc3() -> Vec<[Bn254Fr; 3]> { +pub fn bn254_poseidon2_rc3() -> Vec<[SectFr; 3]> { RC3.iter() .map(|vec| { vec.iter().cloned().map(bn254_from_ark_ff).collect::>().try_into().unwrap() @@ -32,10 +29,10 @@ pub fn bn254_poseidon2_rc3() -> Vec<[Bn254Fr; 3]> { .collect() } -pub fn bn254_poseidon2_rc4() -> Vec<[Bn254Fr; 4]> { +pub fn bn254_poseidon2_rc4() -> Vec<[SectFr; 4]> { RC3.iter() .map(|vec| { - let result: [Bn254Fr; 3] = + let result: [SectFr; 3] = vec.iter().cloned().map(bn254_from_ark_ff).collect::>().try_into().unwrap(); [result[0], result[1], result[2], result[2]] }) diff --git a/crates/recursion/gnark-ffi/go/go.mod b/crates/recursion/gnark-ffi/go/go.mod index a4f4b629e4..b4cda7cd36 100644 --- a/crates/recursion/gnark-ffi/go/go.mod +++ b/crates/recursion/gnark-ffi/go/go.mod @@ -1,6 +1,6 @@ module github.com/succinctlabs/sp1-recursion-gnark -go 1.22.0 +go 1.23.0 require ( github.com/consensys/gnark v0.10.1-0.20240504023521-d9bfacd7cb60 @@ -32,4 +32,6 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/consensys/gnark => github.com/jtguibas/gnark v0.0.0-20240923234830-41125bc1909c +replace github.com/consensys/gnark => github.com/alpenlabs/gnark v0.0.0-20250707125522-2d480d810efb + +replace github.com/consensys/gnark-crypto => github.com/alpenlabs/gnark-crypto v0.0.0-20250521035818-134953372b00 diff --git a/crates/recursion/gnark-ffi/go/go.sum b/crates/recursion/gnark-ffi/go/go.sum index 3f91c58c6d..689cb2b022 100644 --- a/crates/recursion/gnark-ffi/go/go.sum +++ b/crates/recursion/gnark-ffi/go/go.sum @@ -1,11 +1,13 @@ +github.com/alpenlabs/gnark v0.0.0-20250707125522-2d480d810efb h1:X+yy+67rPRtbpY3GIj6+rzCoveYF1Th01j75WaiJeWQ= +github.com/alpenlabs/gnark v0.0.0-20250707125522-2d480d810efb/go.mod h1:0u6evWYINfJpfW9PeqiDycThrEyf5y5KumLRxFTKhWM= +github.com/alpenlabs/gnark-crypto v0.0.0-20250521035818-134953372b00 h1:bOdSFf8NHlW2ZmuG56fFJQRH40ZAud/OdLfZgJJ2j+A= +github.com/alpenlabs/gnark-crypto v0.0.0-20250521035818-134953372b00/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= github.com/bits-and-blooms/bitset v1.14.2 h1:YXVoyPndbdvcEVcseEovVfp0qjJp7S+i5+xgp/Nfbdc= github.com/bits-and-blooms/bitset v1.14.2/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= -github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33 h1:z42ewLaLxoTYeQ17arcF4WExZc/eSaN3YVlF7eEaPt4= github.com/consensys/gnark-ignition-verifier v0.0.0-20230527014722-10693546ab33/go.mod h1:JdKor28c/KR4BbznP88bz8AAvnCgovzrB3KWsiR7lwk= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -23,8 +25,6 @@ github.com/ingonyama-zk/icicle v1.1.0 h1:a2MUIaF+1i4JY2Lnb961ZMvaC8GFs9GqZgSnd9e github.com/ingonyama-zk/icicle v1.1.0/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= -github.com/jtguibas/gnark v0.0.0-20240923234830-41125bc1909c h1:vaqr8feWdNWKvsApw7iBhgbTznreKg+YvNAsbvqvwow= -github.com/jtguibas/gnark v0.0.0-20240923234830-41125bc1909c/go.mod h1:2LbheIOxsBI1a9Ck1XxUoy6PRnH28mSI9qrvtN2HwDY= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= diff --git a/crates/recursion/gnark-ffi/go/sp1/build.go b/crates/recursion/gnark-ffi/go/sp1/build.go index f987dd58c7..2b857428b3 100644 --- a/crates/recursion/gnark-ffi/go/sp1/build.go +++ b/crates/recursion/gnark-ffi/go/sp1/build.go @@ -1,16 +1,21 @@ package sp1 import ( + "bufio" + "encoding/binary" "encoding/json" "fmt" + "io" "log" "os" "strings" "github.com/consensys/gnark-crypto/ecc" + fr "github.com/consensys/gnark-crypto/ecc/sect/fr" "github.com/consensys/gnark-crypto/kzg" - groth16 "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/plonk" + "github.com/consensys/gnark/constraint" + bcs "github.com/consensys/gnark/constraint/sect" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/frontend/cs/scs" @@ -87,7 +92,7 @@ func BuildPlonk(dataDir string) { circuit := NewCircuit(witnessInput) // Compile the circuit. - scs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit) + scs, err := frontend.Compile(fr.Modulus(), scs.NewBuilder, &circuit) if err != nil { panic(err) } @@ -242,108 +247,213 @@ func BuildPlonk(dataDir string) { } } -func BuildGroth16(dataDir string) { - // Set the environment variable for the constraints file. - // - // TODO: There might be some non-determinism if a single process is running this command - // multiple times. - os.Setenv("CONSTRAINTS_JSON", dataDir+"/"+constraintsJsonFile) - os.Setenv("GROTH16", "1") +// Dump writes the coefficient table and the fully‑expanded R1Cs rows into w. +// Caller decides where w points to (file, buffer, network, …). +// Dump writes the coefficient table and the fully-expanded R1Cs rows into w. +// It is functionally identical to the original version but batches I/O +// through an internal bufio.Writer and uses raw little-endian encodes for +// scalars to avoid reflection overhead in binary.Write. +// +// We do not use WriteTo function to dump r1cs here because it writes +// more than what is needed to be exported to dvsnark +// this extraneous stuff includes gnark exclusive parameters and values, +// which can be excluded, instead we export only the R1CS matrix +// by this function. +func Dump(r1cs *bcs.R1CS, w io.Writer) error { + // Wrap the destination with a large buffered writer (1 MiB; tune as needed). + bw := bufio.NewWriterSize(w, 1<<20) + defer bw.Flush() // ensure everything is pushed downstream + + coeffs := r1cs.Coefficients + rows := r1cs.GetR1Cs() + + // A 4-byte scratch reused for every uint32 we encode. + var scratch [4]byte + + putU32 := func(v uint32) error { + binary.LittleEndian.PutUint32(scratch[:], v) + _, err := bw.Write(scratch[:]) + return err + } + + // 1. Coefficient table --------------------------------------------------- + if err := putU32(uint32(len(coeffs))); err != nil { + return err + } + for _, c := range coeffs { + if _, err := bw.Write(c.Marshal()); err != nil { // 32 bytes each + return err + } + } - // Read the file. - witnessInputPath := dataDir + "/" + groth16WitnessPath - data, err := os.ReadFile(witnessInputPath) - if err != nil { - panic(err) + // 2. Full R1CS rows ------------------------------------------------------ + if err := putU32(uint32(len(rows))); err != nil { + return err } - // Deserialize the JSON data into a slice of Instruction structs - var witnessInput WitnessInput - err = json.Unmarshal(data, &witnessInput) - if err != nil { - panic(err) + dumpLE := func(expr constraint.LinearExpression) error { + for _, t := range expr { + if err := putU32(uint32(t.WireID())); err != nil { + return err + } + if err := putU32(uint32(t.CoeffID())); err != nil { + return err + } + } + return nil } - // Initialize the circuit. - circuit := NewCircuit(witnessInput) + for _, r := range rows { + if err := putU32(uint32(len(r.L))); err != nil { + return err + } + if err := putU32(uint32(len(r.R))); err != nil { + return err + } + if err := putU32(uint32(len(r.O))); err != nil { + return err + } - // Compile the circuit. - r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) - if err != nil { - panic(err) + if err := dumpLE(r.L); err != nil { + return err + } + if err := dumpLE(r.R); err != nil { + return err + } + if err := dumpLE(r.O); err != nil { + return err + } } - // Generate the proving and verifying key. - pk, vk, err := groth16.Setup(r1cs) - if err != nil { - panic(err) + return bw.Flush() // explicit flush + propagate any error +} + +// If `r1cs_cached` exists, convert it to `r1cs_to_dvsnark`; otherwise return false. +func DumpR1CSIfItExists() bool { + // Check input exists + if stat, err := os.Stat("/r1cs_cached"); err != nil { + // doesn't exist or not accessible + return false + } else if stat.Size() < 1024 { + return false } - // Generate proof. - assignment := NewCircuit(witnessInput) - witness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + // Open input + r1cs_fn := "/r1cs_cached" + file, err := os.Open(r1cs_fn) if err != nil { - panic(err) + log.Fatalf("Failed to create file: %v", err) } - proof, err := groth16.Prove(r1cs, pk, witness) + var r1cs bcs.R1CS + bytesRead, err := r1cs.ReadFrom(file) if err != nil { panic(err) } + fmt.Printf("Successfully read %d bytes from %s\n", bytesRead, r1cs_fn) - // Verify proof. - publicWitness, err := witness.Public() + // Create output + new_r1cs_fn := "/r1cs_to_dvsnark" + new_file, err := os.Create(new_r1cs_fn) if err != nil { - panic(err) + log.Fatalf("Failed to create file: %v", err) } - err = groth16.Verify(proof, vk, publicWitness) + defer new_file.Close() + + log.Printf("DumpR1CSIfItExists; Dump to file %s", new_r1cs_fn) + err = Dump(&r1cs, new_file) if err != nil { - panic(err) + log.Fatalf("Failed to dump to file: %v", err) } - // Create the build directory. - os.MkdirAll(dataDir, 0755) + return true +} - // Write the solidity verifier. - solidityVerifierFile, err := os.Create(dataDir + "/" + groth16VerifierContractPath) - if err != nil { - panic(err) +// This function builds r1cs constraints of stark verifier to be used by dv-pari. +// It dumps the same constraints in different format in two files `r1cs_cached` and `r1cs_to_dvsnark`. +// `r1cs_cached`: R1CS in gnark's native format, optimized with extra tricks to reduce memory. +// `r1cs_to_dvsnark`: Same R1CS, but stripped of gnark-specific parameters and stored with a simpler sparse matrix representation. +// +// We opt for a simpler representation for R1CS here because we need to write an equivalent file reader in rust over the dv-pari side. +func BuildGroth16(dataDir string) { + r1cs_dumped := DumpR1CSIfItExists() + if r1cs_dumped { + fmt.Println("r1cs_cache already exists, converted to format r1cs_to_dvsnark") + return } - vk.ExportSolidity(solidityVerifierFile) - // Modify the solidity verifier. - modifyGroth16Verifier(solidityVerifierFile) - defer solidityVerifierFile.Close() + os.Setenv("CONSTRAINTS_JSON", dataDir+"/"+constraintsJsonFile) + os.Setenv("GROTH16", "1") - // Write the R1CS. - r1csFile, err := os.Create(dataDir + "/" + groth16CircuitPath) + // Read the file. + witnessInputPath := dataDir + "/" + groth16WitnessPath + data, err := os.ReadFile(witnessInputPath) if err != nil { panic(err) } - defer r1csFile.Close() - _, err = r1cs.WriteTo(r1csFile) + + // Deserialize the JSON data into a slice of Instruction structs + var witnessInput WitnessInput + err = json.Unmarshal(data, &witnessInput) if err != nil { panic(err) } - // Write the verifier key. - vkFile, err := os.Create(dataDir + "/" + groth16VkPath) + // Initialize the circuit. + circuit := NewCircuit(witnessInput) + + // Compile the circuit. + r1cs, err := frontend.Compile(fr.Modulus(), r1cs.NewBuilder, &circuit) if err != nil { panic(err) } - defer vkFile.Close() - _, err = vk.WriteTo(vkFile) - if err != nil { - panic(err) + + { + // benchmark + nbCoeff := r1cs.GetNbCoefficients() + bytesCoeffTable := nbCoeff * 32 + fmt.Printf("Coeff-table: %d elements ≈ %d bytes\n", + nbCoeff, bytesCoeffTable) + + var nTerms int + + r1cs_contr := r1cs.(*bcs.R1CS) + for _, r := range r1cs_contr.GetR1Cs() { // materialises each row once + nTerms += len(r.L) + len(r.R) + len(r.O) // three linear-expressions + } + + fmt.Printf("Total terms in matrix: %d (≈ %d bytes)\n", + nTerms, nTerms*8) // a Term is 2×uint32 = 8 B + + num_vars := (r1cs.GetNbSecretVariables() + r1cs.GetNbPublicVariables() + r1cs.GetNbInternalVariables()) + naive := 3 * r1cs.GetNbConstraints() * num_vars * 32 + + fmt.Printf("Naive cost num_vars=(%d) num_constraints=(%d) (≈ %d bytes)\n", num_vars, r1cs.GetNbConstraints(), naive) // a Term is 2×uint32 = 8 B } - // Write the proving key. - pkFile, err := os.Create(dataDir + "/" + groth16PkPath) - if err != nil { - panic(err) + { + r1cs_fn := "/r1cs_cached" + file, err := os.Create(r1cs_fn) + if err != nil { + log.Fatalf("Failed to create file: %v", err) + } + defer file.Close() + + bytesWritten, err := r1cs.WriteTo(file) + if err != nil { + panic("err is not nil for solve") + } + fmt.Printf("Successfully wrote %d bytes to %s\n", bytesWritten, r1cs_fn) } - defer pkFile.Close() - err = pk.WriteDump(pkFile) - if err != nil { - panic(err) + + { + r1cs_fn := "/r1cs_to_dvsnark" + file, err := os.Create(r1cs_fn) + if err != nil { + log.Fatalf("Failed to create file: %v", err) + } + defer file.Close() + + r1cs_contr := r1cs.(*bcs.R1CS) + Dump(r1cs_contr, file) } } diff --git a/crates/recursion/gnark-ffi/go/sp1/poseidon2/constants.go b/crates/recursion/gnark-ffi/go/sp1/poseidon2/constants.go index 617d828a68..b8fe5f5262 100644 --- a/crates/recursion/gnark-ffi/go/sp1/poseidon2/constants.go +++ b/crates/recursion/gnark-ffi/go/sp1/poseidon2/constants.go @@ -7,466 +7,339 @@ import ( ) // Poseidon2 round constants for a state consisting of three BN254 field elements. -var rc3 [numExternalRounds + numInternalRounds][width]frontend.Variable +// var rc3 [numExternalRounds + numInternalRounds][width]frontend.Variable // Poseidon2 round constraints for a state consisting of 16 BabyBear field elements. var rc16 [30][BABYBEAR_WIDTH]babybear.Variable func init() { - init_rc3() init_rc16() } -func init_rc3() { - round := 0 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816"), - frontend.Variable("0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610"), - frontend.Variable("0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5"), - frontend.Variable("0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28"), - frontend.Variable("0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a"), - frontend.Variable("0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d"), - frontend.Variable("0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4"), - frontend.Variable("0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e"), - frontend.Variable("0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000000000"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0"), - frontend.Variable("0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5"), - frontend.Variable("0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d"), - frontend.Variable("0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e"), - frontend.Variable("0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1"), - frontend.Variable("0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe"), - frontend.Variable("0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166"), - } - round += 1 - - rc3[round] = [width]frontend.Variable{ - frontend.Variable("0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce"), - frontend.Variable("0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57"), - frontend.Variable("0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6"), - } +// Poseidon2 round constants for Sect233k1 field elements. +// copied from `crates::p3-sect-fr::params::RC3` +var rc3 [numExternalRounds + numInternalRounds][width]frontend.Variable = [64][3]frontend.Variable{ + { + frontend.Variable("0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97"), + frontend.Variable("0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d3"), + frontend.Variable("0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0"), + }, + { + frontend.Variable("0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded8"), + frontend.Variable("0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595"), + frontend.Variable("0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c90"), + }, + { + frontend.Variable("0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae150"), + frontend.Variable("0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd6551561"), + frontend.Variable("0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8"), + }, + { + frontend.Variable("0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a"), + frontend.Variable("0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d81"), + frontend.Variable("0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ff"), + }, + { + frontend.Variable("0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f235"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd3838313"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e6"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a53"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945db"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a9"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb1"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829b"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f694"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b460682"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef68522"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2f"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f77"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f752601"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7e"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706c"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f1037"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a58"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17d"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438d"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea1"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6e"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d8"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311b"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde22999"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + frontend.Variable("0x0000000000000000000000000000000000000000000000000000000000"), + }, + { + frontend.Variable("0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8"), + frontend.Variable("0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a"), + frontend.Variable("0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b"), + }, + { + frontend.Variable("0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224"), + frontend.Variable("0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28"), + frontend.Variable("0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9"), + }, + { + frontend.Variable("0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb"), + frontend.Variable("0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b"), + frontend.Variable("0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af"), + }, + { + frontend.Variable("0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961"), + frontend.Variable("0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e"), + frontend.Variable("0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c"), + }, } func init_rc16() { diff --git a/crates/recursion/gnark-ffi/go/sp1/prove.go b/crates/recursion/gnark-ffi/go/sp1/prove.go index 270040396e..01991c67f6 100644 --- a/crates/recursion/gnark-ffi/go/sp1/prove.go +++ b/crates/recursion/gnark-ffi/go/sp1/prove.go @@ -4,14 +4,17 @@ import ( "bufio" "encoding/json" "fmt" + "log" "os" "sync" "time" "github.com/consensys/gnark-crypto/ecc" + fr "github.com/consensys/gnark-crypto/ecc/sect/fr" "github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/constraint" + bcs "github.com/consensys/gnark/constraint/sect" "github.com/consensys/gnark/frontend" ) @@ -95,7 +98,90 @@ func ProvePlonk(dataDir string, witnessPath string) Proof { return NewSP1PlonkBn254Proof(&proof, witnessInput) } +// Generates full witness vector using stark proof present in witnessPath +func SaveWitnessToFile(witnessPath string) { + + r1cs_fn := "/r1cs_cached" + file, err := os.Open(r1cs_fn) + if err != nil { + log.Fatalf("Failed to create file: %v", err) + } + var r1cs bcs.R1CS + bytesRead, err := r1cs.ReadFrom(file) + if err != nil { + panic(err) + } + fmt.Printf("Successfully read %d bytes from %s\n", bytesRead, r1cs_fn) + + start := time.Now() + // Read the file. + data, err := os.ReadFile(witnessPath) + if err != nil { + panic(err) + } + + start = time.Now() + // Deserialize the JSON data into a slice of Instruction structs + var witnessInput WitnessInput + err = json.Unmarshal(data, &witnessInput) + if err != nil { + panic(err) + } + fmt.Printf("Deserializing JSON data took %s\n", time.Since(start)) + + start = time.Now() + // Generate the witness. + assignment := NewCircuit(witnessInput) + witness, err := frontend.NewWitness(&assignment, fr.Modulus()) + if err != nil { + panic(err) + } + fmt.Printf("Generating witness took %s\n", time.Since(start)) + + _solution, err := r1cs.Solve(witness) + if err != nil { + panic(err) + } + solution := _solution.(*bcs.R1CSSolution) + + witness_fn := "/witness_to_dvsnark" + wfile, err := os.Create(witness_fn) + if err != nil { + log.Fatalf("Failed to create file: %v", err) + } + defer wfile.Close() + + bytesWritten, err := solution.W.WriteTo(wfile) + if err != nil { + log.Fatalf("Failed to write to file: %v", err) + } + + fmt.Printf("Successfully wrote %d bytes to %s\n", bytesWritten, witness_fn) + +} + +// Generate and Write Witness, that satisfies R1CS, to the file `witness_to_dvsnark`. +// `witnessPath` includes public and private values (which includes stark proof). +// but it doesn't include the full witness vector. +// The purpose of this function is to generate witness in full using the R1CS matrix. +// As such this function expects `r1cs_cached`, where R1CS matrix was previously dumped func ProveGroth16(dataDir string, witnessPath string) Proof { + + fmt.Println("start SaveWitnessToFile") + + SaveWitnessToFile(witnessPath) + + fmt.Println("finished SaveWitnessToFile") + + return Proof{ + PublicInputs: [2]string{"", ""}, + EncodedProof: "", + RawProof: "", + } +} + +// Previous implementation of ProveGroth16, only name changed +func ProveGroth16Old(dataDir string, witnessPath string) Proof { // Sanity check the required arguments have been provided. if dataDir == "" { panic("dataDirStr is required") diff --git a/crates/recursion/gnark-ffi/go/sp1/utils.go b/crates/recursion/gnark-ffi/go/sp1/utils.go index a542b34727..94c2ef2017 100644 --- a/crates/recursion/gnark-ffi/go/sp1/utils.go +++ b/crates/recursion/gnark-ffi/go/sp1/utils.go @@ -68,10 +68,10 @@ func NewCircuit(witnessInput WitnessInput) Circuit { exts[i] = babybear.NewE(witnessInput.Exts[i]) } return Circuit{ - VkeyHash: witnessInput.VkeyHash, + VkeyHash: witnessInput.VkeyHash, CommittedValuesDigest: witnessInput.CommittedValuesDigest, - Vars: vars, - Felts: felts, - Exts: exts, + Vars: vars, + Felts: felts, + Exts: exts, } } diff --git a/crates/recursion/gnark-ffi/go/sp1/verify.go b/crates/recursion/gnark-ffi/go/sp1/verify.go index 3d53fad71c..c0de53a4ef 100644 --- a/crates/recursion/gnark-ffi/go/sp1/verify.go +++ b/crates/recursion/gnark-ffi/go/sp1/verify.go @@ -38,10 +38,10 @@ func VerifyPlonk(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkeyHa // Compute the public witness. circuit := Circuit{ - Vars: []frontend.Variable{}, - Felts: []babybear.Variable{}, - Exts: []babybear.ExtensionVariable{}, - VkeyHash: verifyCmdVkeyHash, + Vars: []frontend.Variable{}, + Felts: []babybear.Variable{}, + Exts: []babybear.ExtensionVariable{}, + VkeyHash: verifyCmdVkeyHash, CommittedValuesDigest: verifyCmdCommittedValuesDigest, } witness, err := frontend.NewWitness(&circuit, ecc.BN254.ScalarField()) @@ -84,10 +84,10 @@ func VerifyGroth16(verifyCmdDataDir string, verifyCmdProof string, verifyCmdVkey // Compute the public witness. circuit := Circuit{ - Vars: []frontend.Variable{}, - Felts: []babybear.Variable{}, - Exts: []babybear.ExtensionVariable{}, - VkeyHash: verifyCmdVkeyHash, + Vars: []frontend.Variable{}, + Felts: []babybear.Variable{}, + Exts: []babybear.ExtensionVariable{}, + VkeyHash: verifyCmdVkeyHash, CommittedValuesDigest: verifyCmdCommittedValuesDigest, } witness, err := frontend.NewWitness(&circuit, ecc.BN254.ScalarField()) diff --git a/crates/recursion/gnark-ffi/src/ffi/docker.rs b/crates/recursion/gnark-ffi/src/ffi/docker.rs index 22ff593f7c..fe95fc3c7a 100644 --- a/crates/recursion/gnark-ffi/src/ffi/docker.rs +++ b/crates/recursion/gnark-ffi/src/ffi/docker.rs @@ -1,6 +1,6 @@ use crate::{Groth16Bn254Proof, PlonkBn254Proof, ProofBn254, SP1_CIRCUIT_VERSION}; use anyhow::{anyhow, Result}; -use std::{io::Write, process::Command}; +use std::{fs::File, io::Write, process::Command}; /// Represents the proof system being used enum ProofSystem { @@ -30,6 +30,7 @@ fn assert_docker() { } } +#[allow(dead_code)] fn get_docker_image() -> String { std::env::var("SP1_GNARK_IMAGE") .unwrap_or_else(|_| format!("ghcr.io/succinctlabs/sp1-gnark:{}", SP1_CIRCUIT_VERSION)) @@ -40,16 +41,43 @@ fn get_docker_image() -> String { /// Note: files created here by `call_docker` are read-only for after the process exits. /// To fix this, manually set the docker user to the current user by supplying a `-u` flag. fn call_docker(args: &[&str], mounts: &[(&str, &str)]) -> Result<()> { + tracing::info!("Calling docer {:?}", args); tracing::info!("Running {} in docker", args[0]); let mut cmd = Command::new("docker"); - cmd.args(["run", "--rm"]); + cmd.args(["run"]); for (src, dest) in mounts { cmd.arg("-v").arg(format!("{}:{}", src, dest)); } - cmd.arg(get_docker_image()); + + let home = std::env::home_dir().expect("Failed to find the home directory."); + let circuits_dir = home.join(".sp1/circuits"); + let r1cs_to_dvsnark_path = circuits_dir.join("r1cs_to_dvsnark"); // r1cs dump export to dv-pari + let r1cs_cached_path = circuits_dir.join("r1cs_cached"); // r1cs dump gnark format + let witness_to_dvsnark_path = circuits_dir.join("witness_to_dvsnark"); // witness dump export to dv-pari + + let paths_to_create = [&r1cs_to_dvsnark_path, &r1cs_cached_path, &witness_to_dvsnark_path]; + + // Iterate over the paths and create a file if it doesn't exist. + for path in &paths_to_create { + if !path.exists() { + // File::create will create the file or truncate it if it exists. + // Since we check for existence first, it will only create it. + File::create(path)?; + tracing::info!("Created file: {:?}", path); + } + } + + cmd.arg("-v").arg(format!("{}:{}", r1cs_to_dvsnark_path.to_string_lossy(), "/r1cs_to_dvsnark")); + cmd.arg("-v").arg(format!("{}:{}", r1cs_cached_path.to_string_lossy(), "/r1cs_cached")); + cmd.arg("-v").arg(format!( + "{}:{}", + witness_to_dvsnark_path.to_string_lossy(), + "/witness_to_dvsnark" + )); + + cmd.arg("sp1-gnark:latest"); // custom sp1-gnark docker image to dump r1cs and witness required by dv-pari cmd.args(args); - cmd.stdout(std::process::Stdio::piped()); - cmd.stderr(std::process::Stdio::piped()); + tracing::info!("Command {:?}", cmd); let result = cmd.output()?; if !result.status.success() { let stderr = String::from_utf8_lossy(&result.stderr); @@ -100,6 +128,10 @@ pub fn prove_groth16_bn254(data_dir: &str, witness_path: &str) -> Groth16Bn254Pr } } +pub fn prove_witness_sect(data_dir: &str, witness_path: &str) { + let _ = prove(ProofSystem::Groth16, data_dir, witness_path); +} + fn build(system: ProofSystem, data_dir: &str) -> Result<()> { let circuit_dir = if data_dir.ends_with("dev") { "/circuit_dev" } else { "/circuit" }; let mounts = [(data_dir, circuit_dir)]; diff --git a/crates/recursion/gnark-ffi/src/ffi/native.rs b/crates/recursion/gnark-ffi/src/ffi/native.rs index dbc0650238..2961ebce13 100644 --- a/crates/recursion/gnark-ffi/src/ffi/native.rs +++ b/crates/recursion/gnark-ffi/src/ffi/native.rs @@ -176,6 +176,10 @@ pub fn prove_groth16_bn254(data_dir: &str, witness_path: &str) -> Groth16Bn254Pr } } +pub fn prove_witness_sect(data_dir: &str, witness_path: &str) { + prove(ProofSystem::Groth16, data_dir, witness_path); +} + pub fn verify_groth16_bn254( data_dir: &str, proof: &str, diff --git a/crates/recursion/gnark-ffi/src/groth16_bn254.rs b/crates/recursion/gnark-ffi/src/groth16_bn254.rs index 20f7ad37e3..b6990293e0 100644 --- a/crates/recursion/gnark-ffi/src/groth16_bn254.rs +++ b/crates/recursion/gnark-ffi/src/groth16_bn254.rs @@ -86,7 +86,8 @@ impl Groth16Bn254Prover { build_groth16_bn254(build_dir.to_str().unwrap()); // Build the contracts. - Self::build_contracts(build_dir); + // Self::build_contracts(build_dir); // commented because we can't build solidity contracts + // for sect233k1 dv-pari system } /// Generates a Groth16 proof given a witness. diff --git a/crates/recursion/gnark-ffi/src/lib.rs b/crates/recursion/gnark-ffi/src/lib.rs index 0aa5c40e60..403bae2eea 100644 --- a/crates/recursion/gnark-ffi/src/lib.rs +++ b/crates/recursion/gnark-ffi/src/lib.rs @@ -4,11 +4,13 @@ pub mod ffi; pub mod groth16_bn254; pub mod plonk_bn254; pub mod proof; +pub mod sect_wit_gen; pub mod witness; pub use groth16_bn254::*; pub use plonk_bn254::*; pub use proof::*; +pub use sect_wit_gen::*; pub use witness::*; /// The global version for all components of SP1. diff --git a/crates/recursion/gnark-ffi/src/proof.rs b/crates/recursion/gnark-ffi/src/proof.rs index fa71022f42..ed90e239cb 100644 --- a/crates/recursion/gnark-ffi/src/proof.rs +++ b/crates/recursion/gnark-ffi/src/proof.rs @@ -21,3 +21,6 @@ pub struct Groth16Bn254Proof { pub raw_proof: String, pub groth16_vkey_hash: [u8; 32], } + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct SectWitness {} diff --git a/crates/recursion/gnark-ffi/src/sect_wit_gen.rs b/crates/recursion/gnark-ffi/src/sect_wit_gen.rs new file mode 100644 index 0000000000..12c752e762 --- /dev/null +++ b/crates/recursion/gnark-ffi/src/sect_wit_gen.rs @@ -0,0 +1,22 @@ +use std::{io::Write, path::PathBuf}; + +use sp1_recursion_compiler::ir::{Config, Witness}; + +use crate::{ffi::prove_witness_sect, GnarkWitness, SectWitness}; + +#[derive(Debug, Clone, Default)] +pub struct SectWitnessGenerator; + +impl SectWitnessGenerator { + // referenced from Groth16Bn254Prover::prove + pub fn prove(&self, witness: Witness, build_dir: PathBuf) -> SectWitness { + // Write witness. + let mut witness_file = tempfile::NamedTempFile::new().unwrap(); + let gnark_witness = GnarkWitness::new(witness); + let serialized = serde_json::to_string(&gnark_witness).unwrap(); + witness_file.write_all(serialized.as_bytes()).unwrap(); + + prove_witness_sect(build_dir.to_str().unwrap(), witness_file.path().to_str().unwrap()); + SectWitness {} + } +} diff --git a/crates/sdk/src/cpu/mod.rs b/crates/sdk/src/cpu/mod.rs index 9de4479030..a2cc36af04 100644 --- a/crates/sdk/src/cpu/mod.rs +++ b/crates/sdk/src/cpu/mod.rs @@ -9,14 +9,15 @@ pub mod prove; use anyhow::Result; use execute::CpuExecuteBuilder; use prove::CpuProveBuilder; -use sp1_core_executor::{SP1Context, SP1ContextBuilder}; +use sp1_core_executor::{SP1Context, SP1ContextBuilder, SP1ReduceProof}; use sp1_core_machine::io::SP1Stdin; use sp1_prover::{ components::CpuProverComponents, verify::{verify_groth16_bn254_public_inputs, verify_plonk_bn254_public_inputs}, Groth16Bn254Proof, PlonkBn254Proof, SP1CoreProofData, SP1ProofWithMetadata, SP1Prover, + SP1PublicValues, }; -use sp1_stark::{SP1CoreOpts, SP1ProverOpts}; +use sp1_stark::{baby_bear_poseidon2::BabyBearPoseidon2, SP1CoreOpts, SP1ProverOpts}; use crate::{ install::try_install_circuit_artifacts, prover::verify_proof, Prover, SP1Proof, SP1ProofMode, @@ -83,6 +84,14 @@ impl CpuProver { /// let (pk, vk) = client.setup(elf); /// let builder = client.prove(&pk, &stdin).core().run(); /// ``` + /// # Fields + /// - `init_with_compressed`: if true, stdin should include compressed proof, else raw + /// pulbic inputs as it was previously + /// The purpose of `init_with_compressed` is to make it possible to have the heavy part of the + /// proving, which includes core and compressed proof generation, be done in SP1 cluster, + /// while the cheaper part, which is generating SNARK, be done locally. This is necessary in + /// our use case because our fork only makes change to the `OuterProof` (wrapping SNARK) and + /// not the Inner Proof. pub fn prove<'a>(&'a self, pk: &'a SP1ProvingKey, stdin: &SP1Stdin) -> CpuProveBuilder<'a> { CpuProveBuilder { prover: self, @@ -93,9 +102,12 @@ impl CpuProver { core_opts: SP1CoreOpts::default(), recursion_opts: SP1CoreOpts::recursion(), mock: self.mock, + init_with_compressed: false, } } + /// `input_is_compressed_proof` is set to true when the user has passed compressed proof + /// directly as input. pub(crate) fn prove_impl<'a>( &'a self, pk: &SP1ProvingKey, @@ -103,37 +115,56 @@ impl CpuProver { opts: SP1ProverOpts, context: SP1Context<'a>, mode: SP1ProofMode, + input_is_compressed_proof: bool, ) -> Result { - let program = self.prover.get_program(&pk.elf).unwrap(); + tracing::info!("input_is_compressed_proof {input_is_compressed_proof}"); + // If true, read compressed proof from stdin + let (reduce_proof, public_values) = if input_is_compressed_proof { + let compressed_proof_bytes = &stdin.buffer; + assert_eq!(compressed_proof_bytes.len(), 1); + let reduce_proof: SP1ReduceProof = + serde_json::from_slice(&compressed_proof_bytes[0])?; + // here, the user has directly passed the compressed proof as input to be wrapped, + // he already possesses SP1PublicValues while generating the compressed proof itself, + // so you can return empty + (reduce_proof, SP1PublicValues::default()) + } else { + // If false, compute compressed proof + let program = self.prover.get_program(&pk.elf).unwrap(); - // If we're in mock mode, return a mock proof. - if self.mock { - return self.mock_prove_impl(pk, stdin, context, mode); - } + // If we're in mock mode, return a mock proof. + if self.mock { + return self.mock_prove_impl(pk, stdin, context, mode); + } - // Generate the core proof. - let proof: SP1ProofWithMetadata = - self.prover.prove_core(&pk.pk, program, stdin, opts, context)?; - if mode == SP1ProofMode::Core { - return Ok(SP1ProofWithPublicValues::new( - SP1Proof::Core(proof.proof.0), - proof.public_values, - self.version().to_string(), - )); - } + // Generate the core proof. + let proof: SP1ProofWithMetadata = + self.prover.prove_core(&pk.pk, program, stdin, opts, context)?; + tracing::info!("public values {:?}", proof.public_values); + if mode == SP1ProofMode::Core { + return Ok(SP1ProofWithPublicValues::new( + SP1Proof::Core(proof.proof.0), + proof.public_values, + self.version().to_string(), + )); + } - // Generate the compressed proof. - let deferred_proofs = - stdin.proofs.iter().map(|(reduce_proof, _)| reduce_proof.clone()).collect(); - let public_values = proof.public_values.clone(); - let reduce_proof = self.prover.compress(&pk.vk, proof, deferred_proofs, opts)?; - if mode == SP1ProofMode::Compressed { - return Ok(SP1ProofWithPublicValues::new( - SP1Proof::Compressed(Box::new(reduce_proof)), - public_values, - self.version().to_string(), - )); - } + // Generate the compressed proof. + let deferred_proofs = + stdin.proofs.iter().map(|(reduce_proof, _)| reduce_proof.clone()).collect(); + let public_values = proof.public_values.clone(); + let reduce_proof: SP1ReduceProof = + self.prover.compress(&pk.vk, proof, deferred_proofs, opts)?; + if mode == SP1ProofMode::Compressed { + return Ok(SP1ProofWithPublicValues::new( + SP1Proof::Compressed(Box::new(reduce_proof)), + public_values, + self.version().to_string(), + )); + }; + // return public_values as well so that it can be returned alongside wrapped proof + (reduce_proof, public_values) + }; // Generate the shrink proof. let compress_proof = self.prover.shrink(reduce_proof, opts)?; @@ -144,19 +175,17 @@ impl CpuProver { // Generate the gnark proof. match mode { SP1ProofMode::Groth16 => { - let groth16_bn254_artifacts = if sp1_prover::build::sp1_dev_mode() { + let groth16_bn254_artifacts = sp1_prover::build::try_build_groth16_bn254_artifacts_dev( &outer_proof.vk, &outer_proof.proof, - ) - } else { - try_install_circuit_artifacts("groth16") - }; + ); - let proof = self.prover.wrap_groth16_bn254(outer_proof, &groth16_bn254_artifacts); + let _sect_witness = self.prover.wrap_sect(outer_proof, &groth16_bn254_artifacts); Ok(SP1ProofWithPublicValues::new( - SP1Proof::Groth16(proof), - public_values, + SP1Proof::Core(vec![]), + public_values, /* return raw public values as it will be needed to verify + * public input again r1cs witness */ self.version().to_string(), )) } @@ -172,7 +201,7 @@ impl CpuProver { let proof = self.prover.wrap_plonk_bn254(outer_proof, &plonk_bn254_artifacts); Ok(SP1ProofWithPublicValues::new( SP1Proof::Plonk(proof), - public_values, + SP1PublicValues::default(), self.version().to_string(), )) } @@ -225,7 +254,7 @@ impl Prover for CpuProver { stdin: &SP1Stdin, mode: SP1ProofMode, ) -> Result { - self.prove_impl(pk, stdin, SP1ProverOpts::default(), SP1Context::default(), mode) + self.prove_impl(pk, stdin, SP1ProverOpts::default(), SP1Context::default(), mode, false) } fn verify( diff --git a/crates/sdk/src/cpu/prove.rs b/crates/sdk/src/cpu/prove.rs index 99014e8327..6544ff8a6f 100644 --- a/crates/sdk/src/cpu/prove.rs +++ b/crates/sdk/src/cpu/prove.rs @@ -24,6 +24,7 @@ pub struct CpuProveBuilder<'a> { pub(crate) core_opts: SP1CoreOpts, pub(crate) recursion_opts: SP1CoreOpts, pub(crate) mock: bool, + pub(crate) init_with_compressed: bool, } impl<'a> CpuProveBuilder<'a> { @@ -122,6 +123,14 @@ impl<'a> CpuProveBuilder<'a> { self } + /// groth16 given compressed proof as input + #[must_use] + pub fn groth16_with_compressed(mut self) -> Self { + self.mode = SP1ProofMode::Groth16; + self.init_with_compressed = true; + self + } + /// Set the proof mode to the given [`SP1ProofKind`]. /// /// # Details @@ -303,8 +312,17 @@ impl<'a> CpuProveBuilder<'a> { /// ``` pub fn run(self) -> Result { // Get the arguments. - let Self { prover, mode, pk, stdin, mut context_builder, core_opts, recursion_opts, mock } = - self; + let Self { + prover, + mode, + pk, + stdin, + mut context_builder, + core_opts, + recursion_opts, + mock, + init_with_compressed, + } = self; let opts = SP1ProverOpts { core_opts, recursion_opts }; let context = context_builder.build(); @@ -315,7 +333,7 @@ impl<'a> CpuProveBuilder<'a> { if mock { prover.mock_prove_impl(pk, &stdin, context, mode) } else { - prover.prove_impl(pk, &stdin, opts, context, mode) + prover.prove_impl(pk, &stdin, opts, context, mode, init_with_compressed) } } } diff --git a/crates/sdk/src/cuda/mod.rs b/crates/sdk/src/cuda/mod.rs index 4e6e399ab0..e436208eb3 100644 --- a/crates/sdk/src/cuda/mod.rs +++ b/crates/sdk/src/cuda/mod.rs @@ -10,7 +10,7 @@ use prove::CudaProveBuilder; use sp1_core_executor::SP1ContextBuilder; use sp1_core_machine::io::SP1Stdin; use sp1_cuda::{MoongateServer, SP1CudaProver}; -use sp1_prover::{components::CpuProverComponents, SP1Prover}; +use sp1_prover::{components::CpuProverComponents, SP1Prover, SP1PublicValues}; use crate::{ cpu::execute::CpuExecuteBuilder, install::try_install_circuit_artifacts, Prover, SP1Proof, @@ -137,19 +137,32 @@ impl CudaProver { ); return Ok((proof_with_pv, cycles)); } else if kind == SP1ProofMode::Groth16 { - let groth16_bn254_artifacts = if sp1_prover::build::sp1_dev_mode() { - sp1_prover::build::try_build_groth16_bn254_artifacts_dev( - &outer_proof.vk, - &outer_proof.proof, - ) - } else { - try_install_circuit_artifacts("groth16") - }; + // let groth16_bn254_artifacts = if sp1_prover::build::sp1_dev_mode() { + // sp1_prover::build::try_build_groth16_bn254_artifacts_dev( + // &outer_proof.vk, + // &outer_proof.proof, + // ) + // } else { + // try_install_circuit_artifacts("groth16") + // }; + + // let proof = self.cpu_prover.wrap_groth16_bn254(outer_proof, + // &groth16_bn254_artifacts); let proof_with_pv = + // SP1ProofWithPublicValues::new( SP1Proof::Groth16(proof), + // public_values, + // self.version().to_string(), + // ); + // return Ok((proof_with_pv, cycles)); + + let groth16_bn254_artifacts = sp1_prover::build::try_build_groth16_bn254_artifacts_dev( + &outer_proof.vk, + &outer_proof.proof, + ); - let proof = self.cpu_prover.wrap_groth16_bn254(outer_proof, &groth16_bn254_artifacts); + let _sect_witness = self.cpu_prover.wrap_sect(outer_proof, &groth16_bn254_artifacts); let proof_with_pv = SP1ProofWithPublicValues::new( - SP1Proof::Groth16(proof), - public_values, + SP1Proof::Core(vec![]), + SP1PublicValues::default(), self.version().to_string(), ); return Ok((proof_with_pv, cycles)); diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index fadca07035..6f25080268 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -69,6 +69,7 @@ mod tests { use sp1_primitives::io::SP1PublicValues; use crate::{utils, Prover, ProverClient, SP1Stdin}; + use sp1_prover::HashableKey; #[test] fn test_execute() { @@ -158,23 +159,43 @@ mod tests { } #[test] - fn test_e2e_prove_plonk() { + #[ignore = "test requires custom gnark image"] + fn test_generate_sect_proof_step_wise() { utils::setup_logger(); + // IRL upto compressed proof is generated by SP1 cluster + // because this is the heavy computation part let client = ProverClient::builder().cpu().build(); - let elf = test_artifacts::FIBONACCI_ELF; + let elf = test_artifacts::FIBONACCI_BLAKE3_ELF; let (pk, vk) = client.setup(elf); - let mut stdin = SP1Stdin::new(); - stdin.write(&10usize); - - // Generate proof & verify. - let mut proof = client.prove(&pk, &stdin).plonk().run().unwrap(); - client.verify(&proof, &vk).unwrap(); + tracing::info!("verification key {:?}", vk.hash_bn254()); + let stdin = SP1Stdin::default(); + let proof = client.prove(&pk, &stdin).compressed().run().unwrap(); + tracing::info!("proof public values {:?}", proof.public_values); + + // Now use the compressed proof returned by SP1 Cluster + // to generate wrapped proof (only sect witness) locally + // This can't be offloaded to SP1 cluster now because + // cluster doesn't handle forked code + let compressed_proof_bytes = proof.bytes(); + let mut st = SP1Stdin::default(); + st.write_slice(&compressed_proof_bytes); + let client = ProverClient::builder().cpu().build(); + let elf = test_artifacts::FIBONACCI_BLAKE3_ELF; + let (pk, _) = client.setup(elf); + let _ = client.prove(&pk, &st).groth16_with_compressed().run().unwrap(); + } - // Test invalid public values. - proof.public_values = SP1PublicValues::from(&[255, 4, 84]); - if client.verify(&proof, &vk).is_ok() { - panic!("verified proof with invalid public values") - } + #[test] + #[ignore = "test requires custom gnark image"] + fn test_generate_sect_proof_single_step() { + utils::setup_logger(); + let client = ProverClient::builder().cpu().build(); + let elf = test_artifacts::FIBONACCI_BLAKE3_ELF; + let (pk, vk) = client.setup(elf); + tracing::info!("verification key {:?}", vk.hash_bn254()); + let stdin = SP1Stdin::default(); + let proof = client.prove(&pk, &stdin).groth16().run().unwrap(); + tracing::info!("proof public values {:?}", proof.public_values); } #[test] diff --git a/crates/sdk/src/proof.rs b/crates/sdk/src/proof.rs index 9d84921b9c..11af570039 100644 --- a/crates/sdk/src/proof.rs +++ b/crates/sdk/src/proof.rs @@ -172,6 +172,7 @@ impl SP1ProofWithPublicValues { [groth16_proof.groth16_vkey_hash[..4].to_vec(), proof_bytes].concat() } + SP1Proof::Compressed(compressed_proof) => serde_json::to_vec(compressed_proof).unwrap(), proof => panic!( "Proof type {proof} is not supported for onchain verification. \ Only Plonk and Groth16 proofs are verifiable onchain" diff --git a/crates/verifier/guest-verify-programs/Cargo.lock b/crates/verifier/guest-verify-programs/Cargo.lock index 11247142a8..1f0e1d46bd 100644 --- a/crates/verifier/guest-verify-programs/Cargo.lock +++ b/crates/verifier/guest-verify-programs/Cargo.lock @@ -2032,21 +2032,6 @@ dependencies = [ "serde", ] -[[package]] -name = "p3-bn254-fr" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0dd4d095d254783098bd09fc5fdf33fd781a1be54608ab93cb3ed4bd723da54" -dependencies = [ - "ff 0.13.1", - "num-bigint 0.4.6", - "p3-field", - "p3-poseidon2", - "p3-symmetric", - "rand 0.8.5", - "serde", -] - [[package]] name = "p3-challenger" version = "0.2.3-succinct" @@ -2216,6 +2201,24 @@ dependencies = [ "serde", ] +[[package]] +name = "p3-sect-fr" +version = "5.0.0" +dependencies = [ + "ark-ff", + "ff 0.13.1", + "lazy_static", + "num-bigint 0.4.6", + "num-traits", + "p3-field", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.5", + "serde", + "serde_json", + "zkhash", +] + [[package]] name = "p3-symmetric" version = "0.2.3-succinct" @@ -3312,11 +3315,11 @@ dependencies = [ "lru", "num-bigint 0.4.6", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-field", "p3-matrix", + "p3-sect-fr", "p3-symmetric", "p3-util", "rayon", @@ -3347,13 +3350,13 @@ dependencies = [ "num-traits", "p3-air", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-dft", "p3-field", "p3-fri", "p3-matrix", + "p3-sect-fr", "p3-symmetric", "p3-uni-stark", "p3-util", @@ -3378,8 +3381,8 @@ dependencies = [ "backtrace", "itertools 0.13.0", "p3-baby-bear", - "p3-bn254-fr", "p3-field", + "p3-sect-fr", "p3-symmetric", "serde", "sp1-core-machine", @@ -3406,7 +3409,6 @@ dependencies = [ "num_cpus", "p3-air", "p3-baby-bear", - "p3-bn254-fr", "p3-challenger", "p3-commit", "p3-dft", @@ -3416,6 +3418,7 @@ dependencies = [ "p3-maybe-rayon", "p3-merkle-tree", "p3-poseidon2", + "p3-sect-fr", "p3-symmetric", "p3-util", "pathdiff", diff --git a/patch-testing/Cargo.lock b/patch-testing/Cargo.lock index 65c3ca0b70..55dd6935e2 100644 --- a/patch-testing/Cargo.lock +++ b/patch-testing/Cargo.lock @@ -2688,17 +2688,18 @@ dependencies = [ ] [[package]] -name = "p3-bn254-fr" -version = "0.2.2-succinct" -source = "git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix#e780dafcdbd9560b41e248d061837d3000ebdd15" +name = "p3-bls12-fr" +version = "4.2.1" dependencies = [ "ff 0.13.0", "num-bigint 0.4.6", - "p3-field 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-poseidon2 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-symmetric 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", + "num-traits", + "p3-field", + "p3-poseidon2", + "p3-symmetric", "rand", "serde", + "serde_json", ] [[package]] @@ -2930,6 +2931,24 @@ dependencies = [ "serde", ] +[[package]] +name = "p3-sect-fr" +version = "4.2.1" +dependencies = [ + "ark-ff", + "ff 0.13.0", + "lazy_static", + "num-bigint 0.4.6", + "num-traits", + "p3-field", + "p3-poseidon2", + "p3-symmetric", + "rand", + "serde", + "serde_json", + "zkhash", +] + [[package]] name = "p3-symmetric" version = "0.2.2-succinct" @@ -4313,14 +4332,14 @@ dependencies = [ "itertools 0.13.0", "lru", "num-bigint 0.4.6", - "p3-baby-bear 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-bn254-fr", + "p3-baby-bear", + "p3-bls12-fr", "p3-challenger", "p3-commit", - "p3-field 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-matrix 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-symmetric 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-util 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", "rayon", "serde", "serde_json", @@ -4348,15 +4367,15 @@ dependencies = [ "itertools 0.13.0", "num-traits", "p3-air", - "p3-baby-bear 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-bn254-fr", + "p3-baby-bear", + "p3-bls12-fr", "p3-challenger", "p3-commit", "p3-dft 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", "p3-field 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", "p3-fri", - "p3-matrix 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-symmetric 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", + "p3-matrix", + "p3-symmetric", "p3-uni-stark", "p3-util 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", "rand", @@ -4379,10 +4398,11 @@ version = "5.0.0" dependencies = [ "backtrace", "itertools 0.13.0", - "p3-baby-bear 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-bn254-fr", - "p3-field 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-symmetric 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", + "p3-baby-bear", + "p3-bls12-fr", + "p3-field", + "p3-sect-fr", + "p3-symmetric", "serde", "sp1-core-machine", "sp1-primitives 5.0.0", @@ -4407,8 +4427,8 @@ dependencies = [ "itertools 0.13.0", "num_cpus", "p3-air", - "p3-baby-bear 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-bn254-fr", + "p3-baby-bear", + "p3-bls12-fr", "p3-challenger", "p3-commit", "p3-dft 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", @@ -4417,9 +4437,9 @@ dependencies = [ "p3-matrix 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", "p3-maybe-rayon 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", "p3-merkle-tree", - "p3-poseidon2 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-symmetric 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", - "p3-util 0.2.2-succinct (git+https://github.com/succinctlabs/plonky3-private?branch=min%2Fp3-vuln-fix)", + "p3-poseidon2", + "p3-symmetric", + "p3-util", "pathdiff", "rand", "serde", diff --git a/patch-testing/rustcrypto-bigint/program/bin/mul_mod_special.rs b/patch-testing/rustcrypto-bigint/program/bin/mul_mod_special.rs index 5f73dfec7e..46ffb1e20c 100644 --- a/patch-testing/rustcrypto-bigint/program/bin/mul_mod_special.rs +++ b/patch-testing/rustcrypto-bigint/program/bin/mul_mod_special.rs @@ -9,11 +9,13 @@ pub fn main() { for _ in 0..times { let a: [u32; 8] = sp1_lib::io::read::>().try_into().unwrap(); let b: [u32; 8] = sp1_lib::io::read::>().try_into().unwrap(); + let a: [u64; 8] = a.map(|x| x as u64); + let b: [u64; 8] = b.map(|x| x as u64); let a = Uint::<8>::from_words(a); let b = Uint::<8>::from_words(b); let c: u32 = 356u32; - let c = Limb(c); + let c = Limb(c.into()); let result = a.mul_mod_special(&b, c); sp1_lib::io::commit(&result.to_be_bytes().to_vec());