sonobe_primitives/circuits/
utils.rs1use ark_ff::{Field, PrimeField};
4use ark_r1cs_std::{
5 GR1CSVar,
6 alloc::AllocVar,
7 fields::fp::{AllocatedFp, FpVar},
8};
9use ark_relations::gr1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError, Variable};
10
11use super::Assignments;
12use crate::{arithmetizations::r1cs::R1CS, circuits::FCircuit, traits::SonobeField};
13
14pub struct CircuitForTest<F: PrimeField> {
20 pub x: F,
22}
23
24impl<F: PrimeField> ConstraintSynthesizer<F> for CircuitForTest<F> {
25 fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
26 let x = AllocatedFp::new_input(cs.clone(), || Ok(self.x))?;
29 let y = AllocatedFp::new_witness(cs.clone(), || Ok(self.x.pow([3]) + self.x + F::from(5)))?;
31
32 let x_square = x.square()?;
34 let x_cube = x_square.mul(&x);
36 let t = AllocatedFp::new_witness(cs.clone(), || Ok(self.x.pow([3]) + self.x))?;
38 let x_cube_plus_x = x.add(&x_cube);
39 cs.enforce_r1cs_constraint(
41 || x_cube_plus_x.variable.into(),
42 || Variable::one().into(),
43 || t.variable.into(),
44 )?;
45 let x_cube_plus_x_plus_5 = t.add_constant(F::from(5));
46 cs.enforce_r1cs_constraint(
48 || x_cube_plus_x_plus_5.variable.into(),
49 || Variable::one().into(),
50 || y.variable.into(),
51 )?;
52 Ok(())
53 }
54}
55
56impl<F: SonobeField> FCircuit for CircuitForTest<F> {
57 type Field = F;
58 type State = [F; 1];
59 type StateVar = [FpVar<F>; 1];
60
61 type ExternalInputs = ();
62 type ExternalOutputs = ();
63
64 fn dummy_state(&self) -> Self::State {
65 [F::zero(); 1]
66 }
67
68 fn same_state_shape(_a: &Self::State, _b: &Self::State) -> bool {
69 true
71 }
72
73 fn dummy_external_inputs(&self) -> Self::ExternalInputs {}
74
75 fn generate_step_constraints(
76 &self,
77 _i: FpVar<Self::Field>,
78 z_i: Self::StateVar,
79 _external_inputs: Self::ExternalInputs,
80 ) -> Result<(Self::StateVar, Self::ExternalOutputs), SynthesisError> {
81 let cs = z_i.cs();
82
83 let x = if let FpVar::Var(x) = z_i[0].clone() {
86 x
87 } else {
88 unreachable!()
89 };
90 let y = AllocatedFp::new_witness(cs.clone(), || {
92 Ok(x.value()?.pow([3]) + x.value()? + F::from(5))
93 })?;
94
95 let x_square = x.square()?;
97 let x_cube = x_square.mul(&x);
99 let t = AllocatedFp::new_witness(cs.clone(), || Ok(x.value()?.pow([3]) + x.value()?))?;
101 let x_cube_plus_x = x.add(&x_cube);
102 cs.enforce_r1cs_constraint(
104 || x_cube_plus_x.variable.into(),
105 || Variable::one().into(),
106 || t.variable.into(),
107 )?;
108 let x_cube_plus_x_plus_5 = t.add_constant(F::from(5));
109 cs.enforce_r1cs_constraint(
111 || x_cube_plus_x_plus_5.variable.into(),
112 || Variable::one().into(),
113 || y.variable.into(),
114 )?;
115 Ok(([FpVar::Var(x_cube_plus_x_plus_5)], ()))
116 }
117}
118
119#[allow(non_snake_case)]
121pub fn constraints_for_test<F: Field>() -> R1CS<F> {
122 let A = vec![
125 vec![(F::one(), 1)],
126 vec![(F::one(), 3)],
127 vec![(F::one(), 1), (F::one(), 4)],
128 vec![(F::from(5), 0), (F::one(), 5)],
129 ];
130 let B = vec![
131 vec![(F::one(), 1)],
132 vec![(F::one(), 1)],
133 vec![(F::one(), 0)],
134 vec![(F::one(), 0)],
135 ];
136 let C = vec![
137 vec![(F::one(), 3)],
138 vec![(F::one(), 4)],
139 vec![(F::one(), 5)],
140 vec![(F::one(), 2)],
141 ];
142
143 R1CS::<F>::new_without_validity_check(4, 6, 1, [A, B, C])
144}
145
146pub fn satisfying_assignments_for_test<F: Field>(x: F) -> Assignments<F, Vec<F>> {
149 Assignments::from((
150 F::one(),
151 vec![x],
152 vec![
153 x * x * x + x + F::from(5), x * x, x * x * x, x * x * x + x, ],
158 ))
159}