mirror of
https://github.com/arnaucube/eth-kzg-ceremony-alt.git
synced 2026-01-07 14:31:31 +01:00
Polishing & documenting, add compile script
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
bin
|
||||
parsed_state.json
|
||||
new_state.json
|
||||
cmd/prevBatchContribution.json
|
||||
cmd/contribution.json
|
||||
cmd/contribution_receipt.json
|
||||
prevBatchContribution.json
|
||||
contribution.json
|
||||
contribution_receipt.json
|
||||
|
||||
14
README.md
14
README.md
@@ -13,22 +13,28 @@ This implementation has been done without looking at the other impls code (excep
|
||||
|
||||
> This code has not been audited, use it at your own risk.
|
||||
|
||||
Why in Go? Ideally would have done this code using Rust & arkworks, but the official impl already uses that.
|
||||
Why in Go? Ideally would have done this code using Rust & arkworks, but the official impl already uses that. This implementation uses [Kilic's BLS12-381 pairing implementation](https://github.com/kilic/bls12-381).
|
||||
|
||||
Documents used for this implementation:
|
||||
- [KZG10-Ceremony-audit-report.pdf, section *3.1 Overview of PoT ceremonies*](https://github.com/ethereum/kzg-ceremony/blob/main/KZG10-Ceremony-audit-report.pdf)
|
||||
- [*Why and how zkSNARKs work*, by Maksym Petkus](https://arxiv.org/abs/1906.07221v1)
|
||||
|
||||
### Usage
|
||||
Go into the `cmd` dir, and run:
|
||||
Get the binary from the [releases](https://github.com/arnaucube/eth-kzg-ceremony-alt/releases) (alternative you can compile it from source), and run:
|
||||
```
|
||||
> go run cmd.go
|
||||
> ./kzgceremony
|
||||
|
||||
eth-kzg-ceremony-alt
|
||||
====================
|
||||
|
||||
Usage of /tmp/go-build4278582969/b001/exe/cmd:
|
||||
Usage of ./kzgceremony:
|
||||
-u, --url string sequencer url (default "https://kzg-ceremony-sequencer-dev.fly.dev")
|
||||
-r, --rand string randomness
|
||||
-s, --sleeptime uint time (seconds) sleeping before trying again to be the next contributor (default 10)
|
||||
```
|
||||
|
||||
So for example, run your contribution with:
|
||||
```
|
||||
./kzgceremony -r "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod"
|
||||
```
|
||||
(where the "Lorem ipsum..." is your source of randomness)
|
||||
|
||||
@@ -6,8 +6,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"kzgceremony"
|
||||
"net/http"
|
||||
|
||||
kzgceremony "github.com/arnaucube/eth-kzg-ceremony-alt"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
|
||||
88
cmd/cmd.go
88
cmd/cmd.go
@@ -5,88 +5,80 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"kzgceremony"
|
||||
"kzgceremony/client"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
kzgceremony "github.com/arnaucube/eth-kzg-ceremony-alt"
|
||||
"github.com/arnaucube/eth-kzg-ceremony-alt/client"
|
||||
"github.com/fatih/color"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
sequencerURL string
|
||||
randomness string
|
||||
sleepTime uint64
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("eth-kzg-ceremony-alt")
|
||||
fmt.Printf("====================\n\n")
|
||||
|
||||
red := color.New(color.FgRed)
|
||||
redB := color.New(color.FgRed, color.Bold)
|
||||
cyan := color.New(color.FgCyan)
|
||||
cyanB := color.New(color.FgCyan, color.Bold)
|
||||
green := color.New(color.FgHiGreen)
|
||||
greenB := color.New(color.FgHiGreen, color.Bold)
|
||||
|
||||
config := Config{}
|
||||
flag.StringVarP(&config.sequencerURL, "url", "u",
|
||||
var sequencerURL string
|
||||
var randomness string
|
||||
var sleepTime uint64
|
||||
flag.StringVarP(&sequencerURL, "url", "u",
|
||||
"https://kzg-ceremony-sequencer-dev.fly.dev", "sequencer url")
|
||||
flag.StringVarP(&config.randomness, "rand", "r",
|
||||
"", "randomness")
|
||||
flag.Uint64VarP(&config.sleepTime, "sleeptime", "s",
|
||||
flag.StringVarP(&randomness, "rand", "r",
|
||||
"", fmt.Sprintf("randomness, needs to be bigger than %d", kzgceremony.MinRandomnessLen))
|
||||
flag.Uint64VarP(&sleepTime, "sleeptime", "s",
|
||||
10, "time (seconds) sleeping before trying again to be the next contributor")
|
||||
|
||||
flag.CommandLine.SortFlags = false
|
||||
flag.Parse()
|
||||
|
||||
c := client.NewClient(config.sequencerURL)
|
||||
c := client.NewClient(sequencerURL)
|
||||
|
||||
// get status
|
||||
msgStatus, err := c.GetCurrentStatus()
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
fmt.Println(msgStatus)
|
||||
|
||||
if config.randomness == "" {
|
||||
cyanB.Println("To contribute to the ceremony, please set your randomness. Use -h to show the available flags.")
|
||||
if randomness == "" {
|
||||
_, _ =
|
||||
cyanB.Println("To contribute to the ceremony, please set your randomness. Use -h to show the available flags.")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if len([]byte(config.randomness)) < kzgceremony.MinRandomnessLen {
|
||||
redB.Printf("Randomness must be longer than %d, current length: %d\n",
|
||||
kzgceremony.MinRandomnessLen, len([]byte(config.randomness)))
|
||||
if len([]byte(randomness)) < kzgceremony.MinRandomnessLen {
|
||||
_, _ = redB.Printf("Randomness must be longer than %d, current length: %d\n",
|
||||
kzgceremony.MinRandomnessLen, len([]byte(randomness)))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Auth
|
||||
msgReqLink, err := c.GetRequestLink()
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
|
||||
green.Printf("Please go to\n%s\n and authenticate with Github.\n", msgReqLink.GithubAuthURL)
|
||||
_, _ = green.Printf("Please go to\n%s\n and authenticate with Github.\n", msgReqLink.GithubAuthURL)
|
||||
fmt.Println("(currently only Github auth is supported)")
|
||||
|
||||
greenB.Printf("Paste here the RawData from the auth answer:\n")
|
||||
_, _ = greenB.Printf("Paste here the RawData from the auth answer:\n")
|
||||
s, err := readInput()
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
var authMsg client.MsgAuthCallback
|
||||
if err = json.Unmarshal([]byte(s), &authMsg); err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
fmt.Print("Parsed auth msg: ")
|
||||
cyan.Printf("%#v\n", authMsg)
|
||||
_, _ = cyan.Printf("%#v\n", authMsg)
|
||||
|
||||
// TODO this will be only triggered by a flag
|
||||
// msg, err := c.PostAbortContribution(authMsg.SessionID)
|
||||
@@ -104,14 +96,14 @@ func main() {
|
||||
var retry bool
|
||||
prevBatchContribution, retry, err = c.PostTryContribute(authMsg.SessionID)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
_, _ = cyan.Println(err)
|
||||
}
|
||||
if !retry {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%s try_contribute unsuccessful, going to sleep %d seconds\n",
|
||||
time.Now().Format("2006-01-02 15:04:05"), config.sleepTime)
|
||||
time.Sleep(time.Duration(config.sleepTime) * time.Second)
|
||||
time.Now().Format("2006-01-02 15:04:05"), sleepTime)
|
||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||
}
|
||||
|
||||
// get latest state
|
||||
@@ -122,48 +114,48 @@ func main() {
|
||||
// }
|
||||
|
||||
fmt.Println("starting to compute new contribution")
|
||||
newBatchContribution, err := prevBatchContribution.Contribute([]byte(config.randomness))
|
||||
newBatchContribution, err := prevBatchContribution.Contribute([]byte(randomness))
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
// store contribution
|
||||
fmt.Println("storing contribution.json")
|
||||
b, err := json.Marshal(newBatchContribution)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
err = ioutil.WriteFile("contribution.json", b, 0600)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
|
||||
// send contribution
|
||||
fmt.Println("sending contribution")
|
||||
receipt, err := c.PostContribute(authMsg.SessionID, newBatchContribution)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
fmt.Println("Receipt:")
|
||||
green.Println(receipt)
|
||||
_, _ = green.Println(receipt)
|
||||
|
||||
// store receipt
|
||||
fmt.Println("storing contribution_receipt.json")
|
||||
b, err = json.Marshal(receipt)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
err = ioutil.WriteFile("contribution_receipt.json", b, 0600)
|
||||
if err != nil {
|
||||
red.Println(err)
|
||||
os.Exit(1)
|
||||
printErrAndExit(err)
|
||||
}
|
||||
}
|
||||
|
||||
func printErrAndExit(err error) {
|
||||
red := color.New(color.FgRed)
|
||||
_, _ = red.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func readInput() (string, error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
input, err := reader.ReadString('\n')
|
||||
|
||||
14
compile.sh
Executable file
14
compile.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p bin
|
||||
|
||||
cd cmd
|
||||
|
||||
echo "building linux binaries"
|
||||
GOOS=linux GOARCH=amd64 go build -o ../bin/kzgceremony-amd64-linux *.go
|
||||
|
||||
echo "building windows binaries"
|
||||
GOOS=windows GOARCH=amd64 go build -o ../bin/kzgceremony-amd64.exe *.go
|
||||
|
||||
echo "building macOS binaries"
|
||||
GOOS=darwin GOARCH=amd64 go build -o ../bin/kzgceremony-amd64-darwin *.go
|
||||
2
go.mod
2
go.mod
@@ -1,4 +1,4 @@
|
||||
module kzgceremony
|
||||
module github.com/arnaucube/eth-kzg-ceremony-alt
|
||||
|
||||
go 1.19
|
||||
|
||||
|
||||
31
parsers.go
31
parsers.go
@@ -9,6 +9,8 @@ import (
|
||||
bls12381 "github.com/kilic/bls12-381"
|
||||
)
|
||||
|
||||
// UnmarshalJSON implements the State json unmarshaler, compatible
|
||||
// with the official Ethereum KZG Ceremony formats
|
||||
func (s *State) UnmarshalJSON(b []byte) error {
|
||||
var sStr stateStr
|
||||
if err := json.Unmarshal(b, &sStr); err != nil {
|
||||
@@ -57,10 +59,11 @@ func (s *State) UnmarshalJSON(b []byte) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// TODO validate data (G1 & G2 subgroup checks, etc)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON implements the State json marshaler, compatible with the
|
||||
// official Ethereum KZG Ceremony formats
|
||||
func (s State) MarshalJSON() ([]byte, error) {
|
||||
var sStr stateStr
|
||||
sStr.ParticipantIDs = s.ParticipantIDs
|
||||
@@ -93,13 +96,14 @@ func (s State) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(sStr)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the BatchContribution json unmarshaler, compatible
|
||||
// with the official Ethereum KZG Ceremony formats
|
||||
func (c *BatchContribution) UnmarshalJSON(b []byte) error {
|
||||
var cStr batchContributionStr
|
||||
if err := json.Unmarshal(b, &cStr); err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
g2 := bls12381.NewG2()
|
||||
|
||||
c.Contributions = make([]Contribution, len(cStr.Contributions))
|
||||
for i := 0; i < len(cStr.Contributions); i++ {
|
||||
@@ -129,9 +133,10 @@ func (c *BatchContribution) UnmarshalJSON(b []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON implements the BatchContribution json marshaler, compatible
|
||||
// with the official Ethereum KZG Ceremony formats
|
||||
func (c BatchContribution) MarshalJSON() ([]byte, error) {
|
||||
var cStr batchContributionStr
|
||||
g2 := bls12381.NewG2()
|
||||
|
||||
cStr.Contributions = make([]contributionStr, len(c.Contributions))
|
||||
for i := 0; i < len(c.Contributions); i++ {
|
||||
@@ -143,7 +148,8 @@ func (c BatchContribution) MarshalJSON() ([]byte, error) {
|
||||
cStr.Contributions[i].PowersOfTau.G2Powers =
|
||||
g2PointsToStrings(c.Contributions[i].PowersOfTau.G2Powers)
|
||||
|
||||
cStr.Contributions[i].PotPubKey = "0x" + hex.EncodeToString(g2.ToCompressed(c.Contributions[i].PotPubKey))
|
||||
cStr.Contributions[i].PotPubKey = "0x" +
|
||||
hex.EncodeToString(g2.ToCompressed(c.Contributions[i].PotPubKey))
|
||||
}
|
||||
return json.Marshal(cStr)
|
||||
}
|
||||
@@ -184,7 +190,6 @@ type stateStr struct {
|
||||
}
|
||||
|
||||
func g1PointsToStrings(points []*bls12381.PointG1) []string {
|
||||
g1 := bls12381.NewG1() // TODO unify g1 instantiation (& g2)
|
||||
n := len(points)
|
||||
g1s := make([]string, n)
|
||||
for i := 0; i < n; i++ {
|
||||
@@ -198,7 +203,6 @@ func g1PointsToStrings(points []*bls12381.PointG1) []string {
|
||||
}
|
||||
|
||||
func g2PointsToStrings(points []*bls12381.PointG2) []string {
|
||||
g2 := bls12381.NewG2()
|
||||
n := len(points)
|
||||
g2s := make([]string, n)
|
||||
for i := 0; i < n; i++ {
|
||||
@@ -211,8 +215,10 @@ func g2PointsToStrings(points []*bls12381.PointG2) []string {
|
||||
return g2s
|
||||
}
|
||||
|
||||
// stringsToPointsG1 parses the strings that represent the G1 points in the
|
||||
// ZCash compressed format into bls12381.PointG1 data structure. Additionally
|
||||
// it checks the points correctness
|
||||
func stringsToPointsG1(s []string) ([]*bls12381.PointG1, error) {
|
||||
g1 := bls12381.NewG1() // TODO unify g1 instantiation (& g2)
|
||||
n := len(s)
|
||||
g1s := make([]*bls12381.PointG1, n)
|
||||
for i := 0; i < n; i++ {
|
||||
@@ -227,12 +233,18 @@ func stringsToPointsG1(s []string) ([]*bls12381.PointG1, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkG1PointCorrectness(g1s_i); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g1s[i] = g1s_i
|
||||
}
|
||||
return g1s, nil
|
||||
}
|
||||
|
||||
// stringsToPointsG2 parses the strings that represent the G2 points in the
|
||||
// ZCash compressed format into bls12381.PointG2 data structure. Additionally
|
||||
// it checks the points correctness
|
||||
func stringsToPointsG2(s []string) ([]*bls12381.PointG2, error) {
|
||||
g2 := bls12381.NewG2()
|
||||
n := len(s)
|
||||
g2s := make([]*bls12381.PointG2, n)
|
||||
for i := 0; i < n; i++ {
|
||||
@@ -247,6 +259,9 @@ func stringsToPointsG2(s []string) ([]*bls12381.PointG2, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := checkG2PointCorrectness(g2s_i); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g2s[i] = g2s_i
|
||||
}
|
||||
return g2s, nil
|
||||
|
||||
@@ -35,6 +35,7 @@ func TestParseCompressedG1Point(t *testing.T) {
|
||||
|
||||
p1Str := "0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb"
|
||||
g1Bytes, err := hex.DecodeString(strings.TrimPrefix(p1Str, "0x"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
g1Point, err := g1.FromCompressed(g1Bytes)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
@@ -43,6 +44,7 @@ func TestParseCompressedG1Point(t *testing.T) {
|
||||
|
||||
p1Str = "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
g1Bytes, err = hex.DecodeString(strings.TrimPrefix(p1Str, "0x"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
g1Point, err = g1.FromCompressed(g1Bytes)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
@@ -61,6 +63,7 @@ func TestParseCompressedG2Point(t *testing.T) {
|
||||
|
||||
p2Str := "0x93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"
|
||||
g2Bytes, err := hex.DecodeString(strings.TrimPrefix(p2Str, "0x"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
g2Point, err := g2.FromCompressed(g2Bytes)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
@@ -69,6 +72,7 @@ func TestParseCompressedG2Point(t *testing.T) {
|
||||
|
||||
p2Str = "0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
g2Bytes, err = hex.DecodeString(strings.TrimPrefix(p2Str, "0x"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
g2Point, err = g2.FromCompressed(g2Bytes)
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
|
||||
172
powersoftau.go
172
powersoftau.go
@@ -7,14 +7,37 @@ import (
|
||||
bls12381 "github.com/kilic/bls12-381"
|
||||
)
|
||||
|
||||
// todo: unify addition & multiplicative notation in the comments
|
||||
|
||||
// MinRandomnessLen is the minimum accepted length for the user defined
|
||||
// randomness
|
||||
const MinRandomnessLen = 64
|
||||
|
||||
type Witness struct {
|
||||
RunningProducts []*bls12381.PointG1
|
||||
PotPubKeys []*bls12381.PointG2
|
||||
BLSSignatures []*bls12381.PointG1
|
||||
var g1 *bls12381.G1
|
||||
var g2 *bls12381.G2
|
||||
|
||||
func init() {
|
||||
g1 = bls12381.NewG1()
|
||||
g2 = bls12381.NewG2()
|
||||
}
|
||||
|
||||
// State represents the data structure obtained from the Sequencer at the
|
||||
// /info/current_state endpoint
|
||||
type State struct {
|
||||
Transcripts []Transcript
|
||||
ParticipantIDs []string // WIP
|
||||
ParticipantECDSASignatures []string
|
||||
}
|
||||
|
||||
// BatchContribution represents the data structure obtained from the Sequencer
|
||||
// at the /contribute endpoint
|
||||
type BatchContribution struct {
|
||||
Contributions []Contribution
|
||||
}
|
||||
|
||||
type Contribution struct {
|
||||
NumG1Powers uint64
|
||||
NumG2Powers uint64
|
||||
PowersOfTau *SRS
|
||||
PotPubKey *bls12381.PointG2
|
||||
}
|
||||
|
||||
type Transcript struct {
|
||||
@@ -24,22 +47,33 @@ type Transcript struct {
|
||||
Witness *Witness
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Transcripts []Transcript
|
||||
ParticipantIDs []string // WIP
|
||||
ParticipantECDSASignatures []string
|
||||
type Witness struct {
|
||||
RunningProducts []*bls12381.PointG1
|
||||
PotPubKeys []*bls12381.PointG2
|
||||
BLSSignatures []*bls12381.PointG1
|
||||
}
|
||||
|
||||
type Contribution struct {
|
||||
NumG1Powers uint64
|
||||
NumG2Powers uint64
|
||||
PowersOfTau *SRS
|
||||
PotPubKey *bls12381.PointG2
|
||||
}
|
||||
type BatchContribution struct {
|
||||
Contributions []Contribution
|
||||
// SRS contains the powers of tau in G1 & G2, eg.
|
||||
// [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
|
||||
// [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
|
||||
type SRS struct {
|
||||
G1Powers []*bls12381.PointG1
|
||||
G2Powers []*bls12381.PointG2
|
||||
}
|
||||
|
||||
type toxicWaste struct {
|
||||
tau *big.Int
|
||||
TauG2 *bls12381.PointG2 // Proof.G2P
|
||||
}
|
||||
|
||||
// Proof contains g₂ᵖ and g₂^τ', used by the verifier
|
||||
type Proof struct {
|
||||
G2P *bls12381.PointG2 // g₂ᵖ
|
||||
G1PTau *bls12381.PointG1 // g₂^τ' = g₂^{p ⋅ τ}
|
||||
}
|
||||
|
||||
// Contribute takes the last State and computes a new State using the defined
|
||||
// randomness
|
||||
func (cs *State) Contribute(randomness []byte) (*State, error) {
|
||||
ns := State{}
|
||||
ns.Transcripts = make([]Transcript, len(cs.Transcripts))
|
||||
@@ -66,6 +100,8 @@ func (cs *State) Contribute(randomness []byte) (*State, error) {
|
||||
return &ns, nil
|
||||
}
|
||||
|
||||
// Contribute takes the last BatchContribution and computes a new
|
||||
// BatchContribution using the defined randomness
|
||||
func (pb *BatchContribution) Contribute(randomness []byte) (*BatchContribution, error) {
|
||||
nb := BatchContribution{}
|
||||
nb.Contributions = make([]Contribution, len(pb.Contributions))
|
||||
@@ -85,46 +121,21 @@ func (pb *BatchContribution) Contribute(randomness []byte) (*BatchContribution,
|
||||
return &nb, nil
|
||||
}
|
||||
|
||||
// SRS contains the powers of tau in G1 & G2, eg.
|
||||
// [τ'⁰]₁, [τ'¹]₁, [τ'²]₁, ..., [τ'ⁿ⁻¹]₁,
|
||||
// [τ'⁰]₂, [τ'¹]₂, [τ'²]₂, ..., [τ'ⁿ⁻¹]₂
|
||||
type SRS struct {
|
||||
G1Powers []*bls12381.PointG1
|
||||
G2Powers []*bls12381.PointG2
|
||||
}
|
||||
|
||||
type toxicWaste struct {
|
||||
tau *big.Int
|
||||
TauG2 *bls12381.PointG2
|
||||
}
|
||||
|
||||
// Proof contains g₂ᵖ and g₂^τ', used by the verifier
|
||||
type Proof struct {
|
||||
G2P *bls12381.PointG2 // g₂ᵖ
|
||||
G1PTau *bls12381.PointG1 // g₂^τ' = g₂^{p ⋅ τ}
|
||||
}
|
||||
|
||||
// newEmptySRS creates an empty SRS
|
||||
// newEmptySRS creates an empty SRS filled by [1]₁ & [1]₂ points in all
|
||||
// respective arrays positions
|
||||
func newEmptySRS(nG1, nG2 int) *SRS {
|
||||
g1s := make([]*bls12381.PointG1, nG1)
|
||||
g2s := make([]*bls12381.PointG2, nG2)
|
||||
g1 := bls12381.NewG1()
|
||||
g2 := bls12381.NewG2()
|
||||
// one_G1 := g1.One()
|
||||
// one_G2 := g2.One()
|
||||
for i := 0; i < nG1; i++ {
|
||||
g1s[i] = g1.One()
|
||||
// g1.MulScalar(g1s[i], one_G1, big.NewInt(int64(i)))
|
||||
}
|
||||
for i := 0; i < nG2; i++ {
|
||||
g2s[i] = g2.One()
|
||||
// g2.MulScalar(g2s[i], one_G2, big.NewInt(int64(i)))
|
||||
}
|
||||
return &SRS{g1s, g2s}
|
||||
}
|
||||
|
||||
func tau(randomness []byte) *toxicWaste {
|
||||
g2 := bls12381.NewG2()
|
||||
tau := new(big.Int).Mod(
|
||||
new(big.Int).SetBytes(randomness),
|
||||
g2.Q())
|
||||
@@ -137,8 +148,6 @@ func tau(randomness []byte) *toxicWaste {
|
||||
|
||||
func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS {
|
||||
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))
|
||||
@@ -158,7 +167,6 @@ func computeContribution(t *toxicWaste, prevSRS *SRS) *SRS {
|
||||
}
|
||||
|
||||
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.G1Powers[1], tau_Fr) // g_1^{tau'} = g_1^{p * tau}, where p=toxicWaste.tau
|
||||
@@ -182,45 +190,57 @@ func Contribute(prevSRS *SRS, randomness []byte) (*SRS, *Proof, error) {
|
||||
return newSRS, proof, nil
|
||||
}
|
||||
|
||||
func checkG1PointCorrectness(p *bls12381.PointG1) error {
|
||||
// i) non-empty
|
||||
if p == nil {
|
||||
return fmt.Errorf("empty point value")
|
||||
}
|
||||
// ii) non-zero
|
||||
if g1.IsZero(p) {
|
||||
return fmt.Errorf("point can not be zero")
|
||||
}
|
||||
// iii) in the correct prime order of subgroups
|
||||
if !g1.IsOnCurve(p) {
|
||||
return fmt.Errorf("point not on curve")
|
||||
}
|
||||
if !g1.InCorrectSubgroup(p) {
|
||||
return fmt.Errorf("point not in the correct prime order of subgroups")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkG2PointCorrectness(p *bls12381.PointG2) error {
|
||||
// i) non-empty
|
||||
if p == nil {
|
||||
return fmt.Errorf("empty point value")
|
||||
}
|
||||
// ii) non-zero
|
||||
if g2.IsZero(p) {
|
||||
return fmt.Errorf("point can not be zero")
|
||||
}
|
||||
// iii) in the correct prime order of subgroups
|
||||
if !g2.IsOnCurve(p) {
|
||||
return fmt.Errorf("point not on curve")
|
||||
}
|
||||
if !g2.InCorrectSubgroup(p) {
|
||||
return fmt.Errorf("point not in the correct prime order of subgroups")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify checks the correct computation of the new SRS respectively from the
|
||||
// previous SRS
|
||||
func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
|
||||
g1 := bls12381.NewG1()
|
||||
g2 := bls12381.NewG2()
|
||||
pairing := bls12381.NewEngine()
|
||||
|
||||
// 1. check that elements of the newSRS are valid points
|
||||
for i := 0; i < len(newSRS.G1Powers); i++ {
|
||||
// i) non-empty
|
||||
if newSRS.G1Powers[i] == nil {
|
||||
return false
|
||||
}
|
||||
// ii) non-zero
|
||||
if g1.IsZero(newSRS.G1Powers[i]) {
|
||||
return false
|
||||
}
|
||||
// iii) in the correct prime order of subgroups
|
||||
if !g1.IsOnCurve(newSRS.G1Powers[i]) {
|
||||
return false
|
||||
}
|
||||
if !g1.InCorrectSubgroup(newSRS.G1Powers[i]) {
|
||||
if err := checkG1PointCorrectness(newSRS.G1Powers[i]); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(newSRS.G2Powers); i++ {
|
||||
// i) non-empty
|
||||
if newSRS.G2Powers[i] == nil {
|
||||
return false
|
||||
}
|
||||
// ii) non-zero
|
||||
if g2.IsZero(newSRS.G2Powers[i]) {
|
||||
return false
|
||||
}
|
||||
// iii) in the correct prime order of subgroups
|
||||
if !g2.IsOnCurve(newSRS.G2Powers[i]) {
|
||||
return false
|
||||
}
|
||||
if !g2.InCorrectSubgroup(newSRS.G2Powers[i]) {
|
||||
if err := checkG2PointCorrectness(newSRS.G2Powers[i]); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package kzgceremony
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
@@ -58,7 +57,6 @@ func TestBatchContribution(t *testing.T) {
|
||||
bc.Contribute([]byte("1111111111111111111111111111111111111111111111111111111111111111"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
b, err := json.Marshal(nb)
|
||||
_, err = json.Marshal(nb)
|
||||
c.Assert(err, qt.IsNil)
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user