Browse Source

Add State transcripts contribute logic

main
arnaucube 1 year ago
parent
commit
0b45edde8d
2 changed files with 83 additions and 39 deletions
  1. +1
    -0
      README.md
  2. +82
    -39
      powersoftau.go

+ 1
- 0
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 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. 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. 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. 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.

+ 82
- 39
powersoftau.go

@ -1,6 +1,7 @@
package kzgceremony package kzgceremony
import ( import (
"fmt"
"math/big" "math/big"
bls12381 "github.com/kilic/bls12-381" bls12381 "github.com/kilic/bls12-381"
@ -8,18 +9,57 @@ import (
// todo: unify addition & multiplicative notation in the comments // 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. // SRS contains the powers of tau in G1 & G2, eg.
// [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, // [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
// [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂ // [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
type SRS struct { type SRS struct {
G1s []*bls12381.PointG1
G2s []*bls12381.PointG2
G1Powers []*bls12381.PointG1
G2Powers []*bls12381.PointG2
} }
type toxicWaste struct { type toxicWaste struct {
@ -65,22 +105,22 @@ func tau(randomness []byte) *toxicWaste {
} }
func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS { 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() g1 := bls12381.NewG1()
g2 := bls12381.NewG2() g2 := bls12381.NewG2()
Q := g1.Q() // Q = |G1| == |G2| Q := g1.Q() // Q = |G1| == |G2|
// fmt.Println("Computing [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁, for n =", len(prevSRS.G1s)) // 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 := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes()) 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)) // 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 := new(big.Int).Exp(t.tau, big.NewInt(int64(i)), Q)
tau_i_Fr := bls12381.NewFr().FromBytes(tau_i.Bytes()) 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 return srs
@ -90,14 +130,17 @@ func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof {
g1 := bls12381.NewG1() g1 := bls12381.NewG1()
G1_p := g1.New() G1_p := g1.New()
tau_Fr := bls12381.NewFr().FromBytes(toxicWaste.tau.Bytes()) 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} 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 // set tau from randomness
tw := tau(randomness) tw := tau(randomness)
@ -105,7 +148,7 @@ func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) {
proof := genProof(tw, prevSRS, newSRS) 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 // 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() pairing := bls12381.NewEngine()
// 1. check that elements of the newSRS are valid points // 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 // i) non-empty
if newSRS.G1s[i] == nil {
if newSRS.G1Powers[i] == nil {
return false return false
} }
// ii) non-zero // ii) non-zero
if g1.IsZero(newSRS.G1s[i]) {
if g1.IsZero(newSRS.G1Powers[i]) {
return false return false
} }
// iii) in the correct prime order of subgroups // iii) in the correct prime order of subgroups
if !g1.IsOnCurve(newSRS.G1s[i]) {
if !g1.IsOnCurve(newSRS.G1Powers[i]) {
return false return false
} }
if !g1.InCorrectSubgroup(newSRS.G1s[i]) {
if !g1.InCorrectSubgroup(newSRS.G1Powers[i]) {
return false return false
} }
} }
for i := 0; i < len(newSRS.G2s); i++ {
for i := 0; i < len(newSRS.G2Powers); i++ {
// i) non-empty // i) non-empty
if newSRS.G2s[i] == nil {
if newSRS.G2Powers[i] == nil {
return false return false
} }
// ii) non-zero // ii) non-zero
if g2.IsZero(newSRS.G2s[i]) {
if g2.IsZero(newSRS.G2Powers[i]) {
return false return false
} }
// iii) in the correct prime order of subgroups // iii) in the correct prime order of subgroups
if !g2.IsOnCurve(newSRS.G2s[i]) {
if !g2.IsOnCurve(newSRS.G2Powers[i]) {
return false return false
} }
if !g2.InCorrectSubgroup(newSRS.G2s[i]) {
if !g2.InCorrectSubgroup(newSRS.G2Powers[i]) {
return false 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 return false
} }
// 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ) // 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
// e([τ]₁, [p]₂) == e([τ']₁, [1]₂) // 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 return false
} }
// 4. check newSRS following the powers of tau structure // 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] // 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 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] // 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 return false
} }
} }

Loading…
Cancel
Save