From 7ce3d34a2f2b7cd50bad9b41347c01ff7f7e2683 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Tue, 1 Nov 2022 13:18:24 -0700 Subject: [PATCH 01/15] chore: set up Plonky2 dependency Signed-off-by: Brandon H. Gomes --- plugins/plonky2/Cargo.toml | 29 +++++++++++++++++++++++++++++ plugins/plonky2/src/lib.rs | 9 +++++++++ 2 files changed, 38 insertions(+) create mode 100644 plugins/plonky2/Cargo.toml create mode 100644 plugins/plonky2/src/lib.rs diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml new file mode 100644 index 00000000..6f57a8f5 --- /dev/null +++ b/plugins/plonky2/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "openzl-plugin-plonky2" +version = "0.0.0" +edition = "2021" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/openzklib/openzl" +homepage = "https://openzl.org" +documentation = "https://docs.rs/openzl-plugin-plonky2" +categories = [""] +keywords = [""] +description = "Open ZL Plonky2 Plugin" + +[package.metadata.docs.rs] +# To build locally: +# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --all-features --open +all-features = true +rustdoc-args = ["--cfg", "doc_cfg"] + +[badges] +is-it-maintained-issue-resolution = { repository = "openzklib/openzl" } +is-it-maintained-open-issues = { repository = "openzklib/openzl" } +maintenance = { status = "actively-developed" } + +[dependencies] +eclair = { path = "../../eclair", default-features = false } +openzl-crypto = { path = "../../openzl-crypto", default-features = false } +openzl-util = { path = "../../openzl-util", default-features = false } +plonky2 = { version = "0.1.0", git = "https://github.com/mir-protocol/plonky2", default-features = false } diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs new file mode 100644 index 00000000..0759ab7d --- /dev/null +++ b/plugins/plonky2/src/lib.rs @@ -0,0 +1,9 @@ +//! Plonky2 OpenZL Plugin + +#![cfg_attr(not(any(feature = "std", test)), no_std)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![forbid(rustdoc::broken_intra_doc_links)] +#![forbid(missing_docs)] + +#[doc(inline)] +pub use plonky2; From 52e395f59d2a25937f222f8309f6a54346833345 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 2 Nov 2022 10:46:45 -0700 Subject: [PATCH 02/15] feat: add boolean and field variables Signed-off-by: Brandon H. Gomes --- plugins/plonky2/src/bool.rs | 121 +++++++++++++++++ plugins/plonky2/src/compiler.rs | 11 ++ plugins/plonky2/src/field.rs | 221 ++++++++++++++++++++++++++++++++ plugins/plonky2/src/lib.rs | 6 +- 4 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 plugins/plonky2/src/bool.rs create mode 100644 plugins/plonky2/src/compiler.rs create mode 100644 plugins/plonky2/src/field.rs diff --git a/plugins/plonky2/src/bool.rs b/plugins/plonky2/src/bool.rs new file mode 100644 index 00000000..12cc6db6 --- /dev/null +++ b/plugins/plonky2/src/bool.rs @@ -0,0 +1,121 @@ +//! Plonky2 Booleans + +use crate::compiler::Compiler; +use core::marker::PhantomData; +use eclair::{ + alloc::{ + mode::{Public, Secret}, + Constant, Variable, + }, + bool::Assert, + ops::{BitAnd, Not}, + Has, +}; +use plonky2::{field::extension::Extendable, hash::hash_types::RichField, iop::target::BoolTarget}; + +/// Boolean Type +pub struct Bool { + /// Target + pub target: BoolTarget, + + /// Type Parameter Marker + __: PhantomData, +} + +impl Bool { + /// Builds a new [`Bool`] variable from a `target`. + #[inline] + pub fn new(target: BoolTarget) -> Self { + Self { + target, + __: PhantomData, + } + } +} + +impl Has for Compiler +where + F: RichField + Extendable, +{ + type Type = Bool; +} + +impl Assert for Compiler +where + F: RichField + Extendable, +{ + #[inline] + fn assert(&mut self, b: &Bool) { + self.0.assert_bool(b.target) + } +} + +impl Constant> for Bool +where + F: RichField + Extendable, +{ + type Type = bool; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut Compiler) -> Self { + Self::new(compiler.0.constant_bool(*this)) + } +} + +impl Variable> for Bool +where + F: RichField + Extendable, +{ + type Type = bool; + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + todo!() + } + + #[inline] + fn new_unknown(compiler: &mut Compiler) -> Self { + todo!() + } +} + +impl Variable> for Bool +where + F: RichField + Extendable, +{ + type Type = bool; + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + todo!() + } + + #[inline] + fn new_unknown(compiler: &mut Compiler) -> Self { + todo!() + } +} + +impl BitAnd> for Bool +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn bitand(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.and(self.target, rhs.target)) + } +} + +impl Not> for Bool +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn not(self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.not(self.target)) + } +} diff --git a/plugins/plonky2/src/compiler.rs b/plugins/plonky2/src/compiler.rs new file mode 100644 index 00000000..25381ce9 --- /dev/null +++ b/plugins/plonky2/src/compiler.rs @@ -0,0 +1,11 @@ +//! Plonky2 Compiler + +use plonky2::{ + field::extension::Extendable, hash::hash_types::RichField, + plonk::circuit_builder::CircuitBuilder, +}; + +/// Compiler +pub struct Compiler(pub CircuitBuilder) +where + F: RichField + Extendable; diff --git a/plugins/plonky2/src/field.rs b/plugins/plonky2/src/field.rs new file mode 100644 index 00000000..89f8b291 --- /dev/null +++ b/plugins/plonky2/src/field.rs @@ -0,0 +1,221 @@ +//! Plonky2 Field Elements + +use crate::{bool::Bool, compiler::Compiler}; +use core::marker::PhantomData; +use eclair::{ + alloc::{ + mode::{Public, Secret}, + Constant, Variable, + }, + bool::{Assert, ConditionalSelect}, + cmp::PartialEq, + num::{One, Zero}, + ops::{Add, Div, Mul, Neg, Sub}, + Has, +}; +use plonky2::{field::extension::Extendable, hash::hash_types::RichField, iop::target::Target}; + +/// Boolean Type +pub struct Field { + /// Target + pub target: Target, + + /// Type Parameter Marker + __: PhantomData, +} + +impl Field { + /// Builds a new [`Field`] variable from a `target`. + #[inline] + pub fn new(target: Target) -> Self { + Self { + target, + __: PhantomData, + } + } +} + +impl Constant> for Field +where + F: RichField + Extendable, +{ + type Type = F; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut Compiler) -> Self { + Self::new(compiler.0.constant(*this)) + } +} + +impl Variable> for Field +where + F: RichField + Extendable, +{ + type Type = F; + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + todo!() + } + + #[inline] + fn new_unknown(compiler: &mut Compiler) -> Self { + todo!() + } +} + +impl Variable> for Field +where + F: RichField + Extendable, +{ + type Type = F; + + #[inline] + fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + todo!() + } + + #[inline] + fn new_unknown(compiler: &mut Compiler) -> Self { + todo!() + } +} + +impl Add> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn add(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.add(self.target, rhs.target)) + } +} + +impl Add> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn add(self, rhs: F, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.add_const(self.target, rhs)) + } +} + +impl Sub> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn sub(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.sub(self.target, rhs.target)) + } +} + +impl Mul> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn mul(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.mul(self.target, rhs.target)) + } +} + +impl Mul> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn mul(self, rhs: F, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.mul_const(rhs, self.target)) + } +} + +impl Div> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn div(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.div(self.target, rhs.target)) + } +} + +impl Neg> for Field +where + F: RichField + Extendable, +{ + type Output = Self; + + #[inline] + fn neg(self, compiler: &mut Compiler) -> Self::Output { + Self::new(compiler.0.neg(self.target)) + } +} + +impl PartialEq> for Field +where + F: RichField + Extendable, +{ + #[inline] + fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Bool { + Bool::new(compiler.0.is_equal(self.target, rhs.target)) + } +} + +impl ConditionalSelect> for Field +where + F: RichField + Extendable, +{ + #[inline] + fn select(bit: &Bool, lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Self { + // FIXME: Check the parity + Self::new(compiler.0._if(bit.target, lhs.target, rhs.target)) + } +} + +impl Zero> for Field +where + F: RichField + Extendable, +{ + type Verification = Bool; + + #[inline] + fn zero(compiler: &mut Compiler) -> Self { + Self::new(compiler.0.zero()) + } + + #[inline] + fn is_zero(&self, compiler: &mut Compiler) -> Self::Verification { + todo!() + } +} + +impl One> for Field +where + F: RichField + Extendable, +{ + type Verification = Bool; + + #[inline] + fn one(compiler: &mut Compiler) -> Self { + Self::new(compiler.0.one()) + } + + #[inline] + fn is_one(&self, compiler: &mut Compiler) -> Self::Verification { + todo!() + } +} diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index 0759ab7d..4c9d903a 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -6,4 +6,8 @@ #![forbid(missing_docs)] #[doc(inline)] -pub use plonky2; +pub use plonky2::*; + +pub mod bool; +pub mod compiler; +pub mod field; From b119db6a3433a20d74fc39a0052d91f94f25dd00 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 2 Nov 2022 16:03:14 -0700 Subject: [PATCH 03/15] wip: move to plonky2 fork Signed-off-by: Brandon H. Gomes --- plugins/plonky2/Cargo.toml | 2 +- plugins/plonky2/src/bool.rs | 15 +++++++++++++-- plugins/plonky2/src/field.rs | 17 +++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index 6f57a8f5..e5098c7b 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -26,4 +26,4 @@ maintenance = { status = "actively-developed" } eclair = { path = "../../eclair", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { version = "0.1.0", git = "https://github.com/mir-protocol/plonky2", default-features = false } +plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } diff --git a/plugins/plonky2/src/bool.rs b/plugins/plonky2/src/bool.rs index 12cc6db6..1f9b6f8c 100644 --- a/plugins/plonky2/src/bool.rs +++ b/plugins/plonky2/src/bool.rs @@ -8,6 +8,7 @@ use eclair::{ Constant, Variable, }, bool::Assert, + cmp::PartialEq, ops::{BitAnd, Not}, Has, }; @@ -62,7 +63,7 @@ where } } -impl Variable> for Bool +impl Variable> for Bool where F: RichField + Extendable, { @@ -79,7 +80,7 @@ where } } -impl Variable> for Bool +impl Variable> for Bool where F: RichField + Extendable, { @@ -119,3 +120,13 @@ where Self::new(compiler.0.not(self.target)) } } + +impl PartialEq> for Bool +where + F: RichField + Extendable, +{ + #[inline] + fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Self { + todo!() + } +} diff --git a/plugins/plonky2/src/field.rs b/plugins/plonky2/src/field.rs index 89f8b291..da1c4e61 100644 --- a/plugins/plonky2/src/field.rs +++ b/plugins/plonky2/src/field.rs @@ -47,7 +47,7 @@ where } } -impl Variable> for Field +impl Variable> for Field where F: RichField + Extendable, { @@ -55,16 +55,18 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + // FIXME: Review todo!() } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - todo!() + // FIXME: Review + Self::new(compiler.0.add_virtual_target()) } } -impl Variable> for Field +impl Variable> for Field where F: RichField + Extendable, { @@ -72,12 +74,16 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + // FIXME: Review todo!() } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - todo!() + // FIXME: Review + let target = compiler.0.add_virtual_target(); + compiler.0.register_public_input(target); + Self::new(target) } } @@ -181,8 +187,7 @@ where { #[inline] fn select(bit: &Bool, lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Self { - // FIXME: Check the parity - Self::new(compiler.0._if(bit.target, lhs.target, rhs.target)) + Self::new(compiler.0.select(bit.target, lhs.target, rhs.target)) } } From a17f960250970d826de47f4702d32c851da49745 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 3 Nov 2022 12:23:12 -0700 Subject: [PATCH 04/15] wip: start ecdsa-wasm example Signed-off-by: Brandon H. Gomes --- Cargo.toml | 2 +- examples/ecdsa-wasm/Cargo.toml | 12 ++++++++++++ examples/ecdsa-wasm/src/lib.rs | 0 plugins/plonky2/Cargo.toml | 6 +++++- 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 examples/ecdsa-wasm/Cargo.toml create mode 100644 examples/ecdsa-wasm/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index ed1f4f2c..9f2f2837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["eclair", "openzl-*", "plugins/*"] +members = ["eclair", "examples/*", "openzl", "openzl-*", "plugins/*"] diff --git a/examples/ecdsa-wasm/Cargo.toml b/examples/ecdsa-wasm/Cargo.toml new file mode 100644 index 00000000..b1e3d867 --- /dev/null +++ b/examples/ecdsa-wasm/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "ecdsa-wasm" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +getrandom = { version = "0.2.8", features = ["js"] } +openzl-plugin-plonky2 = { path = "../../plugins/plonky2", default-features = false } +wasm-bindgen = { version = "0.2.83" } diff --git a/examples/ecdsa-wasm/src/lib.rs b/examples/ecdsa-wasm/src/lib.rs new file mode 100644 index 00000000..e69de29b diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index e5098c7b..d4a336c4 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -22,8 +22,12 @@ is-it-maintained-issue-resolution = { repository = "openzklib/openzl" } is-it-maintained-open-issues = { repository = "openzklib/openzl" } maintenance = { status = "actively-developed" } +[features] +ecdsa = ["plonky2_ecdsa"] + [dependencies] eclair = { path = "../../eclair", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } +plonky2 = { git = "https://github.com/openzklib/plonky2", branch = "feat/no-std-support", default-features = false } +plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", branch = "feat/no-std-support", optional = true, default-features = false } From f7173236ceccd980ecafe1ac5631f9994247fb23 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 3 Nov 2022 20:15:06 -0700 Subject: [PATCH 05/15] feat: add ECDSA WASM example Signed-off-by: Brandon H. Gomes --- examples/ecdsa-wasm/Cargo.toml | 7 ++- examples/ecdsa-wasm/src/lib.rs | 103 +++++++++++++++++++++++++++++++++ plugins/plonky2/src/base.rs | 8 +++ plugins/plonky2/src/bool.rs | 14 ++++- plugins/plonky2/src/field.rs | 11 ++-- plugins/plonky2/src/lib.rs | 4 +- 6 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 plugins/plonky2/src/base.rs diff --git a/examples/ecdsa-wasm/Cargo.toml b/examples/ecdsa-wasm/Cargo.toml index b1e3d867..1011c72f 100644 --- a/examples/ecdsa-wasm/Cargo.toml +++ b/examples/ecdsa-wasm/Cargo.toml @@ -8,5 +8,10 @@ crate-type = ["cdylib", "lib"] [dependencies] getrandom = { version = "0.2.8", features = ["js"] } -openzl-plugin-plonky2 = { path = "../../plugins/plonky2", default-features = false } +openzl-plugin-plonky2 = { path = "../../plugins/plonky2", default-features = false, features = ["ecdsa"] } wasm-bindgen = { version = "0.2.83" } + +[dev-dependencies] +web-sys = { version = "0.3.59", default-features = false, features = ["console"] } +instant = { version = "0.1.12", default-features = false, features = ["wasm-bindgen"] } +wasm-bindgen-test = { version = "0.3.33", default-features = false } diff --git a/examples/ecdsa-wasm/src/lib.rs b/examples/ecdsa-wasm/src/lib.rs index e69de29b..51e3f354 100644 --- a/examples/ecdsa-wasm/src/lib.rs +++ b/examples/ecdsa-wasm/src/lib.rs @@ -0,0 +1,103 @@ +//! ECDSA WASM + +use openzl_plugin_plonky2::base::{ + ecdsa::{ + curve::{ + curve_types::{Curve, CurveScalar}, + ecdsa::{sign_message, ECDSAPublicKey, ECDSASecretKey}, + secp256k1::Secp256K1, + }, + gadgets::{ + curve::CircuitBuilderCurve, + ecdsa::{verify_message_circuit, ECDSAPublicKeyTarget, ECDSASignatureTarget}, + nonnative::CircuitBuilderNonNative, + }, + }, + field::{secp256k1_scalar::Secp256K1Scalar, types::Sample}, + iop::witness::PartialWitness, + plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig, config::GenericConfig}, +}; + +/// Tests the proving and verification of the ECDSA signature circuit. +#[inline] +pub fn test_ecdsa_circuit(config: CircuitConfig) +where + C: GenericConfig, +{ + let pw = PartialWitness::new(); + let mut builder = CircuitBuilder::::new(config); + + let msg = Secp256K1Scalar::rand(); + let msg_target = builder.constant_nonnative(msg); + + let sk = ECDSASecretKey::(Secp256K1Scalar::rand()); + + let pk = ECDSAPublicKey((CurveScalar(sk.0) * Secp256K1::GENERATOR_PROJECTIVE).to_affine()); + let pk_target = ECDSAPublicKeyTarget(builder.constant_affine_point(pk.0)); + + let sig = sign_message(msg, sk); + let sig_target = ECDSASignatureTarget { + r: builder.constant_nonnative(sig.r), + s: builder.constant_nonnative(sig.s), + }; + + verify_message_circuit(&mut builder, msg_target, sig_target, pk_target); + + let data = builder.build::(); + let proof = data.prove(pw).expect("Proving failed."); + data.verify(proof).expect("Verification failed."); +} + +/// Testing Module +#[cfg(test)] +pub mod test { + use super::*; + use openzl_plugin_plonky2::base::plonk::config::PoseidonGoldilocksConfig; + use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure}; + use web_sys::console; + + wasm_bindgen_test_configure!(run_in_browser); + + /// Defines a benchmark over `f` with `REPEAT` repetitions. + #[inline] + fn bench(mut f: F, label: &str) + where + F: FnMut(), + { + let start_time = instant::Instant::now(); + for _ in 0..REPEAT { + f(); + } + let end_time = instant::Instant::now(); + console::log_1( + &format!( + "{:?} Performance: {:?}", + label, + ((end_time - start_time) / REPEAT as u32) + ) + .into(), + ); + } + + /// Runs the ECDSA benchmark for a narrow circuit configuration. + #[wasm_bindgen_test] + pub fn bench_ecdsa_circuit_narrow() { + bench::<_, 3>( + || { + test_ecdsa_circuit::( + CircuitConfig::standard_ecc_config(), + ) + }, + "Bench ECDSA Narrow", + ) + } + + /// Runs the ECDSA benchmark for a narrow circuit configuration. + #[wasm_bindgen_test] + pub fn bench_ecdsa_circuit_wide() { + bench::<_, 3>( + || test_ecdsa_circuit::(CircuitConfig::wide_ecc_config()), + "Bench ECDSA Wide", + ) + } +} diff --git a/plugins/plonky2/src/base.rs b/plugins/plonky2/src/base.rs new file mode 100644 index 00000000..ee2aa5bd --- /dev/null +++ b/plugins/plonky2/src/base.rs @@ -0,0 +1,8 @@ +//! Plonky2 Base Library + +#[doc(inline)] +pub use plonky2::*; + +#[cfg(feature = "ecdsa")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "ecdsa")))] +pub use plonky2_ecdsa as ecdsa; diff --git a/plugins/plonky2/src/bool.rs b/plugins/plonky2/src/bool.rs index 1f9b6f8c..db6de851 100644 --- a/plugins/plonky2/src/bool.rs +++ b/plugins/plonky2/src/bool.rs @@ -71,12 +71,15 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + // FIXME: Review + let _ = (this, compiler); todo!() } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - todo!() + // FIXME: Review + Self::new(compiler.0.add_virtual_bool_target_safe()) } } @@ -88,12 +91,17 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { + // FIXME: Review + let _ = (this, compiler); todo!() } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - todo!() + // FIXME: Review + let target = compiler.0.add_virtual_bool_target_safe(); + compiler.0.register_public_input(target.target); + Self::new(target) } } @@ -127,6 +135,6 @@ where { #[inline] fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Self { - todo!() + Bool::new(compiler.0.is_equal(self.target.target, rhs.target.target)) } } diff --git a/plugins/plonky2/src/field.rs b/plugins/plonky2/src/field.rs index da1c4e61..48a20288 100644 --- a/plugins/plonky2/src/field.rs +++ b/plugins/plonky2/src/field.rs @@ -7,11 +7,10 @@ use eclair::{ mode::{Public, Secret}, Constant, Variable, }, - bool::{Assert, ConditionalSelect}, + bool::ConditionalSelect, cmp::PartialEq, num::{One, Zero}, ops::{Add, Div, Mul, Neg, Sub}, - Has, }; use plonky2::{field::extension::Extendable, hash::hash_types::RichField, iop::target::Target}; @@ -56,6 +55,7 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { // FIXME: Review + let _ = (this, compiler); todo!() } @@ -75,6 +75,7 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { // FIXME: Review + let _ = (this, compiler); todo!() } @@ -204,7 +205,8 @@ where #[inline] fn is_zero(&self, compiler: &mut Compiler) -> Self::Verification { - todo!() + // TODO: is there a better choice here? + self.eq(&Self::zero(compiler), compiler) } } @@ -221,6 +223,7 @@ where #[inline] fn is_one(&self, compiler: &mut Compiler) -> Self::Verification { - todo!() + // TODO: is there a better choice here? + self.eq(&Self::one(compiler), compiler) } } diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index 4c9d903a..6e090cb4 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -5,9 +5,7 @@ #![forbid(rustdoc::broken_intra_doc_links)] #![forbid(missing_docs)] -#[doc(inline)] -pub use plonky2::*; - +pub mod base; pub mod bool; pub mod compiler; pub mod field; From 2bd4b082ef03273df3f2fd8ca0809d53668ca610 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 7 Dec 2022 13:52:29 -0500 Subject: [PATCH 06/15] chore: update dependencies --- examples/ecdsa-wasm/Cargo.toml | 2 +- openzl-crypto/src/accumulator.rs | 2 +- openzl-crypto/src/constraint.rs | 2 +- openzl-derive/src/component.rs | 3 +-- plugins/plonky2/Cargo.toml | 5 +++-- plugins/plonky2/src/lib.rs | 3 +++ 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/ecdsa-wasm/Cargo.toml b/examples/ecdsa-wasm/Cargo.toml index 1011c72f..d9d28de8 100644 --- a/examples/ecdsa-wasm/Cargo.toml +++ b/examples/ecdsa-wasm/Cargo.toml @@ -12,6 +12,6 @@ openzl-plugin-plonky2 = { path = "../../plugins/plonky2", default-features = fal wasm-bindgen = { version = "0.2.83" } [dev-dependencies] -web-sys = { version = "0.3.59", default-features = false, features = ["console"] } instant = { version = "0.1.12", default-features = false, features = ["wasm-bindgen"] } wasm-bindgen-test = { version = "0.3.33", default-features = false } +web-sys = { version = "0.3.59", default-features = false, features = ["console"] } diff --git a/openzl-crypto/src/accumulator.rs b/openzl-crypto/src/accumulator.rs index d3afb39c..cea720e2 100644 --- a/openzl-crypto/src/accumulator.rs +++ b/openzl-crypto/src/accumulator.rs @@ -358,7 +358,7 @@ pub mod test { .collect::>(); for (i, x) in outputs.iter().enumerate() { for (j, y) in outputs.iter().enumerate().skip(i + 1) { - assert_ne!(x, y, "Found matching outputs at {:?} and {:?}.", i, j) + assert_ne!(x, y, "Found matching outputs at {i:?} and {j:?}."); } } } diff --git a/openzl-crypto/src/constraint.rs b/openzl-crypto/src/constraint.rs index dd31f6b7..d2ff1186 100644 --- a/openzl-crypto/src/constraint.rs +++ b/openzl-crypto/src/constraint.rs @@ -343,7 +343,7 @@ pub mod measure { let before = self.base.measure(); let value = f(self.base); self.measurements.push(( - format!("{}", label), + format!("{label}"), self.base .measure() .checked_sub(before) diff --git a/openzl-derive/src/component.rs b/openzl-derive/src/component.rs index 5b6fca30..6023c1f4 100644 --- a/openzl-derive/src/component.rs +++ b/openzl-derive/src/component.rs @@ -55,8 +55,7 @@ pub fn transform(args: TokenStream, input: TokenStream) -> TokenStream { let trait_ident = format_ident!("{}Type", ident); let associated_type_doc = "Component Type"; let type_alias_doc = format!( - "[`{}`]({trait_ident}::{ident}) Type Alias for the [`{}`] Component", - ident, trait_ident + "[`{ident}`]({trait_ident}::{ident}) Type Alias for the [`{trait_ident}`] Component", ); TokenStream::from(quote!( #(#attrs)* diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index d4a336c4..a66036a6 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -29,5 +29,6 @@ ecdsa = ["plonky2_ecdsa"] eclair = { path = "../../eclair", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { git = "https://github.com/openzklib/plonky2", branch = "feat/no-std-support", default-features = false } -plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", branch = "feat/no-std-support", optional = true, default-features = false } +plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } +plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", optional = true, default-features = false } +starky = { git = "https://github.com/openzklib/plonky2", default-features = false } diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index 6e090cb4..5f1e4f09 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -9,3 +9,6 @@ pub mod base; pub mod bool; pub mod compiler; pub mod field; + +#[doc(inline)] +pub use starky; From 8cc4f45ad93858587b214694bd41b93a70ae742b Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 14 Dec 2022 15:37:30 -0500 Subject: [PATCH 07/15] feat: finish allocation system and start proof system Signed-off-by: Brandon H. Gomes --- plugins/plonky2/Cargo.toml | 6 +- plugins/plonky2/src/bool.rs | 30 ++--- plugins/plonky2/src/compiler.rs | 212 +++++++++++++++++++++++++++++++- plugins/plonky2/src/field.rs | 40 +++--- plugins/plonky2/src/lib.rs | 2 + 5 files changed, 244 insertions(+), 46 deletions(-) diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index a66036a6..e555cb86 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -29,6 +29,6 @@ ecdsa = ["plonky2_ecdsa"] eclair = { path = "../../eclair", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } -plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", optional = true, default-features = false } -starky = { git = "https://github.com/openzklib/plonky2", default-features = false } +plonky2 = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } +plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", optional = true, default-features = false } +starky = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } diff --git a/plugins/plonky2/src/bool.rs b/plugins/plonky2/src/bool.rs index db6de851..a2a8f5f3 100644 --- a/plugins/plonky2/src/bool.rs +++ b/plugins/plonky2/src/bool.rs @@ -47,7 +47,7 @@ where { #[inline] fn assert(&mut self, b: &Bool) { - self.0.assert_bool(b.target) + self.builder.assert_bool(b.target) } } @@ -59,7 +59,7 @@ where #[inline] fn new_constant(this: &Self::Type, compiler: &mut Compiler) -> Self { - Self::new(compiler.0.constant_bool(*this)) + Self::new(compiler.builder.constant_bool(*this)) } } @@ -71,15 +71,12 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { - // FIXME: Review - let _ = (this, compiler); - todo!() + Self::new(compiler.add_bool_target(*this)) } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - // FIXME: Review - Self::new(compiler.0.add_virtual_bool_target_safe()) + Self::new(compiler.add_virtual_bool_target()) } } @@ -91,17 +88,12 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { - // FIXME: Review - let _ = (this, compiler); - todo!() + Self::new(compiler.add_public_bool_target(*this)) } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - // FIXME: Review - let target = compiler.0.add_virtual_bool_target_safe(); - compiler.0.register_public_input(target.target); - Self::new(target) + Self::new(compiler.add_virtual_public_bool_target()) } } @@ -113,7 +105,7 @@ where #[inline] fn bitand(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.and(self.target, rhs.target)) + Self::new(compiler.builder.and(self.target, rhs.target)) } } @@ -125,7 +117,7 @@ where #[inline] fn not(self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.not(self.target)) + Self::new(compiler.builder.not(self.target)) } } @@ -135,6 +127,10 @@ where { #[inline] fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Self { - Bool::new(compiler.0.is_equal(self.target.target, rhs.target.target)) + Bool::new( + compiler + .builder + .is_equal(self.target.target, rhs.target.target), + ) } } diff --git a/plugins/plonky2/src/compiler.rs b/plugins/plonky2/src/compiler.rs index 25381ce9..6c02bb16 100644 --- a/plugins/plonky2/src/compiler.rs +++ b/plugins/plonky2/src/compiler.rs @@ -1,11 +1,219 @@ //! Plonky2 Compiler +use alloc::vec::Vec; +use core::marker::PhantomData; +use openzl_crypto::constraint::ProofSystem; +use openzl_util::rand::{CryptoRng, RngCore}; use plonky2::{ - field::extension::Extendable, hash::hash_types::RichField, + field::extension::Extendable, + hash::hash_types::RichField, + iop::{ + target::{BoolTarget, Target}, + witness::{PartialWitness, WitnessWrite}, + }, plonk::circuit_builder::CircuitBuilder, }; /// Compiler -pub struct Compiler(pub CircuitBuilder) +pub struct Compiler +where + F: RichField + Extendable, +{ + /// Circuit Builder + pub builder: CircuitBuilder, + + /// Partial Witness + pub partial_witness: PartialWitness, +} + +impl Compiler +where + F: RichField + Extendable, +{ + /// Builds a new [`Compiler`] using `builder` and `partial_witness`. + #[inline] + pub fn new(builder: CircuitBuilder, partial_witness: PartialWitness) -> Self { + Self { + builder, + partial_witness, + } + } + + /// Sets the `target` to the `value` in the partial witness. + #[inline] + fn set_target(&mut self, target: Target, value: F) { + self.partial_witness.set_target(target, value); + } + + /// Returns a new virtual target. + #[inline] + pub fn add_virtual_target(&mut self) -> Target { + self.builder.add_virtual_target() + } + + /// Returns a new virtual public target. + #[inline] + pub fn add_virtual_public_target(&mut self) -> Target { + let target = self.add_virtual_target(); + self.builder.register_public_input(target); + target + } + + /// Returns a new target assigned to `value`. + #[inline] + pub fn add_target(&mut self, value: F) -> Target { + let target = self.add_virtual_target(); + self.set_target(target, value); + target + } + + /// Returns a new public target assigned to `value`. + #[inline] + pub fn add_public_target(&mut self, value: F) -> Target { + let target = self.add_target(value); + self.builder.register_public_input(target); + target + } + + /// Sets the boolean `target` to the `value` in the partial witness. + #[inline] + fn set_bool_target(&mut self, target: BoolTarget, value: bool) { + self.partial_witness.set_bool_target(target, value); + } + + /// Returns a new virtual boolean target. + #[inline] + pub fn add_virtual_bool_target(&mut self) -> BoolTarget { + self.builder.add_virtual_bool_target_safe() + } + + /// Returns a new virtual public boolean target. + #[inline] + pub fn add_virtual_public_bool_target(&mut self) -> BoolTarget { + let target = self.add_virtual_bool_target(); + self.builder.register_public_input(target.target); + target + } + + /// Returns a new boolean target assigned to `value`. + #[inline] + pub fn add_bool_target(&mut self, value: bool) -> BoolTarget { + let target = self.add_virtual_bool_target(); + self.set_bool_target(target, value); + target + } + + /// Returns a new public boolean target assigned to `value`. + #[inline] + pub fn add_public_bool_target(&mut self, value: bool) -> BoolTarget { + let target = self.add_bool_target(value); + self.builder.register_public_input(target.target); + target + } +} + +impl Default for Compiler +where + F: RichField + Extendable, +{ + #[inline] + fn default() -> Self { + Self::new(CircuitBuilder::new(Default::default()), Default::default()) + } +} + +/// +pub struct ProvingContext; + +/// +pub struct VerifyingContext; + +/// +pub struct Proof; + +/// +pub struct Error; + +/// +pub struct Plonky2(PhantomData) where F: RichField + Extendable; + +impl ProofSystem for Plonky2 +where + F: RichField + Extendable, +{ + type Compiler = Compiler; + type PublicParameters = (); + type ProvingContext = ProvingContext; + type VerifyingContext = VerifyingContext; + type Input = Vec; + type Proof = Proof; + type Error = Error; + + #[inline] + fn context_compiler() -> Self::Compiler { + /* + Self::Compiler::for_contexts() + */ + todo!() + } + + #[inline] + fn proof_compiler() -> Self::Compiler { + /* + Self::Compiler::for_proofs() + */ + todo!() + } + + #[inline] + fn compile( + public_parameters: &Self::PublicParameters, + compiler: Self::Compiler, + rng: &mut R, + ) -> Result<(Self::ProvingContext, Self::VerifyingContext), Self::Error> + where + R: CryptoRng + RngCore + ?Sized, + { + /* + let _ = public_parameters; + let (proving_key, verifying_key) = + ArkGroth16::circuit_specific_setup(compiler, &mut SizedRng(rng)).map_err(|_| Error)?; + Ok(( + ProvingContext(proving_key), + VerifyingContext(ArkGroth16::process_vk(&verifying_key).map_err(|_| Error)?), + )) + */ + todo!() + } + + #[inline] + fn prove( + context: &Self::ProvingContext, + compiler: Self::Compiler, + rng: &mut R, + ) -> Result + where + R: CryptoRng + RngCore + ?Sized, + { + /* + ArkGroth16::prove(&context.0, compiler, &mut SizedRng(rng)) + .map(Proof) + .map_err(|_| Error) + */ + todo!() + } + + #[inline] + fn verify( + context: &Self::VerifyingContext, + input: &Self::Input, + proof: &Self::Proof, + ) -> Result { + /* + ArkGroth16::verify_with_processed_vk(&context.0, input, &proof.0).map_err(|_| Error) + */ + todo!() + } +} diff --git a/plugins/plonky2/src/field.rs b/plugins/plonky2/src/field.rs index 48a20288..1d9c8ce8 100644 --- a/plugins/plonky2/src/field.rs +++ b/plugins/plonky2/src/field.rs @@ -42,7 +42,7 @@ where #[inline] fn new_constant(this: &Self::Type, compiler: &mut Compiler) -> Self { - Self::new(compiler.0.constant(*this)) + Self::new(compiler.builder.constant(*this)) } } @@ -54,15 +54,12 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { - // FIXME: Review - let _ = (this, compiler); - todo!() + Self::new(compiler.add_target(*this)) } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - // FIXME: Review - Self::new(compiler.0.add_virtual_target()) + Self::new(compiler.add_virtual_target()) } } @@ -74,17 +71,12 @@ where #[inline] fn new_known(this: &Self::Type, compiler: &mut Compiler) -> Self { - // FIXME: Review - let _ = (this, compiler); - todo!() + Self::new(compiler.add_public_target(*this)) } #[inline] fn new_unknown(compiler: &mut Compiler) -> Self { - // FIXME: Review - let target = compiler.0.add_virtual_target(); - compiler.0.register_public_input(target); - Self::new(target) + Self::new(compiler.add_virtual_public_target()) } } @@ -96,7 +88,7 @@ where #[inline] fn add(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.add(self.target, rhs.target)) + Self::new(compiler.builder.add(self.target, rhs.target)) } } @@ -108,7 +100,7 @@ where #[inline] fn add(self, rhs: F, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.add_const(self.target, rhs)) + Self::new(compiler.builder.add_const(self.target, rhs)) } } @@ -120,7 +112,7 @@ where #[inline] fn sub(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.sub(self.target, rhs.target)) + Self::new(compiler.builder.sub(self.target, rhs.target)) } } @@ -132,7 +124,7 @@ where #[inline] fn mul(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.mul(self.target, rhs.target)) + Self::new(compiler.builder.mul(self.target, rhs.target)) } } @@ -144,7 +136,7 @@ where #[inline] fn mul(self, rhs: F, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.mul_const(rhs, self.target)) + Self::new(compiler.builder.mul_const(rhs, self.target)) } } @@ -156,7 +148,7 @@ where #[inline] fn div(self, rhs: Self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.div(self.target, rhs.target)) + Self::new(compiler.builder.div(self.target, rhs.target)) } } @@ -168,7 +160,7 @@ where #[inline] fn neg(self, compiler: &mut Compiler) -> Self::Output { - Self::new(compiler.0.neg(self.target)) + Self::new(compiler.builder.neg(self.target)) } } @@ -178,7 +170,7 @@ where { #[inline] fn eq(&self, rhs: &Self, compiler: &mut Compiler) -> Bool { - Bool::new(compiler.0.is_equal(self.target, rhs.target)) + Bool::new(compiler.builder.is_equal(self.target, rhs.target)) } } @@ -188,7 +180,7 @@ where { #[inline] fn select(bit: &Bool, lhs: &Self, rhs: &Self, compiler: &mut Compiler) -> Self { - Self::new(compiler.0.select(bit.target, lhs.target, rhs.target)) + Self::new(compiler.builder.select(bit.target, lhs.target, rhs.target)) } } @@ -200,7 +192,7 @@ where #[inline] fn zero(compiler: &mut Compiler) -> Self { - Self::new(compiler.0.zero()) + Self::new(compiler.builder.zero()) } #[inline] @@ -218,7 +210,7 @@ where #[inline] fn one(compiler: &mut Compiler) -> Self { - Self::new(compiler.0.one()) + Self::new(compiler.builder.one()) } #[inline] diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index 5f1e4f09..f8d21d0a 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -5,6 +5,8 @@ #![forbid(rustdoc::broken_intra_doc_links)] #![forbid(missing_docs)] +extern crate alloc; + pub mod base; pub mod bool; pub mod compiler; From 4a32873647e2b2ed3d475807c9ccb944c0f38ef7 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Wed, 14 Dec 2022 17:30:03 -0500 Subject: [PATCH 08/15] feat: add ProofSystem impl for Plonky2 Signed-off-by: Brandon H. Gomes --- plugins/plonky2/Cargo.toml | 11 ++++ plugins/plonky2/src/compiler.rs | 100 +++++++++++++++++--------------- 2 files changed, 64 insertions(+), 47 deletions(-) diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index e555cb86..c05408e1 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -23,9 +23,20 @@ is-it-maintained-open-issues = { repository = "openzklib/openzl" } maintenance = { status = "actively-developed" } [features] +# ECDSA Library ecdsa = ["plonky2_ecdsa"] +# Standard Library +std = [ + "anyhow/std", + "openzl-crypto/std", + "openzl-util/std", + "plonky2/std", + "starky/std", +] + [dependencies] +anyhow = { version = "1.0.66", default-features = false } eclair = { path = "../../eclair", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } diff --git a/plugins/plonky2/src/compiler.rs b/plugins/plonky2/src/compiler.rs index 6c02bb16..506617af 100644 --- a/plugins/plonky2/src/compiler.rs +++ b/plugins/plonky2/src/compiler.rs @@ -11,7 +11,13 @@ use plonky2::{ target::{BoolTarget, Target}, witness::{PartialWitness, WitnessWrite}, }, - plonk::circuit_builder::CircuitBuilder, + plonk::{ + circuit_builder::CircuitBuilder, + circuit_data::{CircuitData, ProverCircuitData, VerifierCircuitData}, + config::GenericConfig, + proof, + proof::ProofWithPublicInputs, + }, }; /// Compiler @@ -122,49 +128,46 @@ where } } -/// -pub struct ProvingContext; - -/// -pub struct VerifyingContext; +/// Proving Context +pub struct ProvingContext(ProverCircuitData) +where + C: GenericConfig; -/// -pub struct Proof; +/// Verifying Context +pub struct VerifyingContext(VerifierCircuitData) +where + C: GenericConfig; -/// -pub struct Error; +/// Proof +pub struct Proof(proof::Proof) +where + C: GenericConfig; -/// -pub struct Plonky2(PhantomData) +/// Plonky2 Proving System +pub struct Plonky2(PhantomData) where - F: RichField + Extendable; + C: GenericConfig; -impl ProofSystem for Plonky2 +impl ProofSystem for Plonky2 where - F: RichField + Extendable, + C: GenericConfig, { - type Compiler = Compiler; + type Compiler = Compiler; type PublicParameters = (); - type ProvingContext = ProvingContext; - type VerifyingContext = VerifyingContext; - type Input = Vec; - type Proof = Proof; - type Error = Error; + type ProvingContext = ProvingContext; + type VerifyingContext = VerifyingContext; + type Input = Vec; + type Proof = Proof; + type Error = anyhow::Error; #[inline] fn context_compiler() -> Self::Compiler { - /* - Self::Compiler::for_contexts() - */ - todo!() + Default::default() } #[inline] fn proof_compiler() -> Self::Compiler { - /* - Self::Compiler::for_proofs() - */ - todo!() + Default::default() } #[inline] @@ -176,16 +179,22 @@ where where R: CryptoRng + RngCore + ?Sized, { - /* - let _ = public_parameters; - let (proving_key, verifying_key) = - ArkGroth16::circuit_specific_setup(compiler, &mut SizedRng(rng)).map_err(|_| Error)?; + let _ = (public_parameters, rng); + let CircuitData { + prover_only, + verifier_only, + common, + } = compiler.builder.build::(); Ok(( - ProvingContext(proving_key), - VerifyingContext(ArkGroth16::process_vk(&verifying_key).map_err(|_| Error)?), + ProvingContext(ProverCircuitData { + prover_only, + common: common.clone(), + }), + VerifyingContext(VerifierCircuitData { + verifier_only, + common, + }), )) - */ - todo!() } #[inline] @@ -197,12 +206,8 @@ where where R: CryptoRng + RngCore + ?Sized, { - /* - ArkGroth16::prove(&context.0, compiler, &mut SizedRng(rng)) - .map(Proof) - .map_err(|_| Error) - */ - todo!() + let _ = rng; + Ok(Proof(context.0.prove(compiler.partial_witness)?.proof)) } #[inline] @@ -211,9 +216,10 @@ where input: &Self::Input, proof: &Self::Proof, ) -> Result { - /* - ArkGroth16::verify_with_processed_vk(&context.0, input, &proof.0).map_err(|_| Error) - */ - todo!() + context.0.verify(ProofWithPublicInputs { + proof: proof.0.clone(), + public_inputs: input.clone(), + })?; + Ok(true) } } From ce54cc6348d9c879050cb787f61c71dac250cd24 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 15 Dec 2022 14:24:57 -0500 Subject: [PATCH 09/15] chore: add CHANGELOG Signed-off-by: Brandon H. Gomes --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a13e825..dd1b945a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ### Added -- [\#3](https://github.com/openzklib/openzl/pull/3) Migrate some of OpenZL from the Manta-Network codebase -- [\#4](https://github.com/openzklib/openzl/pull/4) Add CI and Relevant Contribution Files - [\#34](https://github.com/openzklib/openzl/pull/34) Migrate Poseidon from the Manta-Network codebase +- [\#14](https://github.com/openzklib/openzl/pull/14) Build initial Plonky2 plugin implementation with Poseidon integration +- [\#4](https://github.com/openzklib/openzl/pull/4) Add CI and Relevant Contribution Files +- [\#3](https://github.com/openzklib/openzl/pull/3) Migrate some of OpenZL from the Manta-Network codebase ### Changed From 8f07581000706f6e1400a3f7aa44b09eb9a7faee Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 15 Dec 2022 15:01:03 -0500 Subject: [PATCH 10/15] feat: add SBoxExponent marker trait Signed-off-by: Brandon H. Gomes --- openzl-crypto/src/poseidon/mod.rs | 10 ++++++++++ plugins/arkworks/src/poseidon/mod.rs | 15 +++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/openzl-crypto/src/poseidon/mod.rs b/openzl-crypto/src/poseidon/mod.rs index 6c63a28f..1d39d2cc 100644 --- a/openzl-crypto/src/poseidon/mod.rs +++ b/openzl-crypto/src/poseidon/mod.rs @@ -112,6 +112,16 @@ pub trait Constants { const ADDITIVE_ROUND_KEYS_COUNT: usize = Self::ROUNDS * Self::WIDTH; } +/// Poseidon S-Box Exponent +/// +/// For Poseidon implementations that use an `x^n` s-box with `n > 0`, this helper `trait` can be +/// used to mark the exponent `n` for convenience. For `n = -1` the s-box "power" needs to be +/// specified in the [`Specification::apply_sbox`] method. +pub trait SBoxExponent { + /// S-Box Exponent Value + const SBOX_EXPONENT: u64; +} + /// Parameter Field Type #[component] pub type ParameterField; diff --git a/plugins/arkworks/src/poseidon/mod.rs b/plugins/arkworks/src/poseidon/mod.rs index 908e95ec..dd00ead1 100644 --- a/plugins/arkworks/src/poseidon/mod.rs +++ b/plugins/arkworks/src/poseidon/mod.rs @@ -9,7 +9,7 @@ use core::marker::PhantomData; use eclair::alloc::Constant; use openzl_crypto::poseidon::{ self, encryption::BlockElement, hash::DomainTag, Constants, FieldGeneration, NativeField, - ParameterFieldType, + ParameterFieldType, SBoxExponent, }; #[cfg(test)] @@ -19,12 +19,9 @@ pub mod test; type Compiler = R1CS<::Field>; /// Poseidon Permutation Specification. -pub trait Specification: Constants { +pub trait Specification: Constants + SBoxExponent { /// Field Type type Field: PrimeField; - - /// S-BOX Exponenet - const SBOX_EXPONENT: u64; } impl NativeField for Fp @@ -151,11 +148,9 @@ where impl Specification for Spec where F: PrimeField, - Self: poseidon::Constants, + Self: poseidon::Constants + SBoxExponent, { type Field = F; - - const SBOX_EXPONENT: u64 = 5; } impl Constant for Spec @@ -297,6 +292,10 @@ where } } +impl SBoxExponent for Spec { + const SBOX_EXPONENT: u64 = 5; +} + impl poseidon::Constants for Spec { const WIDTH: usize = 3; const FULL_ROUNDS: usize = 8; From e2f76b40b6ad8b7a1122cc7cb886260cc0aa1caa Mon Sep 17 00:00:00 2001 From: Francisco Hernandez Iglesias Date: Thu, 15 Dec 2022 21:27:38 +0100 Subject: [PATCH 11/15] compiler changes Signed-off-by: Francisco Hernandez Iglesias --- openzl-crypto/src/accumulator.rs | 2 +- openzl-crypto/src/poseidon/mds.rs | 2 +- plugins/plonky2/src/field.rs | 11 +- plugins/plonky2/src/lib.rs | 1 + plugins/plonky2/src/poseidon/mod.rs | 344 ++++++++++++++++++++++++++++ 5 files changed, 356 insertions(+), 4 deletions(-) create mode 100644 plugins/plonky2/src/poseidon/mod.rs diff --git a/openzl-crypto/src/accumulator.rs b/openzl-crypto/src/accumulator.rs index e1dd3f0b..cea720e2 100644 --- a/openzl-crypto/src/accumulator.rs +++ b/openzl-crypto/src/accumulator.rs @@ -362,4 +362,4 @@ pub mod test { } } } -} \ No newline at end of file +} diff --git a/openzl-crypto/src/poseidon/mds.rs b/openzl-crypto/src/poseidon/mds.rs index 3bdaabf4..e983b890 100644 --- a/openzl-crypto/src/poseidon/mds.rs +++ b/openzl-crypto/src/poseidon/mds.rs @@ -85,7 +85,7 @@ where where F: FieldGeneration, { - let ys: Vec = (t as u64..2 * t as u64).map(F::from_u64).collect(); + let ys: Vec = (t as u64..2 * t as u64).map(F::from_u64).collect(); // Change u64 to integer mod order(F) SquareMatrix::new_unchecked(Matrix::new_unchecked( (0..t as u64) .map(|x| { diff --git a/plugins/plonky2/src/field.rs b/plugins/plonky2/src/field.rs index 1d9c8ce8..51e53c54 100644 --- a/plugins/plonky2/src/field.rs +++ b/plugins/plonky2/src/field.rs @@ -12,9 +12,16 @@ use eclair::{ num::{One, Zero}, ops::{Add, Div, Mul, Neg, Sub}, }; -use plonky2::{field::extension::Extendable, hash::hash_types::RichField, iop::target::Target}; +use openzl_util::derivative; -/// Boolean Type +pub use plonky2::{field::extension::Extendable, hash::hash_types::RichField, iop::target::Target}; + +/// +pub struct Fp(pub F); + +/// Variable Field Type +#[derive(derivative::Derivative)] +#[derivative(Clone, Copy)] pub struct Field { /// Target pub target: Target, diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index f8d21d0a..c3333bd3 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -11,6 +11,7 @@ pub mod base; pub mod bool; pub mod compiler; pub mod field; +pub mod poseidon; #[doc(inline)] pub use starky; diff --git a/plugins/plonky2/src/poseidon/mod.rs b/plugins/plonky2/src/poseidon/mod.rs new file mode 100644 index 00000000..a34b5728 --- /dev/null +++ b/plugins/plonky2/src/poseidon/mod.rs @@ -0,0 +1,344 @@ +//! Poseidon Arkworks Backend + +use crate::{ + base::util::bits_u64, + compiler::Compiler as PlonkCompiler, + field::{Extendable, Field, Fp, RichField}, + // constraint::{fp::Fp, FpVar, R1CS}, + // ff::{BigInteger, Field, FpParameters, PrimeField}, + // r1cs_std::fields::FieldVar, +}; +use core::marker::PhantomData; +use eclair::{ + alloc::Constant, + ops::{Add, Mul, Sub}, +}; +use openzl_crypto::poseidon::{ + self, encryption::BlockElement, hash::DomainTag, Constants, FieldGeneration, NativeField, + ParameterFieldType, +}; +use plonky2::field::types::Field as _; + +/// Compiler Type. +type Compiler = PlonkCompiler<::Field, D>; + +/// Poseidon Permutation Specification. +pub trait Specification: Constants { + /// Field Type + type Field: RichField; + + /// S-BOX Exponenet + const SBOX_EXPONENT: u64; +} + +impl NativeField for Fp +where + F: RichField, +{ + #[inline] + fn zero() -> Self { + Self(F::ZERO) + } + + #[inline] + fn is_zero(&self) -> bool { + self.0 == F::ZERO + } + + #[inline] + fn one() -> Self { + Self(F::ONE) + } + + #[inline] + fn add(&self, rhs: &Self) -> Self { + Self(self.0 + rhs.0) + } + + #[inline] + fn add_assign(&mut self, rhs: &Self) { + self.0 += rhs.0; + } + + #[inline] + fn sub(&self, rhs: &Self) -> Self { + Self(self.0 - rhs.0) + } + + #[inline] + fn mul(&self, rhs: &Self) -> Self { + Self(self.0 * rhs.0) + } + + #[inline] + fn inverse(&self) -> Option { + self.0.try_inverse().map(Self) + } +} + +impl FieldGeneration for Fp +where + F: RichField, +{ + const MODULUS_BITS: usize = F::BITS; + + #[inline] + fn try_from_bits_be(bits: &[bool]) -> Option { + //F::from_repr(F::BigInt::from_bits_be(bits)).map(Self) + todo!() + } + + #[inline] + fn from_u64(elem: u64) -> Self { + //Self(F::from_canonical_u32(elem as u32)) + todo!() // Change this function + } +} + +impl BlockElement for Fp +where + F: RichField, +{ + #[inline] + fn add(&self, rhs: &Self, _: &mut ()) -> Self { + Self(self.0 + rhs.0) + } + + #[inline] + fn sub(&self, rhs: &Self, _: &mut ()) -> Self { + Self(self.0 - rhs.0) + } +} + +impl BlockElement> for Field +where + F: RichField + Extendable, +{ + #[inline] + fn add(&self, rhs: &Self, compiler: &mut PlonkCompiler) -> Self { + Add::add(*self, *rhs, compiler) + } + + #[inline] + fn sub(&self, rhs: &Self, compiler: &mut PlonkCompiler) -> Self { + Sub::sub(*self, *rhs, compiler) + } +} + +/// Domain tag as 2^arity - 1 +pub struct TwoPowerMinusOneDomainTag; + +impl Constant for TwoPowerMinusOneDomainTag { + type Type = Self; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + Self + } +} + +impl DomainTag for TwoPowerMinusOneDomainTag +where + S: Specification + ParameterFieldType>, +{ + #[inline] + fn domain_tag() -> Fp<::Field> { + //Fp(S::Field::from(((1 << (S::WIDTH - 1)) - 1) as u128)) + todo!() + } +} + +/// Poseidon Specification Configuration +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Spec(PhantomData) +where + F: RichField + Extendable; + +impl Specification for Spec +where + F: RichField + Extendable, + Self: poseidon::Constants, +{ + type Field = F; + + const SBOX_EXPONENT: u64 = 5; +} + +impl Constant for Spec +where + F: RichField + Extendable, +{ + type Type = Self; + + #[inline] + fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { + let _ = (this, compiler); + Self(PhantomData) + } +} + +impl ParameterFieldType for Spec +where + Self: Specification, + F: RichField + Extendable, +{ + type ParameterField = Fp<::Field>; +} + +impl poseidon::Field for Spec +where + Self: Specification, + F: RichField + Extendable, +{ + type Field = Fp<::Field>; + + #[inline] + fn add(lhs: &Self::Field, rhs: &Self::Field, _: &mut ()) -> Self::Field { + Fp(lhs.0 + rhs.0) + } + + #[inline] + fn add_const(lhs: &Self::Field, rhs: &Self::ParameterField, _: &mut ()) -> Self::Field { + Fp(lhs.0 + rhs.0) + } + + #[inline] + fn mul(lhs: &Self::Field, rhs: &Self::Field, _: &mut ()) -> Self::Field { + Fp(lhs.0 * rhs.0) + } + + #[inline] + fn mul_const(lhs: &Self::Field, rhs: &Self::ParameterField, _: &mut ()) -> Self::Field { + Fp(lhs.0 * rhs.0) + } + + #[inline] + fn add_assign(lhs: &mut Self::Field, rhs: &Self::Field, _: &mut ()) { + lhs.0 += rhs.0; + } + + #[inline] + fn add_const_assign(lhs: &mut Self::Field, rhs: &Self::ParameterField, _: &mut ()) { + lhs.0 += rhs.0; + } + + #[inline] + fn from_parameter(point: Self::ParameterField) -> Self::Field { + point + } +} + +impl poseidon::Field> for Spec +where + Self: Specification, + F: RichField + Extendable, + ::Field: Extendable, +{ + type Field = Field<::Field, D>; + + #[inline] + fn add(lhs: &Self::Field, rhs: &Self::Field, compiler: &mut Compiler) -> Self::Field { + lhs.add(rhs, compiler) + } + + #[inline] + fn add_const( + lhs: &Self::Field, + rhs: &Self::ParameterField, + compiler: &mut Compiler, + ) -> Self::Field { + lhs.add(&Field::new_constant(&rhs.0, compiler), compiler) + } + + #[inline] + fn mul(lhs: &Self::Field, rhs: &Self::Field, compiler: &mut Compiler) -> Self::Field { + lhs.mul(*rhs, compiler) + } + + #[inline] + fn mul_const( + lhs: &Self::Field, + rhs: &Self::ParameterField, + compiler: &mut Compiler, + ) -> Self::Field { + lhs.mul(Field::new_constant(&rhs.0, compiler), compiler) + } + + #[inline] + fn add_assign(lhs: &mut Self::Field, rhs: &Self::Field, compiler: &mut Compiler) { + *lhs = lhs.add(*rhs, compiler); + } + + #[inline] + fn add_const_assign( + lhs: &mut Self::Field, + rhs: &Self::ParameterField, + compiler: &mut Compiler, + ) { + *lhs = lhs.add(Field::new_constant(&rhs.0, compiler), compiler); + } + + #[inline] + fn from_parameter(point: Self::ParameterField) -> Self::Field { + //Field::new_constant(&point.0, compiler) + todo!() // How? + } +} + +impl poseidon::Specification for Spec +where + Self: Specification, + F: RichField + Extendable, +{ + #[inline] + fn apply_sbox(point: &mut Self::Field, _: &mut ()) { + point.0 = point.0.exp_u64(Self::SBOX_EXPONENT); + } +} + +impl poseidon::Specification> + for Spec +where + Self: Specification, + F: RichField + Extendable, + ::Field: Extendable, +{ + #[inline] + fn apply_sbox(point: &mut Self::Field, compiler: &mut Compiler) { + let mut current = *point; + let mut product = Field::new(compiler.builder.one()); + + for j in 0..bits_u64(Self::SBOX_EXPONENT) { + if (Self::SBOX_EXPONENT >> j & 1) != 0 { + product = product.mul(current, compiler); + } + current = current.mul(current, compiler) + } + *point = product + } +} + +// impl poseidon::Constants for Spec { +// const WIDTH: usize = 3; +// const FULL_ROUNDS: usize = 8; +// const PARTIAL_ROUNDS: usize = 55; +// } + +// impl poseidon::Constants for Spec { +// const WIDTH: usize = 4; +// const FULL_ROUNDS: usize = 8; +// const PARTIAL_ROUNDS: usize = 55; +// } + +// impl poseidon::Constants for Spec { +// const WIDTH: usize = 5; +// const FULL_ROUNDS: usize = 8; +// const PARTIAL_ROUNDS: usize = 56; +// } + +// impl poseidon::Constants for Spec { +// const WIDTH: usize = 6; +// const FULL_ROUNDS: usize = 8; +// const PARTIAL_ROUNDS: usize = 56; +// } From 79cfe479301399db60edaf25bb33b60ea25a458d Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Thu, 15 Dec 2022 15:45:36 -0500 Subject: [PATCH 12/15] feat: move to new SBoxExponent API Signed-off-by: Brandon H. Gomes --- plugins/arkworks/src/poseidon/mod.rs | 8 ++++---- plugins/plonky2/src/poseidon/mod.rs | 30 +++++++++++++--------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/plugins/arkworks/src/poseidon/mod.rs b/plugins/arkworks/src/poseidon/mod.rs index dd00ead1..654aa2de 100644 --- a/plugins/arkworks/src/poseidon/mod.rs +++ b/plugins/arkworks/src/poseidon/mod.rs @@ -11,6 +11,7 @@ use openzl_crypto::poseidon::{ self, encryption::BlockElement, hash::DomainTag, Constants, FieldGeneration, NativeField, ParameterFieldType, SBoxExponent, }; +use openzl_util::derivative; #[cfg(test)] pub mod test; @@ -140,10 +141,9 @@ where } /// Poseidon Specification Configuration -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Spec(PhantomData) -where - F: PrimeField; +#[derive(derivative::Derivative)] +#[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Spec(PhantomData); impl Specification for Spec where diff --git a/plugins/plonky2/src/poseidon/mod.rs b/plugins/plonky2/src/poseidon/mod.rs index a34b5728..bfc87f98 100644 --- a/plugins/plonky2/src/poseidon/mod.rs +++ b/plugins/plonky2/src/poseidon/mod.rs @@ -1,12 +1,9 @@ //! Poseidon Arkworks Backend use crate::{ - base::util::bits_u64, + base::{field::goldilocks_field::GoldilocksField, util::bits_u64}, compiler::Compiler as PlonkCompiler, field::{Extendable, Field, Fp, RichField}, - // constraint::{fp::Fp, FpVar, R1CS}, - // ff::{BigInteger, Field, FpParameters, PrimeField}, - // r1cs_std::fields::FieldVar, }; use core::marker::PhantomData; use eclair::{ @@ -15,20 +12,18 @@ use eclair::{ }; use openzl_crypto::poseidon::{ self, encryption::BlockElement, hash::DomainTag, Constants, FieldGeneration, NativeField, - ParameterFieldType, + ParameterFieldType, SBoxExponent, }; +use openzl_util::derivative; use plonky2::field::types::Field as _; /// Compiler Type. type Compiler = PlonkCompiler<::Field, D>; /// Poseidon Permutation Specification. -pub trait Specification: Constants { +pub trait Specification: Constants + SBoxExponent { /// Field Type type Field: RichField; - - /// S-BOX Exponenet - const SBOX_EXPONENT: u64; } impl NativeField for Fp @@ -150,19 +145,16 @@ where } /// Poseidon Specification Configuration -#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Spec(PhantomData) -where - F: RichField + Extendable; +#[derive(derivative::Derivative)] +#[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Spec(PhantomData); impl Specification for Spec where F: RichField + Extendable, - Self: poseidon::Constants, + Self: poseidon::Constants + SBoxExponent, { type Field = F; - - const SBOX_EXPONENT: u64 = 5; } impl Constant for Spec @@ -319,6 +311,12 @@ where } } +impl poseidon::SBoxExponent + for Spec +{ + const SBOX_EXPONENT: u64 = 7; +} + // impl poseidon::Constants for Spec { // const WIDTH: usize = 3; // const FULL_ROUNDS: usize = 8; From 1fbb5c83382647c07bde41792c19d527cb41f6fa Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 20 Jan 2023 11:59:51 -0500 Subject: [PATCH 13/15] fix: use correct poseidon impl Signed-off-by: Brandon H. Gomes --- openzl-crypto/src/poseidon/hash.rs | 14 +++--- openzl-crypto/src/poseidon/mds.rs | 6 +-- openzl-crypto/src/poseidon/mod.rs | 6 +-- openzl-tutorials/src/poseidon.rs | 2 +- plugins/arkworks/src/poseidon/mod.rs | 6 +-- plugins/plonky2/Cargo.toml | 18 ++++--- plugins/plonky2/src/lib.rs | 3 ++ plugins/plonky2/src/poseidon/mod.rs | 73 +++++++++++++++------------- 8 files changed, 68 insertions(+), 60 deletions(-) diff --git a/openzl-crypto/src/poseidon/hash.rs b/openzl-crypto/src/poseidon/hash.rs index 13f4a2e9..f4eefe73 100644 --- a/openzl-crypto/src/poseidon/hash.rs +++ b/openzl-crypto/src/poseidon/hash.rs @@ -86,8 +86,8 @@ where /// Builds a new [`Hasher`] over `permutation` using `T` to generate the domain tag. #[inline] - pub fn from_permutation(permutation: Permutation) -> Self { - Self::new(permutation, S::from_parameter(T::domain_tag())) + pub fn from_permutation(permutation: Permutation, compiler: &mut COM) -> Self { + Self::new(permutation, S::from_parameter(T::domain_tag(), compiler)) } /// Computes the hash over `input` in the given `compiler` and returns the untruncated state. @@ -116,7 +116,7 @@ where #[inline] fn new_constant(this: &Self::Type, compiler: &mut COM) -> Self { - Self::from_permutation(this.permutation.as_constant(compiler)) + Self::from_permutation(this.permutation.as_constant(compiler), compiler) } } @@ -173,10 +173,10 @@ where } } -impl Sample for Hasher +impl Sample for Hasher where - S: Specification, - Permutation: Sample, + S: Specification, + Permutation: Sample, S::ParameterField: NativeField + FieldGeneration, T: DomainTag, { @@ -185,6 +185,6 @@ where where R: RngCore + ?Sized, { - Self::from_permutation(rng.sample(distribution)) + Self::from_permutation(rng.sample(distribution), &mut ()) } } diff --git a/openzl-crypto/src/poseidon/mds.rs b/openzl-crypto/src/poseidon/mds.rs index e983b890..8af6d6f3 100644 --- a/openzl-crypto/src/poseidon/mds.rs +++ b/openzl-crypto/src/poseidon/mds.rs @@ -85,13 +85,13 @@ where where F: FieldGeneration, { - let ys: Vec = (t as u64..2 * t as u64).map(F::from_u64).collect(); // Change u64 to integer mod order(F) + let ys: Vec = (t as u32..2 * t as u32).map(F::from_u32).collect(); // TODO: Change u64 to integer mod order(F) SquareMatrix::new_unchecked(Matrix::new_unchecked( - (0..t as u64) + (0..t as u32) .map(|x| { ys.iter() .map(|y| { - F::add(&F::from_u64(x), y) + F::add(&F::from_u32(x), y) .inverse() .expect("`x+y` is invertible.") }) diff --git a/openzl-crypto/src/poseidon/mod.rs b/openzl-crypto/src/poseidon/mod.rs index 1d39d2cc..8c5861e4 100644 --- a/openzl-crypto/src/poseidon/mod.rs +++ b/openzl-crypto/src/poseidon/mod.rs @@ -66,8 +66,8 @@ pub trait FieldGeneration { /// Number of bits of modulus of the field. const MODULUS_BITS: usize; - /// Converts a `u64` value to a field element. - fn from_u64(elem: u64) -> Self; + /// Converts a `u32` value to a field element. + fn from_u32(elem: u32) -> Self; /// Converts from `bits` into a field element in big endian order, returning `None` if `bits` /// are out of range. @@ -150,7 +150,7 @@ pub trait Field: ParameterFieldType { fn add_const_assign(lhs: &mut Self::Field, rhs: &Self::ParameterField, compiler: &mut COM); /// Converts a constant parameter `point` for permutation state. - fn from_parameter(point: Self::ParameterField) -> Self::Field; + fn from_parameter(point: Self::ParameterField, compiler: &mut COM) -> Self::Field; } /// Poseidon Permutation Specification diff --git a/openzl-tutorials/src/poseidon.rs b/openzl-tutorials/src/poseidon.rs index 6032b619..3312855f 100644 --- a/openzl-tutorials/src/poseidon.rs +++ b/openzl-tutorials/src/poseidon.rs @@ -311,7 +311,7 @@ pub mod bls12_381 { impl FieldGeneration for BlsScalar { const MODULUS_BITS: usize = 255; - fn from_u64(elem: u64) -> Self { + fn from_u32(elem: u32) -> Self { Self(Fr::from(elem)) } diff --git a/plugins/arkworks/src/poseidon/mod.rs b/plugins/arkworks/src/poseidon/mod.rs index 654aa2de..c72a2583 100644 --- a/plugins/arkworks/src/poseidon/mod.rs +++ b/plugins/arkworks/src/poseidon/mod.rs @@ -82,7 +82,7 @@ where } #[inline] - fn from_u64(elem: u64) -> Self { + fn from_u32(elem: u32) -> Self { Self(F::from(elem)) } } @@ -212,7 +212,7 @@ where } #[inline] - fn from_parameter(point: Self::ParameterField) -> Self::Field { + fn from_parameter(point: Self::ParameterField, _: &mut ()) -> Self::Field { point } } @@ -263,7 +263,7 @@ where } #[inline] - fn from_parameter(point: Self::ParameterField) -> Self::Field { + fn from_parameter(point: Self::ParameterField, _: &mut Compiler) -> Self::Field { FpVar::Constant(point.0) } } diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index c05408e1..f87bdc8d 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -28,18 +28,20 @@ ecdsa = ["plonky2_ecdsa"] # Standard Library std = [ - "anyhow/std", - "openzl-crypto/std", - "openzl-util/std", - "plonky2/std", - "starky/std", + "anyhow/std", + "num-bigint/std", + "openzl-crypto/std", + "openzl-util/std", + "plonky2/std", + "starky/std" ] [dependencies] anyhow = { version = "1.0.66", default-features = false } eclair = { path = "../../eclair", default-features = false } +num-bigint = { version = "0.4.3", default-features = false } openzl-crypto = { path = "../../openzl-crypto", default-features = false } openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } -plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", optional = true, default-features = false } -starky = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } +plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } +plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", optional = true, default-features = false } +starky = { git = "https://github.com/openzklib/plonky2", default-features = false } diff --git a/plugins/plonky2/src/lib.rs b/plugins/plonky2/src/lib.rs index c3333bd3..ccb8853a 100644 --- a/plugins/plonky2/src/lib.rs +++ b/plugins/plonky2/src/lib.rs @@ -13,5 +13,8 @@ pub mod compiler; pub mod field; pub mod poseidon; +#[doc(inline)] +pub use num_bigint; + #[doc(inline)] pub use starky; diff --git a/plugins/plonky2/src/poseidon/mod.rs b/plugins/plonky2/src/poseidon/mod.rs index bfc87f98..c1406461 100644 --- a/plugins/plonky2/src/poseidon/mod.rs +++ b/plugins/plonky2/src/poseidon/mod.rs @@ -1,4 +1,4 @@ -//! Poseidon Arkworks Backend +//! Poseidon Plonky2 Backend use crate::{ base::{field::goldilocks_field::GoldilocksField, util::bits_u64}, @@ -10,6 +10,7 @@ use eclair::{ alloc::Constant, ops::{Add, Mul, Sub}, }; +use num_bigint::BigUint; use openzl_crypto::poseidon::{ self, encryption::BlockElement, hash::DomainTag, Constants, FieldGeneration, NativeField, ParameterFieldType, SBoxExponent, @@ -79,14 +80,26 @@ where #[inline] fn try_from_bits_be(bits: &[bool]) -> Option { - //F::from_repr(F::BigInt::from_bits_be(bits)).map(Self) - todo!() + let mut bytes = Vec::new(); + let mut acc: u8 = 0; + let mut bits = bits.to_vec(); + bits.reverse(); + for bits8 in bits.chunks(8) { + for bit in bits8.iter().rev() { + acc <<= 1; + acc += *bit as u8; + } + bytes.push(acc); + acc = 0; + } + Some(Self(F::from_noncanonical_biguint(BigUint::from_bytes_be( + &bytes, + )))) } #[inline] - fn from_u64(elem: u64) -> Self { - //Self(F::from_canonical_u32(elem as u32)) - todo!() // Change this function + fn from_u32(elem: u32) -> Self { + Self(F::from_canonical_u32(elem)) } } @@ -136,11 +149,11 @@ impl Constant for TwoPowerMinusOneDomainTag { impl DomainTag for TwoPowerMinusOneDomainTag where S: Specification + ParameterFieldType>, + S::Field: From, { #[inline] fn domain_tag() -> Fp<::Field> { - //Fp(S::Field::from(((1 << (S::WIDTH - 1)) - 1) as u128)) - todo!() + Fp(S::Field::from(((1 << (S::WIDTH - 1)) - 1) as u32)) } } @@ -216,7 +229,7 @@ where } #[inline] - fn from_parameter(point: Self::ParameterField) -> Self::Field { + fn from_parameter(point: Self::ParameterField, _: &mut ()) -> Self::Field { point } } @@ -272,9 +285,11 @@ where } #[inline] - fn from_parameter(point: Self::ParameterField) -> Self::Field { - //Field::new_constant(&point.0, compiler) - todo!() // How? + fn from_parameter( + point: Self::ParameterField, + compiler: &mut Compiler, + ) -> Self::Field { + Field::new_constant(&point.0, compiler) } } @@ -317,26 +332,14 @@ impl poseidon::SBoxExponent const SBOX_EXPONENT: u64 = 7; } -// impl poseidon::Constants for Spec { -// const WIDTH: usize = 3; -// const FULL_ROUNDS: usize = 8; -// const PARTIAL_ROUNDS: usize = 55; -// } - -// impl poseidon::Constants for Spec { -// const WIDTH: usize = 4; -// const FULL_ROUNDS: usize = 8; -// const PARTIAL_ROUNDS: usize = 55; -// } - -// impl poseidon::Constants for Spec { -// const WIDTH: usize = 5; -// const FULL_ROUNDS: usize = 8; -// const PARTIAL_ROUNDS: usize = 56; -// } - -// impl poseidon::Constants for Spec { -// const WIDTH: usize = 6; -// const FULL_ROUNDS: usize = 8; -// const PARTIAL_ROUNDS: usize = 56; -// } +impl poseidon::Constants for Spec { + const WIDTH: usize = 8; + const FULL_ROUNDS: usize = 8; + const PARTIAL_ROUNDS: usize = 22; +} + +impl poseidon::Constants for Spec { + const WIDTH: usize = 12; + const FULL_ROUNDS: usize = 8; + const PARTIAL_ROUNDS: usize = 22; +} From 16b729bb20b732671f0829cf8ff13e2495e483ee Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 20 Jan 2023 13:40:33 -0500 Subject: [PATCH 14/15] chore: fix dependencies Signed-off-by: Brandon H. Gomes --- plugins/plonky2/Cargo.toml | 12 ++++++------ plugins/plonky2/src/poseidon/mod.rs | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/plonky2/Cargo.toml b/plugins/plonky2/Cargo.toml index f87bdc8d..639f6089 100644 --- a/plugins/plonky2/Cargo.toml +++ b/plugins/plonky2/Cargo.toml @@ -38,10 +38,10 @@ std = [ [dependencies] anyhow = { version = "1.0.66", default-features = false } -eclair = { path = "../../eclair", default-features = false } +eclair = { path = "../../eclair", default-features = false, features = ["alloc"] } num-bigint = { version = "0.4.3", default-features = false } -openzl-crypto = { path = "../../openzl-crypto", default-features = false } -openzl-util = { path = "../../openzl-util", default-features = false } -plonky2 = { git = "https://github.com/openzklib/plonky2", default-features = false } -plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", optional = true, default-features = false } -starky = { git = "https://github.com/openzklib/plonky2", default-features = false } +openzl-crypto = { path = "../../openzl-crypto", default-features = false, features = ["alloc"] } +openzl-util = { path = "../../openzl-util", default-features = false, features = ["alloc"] } +plonky2 = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } +plonky2_ecdsa = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", optional = true, default-features = false } +starky = { git = "https://github.com/openzklib/plonky2", branch = "feat/circuit-data-serde", default-features = false } diff --git a/plugins/plonky2/src/poseidon/mod.rs b/plugins/plonky2/src/poseidon/mod.rs index c1406461..4aded4fe 100644 --- a/plugins/plonky2/src/poseidon/mod.rs +++ b/plugins/plonky2/src/poseidon/mod.rs @@ -5,6 +5,7 @@ use crate::{ compiler::Compiler as PlonkCompiler, field::{Extendable, Field, Fp, RichField}, }; +use alloc::vec::Vec; use core::marker::PhantomData; use eclair::{ alloc::Constant, From 69805e36d8403ae912da017a33b8be451986c5db Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 20 Jan 2023 13:50:55 -0500 Subject: [PATCH 15/15] wip: remove stable from the CI since it won't work with plonky2 yet Signed-off-by: Brandon H. Gomes --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f416a33..871ea018 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: os: - ubuntu-latest channel: - - stable + # TODO: add custom stable checks for those parts of the workspace that can run on it - nightly runs-on: ${{ matrix.os }} steps: @@ -74,7 +74,7 @@ jobs: - ubuntu-latest - windows-latest channel: - - stable + # TODO: add custom stable checks for those parts of the workspace that can run on it - nightly runs-on: ${{ matrix.os }} steps: @@ -93,7 +93,7 @@ jobs: - ubuntu-latest - windows-latest channel: - - stable + # TODO: add custom stable checks for those parts of the workspace that can run on it - nightly runs-on: ${{ matrix.os }} steps: