Skip to content

Commit d4c771c

Browse files
r1cs replaced with gr1cs (#378)
Co-authored-by: Pratyush Mishra <pratyushmishra@berkeley.edu>
1 parent 748c0ba commit d4c771c

25 files changed

+2560
-1276
lines changed

Cargo.toml

+1-7
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,4 @@ opt-level = 3
3030
lto = "thin"
3131
incremental = true
3232
debug-assertions = true
33-
debug = true
34-
35-
[patch.crates-io]
36-
ark-ff = { git = "https://github.com/arkworks-rs/algebra/" }
37-
ark-ec = { git = "https://github.com/arkworks-rs/algebra/" }
38-
ark-poly = { git = "https://github.com/arkworks-rs/algebra/" }
39-
ark-serialize = { git = "https://github.com/arkworks-rs/algebra/" }
33+
debug = true

relations/Cargo.toml

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[package]
22
name = "ark-relations"
3-
version = "0.4.0"
3+
version = "0.5.0"
44
authors = [ "arkworks contributors" ]
5-
description = "A library for rank-one constraint systems"
5+
description = "A library for generalized rank-one constraint systems"
66
homepage = "https://arkworks.rs"
77
repository = "https://github.com/arkworks-rs/snark"
88
documentation = "https://docs.rs/ark-relations/"
@@ -13,14 +13,27 @@ license = "MIT/Apache-2.0"
1313
edition = "2021"
1414

1515
[dependencies]
16-
ark-ff = { version = "0.4.0", default-features = false }
17-
ark-std = { version = "0.4.0", default-features = false }
18-
tracing = { version = "0.1", default-features = false }
19-
tracing-subscriber = { version = "0.2", default-features = false, optional = true }
16+
ark-ff = { version = "0.5.0", default-features = false }
17+
ark-std = { version = "0.5.0", default-features = false }
18+
ark-poly = { version = "0.5.0", default-features = false }
19+
ark-serialize = { version = "0.5.0", default-features = false }
20+
tracing = { version = "0.1", default-features = false, features = ["attributes"]}
21+
tracing-subscriber = { version = "0.3", default-features = true, optional = true }
2022

2123
[dev-dependencies]
22-
ark-test-curves = { version = "0.4.0", default-features = false, features = [ "bls12_381_scalar_field" ] }
24+
ark-test-curves = { version = "0.5.0", default-features = false, features = [ "bls12_381_scalar_field" ] }
2325

2426
[features]
2527
default = []
2628
std = [ "ark-std/std", "ark-ff/std", "tracing-subscriber", "tracing/std" ]
29+
30+
31+
[[example]]
32+
name = "non-satisfiable"
33+
path = "examples/non_satisfiable.rs"
34+
required-features = ["std"]
35+
36+
[[example]]
37+
name = "satisfiable"
38+
path = "examples/satisfiable.rs"
39+
required-features = ["std"]

relations/examples/README.MD

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
To run the examples, use the following commands:
2+
3+
```bash
4+
# Run the satisfiable example
5+
cargo run --example satisfiable
6+
7+
# Run the non-satisfiable example with the `std` feature enabled to see the output trace
8+
cargo run --example non-satisfiable --features std

relations/examples/non_satisfiable.rs

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use ark_ff::Field;
2+
use ark_relations::gr1cs::{
3+
trace::{ConstraintLayer, TracingMode},
4+
ConstraintSystem, ConstraintSystemRef, LinearCombination, SynthesisError, Variable,
5+
};
6+
use ark_test_curves::bls12_381::Fr;
7+
8+
use tracing_subscriber::{fmt, layer::SubscriberExt, Registry};
9+
10+
fn main() {
11+
// Set up tracing with a ConstraintLayer
12+
let constraint_layer = ConstraintLayer::new(TracingMode::All);
13+
let subscriber = Registry::default()
14+
.with(fmt::layer()) // Optional: Log formatted output to stdout
15+
.with(constraint_layer);
16+
17+
tracing::subscriber::set_global_default(subscriber)
18+
.expect("Failed to set global default subscriber");
19+
20+
// Initialize a constraint system
21+
let cs = ConstraintSystem::<Fr>::new_ref();
22+
23+
// Create input variables
24+
let p1 = cs.new_input_variable(|| Ok(Fr::from(3u32))).unwrap();
25+
let p2 = cs.new_input_variable(|| Ok(Fr::from(4u32))).unwrap();
26+
let p3 = cs.new_input_variable(|| Ok(Fr::from(6u32))).unwrap();
27+
let p4 = cs.new_input_variable(|| Ok(Fr::from(7u32))).unwrap();
28+
29+
// Create witness variables
30+
// Note that w3 has a wrong value
31+
let w1 = cs.new_witness_variable(|| Ok(Fr::from(2u32))).unwrap();
32+
let w2 = cs.new_witness_variable(|| Ok(Fr::from(5u32))).unwrap();
33+
let w3 = cs.new_witness_variable(|| Ok(Fr::from(8u32))).unwrap();
34+
let w4 = cs.new_witness_variable(|| Ok(Fr::from(9u32))).unwrap();
35+
// Create expected result as a witness
36+
let expected_result = cs.new_input_variable(|| Ok(Fr::from(198))).unwrap();
37+
// Build the circuit
38+
let _result_var =
39+
generate_constraints(cs.clone(), p1, p2, p3, p4, w1, w2, w3, w4, expected_result).unwrap();
40+
let trace = cs.which_predicate_is_unsatisfied().unwrap().unwrap();
41+
println!(
42+
"This is the trace of non-satisfied scenario, Check out the trace:\n{}",
43+
trace
44+
)
45+
}
46+
// Function to enforce the overall constraints by combining subcircuits
47+
#[tracing::instrument(target = "gr1cs")]
48+
fn generate_constraints<F: Field>(
49+
cs: ConstraintSystemRef<F>,
50+
p1: Variable,
51+
p2: Variable,
52+
p3: Variable,
53+
p4: Variable,
54+
w1: Variable,
55+
w2: Variable,
56+
w3: Variable,
57+
w4: Variable,
58+
expected_result: Variable,
59+
) -> Result<Variable, SynthesisError> {
60+
// Subcircuit 1
61+
let subcircuit1_result = enforce_subcircuit1(cs.clone(), p1, p2, w1, w2)?;
62+
63+
// Subcircuit 2
64+
let subcircuit2_result = enforce_subcircuit2(cs.clone(), p3, p4, w3, w4)?;
65+
66+
// Final operation: sum the results of the two subcircuits
67+
let final_result = enforce_addition(cs.clone(), subcircuit1_result, subcircuit2_result)?;
68+
// Verify that the final result matches the expected result
69+
cs.enforce_r1cs_constraint(
70+
LinearCombination::from(final_result),
71+
LinearCombination::from(Variable::One),
72+
LinearCombination::from(expected_result),
73+
)?;
74+
75+
Ok(final_result)
76+
}
77+
78+
// Enforces the constraints for Subcircuit 1
79+
#[tracing::instrument(target = "gr1cs")]
80+
fn enforce_subcircuit1<F: Field>(
81+
cs: ConstraintSystemRef<F>,
82+
p1: Variable,
83+
p2: Variable,
84+
w1: Variable,
85+
w2: Variable,
86+
) -> Result<Variable, SynthesisError> {
87+
// let cs = ns!(cs, "subcircuit1").cs();
88+
89+
// Multiplication gate: p1 * p2
90+
let product = enforce_multiplication(cs.clone(), p1, p2)?;
91+
92+
// Addition gate: w1 + w2
93+
let sum = enforce_addition(cs.clone(), w1, w2)?;
94+
95+
// Final multiplication: sum * product
96+
let result = enforce_multiplication(cs, sum, product)?;
97+
98+
Ok(result)
99+
}
100+
101+
// Enforces the constraints for Subcircuit 2
102+
#[tracing::instrument(target = "gr1cs")]
103+
fn enforce_subcircuit2<F: Field>(
104+
cs: ConstraintSystemRef<F>,
105+
p3: Variable,
106+
p4: Variable,
107+
w3: Variable,
108+
w4: Variable,
109+
) -> Result<Variable, SynthesisError> {
110+
// let cs = ns!(cs, "subcircuit2").cs();
111+
112+
// Multiplication gate 1: p3 * w3
113+
let product1 = enforce_multiplication(cs.clone(), p3, p4)?;
114+
115+
// Multiplication gate 2: p4 * w4
116+
let product2 = enforce_multiplication(cs.clone(), w3, w4)?;
117+
118+
// Final addition: product1 + product2
119+
let result = enforce_addition(cs, product1, product2)?;
120+
121+
Ok(result)
122+
}
123+
124+
// Function to enforce a multiplication constraint
125+
#[tracing::instrument(target = "gr1cs")]
126+
fn enforce_multiplication<F: Field>(
127+
cs: ConstraintSystemRef<F>,
128+
left: Variable,
129+
right: Variable,
130+
) -> Result<Variable, SynthesisError> {
131+
// let cs = ns!(cs, "multiplication").cs();
132+
133+
let product = cs.new_witness_variable(|| {
134+
Ok(cs.assigned_value(left).unwrap() * cs.assigned_value(right).unwrap())
135+
})?; // Placeholder for product
136+
137+
cs.enforce_r1cs_constraint(
138+
LinearCombination::from(left),
139+
LinearCombination::from(right),
140+
LinearCombination::from(product),
141+
)?;
142+
143+
Ok(product)
144+
}
145+
146+
// Function to enforce an addition constraint
147+
#[tracing::instrument(target = "gr1cs")]
148+
fn enforce_addition<F: Field>(
149+
cs: ConstraintSystemRef<F>,
150+
left: Variable,
151+
right: Variable,
152+
) -> Result<Variable, SynthesisError> {
153+
// let cs = ns!(cs, "addition").cs();
154+
155+
// Instead of + we use *, This is intentioanlly made to fail
156+
let sum = cs.new_witness_variable(|| {
157+
Ok(cs.assigned_value(left).unwrap() * cs.assigned_value(right).unwrap())
158+
})?; // Placeholder for sum
159+
160+
cs.enforce_r1cs_constraint(
161+
LinearCombination::from(left) + LinearCombination::from(right),
162+
LinearCombination::from(Variable::One),
163+
LinearCombination::from(sum),
164+
)?;
165+
166+
Ok(sum)
167+
}

relations/examples/satisfiable.rs

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
use ark_ff::Field;
2+
use ark_relations::gr1cs::{
3+
ConstraintSystem, ConstraintSystemRef, LinearCombination, SynthesisError, Variable,
4+
};
5+
use ark_test_curves::bls12_381::Fr;
6+
7+
fn main() {
8+
// Initialize a constraint system
9+
let cs = ConstraintSystem::<Fr>::new_ref();
10+
11+
// Create input variables
12+
let p1 = cs.new_input_variable(|| Ok(Fr::from(3u32))).unwrap();
13+
let p2 = cs.new_input_variable(|| Ok(Fr::from(4u32))).unwrap();
14+
let p3 = cs.new_input_variable(|| Ok(Fr::from(6u32))).unwrap();
15+
let p4 = cs.new_input_variable(|| Ok(Fr::from(7u32))).unwrap();
16+
17+
// Create witness variables
18+
let w1 = cs.new_witness_variable(|| Ok(Fr::from(2u32))).unwrap();
19+
let w2 = cs.new_witness_variable(|| Ok(Fr::from(5u32))).unwrap();
20+
let w3 = cs.new_witness_variable(|| Ok(Fr::from(8u32))).unwrap();
21+
let w4 = cs.new_witness_variable(|| Ok(Fr::from(9u32))).unwrap();
22+
// Create expected result as a witness
23+
let expected_result = cs.new_input_variable(|| Ok(Fr::from(198))).unwrap();
24+
25+
// Build the circuit
26+
let _result_var =
27+
generate_constraints(cs.clone(), p1, p2, p3, p4, w1, w2, w3, w4, expected_result).unwrap();
28+
29+
// Verify the constraint system
30+
assert!(cs.is_satisfied().unwrap());
31+
println!("Satisfied scenario successful!",);
32+
}
33+
34+
// Function to enforce the overall constraints by combining subcircuits
35+
#[tracing::instrument(target = "gr1cs")]
36+
fn generate_constraints<F: Field>(
37+
cs: ConstraintSystemRef<F>,
38+
p1: Variable,
39+
p2: Variable,
40+
p3: Variable,
41+
p4: Variable,
42+
w1: Variable,
43+
w2: Variable,
44+
w3: Variable,
45+
w4: Variable,
46+
expected_result: Variable,
47+
) -> Result<Variable, SynthesisError> {
48+
// Subcircuit 1
49+
let subcircuit1_result = enforce_subcircuit1(cs.clone(), p1, p2, w1, w2)?;
50+
51+
// Subcircuit 2
52+
let subcircuit2_result = enforce_subcircuit2(cs.clone(), p3, p4, w3, w4)?;
53+
54+
// Final operation: sum the results of the two subcircuits
55+
let final_result = enforce_addition(cs.clone(), subcircuit1_result, subcircuit2_result)?;
56+
// Verify that the final result matches the expected result
57+
cs.enforce_r1cs_constraint(
58+
LinearCombination::from(final_result),
59+
LinearCombination::from(Variable::One),
60+
LinearCombination::from(expected_result),
61+
)?;
62+
63+
Ok(final_result)
64+
}
65+
66+
// Enforces the constraints for Subcircuit 1
67+
#[tracing::instrument(target = "gr1cs")]
68+
fn enforce_subcircuit1<F: Field>(
69+
cs: ConstraintSystemRef<F>,
70+
p1: Variable,
71+
p2: Variable,
72+
w1: Variable,
73+
w2: Variable,
74+
) -> Result<Variable, SynthesisError> {
75+
// let cs = ns!(cs, "subcircuit1").cs();
76+
77+
// Multiplication gate: p1 * p2
78+
let product = enforce_multiplication(cs.clone(), p1, p2)?;
79+
80+
// Addition gate: w1 + w2
81+
let sum = enforce_addition(cs.clone(), w1, w2)?;
82+
83+
// Final multiplication: sum * product
84+
let result = enforce_multiplication(cs, sum, product)?;
85+
86+
Ok(result)
87+
}
88+
89+
// Enforces the constraints for Subcircuit 2
90+
#[tracing::instrument(target = "gr1cs")]
91+
fn enforce_subcircuit2<F: Field>(
92+
cs: ConstraintSystemRef<F>,
93+
p3: Variable,
94+
p4: Variable,
95+
w3: Variable,
96+
w4: Variable,
97+
) -> Result<Variable, SynthesisError> {
98+
// let cs = ns!(cs, "subcircuit2").cs();
99+
100+
// Multiplication gate 1: p3 * w3
101+
let product1 = enforce_multiplication(cs.clone(), p3, p4)?;
102+
103+
// Multiplication gate 2: p4 * w4
104+
let product2 = enforce_multiplication(cs.clone(), w3, w4)?;
105+
106+
// Final addition: product1 + product2
107+
let result = enforce_addition(cs, product1, product2)?;
108+
109+
Ok(result)
110+
}
111+
112+
// Function to enforce a multiplication constraint
113+
#[tracing::instrument(target = "gr1cs")]
114+
fn enforce_multiplication<F: Field>(
115+
cs: ConstraintSystemRef<F>,
116+
left: Variable,
117+
right: Variable,
118+
) -> Result<Variable, SynthesisError> {
119+
// let cs = ns!(cs, "multiplication").cs();
120+
121+
let product = cs.new_witness_variable(|| {
122+
Ok(cs.assigned_value(left).unwrap() * cs.assigned_value(right).unwrap())
123+
})?; // Placeholder for product
124+
125+
cs.enforce_r1cs_constraint(
126+
LinearCombination::from(left),
127+
LinearCombination::from(right),
128+
LinearCombination::from(product),
129+
)?;
130+
131+
Ok(product)
132+
}
133+
134+
// Function to enforce an addition constraint
135+
#[tracing::instrument(target = "gr1cs")]
136+
fn enforce_addition<F: Field>(
137+
cs: ConstraintSystemRef<F>,
138+
left: Variable,
139+
right: Variable,
140+
) -> Result<Variable, SynthesisError> {
141+
// let cs = ns!(cs, "addition").cs();
142+
143+
let sum = cs.new_witness_variable(|| {
144+
Ok(cs.assigned_value(left).unwrap() + cs.assigned_value(right).unwrap())
145+
})?; // Placeholder for sum
146+
147+
cs.enforce_r1cs_constraint(
148+
LinearCombination::from(left) + LinearCombination::from(right),
149+
LinearCombination::from(Variable::One),
150+
LinearCombination::from(sum),
151+
)?;
152+
153+
Ok(sum)
154+
}

0 commit comments

Comments
 (0)