mirror of
https://github.com/arnaucube/eth-kzg-ceremony-alt.git
synced 2026-01-28 14:26:40 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a5be110fc | ||
|
|
1c95590ba0 |
@@ -20,7 +20,7 @@ Documents used for this implementation:
|
|||||||
- [*Why and how zkSNARKs work*, by Maksym Petkus](https://arxiv.org/abs/1906.07221v1)
|
- [*Why and how zkSNARKs work*, by Maksym Petkus](https://arxiv.org/abs/1906.07221v1)
|
||||||
|
|
||||||
|
|
||||||
You can find more info on the logic behind the powers of tau computation & verification in these notes: http://arnaucube.com/blog/powersoftau.html
|
**You can find more info on the logic behind the powers of tau computation & verification in these notes: http://arnaucube.com/blog/powersoftau.html**
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
Get the binary from the [releases](https://github.com/arnaucube/eth-kzg-ceremony-alt/releases) (alternative you can compile it from source), 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:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
kzgceremony "github.com/arnaucube/eth-kzg-ceremony-alt"
|
kzgceremony "github.com/arnaucube/eth-kzg-ceremony-alt"
|
||||||
)
|
)
|
||||||
@@ -155,7 +156,6 @@ func (c *Client) PostTryContribute(sessionID string) (*kzgceremony.BatchContribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
fmt.Println(string(body))
|
|
||||||
switch resp.StatusCode {
|
switch resp.StatusCode {
|
||||||
case http.StatusBadRequest:
|
case http.StatusBadRequest:
|
||||||
return nil, StatusWait, fmt.Errorf("call came to early. rate limited")
|
return nil, StatusWait, fmt.Errorf("call came to early. rate limited")
|
||||||
@@ -166,13 +166,26 @@ func (c *Client) PostTryContribute(sessionID string) (*kzgceremony.BatchContribu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: a 200 (Ok) code by the Sequencer on try_contribute doesn't
|
||||||
|
// mean that the contributor has been selected. It could mean that the
|
||||||
|
// Sequencer is returning the error AnotherContributionInProgress in a
|
||||||
|
// json msg (see
|
||||||
|
// https://github.com/ethereum/kzg-ceremony-sequencer/blob/2538f2f08d4db880d7f4608e964df0b695bc7d2f/src/api/v1/error_response.rs#L105
|
||||||
|
// )
|
||||||
|
|
||||||
|
// check if body contains the error message of "another contribution in
|
||||||
|
// progress" (despite http statuscode being 200 (Ok))
|
||||||
|
if strings.Contains(string(body), "another contribution in progress") {
|
||||||
|
return nil, StatusWait, fmt.Errorf("another contribution in progress")
|
||||||
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile("prevBatchContribution.json", body, 0600)
|
err = ioutil.WriteFile("prevBatchContribution.json", body, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, StatusError, err
|
return nil, StatusError, err
|
||||||
}
|
}
|
||||||
bc := &kzgceremony.BatchContribution{}
|
bc := &kzgceremony.BatchContribution{}
|
||||||
err = json.Unmarshal(body, bc)
|
err = json.Unmarshal(body, bc)
|
||||||
return bc, StatusError, err
|
return bc, StatusProceed, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PostAbortContribution(sessionID string) ([]byte, error) {
|
func (c *Client) PostAbortContribution(sessionID string) ([]byte, error) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
red = color.New(color.FgRed)
|
||||||
redB = color.New(color.FgRed, color.Bold)
|
redB = color.New(color.FgRed, color.Bold)
|
||||||
cyan = color.New(color.FgCyan)
|
cyan = color.New(color.FgCyan)
|
||||||
cyanB = color.New(color.FgCyan, color.Bold)
|
cyanB = color.New(color.FgCyan, color.Bold)
|
||||||
@@ -114,6 +115,7 @@ func main() {
|
|||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
newBatchContribution, err := prevBatchContribution.Contribute([]byte(randomness))
|
newBatchContribution, err := prevBatchContribution.Contribute([]byte(randomness))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("error on prevBatchContribution.Contribute")
|
||||||
printErrAndExit(err)
|
printErrAndExit(err)
|
||||||
}
|
}
|
||||||
fmt.Println("Contribution computed in", time.Since(t0))
|
fmt.Println("Contribution computed in", time.Since(t0))
|
||||||
@@ -122,11 +124,13 @@ func main() {
|
|||||||
fmt.Println("storing contribution.json")
|
fmt.Println("storing contribution.json")
|
||||||
b, err := json.Marshal(newBatchContribution)
|
b, err := json.Marshal(newBatchContribution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErrAndExit(err)
|
// print error but do not exit
|
||||||
|
_, _ = red.Println(err)
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile("contribution.json", b, 0600)
|
err = ioutil.WriteFile("contribution.json", b, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErrAndExit(err)
|
// print error but do not exit
|
||||||
|
_, _ = red.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// send contribution
|
// send contribution
|
||||||
@@ -174,7 +178,6 @@ func authGH(c *client.Client) client.MsgAuthCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func printErrAndExit(err error) {
|
func printErrAndExit(err error) {
|
||||||
red := color.New(color.FgRed)
|
|
||||||
_, _ = red.Println(err)
|
_, _ = red.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func newEmptySRS(nG1, nG2 int) *SRS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func tau(round int, randomness []byte) *toxicWaste {
|
func tau(round int, randomness []byte) *toxicWaste {
|
||||||
val := blake2b.Sum256(randomness)
|
val := blake2b.Sum256(append(randomness, byte(round)))
|
||||||
tau := new(big.Int).Mod(
|
tau := new(big.Int).Mod(
|
||||||
new(big.Int).SetBytes(val[:]),
|
new(big.Int).SetBytes(val[:]),
|
||||||
g2.Q())
|
g2.Q())
|
||||||
@@ -181,7 +181,8 @@ func genProof(toxicWaste *toxicWaste, prevSRS, newSRS *SRS) *Proof {
|
|||||||
// byte slice, and returns the new SRS together with the Proof
|
// byte slice, and returns the new SRS together with the Proof
|
||||||
func Contribute(prevSRS *SRS, round int, randomness []byte) (*SRS, *Proof, error) {
|
func Contribute(prevSRS *SRS, round int, randomness []byte) (*SRS, *Proof, error) {
|
||||||
if len(randomness) < MinRandomnessLen {
|
if len(randomness) < MinRandomnessLen {
|
||||||
return nil, nil, fmt.Errorf("err randomness") // WIP
|
return nil, nil, fmt.Errorf("err: randomness length < %d",
|
||||||
|
MinRandomnessLen)
|
||||||
}
|
}
|
||||||
// set tau from randomness
|
// set tau from randomness
|
||||||
tw := tau(round, randomness)
|
tw := tau(round, randomness)
|
||||||
@@ -231,9 +232,10 @@ func checkG2PointCorrectness(p *bls12381.PointG2) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify checks the correct computation of the new SRS respectively from the
|
// VerifyNewSRSFromPrevSRS checks the correct computation of the new SRS
|
||||||
// previous SRS
|
// respectively from the previous SRS. These are the checks that the Sequencer
|
||||||
func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
|
// would do.
|
||||||
|
func VerifyNewSRSFromPrevSRS(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
|
||||||
@@ -282,3 +284,58 @@ func Verify(prevSRS, newSRS *SRS, proof *Proof) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyState acts similarly to VerifyNewSRSFromPrevSRS, but verifying the
|
||||||
|
// given State (which can be obtained from the Sequencer)
|
||||||
|
func VerifyState(s *State) bool {
|
||||||
|
pairing := bls12381.NewEngine()
|
||||||
|
|
||||||
|
for _, t := range s.Transcripts {
|
||||||
|
// 1. check that elements of the SRS are valid points
|
||||||
|
for i := 0; i < len(t.PowersOfTau.G1Powers); i++ {
|
||||||
|
if err := checkG1PointCorrectness(t.PowersOfTau.G1Powers[i]); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(t.PowersOfTau.G2Powers); i++ {
|
||||||
|
if err := checkG2PointCorrectness(t.PowersOfTau.G2Powers[i]); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. check t.Witness.RunningProducts[last] == t.PowersOfTau.G1Powers[1]
|
||||||
|
if !g1.Equal(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-1],
|
||||||
|
t.PowersOfTau.G1Powers[1]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. check newSRS.G1s[1] (g₁^τ'), is correctly related to prevSRS.G1s[1] (g₁^τ)
|
||||||
|
// e([τ]₁, [p]₂) == e([τ']₁, [1]₂)
|
||||||
|
eL := pairing.AddPair(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-2], t.Witness.PotPubKeys[len(t.Witness.PotPubKeys)-1]).Result()
|
||||||
|
eR := pairing.AddPair(t.Witness.RunningProducts[len(t.Witness.RunningProducts)-1], g2.One()).Result()
|
||||||
|
if !eL.Equal(eR) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. check newSRS following the powers of tau structure
|
||||||
|
for i := 0; i < len(t.PowersOfTau.G1Powers)-1; i++ {
|
||||||
|
// i) e([τ'ⁱ]₁, [τ']₂) == e([τ'ⁱ⁺¹]₁, [1]₂), for i ∈ [1, n−1]
|
||||||
|
eL := pairing.AddPair(t.PowersOfTau.G1Powers[i], t.PowersOfTau.G2Powers[1]).Result()
|
||||||
|
eR := pairing.AddPair(t.PowersOfTau.G1Powers[i+1], g2.One()).Result()
|
||||||
|
if !eL.Equal(eR) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(t.PowersOfTau.G2Powers)-1; i++ {
|
||||||
|
// ii) e([τ']₁, [τ'ʲ]₂) == e([1]₁, [τ'ʲ⁺¹]₂), for j ∈ [1, m−1]
|
||||||
|
eL := pairing.AddPair(t.PowersOfTau.G1Powers[1], t.PowersOfTau.G2Powers[i]).Result()
|
||||||
|
eR := pairing.AddPair(g1.One(), t.PowersOfTau.G2Powers[i+1]).Result()
|
||||||
|
if !eL.Equal(eR) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ func TestContribution(t *testing.T) {
|
|||||||
[]byte("1111111111111111111111111111111111111111111111111111111111111111"))
|
[]byte("1111111111111111111111111111111111111111111111111111111111111111"))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
c.Assert(Verify(srs_0, srs_1, proof_1), qt.IsTrue)
|
c.Assert(VerifyNewSRSFromPrevSRS(srs_0, srs_1, proof_1), qt.IsTrue)
|
||||||
|
|
||||||
srs_2, proof_2, err := Contribute(srs_1, 0,
|
srs_2, proof_2, err := Contribute(srs_1, 0,
|
||||||
[]byte("2222222222222222222222222222222222222222222222222222222222222222"))
|
[]byte("2222222222222222222222222222222222222222222222222222222222222222"))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
c.Assert(Verify(srs_1, srs_2, proof_2), qt.IsTrue)
|
c.Assert(VerifyNewSRSFromPrevSRS(srs_1, srs_2, proof_2), qt.IsTrue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComputeNewState(t *testing.T) {
|
func TestComputeNewState(t *testing.T) {
|
||||||
@@ -57,6 +57,11 @@ func TestBatchContribution(t *testing.T) {
|
|||||||
bc.Contribute([]byte("1111111111111111111111111111111111111111111111111111111111111111"))
|
bc.Contribute([]byte("1111111111111111111111111111111111111111111111111111111111111111"))
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
|
|
||||||
|
c.Assert(len(nb.Contributions), qt.Equals, 4)
|
||||||
|
c.Assert(g2.Equal(nb.Contributions[0].PotPubKey, nb.Contributions[1].PotPubKey), qt.IsFalse)
|
||||||
|
c.Assert(g2.Equal(nb.Contributions[0].PotPubKey, nb.Contributions[2].PotPubKey), qt.IsFalse)
|
||||||
|
c.Assert(g2.Equal(nb.Contributions[0].PotPubKey, nb.Contributions[3].PotPubKey), qt.IsFalse)
|
||||||
|
|
||||||
_, err = json.Marshal(nb)
|
_, err = json.Marshal(nb)
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user