diff --git a/Cargo.toml b/Cargo.toml index de780d8d5a..a27bd3f934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,6 +137,7 @@ openvm-rv32-adapters = { path = "extensions/rv32-adapters", default-features = f openvm-rv32im-circuit = { path = "extensions/rv32im/circuit", default-features = false } openvm-rv32im-transpiler = { path = "extensions/rv32im/transpiler", default-features = false } openvm-rv32im-guest = { path = "extensions/rv32im/guest", default-features = false } +openvm-snark-verifier = { path = "extensions/verifier", default-features = false } # Plonky3 p3-air = { git = "https://github.com/Plonky3/Plonky3.git", rev = "9b267c4" } diff --git a/extensions/verifier/Cargo.toml b/extensions/verifier/Cargo.toml index fd22ecdfbd..949e42d6e1 100644 --- a/extensions/verifier/Cargo.toml +++ b/extensions/verifier/Cargo.toml @@ -12,7 +12,7 @@ openvm-pairing-guest = { workspace = true, features = [ ] } openvm-keccak256-guest = { workspace = true, default-features = false } openvm-ecc-guest = { workspace = true, features = ["halo2curves"] } -snark-verifier = { git = "https://github.com/axiom-crypto/snark-verifier.git", tag = "v0.1.7-git", default-features = false, features = ["halo2-axiom"] } +snark-verifier-sdk = { workspace = true, default-features = false, features = ["halo2-axiom", "loader_evm"] } ff = { workspace = true } halo2curves-axiom = { workspace = true } itertools.workspace = true diff --git a/extensions/verifier/src/verifier/loader.rs b/extensions/verifier/src/verifier/loader.rs index 6a37562739..94fee3b3a8 100644 --- a/extensions/verifier/src/verifier/loader.rs +++ b/extensions/verifier/src/verifier/loader.rs @@ -3,22 +3,23 @@ use std::{fmt::Debug, marker::PhantomData}; use halo2curves_axiom::bn256::{Bn256, Fq as Halo2Fp, Fr as Halo2Fr, G1Affine, G2Affine}; +use itertools::Itertools; use lazy_static::lazy_static; use openvm_ecc_guest::{ algebra::{field::FieldExtension, IntMod}, msm, AffinePoint, }; use openvm_pairing_guest::{ - affine_point::AffineCoords, bn254::{Bn254, Bn254Fp as Fp, Bn254G1Affine as EcPoint, Fp2, Scalar as Fr}, pairing::PairingCheck, }; -use snark_verifier::{ +use snark_verifier_sdk::snark_verifier::{ loader::{EcPointLoader, Loader, ScalarLoader}, pcs::{ - kzg::{KzgAccumulator, KzgAs, KzgDecidingKey}, - AccumulationDecider, + kzg::{KzgAccumulator, KzgAs, KzgDecidingKey, LimbsEncoding}, + AccumulationDecider, AccumulatorEncoding, }, + util::arithmetic::fe_from_limbs, Error, }; @@ -31,13 +32,59 @@ lazy_static! { #[derive(Clone, Debug)] pub struct OpenVmLoader; +impl AccumulatorEncoding + for LimbsEncoding +{ + type Accumulator = KzgAccumulator; + + fn from_repr(limbs: &[&OpenVmScalar]) -> Result { + assert_eq!(limbs.len(), 4 * LIMBS); + + let [lhs_x, lhs_y, rhs_x, rhs_y]: [_; 4] = limbs + .chunks(LIMBS) + .map(|limbs| { + let v: [Halo2Fr; LIMBS] = limbs + .iter() + .map(|limb| { + let mut buf = limb.0.to_be_bytes(); + buf.reverse(); + Halo2Fr::from_bytes(&buf).expect("Halo2Fr::from_bytes") + }) + .collect_vec() + .try_into() + .unwrap(); + fe_from_limbs::<_, Halo2Fp, LIMBS, BITS>(v) + }) + .collect_vec() + .try_into() + .unwrap(); + let accumulator = KzgAccumulator::new( + OpenVmEcPoint( + EcPoint { + x: Fp::from_le_bytes(&lhs_x.to_bytes()), + y: Fp::from_le_bytes(&lhs_y.to_bytes()), + }, + PhantomData, + ), + OpenVmEcPoint( + EcPoint { + x: Fp::from_le_bytes(&rhs_x.to_bytes()), + y: Fp::from_le_bytes(&rhs_y.to_bytes()), + }, + PhantomData, + ), + ); + Ok(accumulator) + } +} + impl EcPointLoader for OpenVmLoader { type LoadedEcPoint = OpenVmEcPoint; fn ec_point_load_const(&self, value: &G1Affine) -> Self::LoadedEcPoint { let point = EcPoint { - x: Fp::from_be_bytes(&value.x().to_bytes()), - y: Fp::from_be_bytes(&value.y().to_bytes()), + x: Fp::from_le_bytes(&value.x.to_bytes()), + y: Fp::from_le_bytes(&value.y.to_bytes()), }; // new(value.x(), value.y()); OpenVmEcPoint(point, PhantomData) @@ -74,7 +121,7 @@ impl ScalarLoader for OpenVmLoader { type LoadedScalar = OpenVmScalar; fn load_const(&self, value: &Halo2Fr) -> Self::LoadedScalar { - let value = Fr::from_be_bytes(&value.to_bytes()); + let value = Fr::from_le_bytes(&value.to_bytes()); OpenVmScalar(value, PhantomData) } @@ -89,7 +136,7 @@ impl ScalarLoader for OpenVmLoader { type LoadedScalar = OpenVmScalar; fn load_const(&self, value: &Halo2Fp) -> Self::LoadedScalar { - let value = Fp::from_be_bytes(&value.to_bytes()); + let value = Fp::from_le_bytes(&value.to_bytes()); OpenVmScalar(value, PhantomData) } @@ -122,8 +169,8 @@ where let mut P = Vec::with_capacity(2); let mut Q = Vec::with_capacity(2); for t in terms { - let x = t.1.x().to_bytes(); - let y = t.1.y().to_bytes(); + let x = t.1.x.to_bytes(); + let y = t.1.y.to_bytes(); let point = AffinePoint { x: t.0.x, y: t.0.y }; P.push(point); let point = AffinePoint { diff --git a/extensions/verifier/src/verifier/traits.rs b/extensions/verifier/src/verifier/traits.rs index d73f9b3eb7..8af44cfc1e 100644 --- a/extensions/verifier/src/verifier/traits.rs +++ b/extensions/verifier/src/verifier/traits.rs @@ -11,7 +11,7 @@ use halo2curves_axiom::{ }; use openvm_ecc_guest::algebra::{ExpBytes, Field, IntMod}; use openvm_pairing_guest::bn254::{Bn254G1Affine as EcPoint, Fp, Scalar as Fr}; -use snark_verifier::{ +use snark_verifier_sdk::snark_verifier::{ loader::{LoadedEcPoint, LoadedScalar}, util::arithmetic::FieldOps, }; diff --git a/extensions/verifier/src/verifier/transcript.rs b/extensions/verifier/src/verifier/transcript.rs index d31d750b4e..ba0a411efc 100644 --- a/extensions/verifier/src/verifier/transcript.rs +++ b/extensions/verifier/src/verifier/transcript.rs @@ -10,11 +10,8 @@ use halo2curves_axiom::{ use itertools::Itertools; use openvm_ecc_guest::algebra::IntMod; use openvm_keccak256_guest::keccak256; -use openvm_pairing_guest::{ - affine_point::AffineCoords, - bn254::{Bn254G1Affine as EcPoint, Fp, Scalar as Fr}, -}; -use snark_verifier::{ +use openvm_pairing_guest::bn254::{Bn254G1Affine as EcPoint, Fp, Scalar as Fr}; +use snark_verifier_sdk::snark_verifier::{ util::transcript::{Transcript, TranscriptRead}, Error, }; @@ -31,6 +28,17 @@ pub struct OpenVmTranscript { _marker: PhantomData, } +impl OpenVmTranscript> { + /// Initialize [`OpenVmTranscript`] given readable or writeable stream for + /// verifying or proving with [`OpenVmLoader`]. + pub fn new(stream: S) -> Self { + Self { + stream, + buf: Vec::new(), + _marker: PhantomData, + } + } +} impl Transcript for OpenVmTranscript> { fn loader(&self) -> &OpenVmLoader { &LOADER @@ -38,7 +46,7 @@ impl Transcript for OpenVmTranscript >::LoadedScalar + ) -> >::LoadedScalar { let data = self .buf @@ -52,7 +60,9 @@ impl Transcript for OpenVmTranscript Transcript for OpenVmTranscript>::from( - G1Affine::new(Fq::from_bytes(&x).unwrap(), Fq::from_bytes(&y).unwrap()).coordinates(), + G1Affine { + x: Fq::from_bytes(&x).unwrap(), + y: Fq::from_bytes(&y).unwrap(), + } + .coordinates(), ) .ok_or_else(|| { Error::Transcript( @@ -108,7 +122,6 @@ where self.stream .read_exact(repr.as_mut()) .map_err(|err| Error::Transcript(err.kind(), err.to_string()))?; - repr.as_mut().reverse(); } let x = Fp::from_be_bytes(&x); let y = Fp::from_be_bytes(&y);