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  }