Skip to content

Commit e273877

Browse files
Migrate to GR1CS (#154)
* Refacto: R1CS to GR1CS * tweak * tweak * relations crate fixed * added the migration script * fmt * doc test fix * mwork * work * work * addressed comments --------- Co-authored-by: Pratyush Mishra <[email protected]>
1 parent c6f9a57 commit e273877

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+779
-678
lines changed

Cargo.toml

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "ark-r1cs-std"
33
version = "0.5.0"
4-
authors = [ "arkworks contributors" ]
4+
authors = ["arkworks contributors"]
55
description = "A standard library for constraint system gadgets"
66
homepage = "https://arkworks.rs"
77
repository = "https://github.com/arkworks-rs/r1cs-std"
@@ -20,28 +20,33 @@ ark-std = { version = "0.5.0", default-features = false }
2020
ark-relations = { version = "0.5.0", default-features = false }
2121

2222
educe = "0.6.0"
23-
tracing = { version = "0.1", default-features = false, features = [ "attributes" ] }
23+
tracing = { version = "^0.1.0", default-features = false, features = ["attributes"] }
2424
num-bigint = { version = "0.4", default-features = false }
2525
num-traits = { version = "0.2", default-features = false }
2626
num-integer = { version = "0.1.44", default-features = false }
2727

2828
[dev-dependencies]
29-
ark-test-curves = { version = "0.5.0", default-features = false, features = ["bls12_381_scalar_field", "bls12_381_curve", "mnt4_753_scalar_field"] }
29+
ark-test-curves = { version = "0.5.0", default-features = false, features = [
30+
"bls12_381_scalar_field",
31+
"bls12_381_curve",
32+
"mnt4_753_scalar_field",
33+
] }
3034
ark-poly = { version = "0.5.0", default-features = false }
3135
paste = "1.0"
32-
ark-bls12-377 = { version = "0.5.0", features = ["curve"], default-features = false }
33-
ark-bls12-381 = { version = "0.5.0", features = ["curve"], default-features = false }
34-
ark-mnt4-298 = { version = "0.5.0", features = ["curve"], default-features = false }
35-
ark-mnt4-753 = { version = "0.5.0", features = ["curve"], default-features = false }
36-
ark-mnt6-298 = { version = "0.5.0", default-features = false }
37-
ark-mnt6-753 = { version = "0.5.0", default-features = false }
38-
ark-pallas = { version = "0.5.0", features = ["curve"], default-features = false }
39-
ark-bn254 = { version = "0.5.0", features = ["curve"], default-features = false }
36+
ark-bls12-377 = { version = "0.5.0", features = ["curve"], default-features = false }
37+
ark-bls12-381 = { version = "0.5.0", features = ["curve"], default-features = false }
38+
ark-mnt4-298 = { version = "0.5.0", features = ["curve"], default-features = false }
39+
ark-mnt4-753 = { version = "0.5.0", features = ["curve"], default-features = false }
40+
ark-mnt6-298 = { version = "0.5.0", default-features = false }
41+
ark-mnt6-753 = { version = "0.5.0", default-features = false }
42+
ark-pallas = { version = "0.5.0", features = ["curve"], default-features = false }
43+
ark-bn254 = { version = "0.5.0", features = ["curve"], default-features = false }
44+
tracing-subscriber = { version = "0.3", default-features = true }
4045

4146
[features]
4247
default = ["std"]
43-
std = [ "ark-ff/std", "ark-relations/std", "ark-std/std", "num-bigint/std" ]
44-
parallel = [ "std", "ark-ff/parallel", "ark-std/parallel"]
48+
std = ["ark-ff/std", "ark-relations/std", "ark-std/std", "num-bigint/std"]
49+
parallel = ["std", "ark-ff/parallel", "ark-std/parallel"]
4550

4651
[[bench]]
4752
name = "emulated-bench"
@@ -76,3 +81,7 @@ debug = true
7681
[lints.rust]
7782
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(ci)'] }
7883

84+
85+
# patch
86+
[patch.crates-io]
87+
ark-relations = { git = "https://github.com/arkworks-rs/snark.git", default-features = true }

benches/bench.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use ark_r1cs_std::{
55
fields::{emulated_fp::EmulatedFpVar, FieldVar},
66
};
77
use ark_relations::{
8+
gr1cs::{ConstraintSystem, ConstraintSystemRef, OptimizationGoal},
89
ns,
9-
r1cs::{ConstraintSystem, ConstraintSystemRef, OptimizationGoal},
1010
};
1111
use ark_std::rand::RngCore;
1212

@@ -19,9 +19,20 @@ fn get_density<BaseField: PrimeField>(cs: &ConstraintSystemRef<BaseField>) -> us
1919
let mut cs_bak = r.borrow().clone();
2020

2121
cs_bak.finalize();
22-
let matrices = cs_bak.to_matrices().unwrap();
23-
24-
matrices.a_num_non_zero + matrices.b_num_non_zero + matrices.c_num_non_zero
22+
let matrices_map = cs_bak.to_matrices().unwrap();
23+
match matrices_map.get(ark_relations::gr1cs::R1CS_PREDICATE_LABEL) {
24+
None => 0,
25+
Some(matrices) => {
26+
let a = &matrices[0];
27+
let b = &matrices[1];
28+
let c = &matrices[2];
29+
let a_num_non_zero: usize = a.iter().map(|lc| lc.len()).sum();
30+
let b_num_non_zero: usize = b.iter().map(|lc| lc.len()).sum();
31+
let c_num_non_zero: usize = c.iter().map(|lc| lc.len()).sum();
32+
33+
a_num_non_zero + b_num_non_zero + c_num_non_zero
34+
},
35+
}
2536
},
2637
}
2738
}

scripts/migrate.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env bash
2+
3+
# -----------------------------------------------------------------------------
4+
# rename_r1cs.sh (Regex Version)
5+
#
6+
# Recursively:
7+
# 1. Renames .rs filenames: R1CS->GR1CS, r1cs->gr1cs (except those with r1cs_std).
8+
# 2. In .rs file contents, replaces R1CS->GR1CS, r1cs->gr1cs (except lines with r1cs_std),
9+
# ensuring words already in GR1CS/gr1cs are not changed again.
10+
# 3. Finally replaces enforce_constraint->enforce_r1cs_constraint (except lines with r1cs_std),
11+
# ensuring enforce_r1cs_constraint is not changed again.
12+
# -----------------------------------------------------------------------------
13+
14+
# --- Detect which 'sed' in-place flag to use (GNU vs BSD/macOS) ---
15+
if sed --version 2>/dev/null | grep -q "GNU"; then
16+
SED_INPLACE=(-i)
17+
else
18+
SED_INPLACE=(-i '')
19+
fi
20+
21+
echo "###############################################"
22+
echo "# Make sure you have a backup before running. #"
23+
echo "###############################################"
24+
echo
25+
read -p "Are you sure you want to continue? (yes/no) " choice
26+
27+
if [[ "$choice" != "yes" ]]; then
28+
echo "Aborting script execution."
29+
exit 1
30+
fi
31+
32+
# 1) Rename files that contain 'r1cs' or 'R1CS' in their name, skipping 'r1cs_std' and existing 'gr1cs'.
33+
echo "Renaming files that contain 'r1cs' or 'R1CS' (but not 'r1cs_std' and already converted ones)..."
34+
export LC_ALL=C # Ensure consistent behavior for case conversions
35+
36+
while IFS= read -r -d '' file; do
37+
if [[ "$file" =~ r1cs_std || "$file" =~ gr1cs ]]; then
38+
continue
39+
fi
40+
newfile="$(echo "$file" | sed -E 's/(^|[^g])r1cs/\1gr1cs/g; s/(^|[^G])R1CS/\1GR1CS/g')"
41+
if [[ "$newfile" != "$file" ]]; then
42+
echo " -> Renaming: $file -> $newfile"
43+
mv "$file" "$newfile"
44+
fi
45+
done < <(find . -type f -name "*.rs" -print0)
46+
47+
# 2) Replace R1CS->GR1CS and r1cs->gr1cs in file contents,
48+
# skipping lines that have 'r1cs_std' and ensuring already transformed words are not changed again.
49+
echo "Replacing (R1CS->GR1CS, r1cs->gr1cs) in .rs file contents..."
50+
while IFS= read -r -d '' file; do
51+
sed "${SED_INPLACE[@]}" -E '/r1cs_std|enforce_r1cs_constraint/! s/(^|[^g])r1cs/\1gr1cs/g' "$file"
52+
sed "${SED_INPLACE[@]}" -E '/r1cs_std|enforce_r1cs_constraint/! s/(^|[^G])R1CS/\1GR1CS/g' "$file"
53+
done < <(find . -type f -name "*.rs" ! -name "*r1cs_std*" -print0)
54+
55+
# 3) Replace 'enforce_constraint' -> 'enforce_r1cs_constraint',
56+
# skipping lines that have 'r1cs_std' and ensuring enforce_r1cs_constraint is not changed again.
57+
echo "Replacing enforce_constraint->enforce_r1cs_constraint..."
58+
while IFS= read -r -d '' file; do
59+
sed "${SED_INPLACE[@]}" '/r1cs_std|enforce_r1cs_constraint/! s/enforce_constraint/enforce_r1cs_constraint/g' "$file"
60+
done < <(find . -type f -name "*.rs" ! -name "*r1cs_std*" -print0)
61+
62+
echo "Done!"

src/alloc.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::Vec;
22
use ark_ff::Field;
3-
use ark_relations::r1cs::{Namespace, SynthesisError};
3+
use ark_relations::gr1cs::{Namespace, SynthesisError};
44
use core::borrow::Borrow;
55

66
/// Describes the mode that a variable should be allocated in within
@@ -49,7 +49,7 @@ pub trait AllocVar<V: ?Sized, F: Field>: Sized {
4949
/// Allocates a new constant of type `Self` in the `ConstraintSystem` `cs`.
5050
///
5151
/// This should *not* allocate any new variables or constraints in `cs`.
52-
#[tracing::instrument(target = "r1cs", skip(cs, t))]
52+
#[tracing::instrument(target = "gr1cs", skip(cs, t))]
5353
fn new_constant(
5454
cs: impl Into<Namespace<F>>,
5555
t: impl Borrow<V>,
@@ -59,7 +59,7 @@ pub trait AllocVar<V: ?Sized, F: Field>: Sized {
5959

6060
/// Allocates a new public input of type `Self` in the `ConstraintSystem`
6161
/// `cs`.
62-
#[tracing::instrument(target = "r1cs", skip(cs, f))]
62+
#[tracing::instrument(target = "gr1cs", skip(cs, f))]
6363
fn new_input<T: Borrow<V>>(
6464
cs: impl Into<Namespace<F>>,
6565
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -69,7 +69,7 @@ pub trait AllocVar<V: ?Sized, F: Field>: Sized {
6969

7070
/// Allocates a new private witness of type `Self` in the `ConstraintSystem`
7171
/// `cs`.
72-
#[tracing::instrument(target = "r1cs", skip(cs, f))]
72+
#[tracing::instrument(target = "gr1cs", skip(cs, f))]
7373
fn new_witness<T: Borrow<V>>(
7474
cs: impl Into<Namespace<F>>,
7575
f: impl FnOnce() -> Result<T, SynthesisError>,
@@ -90,8 +90,8 @@ pub trait AllocVar<V: ?Sized, F: Field>: Sized {
9090
/// variable, one can write:
9191
/// ```
9292
/// use ark_ff::PrimeField;
93-
/// use ark_r1cs_std::{alloc::AllocVar, fields::{fp::FpVar, FieldVar}, R1CSVar};
94-
/// use ark_relations::r1cs::SynthesisError;
93+
/// use ark_r1cs_std::{alloc::AllocVar, fields::{fp::FpVar, FieldVar}, GR1CSVar};
94+
/// use ark_relations::gr1cs::SynthesisError;
9595
///
9696
/// fn div<F: PrimeField>(x_var: &FpVar<F>, y_var: &FpVar<F>) -> Result<FpVar<F>, SynthesisError> {
9797
/// let cs = x_var.cs().or(y_var.cs());

src/boolean/allocated.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::borrow::Borrow;
22

33
use ark_ff::{Field, PrimeField};
4-
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError, Variable};
4+
use ark_relations::gr1cs::{ConstraintSystemRef, Namespace, SynthesisError, Variable};
55

66
use crate::{
77
alloc::{AllocVar, AllocationMode},
@@ -58,7 +58,7 @@ impl<F: Field> AllocatedBool<F> {
5858

5959
/// Performs an XOR operation over the two operands, returning
6060
/// an `AllocatedBool`.
61-
#[tracing::instrument(target = "r1cs")]
61+
#[tracing::instrument(target = "gr1cs")]
6262
pub fn not(&self) -> Result<Self, SynthesisError> {
6363
let variable = self.cs.new_lc(lc!() + Variable::One - self.variable)?;
6464
Ok(Self {
@@ -69,7 +69,7 @@ impl<F: Field> AllocatedBool<F> {
6969

7070
/// Performs an XOR operation over the two operands, returning
7171
/// an `AllocatedBool`.
72-
#[tracing::instrument(target = "r1cs")]
72+
#[tracing::instrument(target = "gr1cs")]
7373
pub fn xor(&self, b: &Self) -> Result<Self, SynthesisError> {
7474
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
7575
Ok(self.value()? ^ b.value()?)
@@ -90,7 +90,7 @@ impl<F: Field> AllocatedBool<F> {
9090
// -2a * b = c - a - b
9191
// 2a * b = a + b - c
9292
// (a + a) * b = a + b - c
93-
self.cs.enforce_constraint(
93+
self.cs.enforce_r1cs_constraint(
9494
lc!() + self.variable + self.variable,
9595
lc!() + b.variable,
9696
lc!() + self.variable + b.variable - result.variable,
@@ -101,15 +101,15 @@ impl<F: Field> AllocatedBool<F> {
101101

102102
/// Performs an AND operation over the two operands, returning
103103
/// an `AllocatedBool`.
104-
#[tracing::instrument(target = "r1cs")]
104+
#[tracing::instrument(target = "gr1cs")]
105105
pub fn and(&self, b: &Self) -> Result<Self, SynthesisError> {
106106
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
107107
Ok(self.value()? & b.value()?)
108108
})?;
109109

110110
// Constrain (a) * (b) = (c), ensuring c is 1 iff
111111
// a AND b are both 1.
112-
self.cs.enforce_constraint(
112+
self.cs.enforce_r1cs_constraint(
113113
lc!() + self.variable,
114114
lc!() + b.variable,
115115
lc!() + result.variable,
@@ -120,15 +120,15 @@ impl<F: Field> AllocatedBool<F> {
120120

121121
/// Performs an OR operation over the two operands, returning
122122
/// an `AllocatedBool`.
123-
#[tracing::instrument(target = "r1cs")]
123+
#[tracing::instrument(target = "gr1cs")]
124124
pub fn or(&self, b: &Self) -> Result<Self, SynthesisError> {
125125
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
126126
Ok(self.value()? | b.value()?)
127127
})?;
128128

129129
// Constrain (1 - a) * (1 - b) = (1 - c), ensuring c is 0 iff
130130
// a and b are both false, and otherwise c is 1.
131-
self.cs.enforce_constraint(
131+
self.cs.enforce_r1cs_constraint(
132132
lc!() + Variable::One - self.variable,
133133
lc!() + Variable::One - b.variable,
134134
lc!() + Variable::One - result.variable,
@@ -138,15 +138,15 @@ impl<F: Field> AllocatedBool<F> {
138138
}
139139

140140
/// Calculates `a AND (NOT b)`.
141-
#[tracing::instrument(target = "r1cs")]
141+
#[tracing::instrument(target = "gr1cs")]
142142
pub fn and_not(&self, b: &Self) -> Result<Self, SynthesisError> {
143143
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
144144
Ok(self.value()? & !b.value()?)
145145
})?;
146146

147147
// Constrain (a) * (1 - b) = (c), ensuring c is 1 iff
148148
// a is true and b is false, and otherwise c is 0.
149-
self.cs.enforce_constraint(
149+
self.cs.enforce_r1cs_constraint(
150150
lc!() + self.variable,
151151
lc!() + Variable::One - b.variable,
152152
lc!() + result.variable,
@@ -156,15 +156,15 @@ impl<F: Field> AllocatedBool<F> {
156156
}
157157

158158
/// Calculates `(NOT a) AND (NOT b)`.
159-
#[tracing::instrument(target = "r1cs")]
159+
#[tracing::instrument(target = "gr1cs")]
160160
pub fn nor(&self, b: &Self) -> Result<Self, SynthesisError> {
161161
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
162162
Ok(!(self.value()? | b.value()?))
163163
})?;
164164

165165
// Constrain (1 - a) * (1 - b) = (c), ensuring c is 1 iff
166166
// a and b are both false, and otherwise c is 0.
167-
self.cs.enforce_constraint(
167+
self.cs.enforce_r1cs_constraint(
168168
lc!() + Variable::One - self.variable,
169169
lc!() + Variable::One - b.variable,
170170
lc!() + result.variable,
@@ -205,15 +205,15 @@ impl<F: Field> AllocVar<bool, F> for AllocatedBool<F> {
205205
// Constrain: (1 - a) * a = 0
206206
// This constrains a to be either 0 or 1.
207207

208-
cs.enforce_constraint(lc!() + Variable::One - variable, lc!() + variable, lc!())?;
208+
cs.enforce_r1cs_constraint(lc!() + Variable::One - variable, lc!() + variable, lc!())?;
209209

210210
Ok(Self { variable, cs })
211211
}
212212
}
213213
}
214214

215215
impl<F: PrimeField> CondSelectGadget<F> for AllocatedBool<F> {
216-
#[tracing::instrument(target = "r1cs")]
216+
#[tracing::instrument(target = "gr1cs")]
217217
fn conditionally_select(
218218
cond: &Boolean<F>,
219219
true_val: &Self,
@@ -235,7 +235,7 @@ impl<F: PrimeField> CondSelectGadget<F> for AllocatedBool<F> {
235235
mod test {
236236
use super::*;
237237

238-
use ark_relations::r1cs::ConstraintSystem;
238+
use ark_relations::gr1cs::ConstraintSystem;
239239
use ark_test_curves::bls12_381::Fr;
240240
#[test]
241241
fn allocated_xor() -> Result<(), SynthesisError> {

0 commit comments

Comments
 (0)