@ -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
G1Power s [ ] * bls12381 . PointG1
G2Power s [ ] * 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 . G1Power s ) , len ( prevSRS . G2Power s ) )
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 . G1Power s ) ; 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 . G1Power s [ i ] , prevSRS . G1Power s [ 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 . G2Power s ) ; 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 . G2Power s [ i ] , prevSRS . G2Power s [ 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 . G1Power s [ 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 . G1Power s ) ; i ++ {
// i) non-empty
if newSRS . G1s [ i ] == nil {
if newSRS . G1Power s [ i ] == nil {
return false
}
// ii) non-zero
if g1 . IsZero ( newSRS . G1s [ i ] ) {
if g1 . IsZero ( newSRS . G1Power s [ i ] ) {
return false
}
// iii) in the correct prime order of subgroups
if ! g1 . IsOnCurve ( newSRS . G1s [ i ] ) {
if ! g1 . IsOnCurve ( newSRS . G1Power s [ i ] ) {
return false
}
if ! g1 . InCorrectSubgroup ( newSRS . G1s [ i ] ) {
if ! g1 . InCorrectSubgroup ( newSRS . G1Power s [ i ] ) {
return false
}
}
for i := 0 ; i < len ( newSRS . G2s ) ; i ++ {
for i := 0 ; i < len ( newSRS . G2Power s ) ; i ++ {
// i) non-empty
if newSRS . G2s [ i ] == nil {
if newSRS . G2Power s [ i ] == nil {
return false
}
// ii) non-zero
if g2 . IsZero ( newSRS . G2s [ i ] ) {
if g2 . IsZero ( newSRS . G2Power s [ i ] ) {
return false
}
// iii) in the correct prime order of subgroups
if ! g2 . IsOnCurve ( newSRS . G2s [ i ] ) {
if ! g2 . IsOnCurve ( newSRS . G2Power s [ i ] ) {
return false
}
if ! g2 . InCorrectSubgroup ( newSRS . G2s [ i ] ) {
if ! g2 . InCorrectSubgroup ( newSRS . G2Power s [ i ] ) {
return false
}
}
// 2. check proof.G1PTau == newSRS.G1s[1]
if ! g1 . Equal ( proof . G1PTau , newSRS . G1s [ 1 ] ) {
// 2. check proof.G1PTau == newSRS.G1Power s[1]
if ! g1 . Equal ( proof . G1PTau , newSRS . G1Power s [ 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 . G1Power s [ 1 ] , proof . G2P ) . Result ( )
eR := pairing . AddPair ( newSRS . G1Power s [ 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 . G1Power s ) - 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 . G1Power s [ i ] , newSRS . G2Power s [ 1 ] ) . Result ( )
eR := pairing . AddPair ( newSRS . G1Power s [ 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 . G2Power s ) - 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 . G1Power s [ 1 ] , newSRS . G2Power s [ i ] ) . Result ( )
eR := pairing . AddPair ( g1 . One ( ) , newSRS . G2Power s [ i + 1 ] ) . Result ( )
if ! eL . Equal ( eR ) {
return false
}
}