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