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  }