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// MinRandomnessLen is the minimum accepted length for the user defined
 11// randomness
 12const MinRandomnessLen = 64
 13
 14var g1 *bls12381.G1
 15var g2 *bls12381.G2
 16
 17func init() {
 18	g1 = bls12381.NewG1()
 19	g2 = bls12381.NewG2()
 20}
 21
 22// State represents the data structure obtained from the Sequencer at the
 23// /info/current_state endpoint
 24type State struct {
 25	Transcripts                []Transcript
 26	ParticipantIDs             []string // WIP
 27	ParticipantECDSASignatures []string
 28}
 29
 30// BatchContribution represents the data structure obtained from the Sequencer
 31// at the /contribute endpoint
 32type BatchContribution struct {
 33	Contributions []Contribution
 34}
 35
 36type Contribution struct {
 37	NumG1Powers uint64
 38	NumG2Powers uint64
 39	PowersOfTau *SRS
 40	PotPubKey   *bls12381.PointG2
 41}
 42
 43type Transcript struct {
 44	NumG1Powers uint64
 45	NumG2Powers uint64
 46	PowersOfTau *SRS
 47	Witness     *Witness
 48}
 49
 50type Witness struct {
 51	RunningProducts []*bls12381.PointG1
 52	PotPubKeys      []*bls12381.PointG2
 53	BLSSignatures   []*bls12381.PointG1
 54}
 55
 56// SRS contains the powers of tau in G1 & G2, eg.
 57// [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
 58// [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
 59type SRS struct {
 60	G1Powers []*bls12381.PointG1
 61	G2Powers []*bls12381.PointG2
 62}
 63
 64type toxicWaste struct {
 65	tau   *big.Int
 66	TauG2 *bls12381.PointG2 // Proof.G2P
 67}
 68
 69// Proof contains g₂ᵖ and g₂^τ', used by the verifier
 70type Proof struct {
 71	G2P    *bls12381.PointG2 // g₂ᵖ
 72	G1PTau *bls12381.PointG1 // g₂^τ' = g₂^{p ⋅ τ}
 73}
 74
 75// Contribute takes the last State and computes a new State using the defined
 76// randomness
 77func (cs *State) Contribute(randomness []byte) (*State, error) {
 78	ns := State{}
 79	ns.Transcripts = make([]Transcript, len(cs.Transcripts))
 80	for i := 0; i < len(cs.Transcripts); i++ {
 81		ns.Transcripts[i].NumG1Powers = cs.Transcripts[i].NumG1Powers
 82		ns.Transcripts[i].NumG2Powers = cs.Transcripts[i].NumG2Powers
 83
 84		newSRS, proof, err := Contribute(cs.Transcripts[i].PowersOfTau, randomness)
 85		if err != nil {
 86			return nil, err
 87		}
 88		ns.Transcripts[i].PowersOfTau = newSRS
 89
 90		ns.Transcripts[i].Witness = &Witness{}
 91		ns.Transcripts[i].Witness.RunningProducts =
 92			append(cs.Transcripts[i].Witness.RunningProducts, proof.G1PTau)
 93		ns.Transcripts[i].Witness.PotPubKeys =
 94			append(cs.Transcripts[i].Witness.PotPubKeys, proof.G2P)
 95		ns.Transcripts[i].Witness.BLSSignatures = cs.Transcripts[i].Witness.BLSSignatures
 96	}
 97	ns.ParticipantIDs = cs.ParticipantIDs // TODO add github id (id_token.sub)
 98	ns.ParticipantECDSASignatures = cs.ParticipantECDSASignatures
 99
100	return &ns, nil
101}
102
103// Contribute takes the last BatchContribution and computes a new
104// BatchContribution using the defined randomness
105func (pb *BatchContribution) Contribute(randomness []byte) (*BatchContribution, error) {
106	nb := BatchContribution{}
107	nb.Contributions = make([]Contribution, len(pb.Contributions))
108	for i := 0; i < len(pb.Contributions); i++ {
109		nb.Contributions[i].NumG1Powers = pb.Contributions[i].NumG1Powers
110		nb.Contributions[i].NumG2Powers = pb.Contributions[i].NumG2Powers
111
112		newSRS, proof, err := Contribute(pb.Contributions[i].PowersOfTau, randomness)
113		if err != nil {
114			return nil, err
115		}
116		nb.Contributions[i].PowersOfTau = newSRS
117
118		nb.Contributions[i].PotPubKey = proof.G2P
119	}
120
121	return &nb, nil
122}
123
124// newEmptySRS creates an empty SRS filled by [1]₁ & [1]₂ points in all
125// respective arrays positions
126func newEmptySRS(nG1, nG2 int) *SRS {
127	g1s := make([]*bls12381.PointG1, nG1)
128	g2s := make([]*bls12381.PointG2, nG2)
129	for i := 0; i < nG1; i++ {
130		g1s[i] = g1.One()
131	}
132	for i := 0; i < nG2; i++ {
133		g2s[i] = g2.One()
134	}
135	return &SRS{g1s, g2s}
136}
137
138func tau(randomness []byte) *toxicWaste {
139	tau := new(big.Int).Mod(
140		new(big.Int).SetBytes(randomness),
141		g2.Q())
142	tau_Fr := bls12381.NewFr().FromBytes(tau.Bytes())
143	TauG2 := g2.New()
144	g2.MulScalar(TauG2, g2.One(), tau_Fr)
145
146	return &toxicWaste{tau, TauG2}
147}
148
149func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS {
150	srs := newEmptySRS(len(prevSRS.G1Powers), len(prevSRS.G2Powers))
151	Q := g1.Q() // Q = |G1| == |G2|
152
153	// fmt.Println("Computing [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, for n =", len(prevSRS.G1s))
154	for i := 0; i < len(prevSRS.G1Powers); i++ {
155		tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
156		tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
157		g1.MulScalar(srs.G1Powers[i], prevSRS.G1Powers[i], tau_i_Fr)
158	}
159	// fmt.Println("Computing [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂, for n =", len(prevSRS.G2s))
160	for i := 0; i < len(prevSRS.G2Powers); i++ {
161		tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
162		tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes())
163		g2.MulScalar(srs.G2Powers[i], prevSRS.G2Powers[i], tau_i_Fr)
164	}
165
166	return srs
167}
168
169func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof {
170	G1_p := g1.New()
171	tau_Fr := bls12381.NewFr().FromBytes(toxicWaste.tau.Bytes())
172	g1.MulScalar(G1_p, prevSRS.G1Powers[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau
173
174	return &Proof{toxicWaste.TauG2, G1_p}
175}
176
177// Contribute takes as input the previous SRS and a random
178// byte slice, and returns the new SRS together with the Proof
179func Contribute(prevSRS *SRS, randomness []byte) (*SRS, *Proof, error) {
180	if len(randomness) < MinRandomnessLen {
181		return nil, nil, fmt.Errorf("err randomness") // WIP
182	}
183	// set tau from randomness
184	tw := tau(randomness)
185
186	newSRS := computeContribution(tw, prevSRS)
187
188	proof := genProof(tw, prevSRS, newSRS)
189
190	return newSRS, proof, nil
191}
192
193func checkG1PointCorrectness(p *bls12381.PointG1) error {
194	// i) non-empty
195	if p == nil {
196		return fmt.Errorf("empty point value")
197	}
198	// ii) non-zero
199	if g1.IsZero(p) {
200		return fmt.Errorf("point can not be zero")
201	}
202	// iii) in the correct prime order of subgroups
203	if !g1.IsOnCurve(p) {
204		return fmt.Errorf("point not on curve")
205	}
206	if !g1.InCorrectSubgroup(p) {
207		return fmt.Errorf("point not in the correct prime order of subgroups")
208	}
209	return nil
210}
211
212func checkG2PointCorrectness(p *bls12381.PointG2) error {
213	// i) non-empty
214	if p == nil {
215		return fmt.Errorf("empty point value")
216	}
217	// ii) non-zero
218	if g2.IsZero(p) {
219		return fmt.Errorf("point can not be zero")
220	}
221	// iii) in the correct prime order of subgroups
222	if !g2.IsOnCurve(p) {
223		return fmt.Errorf("point not on curve")
224	}
225	if !g2.InCorrectSubgroup(p) {
226		return fmt.Errorf("point not in the correct prime order of subgroups")
227	}
228	return nil
229}
230
231// Verify checks the correct computation of the new SRS respectively from the
232// previous SRS
233func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
234	pairing := bls12381.NewEngine()
235
236	// 1. check that elements of the newSRS are valid points
237	for i := 0; i < len(newSRS.G1Powers); i++ {
238		if err := checkG1PointCorrectness(newSRS.G1Powers[i]); err != nil {
239			return false
240		}
241	}
242	for i := 0; i < len(newSRS.G2Powers); i++ {
243		if err := checkG2PointCorrectness(newSRS.G2Powers[i]); err != nil {
244			return false
245		}
246	}
247
248	// 2. check proof.G1PTau == newSRS.G1Powers[1]
249	if !g1.Equal(proof.G1PTau, newSRS.G1Powers[1]) {
250		return false
251	}
252
253	// 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
254	//   e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
255	eL := pairing.AddPair(prevSRS.G1Powers[1], proof.G2P).Result()
256	eR := pairing.AddPair(newSRS.G1Powers[1], g2.One()).Result()
257	if !eL.Equal(eR) {
258		return false
259	}
260
261	// 4. check newSRS following the powers of tau structure
262	for i := 0; i < len(newSRS.G1Powers)-1; i++ {
263		// i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
264		eL := pairing.AddPair(newSRS.G1Powers[i], newSRS.G2Powers[1]).Result()
265		eR := pairing.AddPair(newSRS.G1Powers[i+1], g2.One()).Result()
266		if !eL.Equal(eR) {
267			return false
268		}
269	}
270
271	for i := 0; i < len(newSRS.G2Powers)-1; i++ {
272		// ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
273		eL := pairing.AddPair(newSRS.G1Powers[1], newSRS.G2Powers[i]).Result()
274		eR := pairing.AddPair(g1.One(), newSRS.G2Powers[i+1]).Result()
275		if !eL.Equal(eR) {
276			return false
277		}
278	}
279
280	return true
281}