github.com/consensys/gnark@v0.11.0/backend/plonk/bls24-317/verify.go (about) 1 // Copyright 2020 ConsenSys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by gnark DO NOT EDIT 16 17 package plonk 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "math/big" 24 25 "github.com/consensys/gnark/backend/solidity" 26 "time" 27 28 "github.com/consensys/gnark-crypto/ecc" 29 30 curve "github.com/consensys/gnark-crypto/ecc/bls24-317" 31 32 "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" 33 34 "github.com/consensys/gnark-crypto/ecc/bls24-317/fr/hash_to_field" 35 36 "github.com/consensys/gnark-crypto/ecc/bls24-317/kzg" 37 fiatshamir "github.com/consensys/gnark-crypto/fiat-shamir" 38 "github.com/consensys/gnark/backend" 39 "github.com/consensys/gnark/logger" 40 ) 41 42 var ( 43 errAlgebraicRelation = errors.New("algebraic relation does not hold") 44 errInvalidWitness = errors.New("witness length is invalid") 45 errInvalidPoint = errors.New("point is not on the curve") 46 ) 47 48 func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...backend.VerifierOption) error { 49 50 log := logger.Logger().With().Str("curve", "bls24-317").Str("backend", "plonk").Logger() 51 start := time.Now() 52 cfg, err := backend.NewVerifierConfig(opts...) 53 if err != nil { 54 return fmt.Errorf("create backend config: %w", err) 55 } 56 57 if len(proof.Bsb22Commitments) != len(vk.Qcp) { 58 return errors.New("BSB22 Commitment number mismatch") 59 } 60 61 if len(publicWitness) != int(vk.NbPublicVariables) { 62 return errInvalidWitness 63 } 64 65 // check that the points in the proof are on the curve 66 for i := 0; i < len(proof.LRO); i++ { 67 if !proof.LRO[i].IsInSubGroup() { 68 return errInvalidPoint 69 } 70 } 71 if !proof.Z.IsInSubGroup() { 72 return errInvalidPoint 73 } 74 for i := 0; i < len(proof.H); i++ { 75 if !proof.H[i].IsInSubGroup() { 76 return errInvalidPoint 77 } 78 } 79 for i := 0; i < len(proof.Bsb22Commitments); i++ { 80 if !proof.Bsb22Commitments[i].IsInSubGroup() { 81 return errInvalidPoint 82 } 83 } 84 if !proof.BatchedProof.H.IsInSubGroup() { 85 return errInvalidPoint 86 } 87 if !proof.ZShiftedOpening.H.IsInSubGroup() { 88 return errInvalidPoint 89 } 90 91 // transcript to derive the challenge 92 fs := fiatshamir.NewTranscript(cfg.ChallengeHash, "gamma", "beta", "alpha", "zeta") 93 94 // The first challenge is derived using the public data: the commitments to the permutation, 95 // the coefficients of the circuit, and the public inputs. 96 // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) 97 if err := bindPublicData(fs, "gamma", vk, publicWitness); err != nil { 98 return err 99 } 100 gamma, err := deriveRandomness(fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) 101 if err != nil { 102 return err 103 } 104 105 // derive beta from Comm(l), Comm(r), Comm(o) 106 beta, err := deriveRandomness(fs, "beta") 107 if err != nil { 108 return err 109 } 110 111 // derive alpha from Com(Z), Bsb22Commitments 112 alphaDeps := make([]*curve.G1Affine, len(proof.Bsb22Commitments)+1) 113 for i := range proof.Bsb22Commitments { 114 alphaDeps[i] = &proof.Bsb22Commitments[i] 115 } 116 alphaDeps[len(alphaDeps)-1] = &proof.Z 117 alpha, err := deriveRandomness(fs, "alpha", alphaDeps...) 118 if err != nil { 119 return err 120 } 121 122 // derive zeta, the point of evaluation 123 zeta, err := deriveRandomness(fs, "zeta", &proof.H[0], &proof.H[1], &proof.H[2]) 124 if err != nil { 125 return err 126 } 127 128 // evaluation of zhZeta=ζⁿ-1 129 var zetaPowerM, zhZeta, lagrangeZero fr.Element 130 var bExpo big.Int 131 one := fr.One() 132 bExpo.SetUint64(vk.Size) 133 zetaPowerM.Exp(zeta, &bExpo) 134 zhZeta.Sub(&zetaPowerM, &one) // ζⁿ-1 135 lagrangeZero.Sub(&zeta, &one). // ζ-1 136 Inverse(&lagrangeZero). // 1/(ζ-1) 137 Mul(&lagrangeZero, &zhZeta). // (ζ^n-1)/(ζ-1) 138 Mul(&lagrangeZero, &vk.SizeInv) // 1/n * (ζ^n-1)/(ζ-1) 139 140 // compute PI = ∑_{i<n} Lᵢ*wᵢ 141 var pi fr.Element 142 var accw fr.Element 143 { 144 // [ζ-1,ζ-ω,ζ-ω²,..] 145 dens := make([]fr.Element, len(publicWitness)) 146 accw.SetOne() 147 for i := 0; i < len(publicWitness); i++ { 148 dens[i].Sub(&zeta, &accw) 149 accw.Mul(&accw, &vk.Generator) 150 } 151 152 // [1/(ζ-1),1/(ζ-ω),1/(ζ-ω²),..] 153 invDens := fr.BatchInvert(dens) 154 155 accw.SetOne() 156 var xiLi fr.Element 157 for i := 0; i < len(publicWitness); i++ { 158 xiLi.Mul(&zhZeta, &invDens[i]). 159 Mul(&xiLi, &vk.SizeInv). 160 Mul(&xiLi, &accw). 161 Mul(&xiLi, &publicWitness[i]) // Pi[i]*(ωⁱ/n)(ζ^n-1)/(ζ-ω^i) 162 accw.Mul(&accw, &vk.Generator) 163 pi.Add(&pi, &xiLi) 164 } 165 166 if cfg.HashToFieldFn == nil { 167 cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) 168 } 169 var hashedCmt fr.Element 170 nbBuf := fr.Bytes 171 if cfg.HashToFieldFn.Size() < fr.Bytes { 172 nbBuf = cfg.HashToFieldFn.Size() 173 } 174 var wPowI, den, lagrange fr.Element 175 for i, cci := range vk.CommitmentConstraintIndexes { 176 cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) 177 hashBts := cfg.HashToFieldFn.Sum(nil) 178 cfg.HashToFieldFn.Reset() 179 hashedCmt.SetBytes(hashBts[:nbBuf]) 180 181 // Computing Lᵢ(ζ) where i=CommitmentIndex 182 wPowI.Exp(vk.Generator, big.NewInt(int64(vk.NbPublicVariables)+int64(cci))) 183 den.Sub(&zeta, &wPowI) // ζ-wⁱ 184 lagrange.SetOne(). 185 Sub(&zetaPowerM, &lagrange). // ζⁿ-1 186 Mul(&lagrange, &wPowI). // wⁱ(ζⁿ-1) 187 Div(&lagrange, &den). // wⁱ(ζⁿ-1)/(ζ-wⁱ) 188 Mul(&lagrange, &vk.SizeInv) // wⁱ/n (ζⁿ-1)/(ζ-wⁱ) 189 190 xiLi.Mul(&lagrange, &hashedCmt) 191 pi.Add(&pi, &xiLi) 192 } 193 } 194 195 var _s1, _s2, tmp fr.Element 196 l := proof.BatchedProof.ClaimedValues[1] 197 r := proof.BatchedProof.ClaimedValues[2] 198 o := proof.BatchedProof.ClaimedValues[3] 199 s1 := proof.BatchedProof.ClaimedValues[4] 200 s2 := proof.BatchedProof.ClaimedValues[5] 201 202 // Z(ωζ) 203 zu := proof.ZShiftedOpening.ClaimedValue 204 205 // α²*L₁(ζ) 206 var alphaSquarelagrangeZero fr.Element 207 alphaSquarelagrangeZero.Mul(&lagrangeZero, &alpha). 208 Mul(&alphaSquarelagrangeZero, &alpha) // α²*L₁(ζ) 209 210 // computing the constant coefficient of the full algebraic relation 211 // , corresponding to the value of the linearisation polynomiat at ζ 212 // PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) 213 var constLin fr.Element 214 constLin.Mul(&beta, &s1).Add(&constLin, &gamma).Add(&constLin, &l) // (l(ζ)+β*s1(ζ)+γ) 215 tmp.Mul(&s2, &beta).Add(&tmp, &gamma).Add(&tmp, &r) // (r(ζ)+β*s2(ζ)+γ) 216 constLin.Mul(&constLin, &tmp) // (l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ) 217 tmp.Add(&o, &gamma) // (o(ζ)+γ) 218 constLin.Mul(&tmp, &constLin).Mul(&constLin, &alpha).Mul(&constLin, &zu) // α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) 219 220 constLin.Sub(&constLin, &alphaSquarelagrangeZero).Add(&constLin, &pi) // PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) 221 constLin.Neg(&constLin) // -[PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ)] 222 223 // check that the opening of the linearised polynomial is equal to -constLin 224 openingLinPol := proof.BatchedProof.ClaimedValues[0] 225 if !constLin.Equal(&openingLinPol) { 226 return errAlgebraicRelation 227 } 228 229 // computing the linearised polynomial digest 230 // α²*L₁(ζ)*[Z] + 231 // _s1*[s3]+_s2*[Z] + l(ζ)*[Ql] + 232 // l(ζ)r(ζ)*[Qm] + r(ζ)*[Qr] + o(ζ)*[Qo] + [Qk] + ∑ᵢQcp_(ζ)[Pi_i] - 233 // Z_{H}(ζ)*(([H₀] + ζᵐ⁺²*[H₁] + ζ²⁽ᵐ⁺²⁾*[H₂]) 234 // where 235 // _s1 = α*(l(ζ)+β*s1(ζ)+γ)*(r(ζ)+β*s2(ζ)+γ)*β*Z(μζ) 236 // _s2 = -α*(l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ)*(o(ζ)+β*u²*ζ+γ) 237 238 // _s1 = α*(l(ζ)+β*s1(β)+γ)*(r(ζ)+β*s2(β)+γ)*β*Z(μζ) 239 _s1.Mul(&beta, &s1).Add(&_s1, &l).Add(&_s1, &gamma) // (l(ζ)+β*s1(β)+γ) 240 tmp.Mul(&beta, &s2).Add(&tmp, &r).Add(&tmp, &gamma) // (r(ζ)+β*s2(β)+γ) 241 _s1.Mul(&_s1, &tmp).Mul(&_s1, &beta).Mul(&_s1, &alpha).Mul(&_s1, &zu) // α*(l(ζ)+β*s1(β)+γ)*(r(ζ)+β*s2(β)+γ)*β*Z(μζ) 242 243 // _s2 = -α*(l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ)*(o(ζ)+β*u²*ζ+γ) 244 _s2.Mul(&beta, &zeta).Add(&_s2, &gamma).Add(&_s2, &l) // (l(ζ)+β*ζ+γ) 245 tmp.Mul(&beta, &vk.CosetShift).Mul(&tmp, &zeta).Add(&tmp, &gamma).Add(&tmp, &r) // (r(ζ)+β*u*ζ+γ) 246 _s2.Mul(&_s2, &tmp) // (l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ) 247 tmp.Mul(&beta, &vk.CosetShift).Mul(&tmp, &vk.CosetShift).Mul(&tmp, &zeta).Add(&tmp, &o).Add(&tmp, &gamma) // (o(ζ)+β*u²*ζ+γ) 248 _s2.Mul(&_s2, &tmp).Mul(&_s2, &alpha).Neg(&_s2) // -α*(l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ)*(o(ζ)+β*u²*ζ+γ) 249 250 // α²*L₁(ζ) - α*(l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ)*(o(ζ)+β*u²*ζ+γ) 251 var coeffZ fr.Element 252 coeffZ.Add(&alphaSquarelagrangeZero, &_s2) 253 254 // l(ζ)*r(ζ) 255 var rl fr.Element 256 rl.Mul(&l, &r) 257 258 // -ζⁿ⁺²*(ζⁿ-1), -ζ²⁽ⁿ⁺²⁾*(ζⁿ-1), -(ζⁿ-1) 259 nPlusTwo := big.NewInt(int64(vk.Size) + 2) 260 var zetaNPlusTwoZh, zetaNPlusTwoSquareZh, zh fr.Element 261 zetaNPlusTwoZh.Exp(zeta, nPlusTwo) 262 zetaNPlusTwoSquareZh.Mul(&zetaNPlusTwoZh, &zetaNPlusTwoZh) // ζ²⁽ⁿ⁺²⁾ 263 zetaNPlusTwoZh.Mul(&zetaNPlusTwoZh, &zhZeta).Neg(&zetaNPlusTwoZh) // -ζⁿ⁺²*(ζⁿ-1) 264 zetaNPlusTwoSquareZh.Mul(&zetaNPlusTwoSquareZh, &zhZeta).Neg(&zetaNPlusTwoSquareZh) // -ζ²⁽ⁿ⁺²⁾*(ζⁿ-1) 265 zh.Neg(&zhZeta) 266 267 var linearizedPolynomialDigest curve.G1Affine 268 points := append(proof.Bsb22Commitments, 269 vk.Ql, vk.Qr, vk.Qm, vk.Qo, vk.Qk, 270 vk.S[2], proof.Z, 271 proof.H[0], proof.H[1], proof.H[2], 272 ) 273 274 qC := make([]fr.Element, len(proof.Bsb22Commitments)) 275 copy(qC, proof.BatchedProof.ClaimedValues[6:]) 276 277 scalars := append(qC, 278 l, r, rl, o, one, 279 _s1, coeffZ, 280 zh, zetaNPlusTwoZh, zetaNPlusTwoSquareZh, 281 ) 282 if _, err := linearizedPolynomialDigest.MultiExp(points, scalars, ecc.MultiExpConfig{}); err != nil { 283 return err 284 } 285 286 // Fold the first proof 287 digestsToFold := make([]curve.G1Affine, len(vk.Qcp)+6) 288 copy(digestsToFold[6:], vk.Qcp) 289 digestsToFold[0] = linearizedPolynomialDigest 290 digestsToFold[1] = proof.LRO[0] 291 digestsToFold[2] = proof.LRO[1] 292 digestsToFold[3] = proof.LRO[2] 293 digestsToFold[4] = vk.S[0] 294 digestsToFold[5] = vk.S[1] 295 foldedProof, foldedDigest, err := kzg.FoldProof( 296 digestsToFold, 297 &proof.BatchedProof, 298 zeta, 299 cfg.KZGFoldingHash, 300 zu.Marshal(), 301 ) 302 if err != nil { 303 return err 304 } 305 306 // Batch verify 307 var shiftedZeta fr.Element 308 shiftedZeta.Mul(&zeta, &vk.Generator) 309 err = kzg.BatchVerifyMultiPoints([]kzg.Digest{ 310 foldedDigest, 311 proof.Z, 312 }, 313 []kzg.OpeningProof{ 314 foldedProof, 315 proof.ZShiftedOpening, 316 }, 317 []fr.Element{ 318 zeta, 319 shiftedZeta, 320 }, 321 vk.Kzg, 322 ) 323 324 log.Debug().Dur("took", time.Since(start)).Msg("verifier done") 325 326 return err 327 } 328 329 func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk *VerifyingKey, publicInputs []fr.Element) error { 330 331 // permutation 332 if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { 333 return err 334 } 335 if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { 336 return err 337 } 338 if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { 339 return err 340 } 341 342 // coefficients 343 if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { 344 return err 345 } 346 if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { 347 return err 348 } 349 if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { 350 return err 351 } 352 if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { 353 return err 354 } 355 if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { 356 return err 357 } 358 for i := range vk.Qcp { 359 if err := fs.Bind(challenge, vk.Qcp[i].Marshal()); err != nil { 360 return err 361 } 362 } 363 364 // public inputs 365 for i := 0; i < len(publicInputs); i++ { 366 if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { 367 return err 368 } 369 } 370 371 return nil 372 373 } 374 375 func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { 376 377 var buf [curve.SizeOfG1AffineUncompressed]byte 378 var r fr.Element 379 380 for _, p := range points { 381 buf = p.RawBytes() 382 if err := fs.Bind(challenge, buf[:]); err != nil { 383 return r, err 384 } 385 } 386 387 b, err := fs.ComputeChallenge(challenge) 388 if err != nil { 389 return r, err 390 } 391 r.SetBytes(b) 392 return r, nil 393 } 394 395 // ExportSolidity not implemented for BLS24-317 396 func (vk *VerifyingKey) ExportSolidity(w io.Writer, exportOpts ...solidity.ExportOption) error { 397 return errors.New("not implemented") 398 }