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