From fbc014dd10ceda99c32303c9b8f19c123df41a49 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 17 Nov 2024 22:58:59 -0800 Subject: [PATCH 1/2] staging area for bumping arkworks v0.5 in monorepo --- Cargo.toml | 22 +-- crates/bench/Cargo.toml | 2 +- crates/core/asset/src/value.rs | 7 +- .../shielded-pool/src/spend/proof.rs | 10 +- crates/core/keys/src/keys/ivk.rs | 15 +- crates/core/num/src/amount.rs | 20 ++- crates/core/num/src/fixpoint.rs | 156 ++++++++++-------- crates/crypto/proof-setup/Cargo.toml | 2 +- crates/crypto/proof-setup/src/single/dlog.rs | 3 +- crates/crypto/proof-setup/src/single/mod.rs | 3 +- .../crypto/proof-setup/src/single/phase1.rs | 2 +- .../crypto/proof-setup/src/single/phase2.rs | 2 +- crates/crypto/tct/Cargo.toml | 2 +- crates/crypto/tct/src/r1cs.rs | 23 +-- tools/parameter-setup/Cargo.toml | 6 +- 15 files changed, 154 insertions(+), 121 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a2b54d94b0..0b98ddbe3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,14 +111,14 @@ license = "MIT OR Apache-2.0" [workspace.dependencies] anyhow = { version = "1.0.75" } -ark-ec = { default-features = false, version = "0.4.2" } -ark-ff = { default-features = false, version = "0.4.2" } -ark-groth16 = { default-features = false, version = "0.4.0" } -ark-r1cs-std = { default-features = false, version = "0.4.0" } -ark-relations = { version = "0.4" } -ark-serialize = { version = "0.4.2" } -ark-snark = { version = "0.4.0" } -ark-std = { default-features = false, version = "0.4" } +ark-ec = { default-features = false, version = "0.5" } +ark-ff = { default-features = false, version = "0.5" } +ark-groth16 = { default-features = false, version = "0.5" } +ark-r1cs-std = { default-features = false, version = "0.5" } +ark-relations = { version = "0.5" } +ark-serialize = { version = "0.5" } +ark-snark = { version = "0.5" } +ark-std = { default-features = false, version = "0.5" } assert_cmd = { version = "2.0" } async-stream = { version = "0.3.5" } async-trait = { version = "0.1.52" } @@ -138,10 +138,10 @@ cnidarium = { default-features = false, path = "crates/cn cnidarium-component = { default-features = false, path = "crates/cnidarium-component" } cometindex = { path = "crates/util/cometindex" } criterion = { version = "0.4" } -decaf377 = { default-features = false, version = "0.10.1" } +decaf377 = { default-features = false, git = "https://github.com/penumbra-zone/decaf377", branch = "arkworks-0.5" } decaf377-fmd = { path = "crates/crypto/decaf377-fmd" } decaf377-ka = { path = "crates/crypto/decaf377-ka" } -decaf377-rdsa = { version = "0.11.0" } +decaf377-rdsa = { git = "https://github.com/penumbra-zone/decaf377-rdsa", branch = "arkworks-0.5" } derivative = { version = "2.2" } directories = { version = "4.0.1" } ed25519-consensus = { version = "2.1" } @@ -199,7 +199,7 @@ penumbra-wallet = { path = "crates/wallet" } penumbra-extension = { path = "crates/penumbra-extension", default-features = false } pin-project = { version = "1.0.12" } pin-project-lite = { version = "0.2.9" } -poseidon377 = { version = "1.2.0" } +poseidon377 = { git = "https://github.com/penumbra-zone/poseidon377", branch = "arkworks-0.5" } proptest = { version = "1" } proptest-derive = { version = "0.3" } prost = { version = "0.12.3" } diff --git a/crates/bench/Cargo.toml b/crates/bench/Cargo.toml index dc68edfe71..431d36e17a 100644 --- a/crates/bench/Cargo.toml +++ b/crates/bench/Cargo.toml @@ -61,7 +61,7 @@ name = "arkworks" harness = false [dependencies] -ark-bls12-377 = "0.4.0" +ark-bls12-377 = "0.5.0" ark-ec = {workspace = true} ark-ff = {workspace = true, default-features = false} ark-groth16 = {workspace = true, default-features = false} diff --git a/crates/core/asset/src/value.rs b/crates/core/asset/src/value.rs index a8b6b1e9c9..847bb04e93 100644 --- a/crates/core/asset/src/value.rs +++ b/crates/core/asset/src/value.rs @@ -3,7 +3,10 @@ use ark_ff::ToConstraintField; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; -use decaf377::{r1cs::FqVar, Fq}; +use decaf377::{ + r1cs::{fqvar_ext::FqVarExtension, FqVar}, + Fq, +}; use std::{ convert::{TryFrom, TryInto}, @@ -319,7 +322,7 @@ impl EqGadget for ValueVar { fn is_eq(&self, other: &Self) -> Result, SynthesisError> { let amount_eq = self.amount.is_eq(&other.amount)?; let asset_id_eq = self.asset_id.is_eq(&other.asset_id)?; - amount_eq.and(&asset_id_eq) + FqVar::and(&amount_eq, &asset_id_eq) } } diff --git a/crates/core/component/shielded-pool/src/spend/proof.rs b/crates/core/component/shielded-pool/src/spend/proof.rs index 936f03f329..50af43826d 100644 --- a/crates/core/component/shielded-pool/src/spend/proof.rs +++ b/crates/core/component/shielded-pool/src/spend/proof.rs @@ -4,12 +4,14 @@ use tct::Root; use anyhow::Result; use ark_r1cs_std::{ - prelude::{EqGadget, FieldVar}, + prelude::{EqGadget, FieldVar, ToBitsGadget}, uint8::UInt8, - ToBitsGadget, }; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use decaf377::{r1cs::FqVar, Bls12_377, Fq, Fr}; +use decaf377::{ + r1cs::{fqvar_ext::FqVarExtension, FqVar}, + Bls12_377, Fq, Fr, +}; use ark_ff::ToConstraintField; use ark_groth16::{ @@ -189,7 +191,7 @@ impl ConstraintSynthesizer for SpendCircuit { // // We short circuit the merkle path verification if the note is a _dummy_ spend (a spend // with zero value), since these are never committed to the state commitment tree. - let is_not_dummy = note_var.amount().is_eq(&FqVar::zero())?.not(); + let is_not_dummy = FqVar::not(¬e_var.amount().is_eq(&FqVar::zero())?)?; merkle_path_var.verify( cs.clone(), &is_not_dummy, diff --git a/crates/core/keys/src/keys/ivk.rs b/crates/core/keys/src/keys/ivk.rs index 1338e830d4..df8dd4d698 100644 --- a/crates/core/keys/src/keys/ivk.rs +++ b/crates/core/keys/src/keys/ivk.rs @@ -4,7 +4,7 @@ use rand_core::{CryptoRng, RngCore}; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::SynthesisError; use decaf377::{ - r1cs::{ElementVar, FqVar}, + r1cs::{fqvar_ext::FqVarExtension, ElementVar, FqVar}, Fq, Fr, }; @@ -157,12 +157,13 @@ impl IncomingViewingKeyVar { core::cmp::Ordering::Less, false, )?; - let overflows = a_var - .is_eq(&FqVar::new_constant( - cs.clone(), - &Fq::from(MOD_R_QUOTIENT as u64), - )?)? - .and(&is_less_than_q_minus_4_mod_r.not())?; + let overflows = FqVar::and( + &FqVar::is_eq( + &a_var, + &FqVar::new_constant(cs.clone(), &Fq::from(MOD_R_QUOTIENT as u64))?, + )?, + &FqVar::not(&is_less_than_q_minus_4_mod_r)?, + )?; overflows.enforce_equal(&Boolean::FALSE)?; Ok(IncomingViewingKeyVar { inner: ivk_mod_r }) diff --git a/crates/core/num/src/amount.rs b/crates/core/num/src/amount.rs index fbb9eb2ca6..d24d3bcff6 100644 --- a/crates/core/num/src/amount.rs +++ b/crates/core/num/src/amount.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; use std::{fmt::Display, iter::Sum, num::NonZeroU128, ops}; use crate::fixpoint::{bit_constrain, U128x128, U128x128Var}; +use decaf377::r1cs::fqvar_ext::FqVarExtension; use decaf377::r1cs::FqVar; #[derive(Serialize, Default, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] @@ -123,7 +124,7 @@ pub fn is_bit_constrained( } // Construct an FqVar from those n Boolean constraints - let constructed_fqvar = Boolean::::le_bits_to_fp_var(&boolean_constraints.to_bits_le()?) + let constructed_fqvar = Boolean::::le_bits_to_fp(&boolean_constraints.to_bits_le()?) .expect("can convert to bits"); constructed_fqvar.is_eq(&value) } @@ -161,7 +162,8 @@ impl AmountVar { // Constrain either quo_var or divisor_var to be 64 bits to guard against overflow let q_is_64_bits = is_bit_constrained(self.cs(), quo_var.amount.clone(), 64)?; let d_is_64_bits = is_bit_constrained(self.cs(), divisor_var.amount.clone(), 64)?; - let q_or_d_is_64_bits = q_is_64_bits.or(&d_is_64_bits)?; + + let q_or_d_is_64_bits = FqVar::or(&q_is_64_bits, &d_is_64_bits)?; q_or_d_is_64_bits.enforce_equal(&Boolean::constant(true))?; // Constrain: numerator = quo * divisor + rem @@ -528,10 +530,18 @@ impl U128x128Var { impl From for AmountVar { fn from(value: U128x128Var) -> Self { let mut le_bits = Vec::new(); - le_bits.extend_from_slice(&value.limbs[2].to_bits_le()[..]); - le_bits.extend_from_slice(&value.limbs[3].to_bits_le()[..]); + le_bits.extend_from_slice( + &value.limbs[2] + .to_bits_le() + .expect("limb can be converted to bits")[..], + ); + le_bits.extend_from_slice( + &value.limbs[3] + .to_bits_le() + .expect("limb can be converted to bits")[..], + ); Self { - amount: Boolean::::le_bits_to_fp_var(&le_bits[..]).expect("can convert to bits"), + amount: Boolean::::le_bits_to_fp(&le_bits[..]).expect("can convert to bits"), } } } diff --git a/crates/core/num/src/fixpoint.rs b/crates/core/num/src/fixpoint.rs index d41b92d989..050b7a6ae2 100644 --- a/crates/core/num/src/fixpoint.rs +++ b/crates/core/num/src/fixpoint.rs @@ -10,19 +10,16 @@ mod ops; #[cfg(test)] mod tests; +use self::div::stub_div_rem_u384_by_u256; +use crate::{Amount, AmountVar}; use ark_ff::{BigInteger, PrimeField, ToConstraintField, Zero}; -use ark_r1cs_std::bits::uint64::UInt64; use ark_r1cs_std::fields::fp::FpVar; use ark_r1cs_std::prelude::*; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; - +use decaf377::r1cs::fqvar_ext::FqVarExtension; use decaf377::{r1cs::FqVar, Fq}; use ethnum::U256; -use crate::{Amount, AmountVar}; - -use self::div::stub_div_rem_u384_by_u256; - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("overflow")] @@ -238,11 +235,11 @@ impl AllocVar for U128x128Var { .chain(limb_3_var.to_bits_le()) .collect::>(); - hi_128_var.enforce_equal(&Boolean::::le_bits_to_fp_var( - &(hi_128_bits[..]).to_bits_le()?, + hi_128_var.enforce_equal(&Boolean::::le_bits_to_fp( + &(hi_128_bits[..])[0].to_bits_le()?, )?)?; - lo_128_var.enforce_equal(&Boolean::::le_bits_to_fp_var( - &(lo_128_bits[..]).to_bits_le()?, + lo_128_var.enforce_equal(&Boolean::::le_bits_to_fp( + &(lo_128_bits[..])[0].to_bits_le()?, )?)?; Ok(Self { @@ -280,15 +277,23 @@ impl U128x128Var { // x = x0 + x1 * 2^64 + x2 * 2^128 + x3 * 2^192 // y = [y0, y1, y2, y3] // y = y0 + y1 * 2^64 + y2 * 2^128 + y3 * 2^192 - let x0 = Boolean::::le_bits_to_fp_var(&self.limbs[0].to_bits_le())?; - let x1 = Boolean::::le_bits_to_fp_var(&self.limbs[1].to_bits_le())?; - let x2 = Boolean::::le_bits_to_fp_var(&self.limbs[2].to_bits_le())?; - let x3 = Boolean::::le_bits_to_fp_var(&self.limbs[3].to_bits_le())?; - - let y0 = Boolean::::le_bits_to_fp_var(&rhs.limbs[0].to_bits_le())?; - let y1 = Boolean::::le_bits_to_fp_var(&rhs.limbs[1].to_bits_le())?; - let y2 = Boolean::::le_bits_to_fp_var(&rhs.limbs[2].to_bits_le())?; - let y3 = Boolean::::le_bits_to_fp_var(&rhs.limbs[3].to_bits_le())?; + let x0 = Boolean::::le_bits_to_fp(&self.limbs[0].to_bits_le()?)?; + let x1 = Boolean::::le_bits_to_fp(&self.limbs[1].to_bits_le()?)?; + let x2 = Boolean::::le_bits_to_fp(&self.limbs[2].to_bits_le()?)?; + let x3 = Boolean::::le_bits_to_fp(&self.limbs[3].to_bits_le()?)?; + + let y0 = Boolean::::le_bits_to_fp( + &rhs.limbs[0].to_bits_le().expect("convert limbs to bits"), + )?; + let y1 = Boolean::::le_bits_to_fp( + &rhs.limbs[1].to_bits_le().expect("convert limbs to bits"), + )?; + let y2 = Boolean::::le_bits_to_fp( + &rhs.limbs[2].to_bits_le().expect("convert limbs to bits"), + )?; + let y3 = Boolean::::le_bits_to_fp( + &rhs.limbs[3].to_bits_le().expect("convert limbs to bits"), + )?; // z = x + y // z = [z0, z1, z2, z3] @@ -300,17 +305,17 @@ impl U128x128Var { // z0 <= (2^64 - 1) + (2^64 - 1) < 2^(65) => 65 bits let z0_bits = bit_constrain(z0_raw, 65)?; // no carry-in let z0 = UInt64::from_bits_le(&z0_bits[0..64]); - let c1 = Boolean::::le_bits_to_fp_var(&z0_bits[64..].to_bits_le()?)?; + let c1 = Boolean::::le_bits_to_fp(&z0_bits[64..].to_bits_le()?)?; // z1 <= (2^64 - 1) + (2^64 - 1) + 1 < 2^(65) => 65 bits let z1_bits = bit_constrain(z1_raw + c1, 65)?; // carry-in c1 let z1 = UInt64::from_bits_le(&z1_bits[0..64]); - let c2 = Boolean::::le_bits_to_fp_var(&z1_bits[64..].to_bits_le()?)?; + let c2 = Boolean::::le_bits_to_fp(&z1_bits[64..].to_bits_le()?)?; // z2 <= (2^64 - 1) + (2^64 - 1) + 1 < 2^(65) => 65 bits let z2_bits = bit_constrain(z2_raw + c2, 65)?; // carry-in c2 let z2 = UInt64::from_bits_le(&z2_bits[0..64]); - let c3 = Boolean::::le_bits_to_fp_var(&z2_bits[64..].to_bits_le()?)?; + let c3 = Boolean::::le_bits_to_fp(&z2_bits[64..].to_bits_le()?)?; // z3 <= (2^64 - 1) + (2^64 - 1) + 1 < 2^(65) => 65 bits // However, the last bit (65th) which would be used as a final carry flag, should be 0 if there is no overflow. @@ -336,15 +341,15 @@ impl U128x128Var { // x = x0 + x1 * 2^64 + x2 * 2^128 + x3 * 2^192 // y = [y0, y1, y2, y3] // y = y0 + y1 * 2^64 + y2 * 2^128 + y3 * 2^192 - let x0 = Boolean::::le_bits_to_fp_var(&self.limbs[0].to_bits_le())?; - let x1 = Boolean::::le_bits_to_fp_var(&self.limbs[1].to_bits_le())?; - let x2 = Boolean::::le_bits_to_fp_var(&self.limbs[2].to_bits_le())?; - let x3 = Boolean::::le_bits_to_fp_var(&self.limbs[3].to_bits_le())?; + let x0 = Boolean::::le_bits_to_fp(&self.limbs[0].to_bits_le()?)?; + let x1 = Boolean::::le_bits_to_fp(&self.limbs[1].to_bits_le()?)?; + let x2 = Boolean::::le_bits_to_fp(&self.limbs[2].to_bits_le()?)?; + let x3 = Boolean::::le_bits_to_fp(&self.limbs[3].to_bits_le()?)?; - let y0 = Boolean::::le_bits_to_fp_var(&rhs.limbs[0].to_bits_le())?; - let y1 = Boolean::::le_bits_to_fp_var(&rhs.limbs[1].to_bits_le())?; - let y2 = Boolean::::le_bits_to_fp_var(&rhs.limbs[2].to_bits_le())?; - let y3 = Boolean::::le_bits_to_fp_var(&rhs.limbs[3].to_bits_le())?; + let y0 = Boolean::::le_bits_to_fp(&rhs.limbs[0].to_bits_le()?)?; + let y1 = Boolean::::le_bits_to_fp(&rhs.limbs[1].to_bits_le()?)?; + let y2 = Boolean::::le_bits_to_fp(&rhs.limbs[2].to_bits_le()?)?; + let y3 = Boolean::::le_bits_to_fp(&rhs.limbs[3].to_bits_le()?)?; // z = x * y // z = [z0, z1, z2, z3, z4, z5, z6, z7] @@ -372,7 +377,7 @@ impl U128x128Var { // Constrain: t0 fits in 193 bits // t1 = (t0 >> 128) + z2 - let t1 = z2 + Boolean::::le_bits_to_fp_var(&t0_bits[128..193].to_bits_le()?)?; + let t1 = z2 + Boolean::::le_bits_to_fp(&t0_bits[128..193].to_bits_le()?)?; // Constrain: t1 fits in 130 bits let t1_bits = bit_constrain(t1, 130)?; @@ -380,7 +385,7 @@ impl U128x128Var { let w0 = UInt64::from_bits_le(&t1_bits[0..64]); // t2 = (t1 >> 64) + z3 - let t2 = z3 + Boolean::::le_bits_to_fp_var(&t1_bits[64..129].to_bits_le()?)?; + let t2 = z3 + Boolean::::le_bits_to_fp(&t1_bits[64..129].to_bits_le()?)?; // Constrain: t2 fits in 129 bits let t2_bits = bit_constrain(t2, 129)?; @@ -388,7 +393,7 @@ impl U128x128Var { let w1 = UInt64::from_bits_le(&t2_bits[0..64]); // t3 = (t2 >> 64) + z4 - let t3 = z4 + Boolean::::le_bits_to_fp_var(&t2_bits[64..129].to_bits_le()?)?; + let t3 = z4 + Boolean::::le_bits_to_fp(&t2_bits[64..129].to_bits_le()?)?; // Constrain: t3 fits in 128 bits let t3_bits = bit_constrain(t3, 128)?; @@ -396,7 +401,7 @@ impl U128x128Var { let w2 = UInt64::from_bits_le(&t3_bits[0..64]); // t4 = (t3 >> 64) + z5 - let t4 = z5 + Boolean::::le_bits_to_fp_var(&t3_bits[64..128].to_bits_le()?)?; + let t4 = z5 + Boolean::::le_bits_to_fp(&t3_bits[64..128].to_bits_le()?)?; // Constrain: t4 fits in 64 bits let t4_bits = bit_constrain(t4, 64)?; // If we didn't overflow, it will fit in 64 bits. @@ -417,12 +422,15 @@ impl U128x128Var { .to_bits_le() .into_iter() .chain(self.limbs[1].to_bits_le()) + .flat_map(|vec| vec.into_iter()) .collect::>(); let hi_128_bits = self.limbs[2] .to_bits_le() .into_iter() .chain(self.limbs[3].to_bits_le()) + .flat_map(|vec| vec.into_iter()) .collect::>(); + lo_128_bits.into_iter().chain(hi_128_bits).collect() } @@ -447,9 +455,16 @@ impl U128x128Var { // we need to make sure that we don't have self < other. // At this point, if we see a 1 bit for self and a 0 bit for other, // we know that self > other. - gt = gt.or(<.not().and(&p)?.and(&q.not())?)?; + + gt = FqVar::or( + >, + &FqVar::and(&FqVar::and(&FqVar::not(<)?, &p)?, &FqVar::not(&q)?)?, + )?; // The exact same logic, but swapping gt <-> lt, p <-> q - lt = lt.or(>.not().and(&q)?.and(&p.not())?)?; + lt = FqVar::or( + <, + &FqVar::and(&FqVar::and(&FqVar::not(>)?, &q)?, &FqVar::not(&p)?)?, + )?; } match ordering { @@ -525,25 +540,25 @@ impl U128x128Var { // ybar = ybar0 + ybar1 * 2^64 + ybar2 * 2^128 + ybar3 * 2^192 // r = r0 + r1 * 2^64 + r2 * 2^128 + r3 * 2^192 - let xbar0 = Boolean::::le_bits_to_fp_var(&xbar[0].to_bits_le())?; - let xbar1 = Boolean::::le_bits_to_fp_var(&xbar[1].to_bits_le())?; - let xbar2 = Boolean::::le_bits_to_fp_var(&xbar[2].to_bits_le())?; - let xbar3 = Boolean::::le_bits_to_fp_var(&xbar[3].to_bits_le())?; + let xbar0 = Boolean::::le_bits_to_fp(&xbar[0].to_bits_le()?)?; + let xbar1 = Boolean::::le_bits_to_fp(&xbar[1].to_bits_le()?)?; + let xbar2 = Boolean::::le_bits_to_fp(&xbar[2].to_bits_le()?)?; + let xbar3 = Boolean::::le_bits_to_fp(&xbar[3].to_bits_le()?)?; - let ybar0 = Boolean::::le_bits_to_fp_var(&ybar[0].to_bits_le())?; - let ybar1 = Boolean::::le_bits_to_fp_var(&ybar[1].to_bits_le())?; - let ybar2 = Boolean::::le_bits_to_fp_var(&ybar[2].to_bits_le())?; - let ybar3 = Boolean::::le_bits_to_fp_var(&ybar[3].to_bits_le())?; + let ybar0 = Boolean::::le_bits_to_fp(&ybar[0].to_bits_le()?)?; + let ybar1 = Boolean::::le_bits_to_fp(&ybar[1].to_bits_le()?)?; + let ybar2 = Boolean::::le_bits_to_fp(&ybar[2].to_bits_le()?)?; + let ybar3 = Boolean::::le_bits_to_fp(&ybar[3].to_bits_le()?)?; - let qbar0 = Boolean::::le_bits_to_fp_var(&qbar[0].to_bits_le())?; - let qbar1 = Boolean::::le_bits_to_fp_var(&qbar[1].to_bits_le())?; - let qbar2 = Boolean::::le_bits_to_fp_var(&qbar[2].to_bits_le())?; - let qbar3 = Boolean::::le_bits_to_fp_var(&qbar[3].to_bits_le())?; + let qbar0 = Boolean::::le_bits_to_fp(&qbar[0].to_bits_le()?)?; + let qbar1 = Boolean::::le_bits_to_fp(&qbar[1].to_bits_le()?)?; + let qbar2 = Boolean::::le_bits_to_fp(&qbar[2].to_bits_le()?)?; + let qbar3 = Boolean::::le_bits_to_fp(&qbar[3].to_bits_le()?)?; - let r0 = Boolean::::le_bits_to_fp_var(&r[0].to_bits_le())?; - let r1 = Boolean::::le_bits_to_fp_var(&r[1].to_bits_le())?; - let r2 = Boolean::::le_bits_to_fp_var(&r[2].to_bits_le())?; - let r3 = Boolean::::le_bits_to_fp_var(&r[3].to_bits_le())?; + let r0 = Boolean::::le_bits_to_fp(&r[0].to_bits_le()?)?; + let r1 = Boolean::::le_bits_to_fp(&r[1].to_bits_le()?)?; + let r2 = Boolean::::le_bits_to_fp(&r[2].to_bits_le()?)?; + let r3 = Boolean::::le_bits_to_fp(&r[3].to_bits_le()?)?; // Let z = qbar * ybar + r. Then z will be 513 bits in general; we want // to constrain it to be equal to xbar * 2^128 so we need the low 384 @@ -584,36 +599,36 @@ impl U128x128Var { // z0 <= (2^64 - 1)(2^64 - 1) + (2^64 - 1) => 128 bits let z0_bits = bit_constrain(z0_raw, 128)?; // no carry-in - let z0 = Boolean::::le_bits_to_fp_var(&z0_bits[0..64].to_bits_le()?)?; - let c1 = Boolean::::le_bits_to_fp_var(&z0_bits[64..].to_bits_le()?)?; // 64 bits + let z0 = Boolean::::le_bits_to_fp(&z0_bits[0..64].to_bits_le()?)?; + let c1 = Boolean::::le_bits_to_fp(&z0_bits[64..].to_bits_le()?)?; // 64 bits // z1 <= 2*(2^64 - 1)(2^64 - 1) + (2^64 - 1) + carry (2^64 - 1) => 129 bits let z1_bits = bit_constrain(z1_raw + c1, 129)?; // carry-in c1 - let z1 = Boolean::::le_bits_to_fp_var(&z1_bits[0..64].to_bits_le()?)?; - let c2 = Boolean::::le_bits_to_fp_var(&z1_bits[64..].to_bits_le()?)?; // 65 bits + let z1 = Boolean::::le_bits_to_fp(&z1_bits[0..64].to_bits_le()?)?; + let c2 = Boolean::::le_bits_to_fp(&z1_bits[64..].to_bits_le()?)?; // 65 bits // z2 <= 3*(2^64 - 1)(2^64 - 1) + (2^64 - 1) + carry (2^65 - 2) => 130 bits let z2_bits = bit_constrain(z2_raw + c2, 130)?; // carry-in c2 - let z2 = Boolean::::le_bits_to_fp_var(&z2_bits[0..64].to_bits_le()?)?; - let c3 = Boolean::::le_bits_to_fp_var(&z2_bits[64..].to_bits_le()?)?; // 66 bits + let z2 = Boolean::::le_bits_to_fp(&z2_bits[0..64].to_bits_le()?)?; + let c3 = Boolean::::le_bits_to_fp(&z2_bits[64..].to_bits_le()?)?; // 66 bits // z3 <= 4*(2^64 - 1)(2^64 - 1) + (2^64 - 1) + carry (2^66 - 1) => 130 bits let z3_bits = bit_constrain(z3_raw + c3, 130)?; // carry-in c3 - let z3 = Boolean::::le_bits_to_fp_var(&z3_bits[0..64].to_bits_le()?)?; - let c4 = Boolean::::le_bits_to_fp_var(&z3_bits[64..].to_bits_le()?)?; // 66 bits + let z3 = Boolean::::le_bits_to_fp(&z3_bits[0..64].to_bits_le()?)?; + let c4 = Boolean::::le_bits_to_fp(&z3_bits[64..].to_bits_le()?)?; // 66 bits // z4 <= 3*(2^64 - 1)(2^64 - 1) + carry (2^66 - 1) => 130 bits // But extra bits beyond 128 spill into z6, which should be zero, so we can constrain to 128 bits. let z4_bits = bit_constrain(z4_raw + c4, 128)?; // carry-in c4 - let z4 = Boolean::::le_bits_to_fp_var(&z4_bits[0..64].to_bits_le()?)?; - let c5 = Boolean::::le_bits_to_fp_var(&z4_bits[64..].to_bits_le()?)?; // 64 bits + let z4 = Boolean::::le_bits_to_fp(&z4_bits[0..64].to_bits_le()?)?; + let c5 = Boolean::::le_bits_to_fp(&z4_bits[64..].to_bits_le()?)?; // 64 bits // z5 <= 2*(2^64 - 1)(2^64 - 1) + (2^64 - 1) // But if there is no overflow, the final carry (which would be c6 constructed from z5_bits[64..]) // should be zero. So instead of constructing that final carry, we can instead bit constrain z5 to // the first 64 bits to save constraints. let z5_bits = bit_constrain(z5_raw + c5, 64)?; // carry-in c5 - let z5 = Boolean::::le_bits_to_fp_var(&z5_bits[0..64].to_bits_le()?)?; + let z5 = Boolean::::le_bits_to_fp(&z5_bits[0..64].to_bits_le()?)?; // Repeat: // We want to constrain @@ -653,9 +668,10 @@ impl U128x128Var { .to_bits_le() .into_iter() .chain(self.limbs[3].to_bits_le().into_iter()) + .flat_map(|vec| vec.into_iter()) .collect::>>(); Ok(AmountVar { - amount: Boolean::::le_bits_to_fp_var(&bits)?, + amount: Boolean::::le_bits_to_fp(&bits)?, }) } @@ -678,10 +694,9 @@ impl EqGadget for U128x128Var { let limb_3_eq = self.limbs[2].is_eq(&other.limbs[2])?; let limb_4_eq = self.limbs[3].is_eq(&other.limbs[3])?; - let limb_12_eq = limb_1_eq.and(&limb_2_eq)?; - let limb_34_eq = limb_3_eq.and(&limb_4_eq)?; - - limb_12_eq.and(&limb_34_eq) + let limb_12_eq = FqVar::and(&limb_1_eq, &limb_2_eq)?; + let limb_34_eq = FqVar::and(&limb_3_eq, &limb_4_eq)?; + FqVar::and(&limb_12_eq, &limb_34_eq) } } @@ -710,7 +725,8 @@ impl CondSelectGadget for U128x128Var { /// Convert Uint64 into an FqVar pub fn convert_uint64_to_fqvar(value: &UInt64) -> FpVar { - Boolean::::le_bits_to_fp_var(&value.to_bits_le()).expect("can convert to bits") + Boolean::::le_bits_to_fp(&value.to_bits_le().expect("convert limb to bits")) + .expect("can convert to bits") } /// Bit constrain for FqVar and return number of bits @@ -729,7 +745,7 @@ pub fn bit_constrain(value: FqVar, n: usize) -> Result>, Synthes } // Construct an FqVar from those n Boolean constraints, and constrain it to be equal to the original value - let constructed_fqvar = Boolean::::le_bits_to_fp_var(&boolean_constraints.to_bits_le()?) + let constructed_fqvar = Boolean::::le_bits_to_fp(&boolean_constraints.to_bits_le()?) .expect("can convert to bits"); constructed_fqvar.enforce_equal(&value)?; diff --git a/crates/crypto/proof-setup/Cargo.toml b/crates/crypto/proof-setup/Cargo.toml index fe2490c5d5..2346a78cd0 100644 --- a/crates/crypto/proof-setup/Cargo.toml +++ b/crates/crypto/proof-setup/Cargo.toml @@ -24,7 +24,7 @@ anyhow = {workspace = true} ark-ec = {workspace = true, default-features = false} ark-ff = {workspace = true, default-features = false} ark-groth16 = {workspace = true, default-features = false} -ark-poly = { version = "0.4.2", default-features = false } +ark-poly = { version = "0.5", default-features = false } ark-relations = {workspace = true} ark-serialize = {workspace = true} blake2b_simd = {workspace = true} diff --git a/crates/crypto/proof-setup/src/single/dlog.rs b/crates/crypto/proof-setup/src/single/dlog.rs index 36f6bfd267..30c1769d29 100644 --- a/crates/crypto/proof-setup/src/single/dlog.rs +++ b/crates/crypto/proof-setup/src/single/dlog.rs @@ -87,8 +87,7 @@ pub fn verify(ctx: &[u8], statement: Statement, proof: &Proof) -> bool { #[cfg(test)] mod test { use super::*; - - use ark_ec::Group; + use ark_ec::PrimeGroup; use rand_core::OsRng; const TEST_CTX: &[u8] = b"Test Context"; diff --git a/crates/crypto/proof-setup/src/single/mod.rs b/crates/crypto/proof-setup/src/single/mod.rs index ecde9175ba..42d0063113 100644 --- a/crates/crypto/proof-setup/src/single/mod.rs +++ b/crates/crypto/proof-setup/src/single/mod.rs @@ -7,7 +7,8 @@ pub mod log; mod phase1; mod phase2; -use ark_ec::{CurveGroup, Group}; +use ark_ec::CurveGroup; +use ark_ec::PrimeGroup; use ark_ff::Zero; use ark_groth16::data_structures::ProvingKey; use ark_groth16::VerifyingKey; diff --git a/crates/crypto/proof-setup/src/single/phase1.rs b/crates/crypto/proof-setup/src/single/phase1.rs index 47f51164aa..a3db0fa81b 100644 --- a/crates/crypto/proof-setup/src/single/phase1.rs +++ b/crates/crypto/proof-setup/src/single/phase1.rs @@ -1,5 +1,5 @@ use anyhow::anyhow; -use ark_ec::Group; +use ark_ec::PrimeGroup; use ark_ff::{One, Zero}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate}; use rand_core::{CryptoRngCore, OsRng}; diff --git a/crates/crypto/proof-setup/src/single/phase2.rs b/crates/crypto/proof-setup/src/single/phase2.rs index 9b7fffef3e..a0b6962b58 100644 --- a/crates/crypto/proof-setup/src/single/phase2.rs +++ b/crates/crypto/proof-setup/src/single/phase2.rs @@ -1,5 +1,5 @@ //! This module is very similar to the one for phase1, so reading that one might be useful. -use ark_ec::Group; +use ark_ec::PrimeGroup; use ark_ff::Zero; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Compress, Validate}; use rand_core::{CryptoRngCore, OsRng}; diff --git a/crates/crypto/tct/Cargo.toml b/crates/crypto/tct/Cargo.toml index 211051c579..ae4daeaef0 100644 --- a/crates/crypto/tct/Cargo.toml +++ b/crates/crypto/tct/Cargo.toml @@ -10,7 +10,7 @@ r1cs = ["ark-r1cs-std", "ark-relations", "decaf377/r1cs", "poseidon377/r1cs"] parallel = ["ark-r1cs-std/parallel", "ark-ff/parallel", "decaf377/parallel", "poseidon377/parallel"] [dependencies] -ark-ed-on-bls12-377 = "0.4" +ark-ed-on-bls12-377 = "0.5" ark-ff = {workspace = true, default-features = false} ark-r1cs-std = {workspace = true, optional = true, default-features = false} ark-relations = {workspace = true, optional = true} diff --git a/crates/crypto/tct/src/r1cs.rs b/crates/crypto/tct/src/r1cs.rs index 068b370328..aea5cedf8c 100644 --- a/crates/crypto/tct/src/r1cs.rs +++ b/crates/crypto/tct/src/r1cs.rs @@ -1,12 +1,11 @@ //! This module defines how to verify TCT auth paths in a rank-1 constraint system. +use crate::{internal::hash::DOMAIN_SEPARATOR, Position, Proof, StateCommitment}; use ark_ff::ToConstraintField; -use ark_r1cs_std::{prelude::*, uint64::UInt64}; +use ark_r1cs_std::uint64::UInt64; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; - +use decaf377::r1cs::fqvar_ext::FqVarExtension; use decaf377::{r1cs::FqVar, Fq}; -use crate::{internal::hash::DOMAIN_SEPARATOR, Position, Proof, StateCommitment}; - impl ToConstraintField for Position { fn to_field_elements(&self) -> Option> { // The variable created in AllocVar is a UInt64, which is a @@ -44,11 +43,11 @@ impl AllocVar for PositionVar { let inner: Position = *f()?.borrow(); let position = UInt64::new_variable(cs, || Ok(u64::from(inner)), mode)?; - let bits = position.to_bits_le(); + let bits = position.to_bits_le()?; for bit in &bits[48..] { bit.enforce_equal(&Boolean::Constant(false))?; } - let inner = Boolean::::le_bits_to_fp_var(&bits[0..48])?; + let inner = Boolean::::le_bits_to_fp(&bits[0..48])?; Ok(Self { bits: bits[0..48] @@ -69,17 +68,17 @@ impl ToBitsGadget for PositionVar { impl PositionVar { /// Witness the commitment index by taking the last 16 bits of the position. pub fn commitment(&self) -> Result { - Boolean::::le_bits_to_fp_var(&self.bits[0..16]) + Boolean::::le_bits_to_fp(&self.bits[0..16]) } /// Witness the block. pub fn block(&self) -> Result { - Boolean::::le_bits_to_fp_var(&self.bits[16..32]) + Boolean::::le_bits_to_fp(&self.bits[16..32]) } /// Witness the epoch by taking the first 16 bits of the position. pub fn epoch(&self) -> Result { - Boolean::::le_bits_to_fp_var(&self.bits[32..48]) + Boolean::::le_bits_to_fp(&self.bits[32..48]) } } @@ -241,7 +240,8 @@ impl WhichWayVar { // * `is_left`: the left should be the node // * `is_right`: the left should be the second sibling (`siblings[1]`) // * `is_rightmost`: the left should be the second sibling (`siblings[1]`) - let is_left_or_leftmost_case = is_leftmost.or(&is_left)?; + + let is_left_or_leftmost_case = FqVar::or(&is_leftmost, &is_left)?; let left_first_two_cases = FqVar::conditionally_select(&is_left, &node, &siblings[0])?; let left = FqVar::conditionally_select( &is_left_or_leftmost_case, @@ -254,7 +254,8 @@ impl WhichWayVar { // * `is_left`: the right should be the second sibling (`siblings[1]`) // * `is_right`: the right should be the node // * `is_rightmost`: the right should be the last sibling (`siblings[2]`) - let is_right_or_rightmost_case = is_right.or(&is_rightmost)?; + + let is_right_or_rightmost_case = FqVar::or(&is_right, &is_rightmost)?; let right_last_two_cases = FqVar::conditionally_select(&is_right, &node, &siblings[2])?; let right = FqVar::conditionally_select( &is_right_or_rightmost_case, diff --git a/tools/parameter-setup/Cargo.toml b/tools/parameter-setup/Cargo.toml index 111c48e07e..6b09e5b0bc 100644 --- a/tools/parameter-setup/Cargo.toml +++ b/tools/parameter-setup/Cargo.toml @@ -20,7 +20,7 @@ penumbra-shielded-pool = { path = "../../crates/core/component/shielded-pool/", penumbra-stake = { path = "../../crates/core/component/stake/", features = [ "component", ] } -ark-groth16 = "0.4" -ark-serialize = "0.4" -decaf377 = { version = "0.5", features = ["r1cs"] } +ark-groth16 = "0.5" +ark-serialize = "0.5" +decaf377 = { git = "https://github.com/penumbra-zone/decaf377", branch = "arkworks-0.5", features = ["r1cs"] } rand_core = "0.6.4" From 9fffd7eff33888f1852dcc934f1039c935c2a272 Mon Sep 17 00:00:00 2001 From: Tal Derei Date: Sun, 17 Nov 2024 23:18:28 -0800 Subject: [PATCH 2/2] r1cs imports --- crates/crypto/tct/src/r1cs.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/crypto/tct/src/r1cs.rs b/crates/crypto/tct/src/r1cs.rs index aea5cedf8c..ccf7c43e37 100644 --- a/crates/crypto/tct/src/r1cs.rs +++ b/crates/crypto/tct/src/r1cs.rs @@ -1,7 +1,13 @@ //! This module defines how to verify TCT auth paths in a rank-1 constraint system. use crate::{internal::hash::DOMAIN_SEPARATOR, Position, Proof, StateCommitment}; use ark_ff::ToConstraintField; +use ark_r1cs_std::alloc::{AllocVar, AllocationMode}; +use ark_r1cs_std::eq::EqGadget; +use ark_r1cs_std::fields::FieldVar; +use ark_r1cs_std::prelude::{Boolean, ToBitsGadget}; +use ark_r1cs_std::select::CondSelectGadget; use ark_r1cs_std::uint64::UInt64; +use ark_r1cs_std::R1CSVar; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use decaf377::r1cs::fqvar_ext::FqVarExtension; use decaf377::{r1cs::FqVar, Fq};