mirror of
https://github.com/arnaucube/eth-kzg-ceremony-alt.git
synced 2026-01-08 15:01:30 +01:00
Add State transcripts contribute logic
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
121
powersoftau.go
121
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 Witness struct {
|
||||||
type Contribution struct {
|
RunningProducts []*bls12381.PointG1
|
||||||
SRS *SRS
|
PotPubKeys []*bls12381.PointG2
|
||||||
Proof *Proof
|
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
|
G1Powers []*bls12381.PointG1
|
||||||
G2s []*bls12381.PointG2
|
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
|
// Contribute takes as input the previous SRS and a random
|
||||||
// returns the new SRS together with the Proof
|
// byte slice, and returns the new SRS together with the Proof
|
||||||
func Contribute(prevSRS *SRS, randomness []byte) (Contribution, error) {
|
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]
|
// 2. check proof.G1PTau == newSRS.G1Powers[1]
|
||||||
if !g1.Equal(proof.G1PTau, newSRS.G1s[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()
|
eL := pairing.AddPair(prevSRS.G1Powers[1], proof.G2P).Result()
|
||||||
e1 := pairing.AddPair(newSRS.G1s[1], g2.One()).Result()
|
eR := pairing.AddPair(newSRS.G1Powers[1], g2.One()).Result()
|
||||||
if !e0.Equal(e1) {
|
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()
|
eL := pairing.AddPair(newSRS.G1Powers[i], newSRS.G2Powers[1]).Result()
|
||||||
e1 := pairing.AddPair(newSRS.G1s[i+1], g2.One()).Result()
|
eR := pairing.AddPair(newSRS.G1Powers[i+1], g2.One()).Result()
|
||||||
if !e0.Equal(e1) {
|
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()
|
eL := pairing.AddPair(newSRS.G1Powers[1], newSRS.G2Powers[i]).Result()
|
||||||
e4 := pairing.AddPair(g1.One(), newSRS.G2s[i+1]).Result()
|
eR := pairing.AddPair(g1.One(), newSRS.G2Powers[i+1]).Result()
|
||||||
if !e3.Equal(e4) {
|
if !eL.Equal(eR) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user