github.com/consensys/gnark@v0.11.0/constraint/r1cs_test.go (about) 1 package constraint_test 2 3 import ( 4 "fmt" 5 6 "github.com/consensys/gnark-crypto/ecc" 7 "github.com/consensys/gnark/constraint" 8 cs "github.com/consensys/gnark/constraint/bn254" 9 "github.com/consensys/gnark/frontend" 10 "github.com/consensys/gnark/frontend/cs/r1cs" 11 ) 12 13 func ExampleR1CS_GetR1Cs() { 14 // build a constraint system; this is (usually) done by the frontend package 15 // for this Example we want to manipulate the constraints and output a string representation 16 // and build the linear expressions "manually". 17 r1cs := cs.NewR1CS(0) 18 19 blueprint := r1cs.AddBlueprint(&constraint.BlueprintGenericR1C{}) 20 21 ONE := r1cs.AddPublicVariable("1") // the "ONE" wire 22 Y := r1cs.AddPublicVariable("Y") 23 X := r1cs.AddSecretVariable("X") 24 25 v0 := r1cs.AddInternalVariable() // X² 26 v1 := r1cs.AddInternalVariable() // X³ 27 28 // coefficients 29 cOne := r1cs.FromInterface(1) 30 cFive := r1cs.FromInterface(5) 31 32 // X² == X * X 33 r1cs.AddR1C(constraint.R1C{ 34 L: constraint.LinearExpression{r1cs.MakeTerm(cOne, X)}, 35 R: constraint.LinearExpression{r1cs.MakeTerm(cOne, X)}, 36 O: constraint.LinearExpression{r1cs.MakeTerm(cOne, v0)}, 37 }, blueprint) 38 39 // X³ == X² * X 40 r1cs.AddR1C(constraint.R1C{ 41 L: constraint.LinearExpression{r1cs.MakeTerm(cOne, v0)}, 42 R: constraint.LinearExpression{r1cs.MakeTerm(cOne, X)}, 43 O: constraint.LinearExpression{r1cs.MakeTerm(cOne, v1)}, 44 }, blueprint) 45 46 // Y == X³ + X + 5 47 r1cs.AddR1C(constraint.R1C{ 48 R: constraint.LinearExpression{r1cs.MakeTerm(cOne, ONE)}, 49 L: constraint.LinearExpression{r1cs.MakeTerm(cOne, Y)}, 50 O: constraint.LinearExpression{ 51 r1cs.MakeTerm(cFive, ONE), 52 r1cs.MakeTerm(cOne, X), 53 r1cs.MakeTerm(cOne, v1), 54 }, 55 }, blueprint) 56 57 // get the constraints 58 constraints := r1cs.GetR1Cs() 59 60 for _, r1c := range constraints { 61 fmt.Println(r1c.String(r1cs)) 62 // for more granularity use constraint.NewStringBuilder(r) that embeds a string.Builder 63 // and has WriteLinearExpression and WriteTerm methods. 64 } 65 66 // Output: 67 // X ⋅ X == v0 68 // v0 ⋅ X == v1 69 // Y ⋅ 1 == 5 + X + v1 70 } 71 72 func ExampleR1CS_Solve() { 73 // build a constraint system and a witness; 74 ccs, _ := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &cubic{}) 75 w, _ := frontend.NewWitness(&cubic{X: 3, Y: 35}, ecc.BN254.ScalarField()) 76 77 _solution, _ := ccs.Solve(w) 78 79 // concrete solution 80 solution := _solution.(*cs.R1CSSolution) 81 82 // solution vector should have [1, 3, 35, 9, 27] 83 for _, v := range solution.W { 84 fmt.Println(v.String()) 85 } 86 87 // Output: 88 // 1 89 // 3 90 // 35 91 // 9 92 // 27 93 } 94 95 type cubic struct { 96 X, Y frontend.Variable 97 } 98 99 // Define declares the circuit constraints 100 // x**3 + x + 5 == y 101 func (circuit *cubic) Define(api frontend.API) error { 102 x3 := api.Mul(circuit.X, circuit.X, circuit.X) 103 api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5)) 104 return nil 105 }