arnaucube
arnaucube/go-circom-prover-verifierPublic Self-hosted repository
Fix binary parser bug, make go.bin format deterministic
Eduard S eduard@iden3.io
Fri, 22 May 2020 15:39:15 +0200
commit

6e31deb5b830f7ed0cd15afa602f198ea4ecdc52

parent

94dc934f6236840e4ed5896281f6adfb8070cf51

4 files changed, 32 insertions(+), 9 deletions(-)

jump to
A cli/.gitignore

@@ -0,0 +1,1 @@

+cli
M cli/cli.go → cli/cli.go

@@ -159,7 +159,9 @@ pkGBin, err := parsers.PkToGoBin(pk)

if err != nil { return err } - err = ioutil.WriteFile(provingKeyBinPath, pkGBin, 0644) + if err = ioutil.WriteFile(provingKeyBinPath, pkGBin, 0644); err != nil { + return err + } return nil }
M parsers/parsers.go → parsers/parsers.go

@@ -10,6 +10,7 @@ "fmt"

"io" "math/big" "os" + "sort" "strconv" "strings"

@@ -814,9 +815,9 @@ _, err = z.Unmarshal(zb)

if err != nil { return nil, err } - pk.C = append(pk.C, z) // circom behaviour (3x null==["0", "0", "0"]) - pk.C = append(pk.C, z) - pk.C = append(pk.C, z) + for i := 0; i < pk.NPublic+1; i++ { + pk.C = append(pk.C, z) + } for i := pk.NPublic + 1; i < pk.NVars; i++ { b, err = readNBytes(r, 64) if err != nil {

@@ -969,6 +970,15 @@ q,

) } +func sortedKeys(m map[int]*big.Int) []int { + keys := make([]int, 0, len(m)) + for k, _ := range m { + keys = append(keys, k) + } + sort.Ints(keys) + return keys +} + // PkToGoBin converts the ProvingKey (*types.Pk) into binary format defined by // go-circom-prover-verifier. PkGoBin is a own go-circom-prover-verifier // binary format that allows to go faster when parsing.

@@ -1017,7 +1027,8 @@ for i := 0; i < pk.NVars; i++ {

binary.LittleEndian.PutUint32(b[:], uint32(len(pk.PolsA[i]))) r = append(r, b[:]...) o += 4 - for j, v := range pk.PolsA[i] { + for _, j := range sortedKeys(pk.PolsA[i]) { + v := pk.PolsA[i][j] binary.LittleEndian.PutUint32(b[:], uint32(j)) r = append(r, b[:]...) r = append(r, addPadding32(v.Bytes())...)

@@ -1030,7 +1041,8 @@ for i := 0; i < pk.NVars; i++ {

binary.LittleEndian.PutUint32(b[:], uint32(len(pk.PolsB[i]))) r = append(r, b[:]...) o += 4 - for j, v := range pk.PolsB[i] { + for _, j := range sortedKeys(pk.PolsB[i]) { + v := pk.PolsB[i][j] binary.LittleEndian.PutUint32(b[:], uint32(j)) r = append(r, b[:]...) r = append(r, addPadding32(v.Bytes())...)

@@ -1279,9 +1291,9 @@ _, err = z.Unmarshal(zb)

if err != nil { return nil, err } - pk.C = append(pk.C, z) - pk.C = append(pk.C, z) - pk.C = append(pk.C, z) + for i := 0; i < pk.NPublic+1; i++ { + pk.C = append(pk.C, z) + } for i := pk.NPublic + 1; i < pk.NVars; i++ { b, err = readNBytes(r, 64) if err != nil {
M parsers/parsers_test.go → parsers/parsers_test.go

@@ -238,6 +238,10 @@ assert.Equal(t, pkJ.B1, pk.B1)

assert.Equal(t, pkJ.B2, pk.B2) assert.Equal(t, pkJ.C, pk.C) assert.Equal(t, pkJ.HExps[:pkJ.DomainSize], pk.HExps[:pk.DomainSize]) // circom behaviour + + assert.Equal(t, pkJ.NVars, pk.NVars) + assert.Equal(t, pkJ.NPublic, pk.NPublic) + assert.Equal(t, pkJ.DomainSize, pk.DomainSize) } func TestParsePkBin(t *testing.T) {

@@ -274,6 +278,10 @@ assert.Equal(t, pk.C, pkG.C)

assert.Equal(t, pk.HExps, pkG.HExps) assert.Equal(t, pk.PolsA, pkG.PolsA) assert.Equal(t, pk.PolsB, pkG.PolsB) + + assert.Equal(t, pk.NVars, pkG.NVars) + assert.Equal(t, pk.NPublic, pkG.NPublic) + assert.Equal(t, pk.DomainSize, pkG.DomainSize) } func TestGoCircomPkFormat(t *testing.T) {