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  }