Skip to content

Commit bff5399

Browse files
committed
phase2: accept beacon as argument
The randomness package generates beacon once at init. This does not make sense in the offline mode, where the application is ran multiple times. Such approach will generate a different random value at each run, while it must be the same at init and at extract-keys. Change the approach. The extract-keys command now accepts a --beacon argument. User is expect to pass the same beacon that was generated and printed on the init command. Signed-off-by: Wojciech Zmuda <[email protected]>
1 parent ab4799d commit bff5399

File tree

6 files changed

+44
-18
lines changed

6 files changed

+44
-18
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ see the [Constraints](#Constraints) section for more information.
5151

5252
The output Phase 2 file can be used for later contributions.
5353

54+
The command outputs a beacon value, which must then be passed as an argument to [`extract-keys`](#extract-keys).
55+
5456
- `--r1cs` - The R1CS file generated from a Gnark circuit,
5557
- `--phase1` - The Phase 1 file,
5658
- `--phase2` - The output path for the Phase 2 file,
@@ -92,6 +94,7 @@ The output are binary files containing the keys.
9294

9395
- `--r1cs` - The R1CS file generated from the Gnark circuit the ceremony is held for,
9496
- `--srscommons` - The circuit-independent components of the Groth16 SRS file generated on the [Phase 2 initialization](#init).
97+
- `--beacon` - The beacon value output by the [`init`](#init) command.
9598
- `--phase2` - A list of Phase 2 files to verify the contributions in the order they were created. Contributions are
9699
verified in pairs, so at least two files must be provided. This DOES NOT INCLUDE the original Phase 2.
97100
file generated on initialization.

cmd/init.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,29 @@ import (
88
"github.com/urfave/cli/v3"
99

1010
"github.com/reilabs/trusted-setup/phase2"
11+
"github.com/reilabs/trusted-setup/randomness"
1112
)
1213

1314
func Phase2Init(_ context.Context, cmd *cli.Command) error {
1415
phase1FilePath := cmd.String("phase1")
1516
r1csFilePath := cmd.String("r1cs")
1617
outputPhase2FilePath := cmd.String("phase2")
1718
outputSrsCommonsFilePath := cmd.String("srscommons")
19+
beacon := randomness.GetBeacon()
1820
log.Printf(
1921
"Initializing Phase 2:\n"+
20-
"\tLoad Phase 1 from: %s\n"+
21-
"\tLoad R1CS from: %s\n"+
22-
"\tStore Phase 2 to: %s\n"+
23-
"\tStore SRS commons to: %s\n",
24-
25-
phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsFilePath,
22+
"\tLoad Phase 1 from: %s\n"+
23+
"\tLoad R1CS from: %s\n"+
24+
"\tStore Phase 2 to: %s\n"+
25+
"\tStore SRS commons to: %s\n"+
26+
"\tBeacon (pass it to extract-keys): %x\n",
27+
phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsFilePath, beacon,
2628
)
2729
if phase1FilePath == "" || r1csFilePath == "" || outputPhase2FilePath == "" || outputSrsCommonsFilePath == "" {
2830
return fmt.Errorf("one of the required file paths is empty")
2931
}
3032

31-
return phase2.Init(phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsFilePath)
33+
return phase2.Init(
34+
phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsFilePath, beacon,
35+
)
3236
}

cmd/verify.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"context"
5+
"encoding/hex"
56
"fmt"
67
"log"
78

@@ -33,15 +34,20 @@ func Phase2ExtractKeys(_ context.Context, cmd *cli.Command) error {
3334
phase2FilePaths := cmd.StringSlice("phase2")
3435
pkFilePath := cmd.String("pk")
3536
vkFilePath := cmd.String("vk")
37+
beacon, err := hex.DecodeString(cmd.String("beacon"))
38+
if err != nil {
39+
return err
40+
}
3641
log.Printf(
3742
"Verify multiple Phase 2 contributions:\n"+
3843
"\tLoad R1CS from: %s\n"+
39-
"\tLoad SRS commons from: %s\n"+
44+
"\tLoad SRS commons from: %s (beacon: %x)\n"+
4045
"\tLoad Phase 2 from: %s\n"+
4146
"\tStore Proving Key to: %s\n"+
4247
"\tStore Verifying Key to: %s\n",
4348
r1csFilePath,
4449
srsCommonsFilePath,
50+
beacon,
4551
phase2FilePaths,
4652
pkFilePath,
4753
vkFilePath,
@@ -50,5 +56,5 @@ func Phase2ExtractKeys(_ context.Context, cmd *cli.Command) error {
5056
return fmt.Errorf("one of the required file paths is empty")
5157
}
5258

53-
return phase2.ExtractKeys(r1csFilePath, srsCommonsFilePath, phase2FilePaths, pkFilePath, vkFilePath)
59+
return phase2.ExtractKeys(r1csFilePath, srsCommonsFilePath, phase2FilePaths, pkFilePath, vkFilePath, beacon)
5460
}

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ func main() {
122122
" initialization",
123123
Required: true,
124124
},
125+
&cli.StringFlag{
126+
Name: "beacon",
127+
Usage: "Random string generated on the Phase 2 initialization",
128+
Required: true,
129+
},
125130
&cli.StringSliceFlag{
126131
Name: "phase2",
127132
Usage: "List of Phase 2 files to verify the contributions in the order they were\n" +

phase2/phase2.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@ import (
1010

1111
"github.com/reilabs/trusted-setup/phase1"
1212
"github.com/reilabs/trusted-setup/r1cs"
13-
"github.com/reilabs/trusted-setup/randomness"
1413
)
1514

1615
// Init initializes the multi-party computation Phase 2 object based on a serialized Phase 1 and R1CS objects.
1716
//
1817
// The input serialized Phase 1 object is given as phase1FilePath. The input serialized R1CS object is given as r1csFilePath.
19-
// The output Phase 2 object is written to outputPhase2FilePath.
18+
// The random value needed to generate SRS commons is given as beacon.
19+
//
20+
// The output Phase 2 object is written to outputPhase2FilePath, and the SRS commons file is written to outputSrsCommonsPath.
2021
//
2122
// Returns nil on success and error on failure.
2223
func Init(
23-
phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsPath string,
24+
phase1FilePath, r1csFilePath, outputPhase2FilePath, outputSrsCommonsPath string, beacon []byte,
2425
) error {
2526
ccs, err := r1cs.FromFile(r1csFilePath)
2627
if err != nil {
@@ -32,8 +33,8 @@ func Init(
3233
return err
3334
}
3435

35-
log.Printf("Generating SRS commons form Phase 1 (beacon: %x)", randomness.GetBeacon())
36-
srsCommons := p1.Seal(randomness.GetBeacon())
36+
log.Print("Generating SRS commons form Phase 1")
37+
srsCommons := p1.Seal(beacon)
3738
err = SrsCommonsToFile(srsCommons, outputSrsCommonsPath)
3839
if err != nil {
3940
return err
@@ -109,11 +110,15 @@ func Verify(phase2prevFilePath, phase2nextFilePath string) error {
109110
// The constraint system used for Phase 2 initialization and the SRS Commons object being the result if the initialization
110111
// must be provided in the form of file paths.
111112
//
113+
// The random value needed to extract keys from contributions is given as beacon. It must be the same value passed
114+
// to Init when generating SRS that is now being passed to ExtractKeys as srsCommonsFilePath.
115+
//
112116
// The output proving key is written to outputPkFilePath. The output verification key is written to outputVkFilePath.
113117
//
114118
// Returns nil on success and error on failure.
115119
func ExtractKeys(
116120
r1csFilePath, srsCommonsFilePath string, phase2FilePaths []string, outputPkFilePath, outputVkFilePath string,
121+
beacon []byte,
117122
) error {
118123
if len(phase2FilePaths) < 2 {
119124
return fmt.Errorf("at least two phase 2 files must be provided")
@@ -137,8 +142,8 @@ func ExtractKeys(
137142
phase2s = append(phase2s, &p2)
138143
}
139144

140-
log.Printf("Verifying all Phase 2 contributions and generating Keys (beacon: %x)", randomness.GetBeacon())
141-
pk, vk, err := mpcsetup.VerifyPhase2(ccs.(*cs.R1CS), &srsCommons, randomness.GetBeacon(), phase2s...)
145+
log.Print("Verifying all Phase 2 contributions and generating Keys")
146+
pk, vk, err := mpcsetup.VerifyPhase2(ccs.(*cs.R1CS), &srsCommons, beacon, phase2s...)
142147
if err != nil {
143148
return err
144149
}

test/offline_ceremony_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package test
22

33
import (
4+
"bytes"
45
"log"
56
"os"
67
"path/filepath"
@@ -41,6 +42,8 @@ const r1csFileName = "test.r1cs"
4142
const pkFileName = "test.pk"
4243
const vkFileName = "test.vk"
4344

45+
var beacon = bytes.Repeat([]byte{0x42}, 32)
46+
4447
func setup() {
4548
ccs, err := buildCcs()
4649
if err != nil {
@@ -98,7 +101,7 @@ func testPtau(t *testing.T) {
98101
}
99102

100103
func testInit(t *testing.T) {
101-
assert.NoError(t, phase2.Init(phase1FileName, r1csFileName, phase2FileName, srsCommonsFileName))
104+
assert.NoError(t, phase2.Init(phase1FileName, r1csFileName, phase2FileName, srsCommonsFileName, beacon))
102105

103106
p2, err := phase2.FromFile(phase2FileName)
104107
assert.NoError(t, err)
@@ -155,7 +158,7 @@ func testExtractKeys(t *testing.T) {
155158
assert.NoError(
156159
t,
157160
phase2.ExtractKeys(
158-
r1csFileName, srsCommonsFileName, phase2Contributions[1:], pkFileName, vkFileName,
161+
r1csFileName, srsCommonsFileName, phase2Contributions[1:], pkFileName, vkFileName, beacon,
159162
),
160163
)
161164
}

0 commit comments

Comments
 (0)