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