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 }