github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/setup_test.go.tmpl (about)

     1  import (
     2  	"testing"
     3  
     4  	{{- template "import_fr" . }}
     5  	{{- template "import_curve" . }}
     6  	{{- template "import_backend_cs" . }}
     7  
     8  	"github.com/consensys/gnark/backend/groth16"
     9  	"github.com/consensys/gnark/frontend"
    10  	"github.com/consensys/gnark/frontend/cs/r1cs"
    11  	"github.com/consensys/gnark/std/hash/mimc"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	native_mimc "github.com/consensys/gnark-crypto/ecc/{{toLower .Curve}}/fr/mimc"
    15  )
    16  
    17  func TestSetupCircuit(t *testing.T) {
    18  	{{- if ne (toLower .Curve) "bn254" }}
    19  	if testing.Short() {
    20  		t.Skip()
    21  	}
    22  	{{- end}}
    23  	const (
    24  		nContributionsPhase1 = 3
    25  		nContributionsPhase2 = 3
    26  		power                = 9
    27  	)
    28  
    29  	assert := require.New(t)
    30  
    31  	srs1 := InitPhase1(power)
    32  
    33  	// Make and verify contributions for phase1
    34  	for i := 1; i < nContributionsPhase1; i++ {
    35  		// we clone test purposes; but in practice, participant will receive a []byte, deserialize it,
    36  		// add his contribution and send back to coordinator.
    37  		prev := srs1.clone()
    38  
    39  		srs1.Contribute()
    40  		assert.NoError(VerifyPhase1(&prev, &srs1))
    41  	}
    42  
    43  	// Compile the circuit
    44  	var myCircuit Circuit
    45  	ccs, err := frontend.Compile(curve.ID.ScalarField(), r1cs.NewBuilder, &myCircuit)
    46  	assert.NoError(err)
    47  
    48  	var evals Phase2Evaluations
    49  	r1cs := ccs.(*cs.R1CS)
    50  
    51  	// Prepare for phase-2
    52  	srs2, evals := InitPhase2(r1cs, &srs1)
    53  
    54  	// Make and verify contributions for phase1
    55  	for i := 1; i < nContributionsPhase2; i++ {
    56  		// we clone for test purposes; but in practice, participant will receive a []byte, deserialize it,
    57  		// add his contribution and send back to coordinator.
    58  		prev := srs2.clone()
    59  
    60  		srs2.Contribute()
    61  		assert.NoError(VerifyPhase2(&prev, &srs2))
    62  	}
    63  
    64  	// Extract the proving and verifying keys
    65  	pk, vk := ExtractKeys(&srs1, &srs2, &evals, ccs.GetNbConstraints())
    66  
    67  	// Build the witness
    68  	var preImage, hash fr.Element
    69  	{
    70  		m := native_mimc.NewMiMC()
    71  		m.Write(preImage.Marshal())
    72  		hash.SetBytes(m.Sum(nil))
    73  	}
    74  	
    75  	witness, err := frontend.NewWitness(&Circuit{PreImage: preImage, Hash: hash}, curve.ID.ScalarField())
    76  	assert.NoError(err)
    77  
    78  	pubWitness, err := witness.Public()
    79  	assert.NoError(err)
    80  
    81  	// groth16: ensure proof is verified
    82  	proof, err := groth16.Prove(ccs, &pk, witness)
    83  	assert.NoError(err)
    84  
    85  	err = groth16.Verify(proof, &vk, pubWitness)
    86  	assert.NoError(err)
    87  }
    88  
    89  func BenchmarkPhase1(b *testing.B) {
    90  	const power = 14
    91  
    92  	b.Run("init", func(b *testing.B) {
    93  		b.ResetTimer()
    94  		for i := 0; i < b.N; i++ {
    95  			_ = InitPhase1(power)
    96  		}
    97  	})
    98  
    99  	b.Run("contrib", func(b *testing.B) {
   100  		srs1 := InitPhase1(power)
   101  		b.ResetTimer()
   102  		for i := 0; i < b.N; i++ {
   103  			srs1.Contribute()
   104  		}
   105  	})
   106  
   107  }
   108  
   109  func BenchmarkPhase2(b *testing.B) {
   110  	const power = 14
   111  	srs1 := InitPhase1(power)
   112  	srs1.Contribute()
   113  
   114  	var myCircuit Circuit
   115  	ccs, err := frontend.Compile(curve.ID.ScalarField(), r1cs.NewBuilder, &myCircuit)
   116  	if err != nil {
   117  		b.Fatal(err)
   118  	}
   119  
   120  	r1cs := ccs.(*cs.R1CS)
   121  
   122  	b.Run("init", func(b *testing.B) {
   123  		b.ResetTimer()
   124  		for i := 0; i < b.N; i++ {
   125  			_, _ = InitPhase2(r1cs, &srs1)
   126  		}
   127  	})
   128  
   129  	b.Run("contrib", func(b *testing.B) {
   130  		srs2, _ := InitPhase2(r1cs, &srs1)
   131  		b.ResetTimer()
   132  		for i := 0; i < b.N; i++ {
   133  			srs2.Contribute()
   134  		}
   135  	})
   136  
   137  }
   138  
   139  // Circuit defines a pre-image knowledge proof
   140  // mimc(secret preImage) = public hash
   141  type Circuit struct {
   142  	PreImage frontend.Variable
   143  	Hash     frontend.Variable `gnark:",public"`
   144  }
   145  
   146  // Define declares the circuit's constraints
   147  // Hash = mimc(PreImage)
   148  func (circuit *Circuit) Define(api frontend.API) error {
   149  	// hash function
   150  	mimc, _ := mimc.NewMiMC(api)
   151  
   152  	// specify constraints
   153  	mimc.Write(circuit.PreImage)
   154  	api.AssertIsEqual(circuit.Hash, mimc.Sum())
   155  
   156  	return nil
   157  }
   158  
   159  func (phase1 *Phase1) clone() Phase1 {
   160  	r := Phase1{}
   161  	r.Parameters.G1.Tau = append(r.Parameters.G1.Tau, phase1.Parameters.G1.Tau...)
   162  	r.Parameters.G1.AlphaTau = append(r.Parameters.G1.AlphaTau, phase1.Parameters.G1.AlphaTau...)
   163  	r.Parameters.G1.BetaTau = append(r.Parameters.G1.BetaTau, phase1.Parameters.G1.BetaTau...)
   164  
   165  	r.Parameters.G2.Tau = append(r.Parameters.G2.Tau, phase1.Parameters.G2.Tau...)
   166  	r.Parameters.G2.Beta = phase1.Parameters.G2.Beta
   167  
   168  	r.PublicKeys = phase1.PublicKeys
   169  	r.Hash = append(r.Hash, phase1.Hash...)
   170  
   171  	return r
   172  }
   173  
   174  func (phase2 *Phase2) clone() Phase2 {
   175  	r := Phase2{}
   176  	r.Parameters.G1.Delta = phase2.Parameters.G1.Delta
   177  	r.Parameters.G1.L = append(r.Parameters.G1.L, phase2.Parameters.G1.L...)
   178  	r.Parameters.G1.Z = append(r.Parameters.G1.Z, phase2.Parameters.G1.Z...)
   179  	r.Parameters.G2.Delta = phase2.Parameters.G2.Delta
   180  	r.PublicKey = phase2.PublicKey
   181  	r.Hash = append(r.Hash, phase2.Hash...)
   182  
   183  	return r
   184  }