arnaucube
arnaucube/eth-kzg-ceremony-altPublic Self-hosted repository
eth-kzg-ceremony-alt/powersoftau.go
powersoftau.goRaw
  1package kzgceremony
  2
  3import (
  4	"math/big"
  5
  6	bls12381 "github.com/kilic/bls12-381"
  7)
  8
  9// todo: unify addition & multiplicative notation in the comments
 10
 11// Contribution contains the SRS with its Proof
 12type Contribution struct {
 13	SRS   *SRS
 14	Proof *Proof
 15}
 16
 17// SRS contains the powers of tau in G1 & G2, eg.
 18// [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
 19// [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
 20type SRS struct {
 21	G1s []*bls12381.PointG1
 22	G2s []*bls12381.PointG2
 23}
 24
 25type toxicWaste struct {
 26	tau   *big.Int
 27	TauG2 *bls12381.PointG2
 28}
 29
 30// Proof contains g₂ᵖ and g₂^τ', used by the verifier
 31type Proof struct {
 32	G2P    *bls12381.PointG2 // g₂ᵖ
 33	G1PTau *bls12381.PointG1 // g₂^τ' = g₂^{p ⋅ τ}
 34}
 35
 36// newEmptySRS creates an empty SRS
 37func newEmptySRS(nG1, nG2 int) *SRS {
 38	g1s := make([]*bls12381.PointG1, nG1)
 39	g2s := make([]*bls12381.PointG2, nG2)
 40	g1 := bls12381.NewG1()
 41	g2 := bls12381.NewG2()
 42	// one_G1 := g1.One()
 43	// one_G2 := g2.One()
 44	for i := 0; i < nG1; i++ {
 45		g1s[i] = g1.One()
 46		// g1.MulScalar(g1s[i], one_G1, big.NewInt(int64(i)))
 47	}
 48	for i := 0; i < nG2; i++ {
 49		g2s[i] = g2.One()
 50		// g2.MulScalar(g2s[i], one_G2, big.NewInt(int64(i)))
 51	}
 52	return &SRS{g1s, g2s}
 53}
 54
 55func tau(randomness []byte) *toxicWaste {
 56	g2 := bls12381.NewG2()
 57	tau := new(big.Int).Mod(
 58		new(big.Int).SetBytes(randomness),
 59		g2.Q())
 60	tau_Fr := bls12381.NewFr().FromBytes(tau.Bytes())
 61	TauG2 := g2.New()
 62	g2.MulScalar(TauG2, g2.One(), tau_Fr)
 63
 64	return &toxicWaste{tau, TauG2}
 65}
 66
 67func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS {
 68	srs := newEmptySRS(len(prevSRS.G1s), len(prevSRS.G2s))
 69	g1 := bls12381.NewG1()
 70	g2 := bls12381.NewG2()
 71	Q := g1.Q() // Q = |G1| == |G2|
 72
 73	// fmt.Println("Computing [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, for n =", len(prevSRS.G1s))
 74	for i := 0; i < len(prevSRS.G1s); i++ {
 75		tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
 76		tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
 77		g1.MulScalar(srs.G1s[i], prevSRS.G1s[i], tau_i_Fr)
 78	}
 79	// fmt.Println("Computing [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂, for n =", len(prevSRS.G2s))
 80	for i := 0; i < len(prevSRS.G2s); i++ {
 81		tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
 82		tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
 83		g2.MulScalar(srs.G2s[i], prevSRS.G2s[i], tau_i_Fr)
 84	}
 85
 86	return srs
 87}
 88
 89func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof {
 90	g1 := bls12381.NewG1()
 91	G1_p := g1.New()
 92	tau_Fr := bls12381.NewFr().FromBytes(toxicWaste.tau.Bytes())
 93	g1.MulScalar(G1_p, prevSRS.G1s[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau
 94
 95	return &Proof{toxicWaste.TauG2, G1_p}
 96}
 97
 98// Contribute takes as input the previous SRS and a random byte slice, and
 99// returns the new SRS together with the Proof
100func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) {
101	// set tau from randomness
102	tw := tau(randomness)
103
104	newSRS := computeContribution(tw, prevSRS)
105
106	proof := genProof(tw, prevSRS, newSRS)
107
108	return Contribution{SRS: newSRS, Proof: proof}, nil
109}
110
111// Verify checks the correct computation of the new SRS respectively from the
112// previous SRS
113func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
114	g1 := bls12381.NewG1()
115	g2 := bls12381.NewG2()
116	pairing := bls12381.NewEngine()
117
118	// 1. check that elements of the newSRS are valid points
119	for i := 0; i < len(newSRS.G1s); i++ {
120		// i) non-empty
121		if newSRS.G1s[i] == nil {
122			return false
123		}
124		// ii) non-zero
125		if g1.IsZero(newSRS.G1s[i]) {
126			return false
127		}
128		// iii) in the correct prime order of subgroups
129		if !g1.IsOnCurve(newSRS.G1s[i]) {
130			return false
131		}
132		if !g1.InCorrectSubgroup(newSRS.G1s[i]) {
133			return false
134		}
135	}
136	for i := 0; i < len(newSRS.G2s); i++ {
137		// i) non-empty
138		if newSRS.G2s[i] == nil {
139			return false
140		}
141		// ii) non-zero
142		if g2.IsZero(newSRS.G2s[i]) {
143			return false
144		}
145		// iii) in the correct prime order of subgroups
146		if !g2.IsOnCurve(newSRS.G2s[i]) {
147			return false
148		}
149		if !g2.InCorrectSubgroup(newSRS.G2s[i]) {
150			return false
151		}
152	}
153
154	// 2. check proof.G1PTau == newSRS.G1s[1]
155	if !g1.Equal(proof.G1PTau, newSRS.G1s[1]) {
156		return false
157	}
158
159	// 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
160	//   e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
161	e0 := pairing.AddPair(prevSRS.G1s[1], proof.G2P).Result()
162	e1 := pairing.AddPair(newSRS.G1s[1], g2.One()).Result()
163	if !e0.Equal(e1) {
164		return false
165	}
166
167	// 4. check newSRS following the powers of tau structure
168	for i := 0; i < len(newSRS.G1s)-1; i++ {
169		// i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
170		e0 := pairing.AddPair(newSRS.G1s[i], newSRS.G2s[1]).Result()
171		e1 := pairing.AddPair(newSRS.G1s[i+1], g2.One()).Result()
172		if !e0.Equal(e1) {
173			return false
174		}
175	}
176
177	for i := 0; i < len(newSRS.G2s)-1; i++ {
178		// ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
179		e3 := pairing.AddPair(newSRS.G1s[1], newSRS.G2s[i]).Result()
180		e4 := pairing.AddPair(g1.One(), newSRS.G2s[i+1]).Result()
181		if !e3.Equal(e4) {
182			return false
183		}
184	}
185
186	return true
187}