github.com/consensys/gnark-crypto@v0.14.0/internal/generator/pedersen/template/example_test.go.tmpl (about)

     1  import (
     2  	"crypto/rand"
     3  	"fmt"
     4  
     5  	"github.com/consensys/gnark-crypto/ecc"
     6  	curve "github.com/consensys/gnark-crypto/ecc/{{.Name}}"
     7  	"github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr"
     8  )
     9  
    10  // This example demonstrates how to use the Pedersen commitment scheme
    11  // to commit to a set of values and prove knowledge of the committed values.
    12  //
    13  // Does not perform any batching or multi-proof optimization.
    14  func Example_singleProof() {
    15  	const nbElem = 4
    16  	// create a proving key with independent basis elements
    17  	var buf [32]byte
    18  	basis := make([]curve.G1Affine, nbElem)
    19  	for i := range basis {
    20  		_, err := rand.Read(buf[:])
    21  		if err != nil {
    22  			panic(err)
    23  		}
    24  		// we use hash-to-curve to avoid linear dependencies between basis elements
    25  		basis[i], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
    26  		if err != nil {
    27  			panic(err)
    28  		}
    29  	}
    30  	// create a proving and verifying key. NB! Must be done using MPC
    31  	pks, vk, err := Setup([][]curve.G1Affine{basis})
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  	// currently we only have a single proving key
    36  	pk := pks[0]
    37  	toCommit := make([]fr.Element, nbElem)
    38  	for i := range toCommit {
    39  		toCommit[i].SetRandom()
    40  	}
    41  	// commit to the values
    42  	commitment, err := pk.Commit(toCommit)
    43  	if err != nil {
    44  		panic(err)
    45  	}
    46  	// prove knowledge of the committed values
    47  	pok, err := pk.ProveKnowledge(toCommit)
    48  	if err != nil {
    49  		panic(err)
    50  	}
    51  	// verify the proof
    52  	if err := vk.Verify(commitment, pok); err != nil {
    53  		panic(err)
    54  	}
    55  
    56  	fmt.Println("verified")
    57  	// output: verified
    58  }
    59  
    60  // This example shows how to batch the commitment and proof generation.
    61  func ExampleBatchProve() {
    62  	const nbPks = 3
    63  	const nbElem = 4
    64  	// create a proving key with independent basis elements
    65  	var buf [32]byte
    66  	basis := make([][]curve.G1Affine, nbPks)
    67  	for i := range basis {
    68  		basis[i] = make([]curve.G1Affine, nbElem)
    69  		for j := range basis[i] {
    70  			_, err := rand.Read(buf[:])
    71  			if err != nil {
    72  				panic(err)
    73  			}
    74  			// we use hash-to-curve to avoid linear dependencies between basis elements
    75  			basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
    76  			if err != nil {
    77  				panic(err)
    78  			}
    79  		}
    80  	}
    81  	// create a proving and verifying key. NB! Must be done using MPC
    82  	pks, vk, err := Setup(basis)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  	// generate random values to commit to
    87  	toCommit := make([][]fr.Element, nbPks)
    88  	for i := range toCommit {
    89  		toCommit[i] = make([]fr.Element, nbElem)
    90  		for j := range toCommit[i] {
    91  			toCommit[i][j].SetRandom()
    92  		}
    93  	}
    94  	// commit to the values
    95  	commitments := make([]curve.G1Affine, nbPks)
    96  	for i := range commitments {
    97  		commitments[i], err = pks[i].Commit(toCommit[i])
    98  		if err != nil {
    99  			panic(err)
   100  		}
   101  	}
   102  	// combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir!
   103  	var combinationCoeff fr.Element
   104  	combinationCoeff.SetRandom()
   105  	proof, err := BatchProve(pks, toCommit, combinationCoeff)
   106  	if err != nil {
   107  		panic(err)
   108  	}
   109  	// fold the commitments
   110  	foldedCommitment, err := new(curve.G1Affine).Fold(commitments, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1})
   111  	if err != nil {
   112  		panic(err)
   113  	}
   114  	// verify the proof
   115  	if err := vk.Verify(*foldedCommitment, proof); err != nil {
   116  		panic(err)
   117  	}
   118  	fmt.Println("verified")
   119  
   120  	// Output: verified
   121  }
   122  
   123  // This example shows how to batch verify multiple proofs using multiple
   124  // verifying keys.
   125  func ExampleBatchVerifyMultiVk() {
   126  	const nbPks = 3
   127  	const nbElem = 4
   128  	// create a proving key with independent basis elements
   129  	var buf [32]byte
   130  	basis := make([][]curve.G1Affine, nbPks)
   131  	for i := range basis {
   132  		basis[i] = make([]curve.G1Affine, nbElem)
   133  		for j := range basis[i] {
   134  			_, err := rand.Read(buf[:])
   135  			if err != nil {
   136  				panic(err)
   137  			}
   138  			// we use hash-to-curve to avoid linear dependencies between basis elements
   139  			basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i)))
   140  			if err != nil {
   141  				panic(err)
   142  			}
   143  		}
   144  	}
   145  	// we create independent proving keys (different sigmas) with same G2
   146  	// g2Point does not have to be generated in a trusted manner
   147  	_, _, _, g2Point := curve.Generators()
   148  	pks := make([]ProvingKey, nbPks)
   149  	vks := make([]VerifyingKey, nbPks)
   150  	for i := range basis {
   151  		pkss, vkss, err := Setup(basis[i:i+1], WithG2Point(g2Point))
   152  		if err != nil {
   153  			panic(err)
   154  		}
   155  		pks[i] = pkss[0]
   156  		vks[i] = vkss
   157  	}
   158  	// generate random values to commit to
   159  	toCommit := make([][]fr.Element, nbPks)
   160  	for i := range toCommit {
   161  		toCommit[i] = make([]fr.Element, nbElem)
   162  		for j := range toCommit[i] {
   163  			toCommit[i][j].SetRandom()
   164  		}
   165  	}
   166  	// commit to the values
   167  	commitments := make([]curve.G1Affine, nbPks)
   168  	for i := range commitments {
   169  		var err error
   170  		commitments[i], err = pks[i].Commit(toCommit[i])
   171  		if err != nil {
   172  			panic(err)
   173  		}
   174  	}
   175  	// prove the commitments
   176  	proofs := make([]curve.G1Affine, nbPks)
   177  	for i := range proofs {
   178  		var err error
   179  		proofs[i], err = pks[i].ProveKnowledge(toCommit[i])
   180  		if err != nil {
   181  			panic(err)
   182  		}
   183  	}
   184  	// combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir!
   185  	var combinationCoeff fr.Element
   186  	combinationCoeff.SetRandom()
   187  	// batch verify the proofs
   188  	if err := BatchVerifyMultiVk(vks, commitments, proofs, combinationCoeff); err != nil {
   189  		panic(err)
   190  	}
   191  
   192  	// alternatively, we can also provide the folded proof
   193  	foldedProof, err := new(curve.G1Affine).Fold(proofs, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1})
   194  	if err != nil {
   195  		panic(err)
   196  	}
   197  	if err := BatchVerifyMultiVk(vks, commitments, []curve.G1Affine{*foldedProof}, combinationCoeff); err != nil {
   198  		panic(err)
   199  	}
   200  
   201  	fmt.Println("verified")
   202  	// Output: verified
   203  }