github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/mpcsetup/phase1.go.tmpl (about) 1 import ( 2 "crypto/sha256" 3 "errors" 4 "math" 5 "math/big" 6 7 8 {{- template "import_fr" . }} 9 {{- template "import_curve" . }} 10 ) 11 12 // Phase1 represents the Phase1 of the MPC described in 13 // https://eprint.iacr.org/2017/1050.pdf 14 // 15 // Also known as "Powers of Tau" 16 type Phase1 struct { 17 Parameters struct { 18 G1 struct { 19 Tau []curve.G1Affine // {[τ⁰]₁, [τ¹]₁, [τ²]₁, …, [τ²ⁿ⁻²]₁} 20 AlphaTau []curve.G1Affine // {α[τ⁰]₁, α[τ¹]₁, α[τ²]₁, …, α[τⁿ⁻¹]₁} 21 BetaTau []curve.G1Affine // {β[τ⁰]₁, β[τ¹]₁, β[τ²]₁, …, β[τⁿ⁻¹]₁} 22 } 23 G2 struct { 24 Tau []curve.G2Affine // {[τ⁰]₂, [τ¹]₂, [τ²]₂, …, [τⁿ⁻¹]₂} 25 Beta curve.G2Affine // [β]₂ 26 } 27 } 28 PublicKeys struct { 29 Tau, Alpha, Beta PublicKey 30 } 31 Hash []byte // sha256 hash 32 } 33 34 // InitPhase1 initialize phase 1 of the MPC. This is called once by the coordinator before 35 // any randomness contribution is made (see Contribute()). 36 func InitPhase1(power int) (phase1 Phase1) { 37 N := int(math.Pow(2, float64(power))) 38 39 // Generate key pairs 40 var tau, alpha, beta fr.Element 41 tau.SetOne() 42 alpha.SetOne() 43 beta.SetOne() 44 phase1.PublicKeys.Tau = newPublicKey(tau, nil, 1) 45 phase1.PublicKeys.Alpha = newPublicKey(alpha, nil, 2) 46 phase1.PublicKeys.Beta = newPublicKey(beta, nil, 3) 47 48 // First contribution use generators 49 _, _, g1, g2 := curve.Generators() 50 phase1.Parameters.G2.Beta.Set(&g2) 51 phase1.Parameters.G1.Tau = make([]curve.G1Affine, 2*N-1) 52 phase1.Parameters.G2.Tau = make([]curve.G2Affine, N) 53 phase1.Parameters.G1.AlphaTau = make([]curve.G1Affine, N) 54 phase1.Parameters.G1.BetaTau = make([]curve.G1Affine, N) 55 for i := 0; i < len(phase1.Parameters.G1.Tau); i++ { 56 phase1.Parameters.G1.Tau[i].Set(&g1) 57 } 58 for i := 0; i < len(phase1.Parameters.G2.Tau); i++ { 59 phase1.Parameters.G2.Tau[i].Set(&g2) 60 phase1.Parameters.G1.AlphaTau[i].Set(&g1) 61 phase1.Parameters.G1.BetaTau[i].Set(&g1) 62 } 63 64 phase1.Parameters.G2.Beta.Set(&g2) 65 66 // Compute hash of Contribution 67 phase1.Hash = phase1.hash() 68 69 return 70 } 71 72 // Contribute contributes randomness to the phase1 object. This mutates phase1. 73 func (phase1 *Phase1) Contribute() { 74 N := len(phase1.Parameters.G2.Tau) 75 76 // Generate key pairs 77 var tau, alpha, beta fr.Element 78 tau.SetRandom() 79 alpha.SetRandom() 80 beta.SetRandom() 81 phase1.PublicKeys.Tau = newPublicKey(tau, phase1.Hash[:], 1) 82 phase1.PublicKeys.Alpha = newPublicKey(alpha, phase1.Hash[:], 2) 83 phase1.PublicKeys.Beta = newPublicKey(beta, phase1.Hash[:], 3) 84 85 // Compute powers of τ, ατ, and βτ 86 taus := powers(tau, 2*N-1) 87 alphaTau := make([]fr.Element, N) 88 betaTau := make([]fr.Element, N) 89 for i := 0; i < N; i++ { 90 alphaTau[i].Mul(&taus[i], &alpha) 91 betaTau[i].Mul(&taus[i], &beta) 92 } 93 94 // Update using previous parameters 95 // TODO @gbotrel working with jacobian points here will help with perf. 96 scaleG1InPlace(phase1.Parameters.G1.Tau, taus) 97 scaleG2InPlace(phase1.Parameters.G2.Tau, taus[0:N]) 98 scaleG1InPlace(phase1.Parameters.G1.AlphaTau, alphaTau) 99 scaleG1InPlace(phase1.Parameters.G1.BetaTau, betaTau) 100 var betaBI big.Int 101 beta.BigInt(&betaBI) 102 phase1.Parameters.G2.Beta.ScalarMultiplication(&phase1.Parameters.G2.Beta, &betaBI) 103 104 // Compute hash of Contribution 105 phase1.Hash = phase1.hash() 106 } 107 108 func VerifyPhase1(c0, c1 *Phase1, c ...*Phase1) error { 109 contribs := append([]*Phase1{c0, c1}, c...) 110 for i := 0; i < len(contribs)-1; i++ { 111 if err := verifyPhase1(contribs[i], contribs[i+1]); err != nil { 112 return err 113 } 114 } 115 return nil 116 } 117 118 // verifyPhase1 checks that a contribution is based on a known previous Phase1 state. 119 func verifyPhase1(current, contribution *Phase1) error { 120 // Compute R for τ, α, β 121 tauR := genR(contribution.PublicKeys.Tau.SG, contribution.PublicKeys.Tau.SXG, current.Hash[:], 1) 122 alphaR := genR(contribution.PublicKeys.Alpha.SG, contribution.PublicKeys.Alpha.SXG, current.Hash[:], 2) 123 betaR := genR(contribution.PublicKeys.Beta.SG, contribution.PublicKeys.Beta.SXG, current.Hash[:], 3) 124 125 // Check for knowledge of toxic parameters 126 if !sameRatio(contribution.PublicKeys.Tau.SG, contribution.PublicKeys.Tau.SXG, contribution.PublicKeys.Tau.XR, tauR) { 127 return errors.New("couldn't verify public key of τ") 128 } 129 if !sameRatio(contribution.PublicKeys.Alpha.SG, contribution.PublicKeys.Alpha.SXG, contribution.PublicKeys.Alpha.XR, alphaR) { 130 return errors.New("couldn't verify public key of α") 131 } 132 if !sameRatio(contribution.PublicKeys.Beta.SG, contribution.PublicKeys.Beta.SXG, contribution.PublicKeys.Beta.XR, betaR) { 133 return errors.New("couldn't verify public key of β") 134 } 135 136 // Check for valid updates using previous parameters 137 if !sameRatio(contribution.Parameters.G1.Tau[1], current.Parameters.G1.Tau[1], tauR, contribution.PublicKeys.Tau.XR) { 138 return errors.New("couldn't verify that [τ]₁ is based on previous contribution") 139 } 140 if !sameRatio(contribution.Parameters.G1.AlphaTau[0], current.Parameters.G1.AlphaTau[0], alphaR, contribution.PublicKeys.Alpha.XR) { 141 return errors.New("couldn't verify that [α]₁ is based on previous contribution") 142 } 143 if !sameRatio(contribution.Parameters.G1.BetaTau[0], current.Parameters.G1.BetaTau[0], betaR, contribution.PublicKeys.Beta.XR) { 144 return errors.New("couldn't verify that [β]₁ is based on previous contribution") 145 } 146 if !sameRatio(contribution.PublicKeys.Tau.SG, contribution.PublicKeys.Tau.SXG, contribution.Parameters.G2.Tau[1], current.Parameters.G2.Tau[1]) { 147 return errors.New("couldn't verify that [τ]₂ is based on previous contribution") 148 } 149 if !sameRatio(contribution.PublicKeys.Beta.SG, contribution.PublicKeys.Beta.SXG, contribution.Parameters.G2.Beta, current.Parameters.G2.Beta) { 150 return errors.New("couldn't verify that [β]₂ is based on previous contribution") 151 } 152 153 // Check for valid updates using powers of τ 154 _, _, g1, g2 := curve.Generators() 155 tauL1, tauL2 := linearCombinationG1(contribution.Parameters.G1.Tau) 156 if !sameRatio(tauL1, tauL2, contribution.Parameters.G2.Tau[1], g2) { 157 return errors.New("couldn't verify valid powers of τ in G₁") 158 } 159 alphaL1, alphaL2 := linearCombinationG1(contribution.Parameters.G1.AlphaTau) 160 if !sameRatio(alphaL1, alphaL2, contribution.Parameters.G2.Tau[1], g2) { 161 return errors.New("couldn't verify valid powers of α(τ) in G₁") 162 } 163 betaL1, betaL2 := linearCombinationG1(contribution.Parameters.G1.BetaTau) 164 if !sameRatio(betaL1, betaL2, contribution.Parameters.G2.Tau[1], g2) { 165 return errors.New("couldn't verify valid powers of α(τ) in G₁") 166 } 167 tau2L1, tau2L2 := linearCombinationG2(contribution.Parameters.G2.Tau) 168 if !sameRatio(contribution.Parameters.G1.Tau[1], g1, tau2L1, tau2L2) { 169 return errors.New("couldn't verify valid powers of τ in G₂") 170 } 171 172 // Check hash of the contribution 173 h := contribution.hash() 174 for i := 0; i < len(h); i++ { 175 if h[i] != contribution.Hash[i] { 176 return errors.New("couldn't verify hash of contribution") 177 } 178 } 179 180 return nil 181 } 182 183 func (phase1 *Phase1) hash() []byte { 184 sha := sha256.New() 185 phase1.writeTo(sha) 186 return sha.Sum(nil) 187 }