From 0b45edde8dd0850e744eb5531ec19f8d62930a83 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 8 Dec 2022 21:22:05 +0100 Subject: [PATCH] Add State transcripts contribute logic --- README.md | 1 + powersoftau.go | 121 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 83 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 59dfe2b..b3e7051 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Alternative (non-official) implementation in Go of the *contributor* for the [Et The purpose of this repo is to use it to contribute to the upcoming Ethereum KZG Trusted Setup Ceremony, without using the official implementation. The Ceremony is considered safe as long as there is at least one honest participant, with the idea that if you participate, assuming that you consider yourself honest, you can consider the Ceremony safe. +Ethereum will run the Ceremony which will be used at least in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (but probably in other use cases and applications). Probably most of the contributions will be generated with the same code (official impl, which has been audited). The idea of this repo is to try to bring more diversity to the table with another independent implementation. This implementation has been done without looking at the other impls code (neither the python reference nor the rust impl (except for the points parsers test vectors)), in order to not be biased by that code. diff --git a/powersoftau.go b/powersoftau.go index 75cf3b2..7177807 100644 --- a/powersoftau.go +++ b/powersoftau.go @@ -1,6 +1,7 @@ package kzgceremony import ( + "fmt" "math/big" bls12381 "github.com/kilic/bls12-381" @@ -8,18 +9,57 @@ import ( // todo: unify addition & multiplicative notation in the comments -// Contribution contains the SRS with its Proof -type Contribution struct { - SRS *SRS - Proof *Proof +type Witness struct { + RunningProducts []*bls12381.PointG1 + PotPubKeys []*bls12381.PointG2 + BLSSignatures []*bls12381.PointG1 +} + +type Transcript struct { + NumG1Powers uint64 + NumG2Powers uint64 + PowersOfTau *SRS + Witness *Witness +} + +type State struct { + Transcripts []Transcript + ParticipantIDs []string // WIP + ParticipantECDSASignatures []string +} + +func (cs *State) Contribute(randomness []byte) (*State, error) { + ns := State{} + ns.Transcripts = make([]Transcript, len(cs.Transcripts)) + for i := 0; i < len(cs.Transcripts); i++ { + ns.Transcripts[i].NumG1Powers = cs.Transcripts[i].NumG1Powers + ns.Transcripts[i].NumG2Powers = cs.Transcripts[i].NumG2Powers + + newSRS, proof, err := Contribute(cs.Transcripts[i].PowersOfTau, randomness) + if err != nil { + return nil, err + } + ns.Transcripts[i].PowersOfTau = newSRS + + ns.Transcripts[i].Witness = &Witness{} + ns.Transcripts[i].Witness.RunningProducts = + append(cs.Transcripts[i].Witness.RunningProducts, proof.G1PTau) + ns.Transcripts[i].Witness.PotPubKeys = + append(cs.Transcripts[i].Witness.PotPubKeys, proof.G2P) + ns.Transcripts[i].Witness.BLSSignatures = cs.Transcripts[i].Witness.BLSSignatures + } + ns.ParticipantIDs = cs.ParticipantIDs + ns.ParticipantECDSASignatures = cs.ParticipantECDSASignatures + + return &ns, nil } // SRS contains the powers of tau in G1 & G2, eg. // [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, // [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂ type SRS struct { - G1s []*bls12381.PointG1 - G2s []*bls12381.PointG2 + G1Powers []*bls12381.PointG1 + G2Powers []*bls12381.PointG2 } type toxicWaste struct { @@ -65,22 +105,22 @@ func tau(randomness []byte) *toxicWaste { } func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS { - srs := newEmptySRS(len(prevSRS.G1s), len(prevSRS.G2s)) + srs := newEmptySRS(len(prevSRS.G1Powers), len(prevSRS.G2Powers)) g1 := bls12381.NewG1() g2 := bls12381.NewG2() Q := g1.Q() // Q = |G1| == |G2| // fmt.Println("Computing [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, for n =", len(prevSRS.G1s)) - for i := 0; i < len(prevSRS.G1s); i++ { + for i := 0; i < len(prevSRS.G1Powers); i++ { tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q) tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes()) - g1.MulScalar(srs.G1s[i], prevSRS.G1s[i], tau_i_Fr) + g1.MulScalar(srs.G1Powers[i], prevSRS.G1Powers[i], tau_i_Fr) } // fmt.Println("Computing [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂, for n =", len(prevSRS.G2s)) - for i := 0; i < len(prevSRS.G2s); i++ { + for i := 0; i < len(prevSRS.G2Powers); i++ { tau_i := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q) tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes()) - g2.MulScalar(srs.G2s[i], prevSRS.G2s[i], tau_i_Fr) + g2.MulScalar(srs.G2Powers[i], prevSRS.G2Powers[i], tau_i_Fr) } return srs @@ -90,14 +130,17 @@ func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof { g1 := bls12381.NewG1() G1_p := g1.New() tau_Fr := bls12381.NewFr().FromBytes(toxicWaste.tau.Bytes()) - g1.MulScalar(G1_p, prevSRS.G1s[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau + g1.MulScalar(G1_p, prevSRS.G1Powers[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau return &Proof{toxicWaste.TauG2, G1_p} } -// Contribute takes as input the previous SRS and a random byte slice, and -// returns the new SRS together with the Proof -func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) { +// Contribute takes as input the previous SRS and a random +// byte slice, and returns the new SRS together with the Proof +func Contribute(prevSRS *SRS, randomness []byte) (*SRS, *Proof, error) { + if len(randomness) < 64 { + return nil, nil, fmt.Errorf("err randomness") // WIP + } // set tau from randomness tw := tau(randomness) @@ -105,7 +148,7 @@ func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) { proof := genProof(tw, prevSRS, newSRS) - return Contribution{SRS: newSRS, Proof: proof}, nil + return newSRS, proof, nil } // Verify checks the correct computation of the new SRS respectively from the @@ -116,69 +159,69 @@ func Verify(prevSRS, newSRS *SRS, proof *Proof) bool { pairing := bls12381.NewEngine() // 1. check that elements of the newSRS are valid points - for i := 0; i < len(newSRS.G1s); i++ { + for i := 0; i < len(newSRS.G1Powers); i++ { // i) non-empty - if newSRS.G1s[i] == nil { + if newSRS.G1Powers[i] == nil { return false } // ii) non-zero - if g1.IsZero(newSRS.G1s[i]) { + if g1.IsZero(newSRS.G1Powers[i]) { return false } // iii) in the correct prime order of subgroups - if !g1.IsOnCurve(newSRS.G1s[i]) { + if !g1.IsOnCurve(newSRS.G1Powers[i]) { return false } - if !g1.InCorrectSubgroup(newSRS.G1s[i]) { + if !g1.InCorrectSubgroup(newSRS.G1Powers[i]) { return false } } - for i := 0; i < len(newSRS.G2s); i++ { + for i := 0; i < len(newSRS.G2Powers); i++ { // i) non-empty - if newSRS.G2s[i] == nil { + if newSRS.G2Powers[i] == nil { return false } // ii) non-zero - if g2.IsZero(newSRS.G2s[i]) { + if g2.IsZero(newSRS.G2Powers[i]) { return false } // iii) in the correct prime order of subgroups - if !g2.IsOnCurve(newSRS.G2s[i]) { + if !g2.IsOnCurve(newSRS.G2Powers[i]) { return false } - if !g2.InCorrectSubgroup(newSRS.G2s[i]) { + if !g2.InCorrectSubgroup(newSRS.G2Powers[i]) { return false } } - // 2. check proof.G1PTau == newSRS.G1s[1] - if !g1.Equal(proof.G1PTau, newSRS.G1s[1]) { + // 2. check proof.G1PTau == newSRS.G1Powers[1] + if !g1.Equal(proof.G1PTau, newSRS.G1Powers[1]) { return false } // 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ) // e([τ]₁, [p]₂) == e([τ']₁, [1]₂) - e0 := pairing.AddPair(prevSRS.G1s[1], proof.G2P).Result() - e1 := pairing.AddPair(newSRS.G1s[1], g2.One()).Result() - if !e0.Equal(e1) { + eL := pairing.AddPair(prevSRS.G1Powers[1], proof.G2P).Result() + eR := pairing.AddPair(newSRS.G1Powers[1], g2.One()).Result() + if !eL.Equal(eR) { return false } // 4. check newSRS following the powers of tau structure - for i := 0; i < len(newSRS.G1s)-1; i++ { + for i := 0; i < len(newSRS.G1Powers)-1; i++ { // i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1] - e0 := pairing.AddPair(newSRS.G1s[i], newSRS.G2s[1]).Result() - e1 := pairing.AddPair(newSRS.G1s[i+1], g2.One()).Result() - if !e0.Equal(e1) { + eL := pairing.AddPair(newSRS.G1Powers[i], newSRS.G2Powers[1]).Result() + eR := pairing.AddPair(newSRS.G1Powers[i+1], g2.One()).Result() + if !eL.Equal(eR) { return false } } - for i := 0; i < len(newSRS.G2s)-1; i++ { + for i := 0; i < len(newSRS.G2Powers)-1; i++ { // ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1] - e3 := pairing.AddPair(newSRS.G1s[1], newSRS.G2s[i]).Result() - e4 := pairing.AddPair(g1.One(), newSRS.G2s[i+1]).Result() - if !e3.Equal(e4) { + eL := pairing.AddPair(newSRS.G1Powers[1], newSRS.G2Powers[i]).Result() + eR := pairing.AddPair(g1.One(), newSRS.G2Powers[i+1]).Result() + if !eL.Equal(eR) { return false } }