github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/plonkfri/plonk.verify.go.tmpl (about) 1 import ( 2 "fmt" 3 "errors" 4 "math/big" 5 6 {{- template "import_fri" . }} 7 {{- template "import_fr" . }} 8 "github.com/consensys/gnark/backend" 9 fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" 10 ) 11 12 var ErrInvalidAlgebraicRelation = errors.New("algebraic relation does not hold") 13 14 func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { 15 cfg, err := backend.NewVerifierConfig(opts...) 16 if err != nil { 17 return fmt.Errorf("create backend config: %w", err) 18 } 19 20 // 0 - derive the challenges with Fiat Shamir 21 fs := fiatshamir.NewTranscript(cfg.ChallengeHash, "gamma", "beta", "alpha", "zeta") 22 23 dataFiatShamir := make([][fr.Bytes]byte, len(publicWitness)+3) 24 for i := 0; i < len(publicWitness); i++ { 25 copy(dataFiatShamir[i][:], publicWitness[i].Marshal()) 26 } 27 copy(dataFiatShamir[len(publicWitness)][:], proof.LROpp[0].ID) 28 copy(dataFiatShamir[len(publicWitness)+1][:], proof.LROpp[1].ID) 29 copy(dataFiatShamir[len(publicWitness)+2][:], proof.LROpp[2].ID) 30 31 beta, err := deriveRandomnessFixedSize(fs, "gamma", dataFiatShamir...) 32 if err != nil { 33 return err 34 } 35 36 gamma, err := deriveRandomness(fs, "beta", nil) 37 if err != nil { 38 return err 39 } 40 41 alpha, err := deriveRandomness(fs, "alpha", proof.Zpp.ID) 42 if err != nil { 43 return err 44 } 45 46 // compute the size of the domain of evaluation of the committed polynomial, 47 // the opening position. The challenge zeta will be g^{i} where i is the opening 48 // position, and g is the generator of the fri domain. 49 rho := uint64(fri.GetRho()) 50 friSize := 2 * rho * vk.Size 51 var bFriSize big.Int 52 bFriSize.SetInt64(int64(friSize)) 53 frOpeningPosition, err := deriveRandomness(fs, "zeta", proof.Hpp[0].ID, proof.Hpp[1].ID, proof.Hpp[2].ID) 54 if err != nil { 55 return err 56 } 57 var bOpeningPosition big.Int 58 bOpeningPosition.SetBytes(frOpeningPosition.Marshal()).Mod(&bOpeningPosition, &bFriSize) 59 openingPosition := bOpeningPosition.Uint64() 60 61 shiftedOpeningPosition := (openingPosition + uint64(2*rho)) % friSize 62 err = vk.Iopp.VerifyOpening(shiftedOpeningPosition, proof.OpeningsZmp[1], proof.Zpp) 63 if err != nil { 64 return err 65 } 66 67 // 1 - verify that the commitments are low degree polynomials 68 69 // ql, qr, qm, qo, qkIncomplete 70 err = vk.Iopp.VerifyProofOfProximity(vk.Qpp[0]) 71 if err != nil { 72 return err 73 } 74 err = vk.Iopp.VerifyProofOfProximity(vk.Qpp[1]) 75 if err != nil { 76 return err 77 } 78 err = vk.Iopp.VerifyProofOfProximity(vk.Qpp[2]) 79 if err != nil { 80 return err 81 } 82 err = vk.Iopp.VerifyProofOfProximity(vk.Qpp[3]) 83 if err != nil { 84 return err 85 } 86 err = vk.Iopp.VerifyProofOfProximity(vk.Qpp[4]) 87 if err != nil { 88 return err 89 } 90 91 // l, r, o 92 err = vk.Iopp.VerifyProofOfProximity(proof.LROpp[0]) 93 if err != nil { 94 return err 95 } 96 err = vk.Iopp.VerifyProofOfProximity(proof.LROpp[1]) 97 if err != nil { 98 return err 99 } 100 err = vk.Iopp.VerifyProofOfProximity(proof.LROpp[2]) 101 if err != nil { 102 return err 103 } 104 err = vk.Iopp.VerifyProofOfProximity(proof.Zpp) 105 if err != nil { 106 return err 107 } 108 109 // h0, h1, h2 110 err = vk.Iopp.VerifyProofOfProximity(proof.Hpp[0]) 111 if err != nil { 112 return err 113 } 114 err = vk.Iopp.VerifyProofOfProximity(proof.Hpp[1]) 115 if err != nil { 116 return err 117 } 118 err = vk.Iopp.VerifyProofOfProximity(proof.Hpp[2]) 119 if err != nil { 120 return err 121 } 122 123 // s1, s2, s3 124 err = vk.Iopp.VerifyProofOfProximity(vk.Spp[0]) 125 if err != nil { 126 return err 127 } 128 err = vk.Iopp.VerifyProofOfProximity(vk.Spp[1]) 129 if err != nil { 130 return err 131 } 132 err = vk.Iopp.VerifyProofOfProximity(vk.Spp[2]) 133 if err != nil { 134 return err 135 } 136 137 // id1, id2, id3 138 err = vk.Iopp.VerifyProofOfProximity(vk.Idpp[0]) 139 if err != nil { 140 return err 141 } 142 err = vk.Iopp.VerifyProofOfProximity(vk.Idpp[1]) 143 if err != nil { 144 return err 145 } 146 err = vk.Iopp.VerifyProofOfProximity(vk.Idpp[2]) 147 if err != nil { 148 return err 149 } 150 151 // Z 152 err = vk.Iopp.VerifyProofOfProximity(proof.Zpp) 153 if err != nil { 154 return err 155 } 156 157 // 2 - verify the openings 158 159 // ql, qr, qm, qo, qkIncomplete 160 // openingPosition := uint64(2) 161 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsQlQrQmQoQkincompletemp[0], vk.Qpp[0]) 162 if err != nil { 163 return err 164 } 165 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsQlQrQmQoQkincompletemp[1], vk.Qpp[1]) 166 if err != nil { 167 return err 168 } 169 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsQlQrQmQoQkincompletemp[2], vk.Qpp[2]) 170 if err != nil { 171 return err 172 } 173 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsQlQrQmQoQkincompletemp[3], vk.Qpp[3]) 174 if err != nil { 175 return err 176 } 177 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsQlQrQmQoQkincompletemp[4], vk.Qpp[4]) 178 if err != nil { 179 return err 180 } 181 182 // l, r, o 183 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsLROmp[0], proof.LROpp[0]) 184 if err != nil { 185 return err 186 } 187 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsLROmp[1], proof.LROpp[1]) 188 if err != nil { 189 return err 190 } 191 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsLROmp[2], proof.LROpp[2]) 192 if err != nil { 193 return err 194 } 195 196 // h0, h1, h2 197 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsHmp[0], proof.Hpp[0]) 198 if err != nil { 199 return err 200 } 201 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsHmp[1], proof.Hpp[1]) 202 if err != nil { 203 return err 204 } 205 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsHmp[2], proof.Hpp[2]) 206 if err != nil { 207 return err 208 } 209 210 // s0, s1, s2 211 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsS1S2S3mp[0], vk.Spp[0]) 212 if err != nil { 213 return err 214 } 215 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsS1S2S3mp[1], vk.Spp[1]) 216 if err != nil { 217 return err 218 } 219 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsS1S2S3mp[2], vk.Spp[2]) 220 if err != nil { 221 return err 222 } 223 224 // id0, id1, id2 225 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsId1Id2Id3mp[0], vk.Idpp[0]) 226 if err != nil { 227 return err 228 } 229 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsId1Id2Id3mp[1], vk.Idpp[1]) 230 if err != nil { 231 return err 232 } 233 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsId1Id2Id3mp[2], vk.Idpp[2]) 234 if err != nil { 235 return err 236 } 237 238 // Z, Zshift 239 err = vk.Iopp.VerifyOpening(openingPosition, proof.OpeningsZmp[0], proof.Zpp) 240 if err != nil { 241 return err 242 } 243 244 // verification of the algebraic relation 245 var ql, qr, qm, qo, qk fr.Element 246 ql.Set(&proof.OpeningsQlQrQmQoQkincompletemp[0].ClaimedValue) 247 qr.Set(&proof.OpeningsQlQrQmQoQkincompletemp[1].ClaimedValue) 248 qm.Set(&proof.OpeningsQlQrQmQoQkincompletemp[2].ClaimedValue) 249 qo.Set(&proof.OpeningsQlQrQmQoQkincompletemp[3].ClaimedValue) 250 qk.Set(&proof.OpeningsQlQrQmQoQkincompletemp[4].ClaimedValue) // -> to be completed 251 252 var l, r, o fr.Element 253 l.Set(&proof.OpeningsLROmp[0].ClaimedValue) 254 r.Set(&proof.OpeningsLROmp[1].ClaimedValue) 255 o.Set(&proof.OpeningsLROmp[2].ClaimedValue) 256 257 var h1, h2, h3 fr.Element 258 h1.Set(&proof.OpeningsHmp[0].ClaimedValue) 259 h2.Set(&proof.OpeningsHmp[1].ClaimedValue) 260 h3.Set(&proof.OpeningsHmp[2].ClaimedValue) 261 262 var s1, s2, s3 fr.Element 263 s1.Set(&proof.OpeningsS1S2S3mp[0].ClaimedValue) 264 s2.Set(&proof.OpeningsS1S2S3mp[1].ClaimedValue) 265 s3.Set(&proof.OpeningsS1S2S3mp[2].ClaimedValue) 266 267 var id1, id2, id3 fr.Element 268 id1.Set(&proof.OpeningsId1Id2Id3mp[0].ClaimedValue) 269 id2.Set(&proof.OpeningsId1Id2Id3mp[1].ClaimedValue) 270 id3.Set(&proof.OpeningsId1Id2Id3mp[2].ClaimedValue) 271 272 var z, zshift fr.Element 273 z.Set(&proof.OpeningsZmp[0].ClaimedValue) 274 zshift.Set(&proof.OpeningsZmp[1].ClaimedValue) 275 276 // 2 - compute the LHS: (ql*l+..+qk)+ α*(z(μx)*(l+β*s₁+γ)*..-z*(l+β*id1+γ))+α²*z*(l1-1) 277 var zeta fr.Element 278 zeta.Exp(vk.GenOpening, &bOpeningPosition) 279 280 var lhs, t1, t2, t3, tmp, tmp2 fr.Element 281 // 2.1 (ql*l+..+qk) 282 t1.Mul(&l, &ql) 283 tmp.Mul(&r, &qr) 284 t1.Add(&t1, &tmp) 285 tmp.Mul(&qm, &l).Mul(&tmp, &r) 286 t1.Add(&t1, &tmp) 287 tmp.Mul(&o, &qo) 288 t1.Add(&tmp, &t1) 289 tmp = completeQk(publicWitness, vk, zeta) 290 tmp.Add(&qk, &tmp) 291 t1.Add(&tmp, &t1) 292 293 // 2.2 (z(ux)*(l+β*s1+γ)*..-z*(l+β*id1+γ)) 294 t2.Mul(&beta, &s1).Add(&t2, &l).Add(&t2, &gamma) 295 tmp.Mul(&beta, &s2).Add(&tmp, &r).Add(&tmp, &gamma) 296 t2.Mul(&tmp, &t2) 297 tmp.Mul(&beta, &s3).Add(&tmp, &o).Add(&tmp, &gamma) 298 t2.Mul(&tmp, &t2).Mul(&t2, &zshift) 299 300 tmp.Mul(&beta, &id1).Add(&tmp, &l).Add(&tmp, &gamma) 301 tmp2.Mul(&beta, &id2).Add(&tmp2, &r).Add(&tmp2, &gamma) 302 tmp.Mul(&tmp, &tmp2) 303 tmp2.Mul(&beta, &id3).Add(&tmp2, &o).Add(&tmp2, &gamma) 304 tmp.Mul(&tmp2, &tmp).Mul(&tmp, &z) 305 306 t2.Sub(&t2, &tmp) 307 308 // 2.3 (z-1)*l1 309 var one fr.Element 310 one.SetOne() 311 t3.Exp(zeta, big.NewInt(int64(vk.Size))).Sub(&t3, &one) 312 tmp.Sub(&zeta, &one).Inverse(&tmp).Mul(&tmp, &vk.SizeInv) 313 t3.Mul(&tmp, &t3) 314 tmp.Sub(&z, &one) 315 t3.Mul(&tmp, &t3) 316 317 // 2.4 (ql*l+s+qk) + α*(z(ux)*(l+β*s1+γ)*...-z*(l+β*id1+γ)..)+ α²*z*(l1-1) 318 lhs.Set(&t3).Mul(&lhs, &alpha).Add(&lhs, &t2).Mul(&lhs, &alpha).Add(&lhs, &t1) 319 320 // 3 - compute the RHS 321 var rhs fr.Element 322 tmp.Exp(zeta, big.NewInt(int64(vk.Size+2))) 323 rhs.Mul(&h3, &tmp). 324 Add(&rhs, &h2). 325 Mul(&rhs, &tmp). 326 Add(&rhs, &h1) 327 328 tmp.Exp(zeta, big.NewInt(int64(vk.Size))).Sub(&tmp, &one) 329 rhs.Mul(&rhs, &tmp) 330 331 // 4 - verify the relation LHS==RHS 332 if !rhs.Equal(&lhs) { 333 return ErrInvalidAlgebraicRelation 334 } 335 336 return nil 337 338 } 339 340 // completeQk returns ∑_{i<nb_public_inputs}w_i*L_i 341 func completeQk(publicWitness []fr.Element, vk *VerifyingKey, zeta fr.Element) fr.Element { 342 343 var res fr.Element 344 345 // compute l1(zeta). Exceptional case: if zeta=1, then l1(zeta)=1, 346 // we need to manually initialise l to this value otherwise there 347 // is a denominator equal to zero in the formula. 348 var l, tmp, acc, one fr.Element 349 one.SetOne() 350 acc.SetOne() 351 l.Sub(&zeta, &one) 352 if l.IsZero() { 353 l.SetOne() 354 } else { 355 l.Inverse(&l).Mul(&l, &vk.SizeInv) 356 tmp.Exp(zeta, big.NewInt(int64(vk.Size))).Sub(&tmp, &one) 357 l.Mul(&l, &tmp) 358 } 359 360 // use L_i+1 = w*Li*(X-z**i)/(X-z**i+1) 361 for i := 0; i < len(publicWitness); i++ { 362 363 tmp.Mul(&l, &publicWitness[i]) 364 res.Add(&res, &tmp) 365 366 tmp.Sub(&zeta, &acc) 367 l.Mul(&l, &tmp).Mul(&l, &vk.Generator) 368 acc.Mul(&acc, &vk.Generator) 369 tmp.Sub(&zeta, &acc) 370 // if tmp==0, then zeta=vk.Generator**i, so l_i(zeta)=1. We need 371 // to manually set the value to 1, exacty as in the case l_0 before 372 // the loop, otherwise the generic formula leads to a division by zero. 373 if tmp.IsZero() { 374 l.SetOne() 375 } else { 376 l.Div(&l, &tmp) 377 } 378 } 379 380 return res 381 }