-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathbatchcontribution.go
96 lines (79 loc) · 2.46 KB
/
batchcontribution.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package contribution
import (
"encoding/hex"
"fmt"
"math/big"
bls12381Fr "github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"golang.org/x/sync/errgroup"
)
type BatchContribution struct {
Contributions []Contribution
}
func (bc *BatchContribution) Contribute(extRandomness ...[]byte) error {
frs := make([]*bls12381Fr.Element, len(bc.Contributions))
for i := range frs {
frs[i] = &bls12381Fr.Element{}
if _, err := frs[i].SetRandom(); err != nil {
return fmt.Errorf("get random Fr: %s", err)
}
// For every externally provided randomness (if any), we multiply frs[i] (generated with CSRNG),
// with a proper map from the []bytes->Fr.
for _, externalRandomness := range extRandomness {
extFr := &bls12381Fr.Element{}
// SetBytes() is safe to call with an arbitrary sized []byte since:
// - A big.Int `r` will be created from the bytes, which is an arbitrary precision integer.
// - gnark-crypto will automatically make r.Mod(BLS_MODULUS) to have a proper Fr.
extFr.SetBytes(externalRandomness)
frs[i].Mul(frs[i], extFr)
}
}
return bc.contributeWithFrs(frs)
}
func (bc *BatchContribution) contributeWithSecrets(secrets []string) error {
frs := make([]*bls12381Fr.Element, len(secrets))
for i := range secrets {
secretBytes, err := hex.DecodeString(secrets[i][2:])
if err != nil {
return err
}
frs[i] = &bls12381Fr.Element{}
frs[i].SetBytes(secretBytes)
if err != nil {
return fmt.Errorf("set Fr from bytes: %s", err)
}
}
return bc.contributeWithFrs(frs)
}
func (bc *BatchContribution) contributeWithFrs(frs []*bls12381Fr.Element) error {
var g errgroup.Group
for i := range bc.Contributions {
g.Go(func(i int, contribution *Contribution) func() error {
return func() error {
xBig := big.NewInt(0)
frs[i].BigInt(xBig)
contribution.updatePowersOfTau(xBig)
contribution.updateWitness(xBig)
// Cleanup in-memory secret.
xBig.SetInt64(0)
*frs[i] = bls12381Fr.Element{}
return nil
}
}(i, &bc.Contributions[i]))
}
if err := g.Wait(); err != nil {
return fmt.Errorf("contributing to sub-ceremony: %s", err)
}
return nil
}
func (bc *BatchContribution) Verify(prevBatchContribution *BatchContribution) (bool, error) {
for i, contribution := range prevBatchContribution.Contributions {
ok, err := bc.Contributions[i].Verify(&contribution)
if err != nil {
return false, fmt.Errorf("verifying %d-th contribution: %s", i, err)
}
if !ok {
return false, nil
}
}
return true, nil
}