github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/phase2.go.tmpl (about) 1 import ( 2 "crypto/sha256" 3 "errors" 4 "math/big" 5 6 "github.com/consensys/gnark/constraint" 7 8 9 {{- template "import_fr" . }} 10 {{- template "import_curve" . }} 11 {{- template "import_backend_cs" . }} 12 ) 13 14 type Phase2Evaluations struct { 15 G1 struct { 16 A, B, VKK []curve.G1Affine 17 } 18 G2 struct { 19 B []curve.G2Affine 20 } 21 } 22 23 type Phase2 struct { 24 Parameters struct { 25 G1 struct { 26 Delta curve.G1Affine 27 L, Z []curve.G1Affine 28 } 29 G2 struct { 30 Delta curve.G2Affine 31 } 32 } 33 PublicKey PublicKey 34 Hash []byte 35 } 36 37 func InitPhase2(r1cs *cs.R1CS, srs1 *Phase1) (Phase2, Phase2Evaluations) { 38 srs := srs1.Parameters 39 size := len(srs.G1.AlphaTau) 40 if size < r1cs.GetNbConstraints() { 41 panic("Number of constraints is larger than expected") 42 } 43 44 c2 := Phase2{} 45 46 accumulateG1 := func(res *curve.G1Affine, t constraint.Term, value *curve.G1Affine) { 47 cID := t.CoeffID() 48 switch cID { 49 case constraint.CoeffIdZero: 50 return 51 case constraint.CoeffIdOne: 52 res.Add(res, value) 53 case constraint.CoeffIdMinusOne: 54 res.Sub(res, value) 55 case constraint.CoeffIdTwo: 56 res.Add(res, value).Add(res, value) 57 default: 58 var tmp curve.G1Affine 59 var vBi big.Int 60 r1cs.Coefficients[cID].BigInt(&vBi) 61 tmp.ScalarMultiplication(value, &vBi) 62 res.Add(res, &tmp) 63 } 64 } 65 66 accumulateG2 := func(res *curve.G2Affine, t constraint.Term, value *curve.G2Affine) { 67 cID := t.CoeffID() 68 switch cID { 69 case constraint.CoeffIdZero: 70 return 71 case constraint.CoeffIdOne: 72 res.Add(res, value) 73 case constraint.CoeffIdMinusOne: 74 res.Sub(res, value) 75 case constraint.CoeffIdTwo: 76 res.Add(res, value).Add(res, value) 77 default: 78 var tmp curve.G2Affine 79 var vBi big.Int 80 r1cs.Coefficients[cID].BigInt(&vBi) 81 tmp.ScalarMultiplication(value, &vBi) 82 res.Add(res, &tmp) 83 } 84 } 85 86 // Prepare Lagrange coefficients of [τ...]₁, [τ...]₂, [ατ...]₁, [βτ...]₁ 87 coeffTau1 := lagrangeCoeffsG1(srs.G1.Tau, size) 88 coeffTau2 := lagrangeCoeffsG2(srs.G2.Tau, size) 89 coeffAlphaTau1 := lagrangeCoeffsG1(srs.G1.AlphaTau, size) 90 coeffBetaTau1 := lagrangeCoeffsG1(srs.G1.BetaTau, size) 91 92 internal, secret, public := r1cs.GetNbVariables() 93 nWires := internal + secret + public 94 var evals Phase2Evaluations 95 evals.G1.A = make([]curve.G1Affine, nWires) 96 evals.G1.B = make([]curve.G1Affine, nWires) 97 evals.G2.B = make([]curve.G2Affine, nWires) 98 bA := make([]curve.G1Affine, nWires) 99 aB := make([]curve.G1Affine, nWires) 100 C := make([]curve.G1Affine, nWires) 101 102 // TODO @gbotrel use constraint iterator when available. 103 104 i := 0 105 it := r1cs.GetR1CIterator() 106 for c := it.Next(); c!=nil; c = it.Next() { 107 // A 108 for _, t := range c.L { 109 accumulateG1(&evals.G1.A[t.WireID()], t, &coeffTau1[i]) 110 accumulateG1(&bA[t.WireID()], t, &coeffBetaTau1[i]) 111 } 112 // B 113 for _, t := range c.R { 114 accumulateG1(&evals.G1.B[t.WireID()], t, &coeffTau1[i]) 115 accumulateG2(&evals.G2.B[t.WireID()], t, &coeffTau2[i]) 116 accumulateG1(&aB[t.WireID()], t, &coeffAlphaTau1[i]) 117 } 118 // C 119 for _, t := range c.O { 120 accumulateG1(&C[t.WireID()], t, &coeffTau1[i]) 121 } 122 i++ 123 } 124 125 // Prepare default contribution 126 _, _, g1, g2 := curve.Generators() 127 c2.Parameters.G1.Delta = g1 128 c2.Parameters.G2.Delta = g2 129 130 // Build Z in PK as τⁱ(τⁿ - 1) = τ⁽ⁱ⁺ⁿ⁾ - τⁱ for i ∈ [0, n-2] 131 // τⁱ(τⁿ - 1) = τ⁽ⁱ⁺ⁿ⁾ - τⁱ for i ∈ [0, n-2] 132 n := len(srs.G1.AlphaTau) 133 c2.Parameters.G1.Z = make([]curve.G1Affine, n) 134 for i := 0; i < n-1; i++ { 135 c2.Parameters.G1.Z[i].Sub(&srs.G1.Tau[i+n], &srs.G1.Tau[i]) 136 } 137 bitReverse(c2.Parameters.G1.Z) 138 c2.Parameters.G1.Z = c2.Parameters.G1.Z[:n-1] 139 140 // Evaluate L 141 nPrivate := internal + secret 142 c2.Parameters.G1.L = make([]curve.G1Affine, nPrivate) 143 evals.G1.VKK = make([]curve.G1Affine, public) 144 offset := public 145 for i := 0; i < nWires; i++ { 146 var tmp curve.G1Affine 147 tmp.Add(&bA[i], &aB[i]) 148 tmp.Add(&tmp, &C[i]) 149 if i < public { 150 evals.G1.VKK[i].Set(&tmp) 151 } else { 152 c2.Parameters.G1.L[i-offset].Set(&tmp) 153 } 154 } 155 // Set δ public key 156 var delta fr.Element 157 delta.SetOne() 158 c2.PublicKey = newPublicKey(delta, nil, 1) 159 160 // Hash initial contribution 161 c2.Hash = c2.hash() 162 return c2, evals 163 } 164 165 func (c *Phase2) Contribute() { 166 // Sample toxic δ 167 var delta, deltaInv fr.Element 168 var deltaBI, deltaInvBI big.Int 169 delta.SetRandom() 170 deltaInv.Inverse(&delta) 171 172 delta.BigInt(&deltaBI) 173 deltaInv.BigInt(&deltaInvBI) 174 175 // Set δ public key 176 c.PublicKey = newPublicKey(delta, c.Hash, 1) 177 178 // Update δ 179 c.Parameters.G1.Delta.ScalarMultiplication(&c.Parameters.G1.Delta, &deltaBI) 180 c.Parameters.G2.Delta.ScalarMultiplication(&c.Parameters.G2.Delta, &deltaBI) 181 182 // Update Z using δ⁻¹ 183 for i := 0; i < len(c.Parameters.G1.Z); i++ { 184 c.Parameters.G1.Z[i].ScalarMultiplication(&c.Parameters.G1.Z[i], &deltaInvBI) 185 } 186 187 // Update L using δ⁻¹ 188 for i := 0; i < len(c.Parameters.G1.L); i++ { 189 c.Parameters.G1.L[i].ScalarMultiplication(&c.Parameters.G1.L[i], &deltaInvBI) 190 } 191 192 // 4. Hash contribution 193 c.Hash = c.hash() 194 } 195 196 func VerifyPhase2(c0, c1 *Phase2, c ...*Phase2) error { 197 contribs := append([]*Phase2{c0, c1}, c...) 198 for i := 0; i < len(contribs)-1; i++ { 199 if err := verifyPhase2(contribs[i], contribs[i+1]); err != nil { 200 return err 201 } 202 } 203 return nil 204 } 205 206 func verifyPhase2(current, contribution *Phase2) error { 207 // Compute R for δ 208 deltaR := genR(contribution.PublicKey.SG, contribution.PublicKey.SXG, current.Hash[:], 1) 209 210 // Check for knowledge of δ 211 if !sameRatio(contribution.PublicKey.SG, contribution.PublicKey.SXG, contribution.PublicKey.XR, deltaR) { 212 return errors.New("couldn't verify knowledge of δ") 213 } 214 215 // Check for valid updates using previous parameters 216 if !sameRatio(contribution.Parameters.G1.Delta, current.Parameters.G1.Delta, deltaR, contribution.PublicKey.XR) { 217 return errors.New("couldn't verify that [δ]₁ is based on previous contribution") 218 } 219 if !sameRatio(contribution.PublicKey.SG, contribution.PublicKey.SXG, contribution.Parameters.G2.Delta, current.Parameters.G2.Delta) { 220 return errors.New("couldn't verify that [δ]₂ is based on previous contribution") 221 } 222 223 // Check for valid updates of L and Z using 224 L, prevL := merge(contribution.Parameters.G1.L, current.Parameters.G1.L) 225 if !sameRatio(L, prevL, contribution.Parameters.G2.Delta, current.Parameters.G2.Delta) { 226 return errors.New("couldn't verify valid updates of L using δ⁻¹") 227 } 228 Z, prevZ := merge(contribution.Parameters.G1.Z, current.Parameters.G1.Z) 229 if !sameRatio(Z, prevZ, contribution.Parameters.G2.Delta, current.Parameters.G2.Delta) { 230 return errors.New("couldn't verify valid updates of L using δ⁻¹") 231 } 232 233 // Check hash of the contribution 234 h := contribution.hash() 235 for i := 0; i < len(h); i++ { 236 if h[i] != contribution.Hash[i] { 237 return errors.New("couldn't verify hash of contribution") 238 } 239 } 240 241 return nil 242 } 243 244 func (c *Phase2) hash() []byte { 245 sha := sha256.New() 246 c.writeTo(sha) 247 return sha.Sum(nil) 248 }