Skip to content

Commit 66d4dee

Browse files
authored
Add gnark as bls-12-381 backend (#551)
* Add gnark as bls-12-381 backend * Fix lint issues and disable errcheck in bls12381 Errcheck was already not checking other impls * Add equiality check * Fix the test function name * remove gomnd config from golangcilint * Fix comment in gnark/gt.go * Perform correct invocation to appease linter gods --------- Signed-off-by: Jakub Sztandera <[email protected]>
1 parent 23debab commit 66d4dee

File tree

13 files changed

+803
-33
lines changed

13 files changed

+803
-33
lines changed

.golangci.yml

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ linters-settings:
1111
staticcheck:
1212
checks:
1313
- all
14-
- '-SA1019' # Ignore deprecated for now
14+
- "-SA1019" # Ignore deprecated for now
1515
cyclop:
1616
# The maximal code complexity to report.
1717
# Default: 10
@@ -42,23 +42,6 @@ linters-settings:
4242
# Default: 30 (but we recommend 10-20)
4343
min-complexity: 20
4444

45-
gomnd:
46-
# List of function patterns to exclude from analysis.
47-
# Values always ignored: `time.Date`
48-
# Default: []
49-
ignored-functions:
50-
- os.Chmod
51-
- os.Mkdir
52-
- os.MkdirAll
53-
- os.OpenFile
54-
- os.WriteFile
55-
- strconv.FormatFloat
56-
- strconv.FormatInt
57-
- strconv.FormatUint
58-
- strconv.ParseFloat
59-
- strconv.ParseInt
60-
- strconv.ParseUint
61-
6245
govet:
6346
# Enable all analyzers.
6447
# Default: false
@@ -78,7 +61,7 @@ linters-settings:
7861
nolintlint:
7962
# Exclude following linters from requiring an explanation.
8063
# Default: []
81-
allow-no-explanation: [ funlen, gocognit, lll ]
64+
allow-no-explanation: [funlen, gocognit, lll]
8265
# Enable to require an explanation of nonzero length after each nolint directive.
8366
# Default: false
8467
require-explanation: true
@@ -212,7 +195,6 @@ linters:
212195
#- structcheck # [deprecated, replaced by unused] finds unused struct fields
213196
#- varcheck # [deprecated, replaced by unused] finds unused global variables and constants
214197

215-
216198
issues:
217199
# Maximum count of issues with the same text.
218200
# Set to 0 to disable.
@@ -221,13 +203,13 @@ issues:
221203

222204
exclude-rules:
223205
- source: "^//\\s*go:generate\\s"
224-
linters: [ lll ]
206+
linters: [lll]
225207
- source: "(noinspection|TODO)"
226-
linters: [ godot ]
208+
linters: [godot]
227209
- source: "//noinspection"
228-
linters: [ gocritic ]
210+
linters: [gocritic]
229211
- source: "^\\s+if _, ok := err\\.\\([^.]+\\.InternalError\\); ok {"
230-
linters: [ errorlint ]
212+
linters: [errorlint]
231213
- path: ".skeleton"
232214
linters:
233215
- unused
@@ -254,18 +236,18 @@ issues:
254236
text: "unexported-return:"
255237
- linters:
256238
- govet
257-
text: "shadow: declaration of \"err\" shadows declaration"
258-
- path: 'group.go'
239+
text: 'shadow: declaration of "err" shadows declaration'
240+
- path: "group.go"
259241
linters:
260242
- interfacebloat
261-
- path: 'group/edwards25519/scalar.go'
243+
- path: "group/edwards25519/scalar.go"
262244
linters:
263245
- ineffassign
264246
- funlen
265-
- path: 'group/edwards25519/const.go'
247+
- path: "group/edwards25519/const.go"
266248
linters:
267249
- lll
268-
- path: 'group/edwards25519/fe.go'
250+
- path: "group/edwards25519/fe.go"
269251
linters:
270252
- funlen
271253
- path: "share/dkg/pedersen"
@@ -277,7 +259,7 @@ issues:
277259
- path: "group/edwards25519/scalar.go"
278260
linters:
279261
- ineffassign
280-
- path: "pairing/(circl_bls12381|bn254)/."
262+
- path: "pairing/(bls12381|bn254)/."
281263
linters:
282264
- errcheck #TODO: proper error handling
283265
text: "Error return value is not checked"

pairing/bls12381/bls12381_test.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"go.dedis.ch/kyber/v4/internal/test"
1919
"go.dedis.ch/kyber/v4/pairing"
2020
circl "go.dedis.ch/kyber/v4/pairing/bls12381/circl"
21+
"go.dedis.ch/kyber/v4/pairing/bls12381/gnark"
2122
kilic "go.dedis.ch/kyber/v4/pairing/bls12381/kilic"
2223
"go.dedis.ch/kyber/v4/sign/bdn"
2324
"go.dedis.ch/kyber/v4/sign/bls"
@@ -39,6 +40,7 @@ func TestScalarEndianess(t *testing.T) {
3940
suites := []pairing.Suite{
4041
kilic.NewBLS12381Suite(),
4142
circl.NewSuiteBLS12381(),
43+
gnark.NewSuiteBLS12381(),
4244
}
4345

4446
seed := "TestScalarEndianess"
@@ -110,6 +112,16 @@ func TestZKCryptoVectorsG1Compressed(t *testing.T) {
110112
if err != nil && testCaseValid {
111113
panic("Circl: err should be nil")
112114
}
115+
116+
// Test gnark
117+
g3 := gnark.G1Elt{}
118+
err = g3.UnmarshalBinary(byts)
119+
if err == nil && !testCaseValid {
120+
panic("Gnark: err should not be nil")
121+
}
122+
if err != nil && testCaseValid {
123+
panic("Gnark: err should be nil")
124+
}
113125
})
114126
}
115127
}
@@ -157,6 +169,16 @@ func TestZKCryptoVectorsG2Compressed(t *testing.T) {
157169
if err != nil && testCaseValid {
158170
panic("Circl: err should be nil")
159171
}
172+
173+
// Test gnark
174+
g3 := gnark.G2Elt{}
175+
err = g3.UnmarshalBinary(byts)
176+
if err == nil && !testCaseValid {
177+
panic("Gnark: err should not be nil")
178+
}
179+
if err != nil && testCaseValid {
180+
panic("Gnark: err should be nil")
181+
}
160182
})
161183
}
162184
}
@@ -401,6 +423,7 @@ func TestKyberG1(t *testing.T) {
401423
suites := []pairing.Suite{
402424
kilic.NewBLS12381Suite(),
403425
circl.NewSuiteBLS12381(),
426+
gnark.NewSuiteBLS12381(),
404427
}
405428

406429
for _, suite := range suites {
@@ -412,6 +435,7 @@ func TestKyberG2(t *testing.T) {
412435
suites := []pairing.Suite{
413436
kilic.NewBLS12381Suite(),
414437
circl.NewSuiteBLS12381(),
438+
gnark.NewSuiteBLS12381(),
415439
}
416440

417441
for _, suite := range suites {
@@ -423,6 +447,7 @@ func TestKyberPairingG2(t *testing.T) {
423447
suites := []pairing.Suite{
424448
kilic.NewBLS12381Suite(),
425449
circl.NewSuiteBLS12381(),
450+
gnark.NewSuiteBLS12381(),
426451
}
427452

428453
for _, s := range suites {
@@ -450,6 +475,7 @@ func TestRacePairings(_ *testing.T) {
450475
suites := []pairing.Suite{
451476
kilic.NewBLS12381Suite(),
452477
circl.NewSuiteBLS12381(),
478+
gnark.NewSuiteBLS12381(),
453479
}
454480

455481
for _, s := range suites {
@@ -474,6 +500,7 @@ func TestKyberBLSG2(t *testing.T) {
474500
suites := []pairing.Suite{
475501
kilic.NewBLS12381Suite(),
476502
circl.NewSuiteBLS12381(),
503+
gnark.NewSuiteBLS12381(),
477504
}
478505

479506
for _, suite := range suites {
@@ -486,6 +513,7 @@ func TestKyberBLSG1(t *testing.T) {
486513
suites := []pairing.Suite{
487514
kilic.NewBLS12381Suite(),
488515
circl.NewSuiteBLS12381(),
516+
gnark.NewSuiteBLS12381(),
489517
}
490518

491519
for _, suite := range suites {
@@ -498,6 +526,7 @@ func TestKyberThresholdG2(t *testing.T) {
498526
suites := []pairing.Suite{
499527
kilic.NewBLS12381Suite(),
500528
circl.NewSuiteBLS12381(),
529+
gnark.NewSuiteBLS12381(),
501530
}
502531

503532
for _, suite := range suites {
@@ -510,6 +539,7 @@ func TestKyberThresholdG1(t *testing.T) {
510539
suites := []pairing.Suite{
511540
kilic.NewBLS12381Suite(),
512541
circl.NewSuiteBLS12381(),
542+
gnark.NewSuiteBLS12381(),
513543
}
514544

515545
for _, suite := range suites {
@@ -522,6 +552,7 @@ func TestIsValidGroup(t *testing.T) {
522552
suites := []pairing.Suite{
523553
kilic.NewBLS12381Suite(),
524554
circl.NewSuiteBLS12381(),
555+
gnark.NewSuiteBLS12381(),
525556
}
526557

527558
for _, suite := range suites {
@@ -550,6 +581,7 @@ func TestBasicPairing(t *testing.T) {
550581
suites := []pairing.Suite{
551582
kilic.NewBLS12381Suite(),
552583
circl.NewSuiteBLS12381(),
584+
gnark.NewSuiteBLS12381(),
553585
}
554586

555587
for _, suite := range suites {
@@ -602,6 +634,7 @@ func BenchmarkPairingSeparate(bb *testing.B) {
602634
var suites = []pairing.Suite{
603635
kilic.NewBLS12381Suite(),
604636
circl.NewSuiteBLS12381(),
637+
gnark.NewSuiteBLS12381(),
605638
}
606639

607640
for _, s := range suites {
@@ -631,6 +664,7 @@ func BenchmarkPairingInv(bb *testing.B) {
631664
var suites = []pairing.Suite{
632665
kilic.NewBLS12381Suite(),
633666
circl.NewSuiteBLS12381(),
667+
gnark.NewSuiteBLS12381(),
634668
}
635669

636670
for _, s := range suites {
@@ -658,7 +692,7 @@ func BenchmarkPairingInv(bb *testing.B) {
658692
var (
659693
dataSize = 32
660694
numSigs = []int{1, 10, 100, 1000, 10000}
661-
curveOptions = []string{"kilic", "circl"}
695+
curveOptions = []string{"kilic", "circl", "gnark"}
662696
)
663697

664698
// Used to avoid compiler optimizations
@@ -672,9 +706,12 @@ func BenchmarkKilic(b *testing.B) {
672706
func BenchmarkCircl(b *testing.B) {
673707
BDNBenchmark(b, "circl")
674708
}
709+
func BenchmarkGnark(b *testing.B) {
710+
BDNBenchmark(b, "gnark")
711+
}
712+
713+
func BDNBenchmark(b *testing.B, curveOption string) { //nolint: gocyclo,cyclop // breaking this down doesn't make sense
675714

676-
//nolint: gocyclo,cyclop // breaking this down doesn't make sense
677-
func BDNBenchmark(b *testing.B, curveOption string) {
678715
b.Logf("----------------------")
679716
b.Logf("Payload to sign: %d bytes\n", dataSize)
680717
b.Logf("Numbers of signatures: %v\n", numSigs)
@@ -698,6 +735,8 @@ func BDNBenchmark(b *testing.B, curveOption string) {
698735
suite = kilic.NewBLS12381Suite()
699736
case "circl":
700737
suite = circl.NewSuiteBLS12381()
738+
case "gnark":
739+
suite = gnark.NewSuiteBLS12381()
701740
default:
702741
panic(fmt.Errorf("invalid curve option: %s", curveOption))
703742
}

pairing/bls12381/gnark/adapter.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package gnark
2+
3+
import (
4+
"go.dedis.ch/kyber/v4"
5+
)
6+
7+
// SuiteBLS12381 is an adapter that implements the suites.Suite interface so that
8+
// bls12381 can be used as a common suite to generate key pairs for instance but
9+
// still preserves the properties of the pairing (e.g. the Pair function).
10+
//
11+
// It's important to note that the Point function will generate a point
12+
// compatible with public keys only (group G2) where the signature must be
13+
// used as a point from the group G1.
14+
type SuiteBLS12381 struct {
15+
Suite
16+
kyber.Group
17+
}
18+
19+
// NewSuiteBLS12381 makes a new BN256 suite
20+
func NewSuiteBLS12381() *SuiteBLS12381 {
21+
return &SuiteBLS12381{}
22+
}
23+
24+
// Point generates a point from the G2 group that can only be used
25+
// for public keys
26+
func (s *SuiteBLS12381) Point() kyber.Point {
27+
return s.G2().Point()
28+
}
29+
30+
// PointLen returns the length of a G2 point
31+
func (s *SuiteBLS12381) PointLen() int {
32+
return s.G2().PointLen()
33+
}
34+
35+
// Scalar generates a scalar
36+
func (s *SuiteBLS12381) Scalar() kyber.Scalar {
37+
return s.G1().Scalar()
38+
}
39+
40+
// ScalarLen returns the length of a scalar
41+
func (s *SuiteBLS12381) ScalarLen() int {
42+
return s.G1().ScalarLen()
43+
}
44+
45+
// String returns the name of the suite
46+
func (s *SuiteBLS12381) String() string {
47+
return "gnark.adapter"
48+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package gnark
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
"go.dedis.ch/kyber/v4/util/key"
8+
)
9+
10+
func TestAdapter_SuiteBLS12381(t *testing.T) {
11+
suite := NewSuiteBLS12381()
12+
13+
pair := key.NewKeyPair(suite)
14+
pubkey, err := pair.Public.MarshalBinary()
15+
require.Nil(t, err)
16+
privkey, err := pair.Private.MarshalBinary()
17+
require.Nil(t, err)
18+
19+
pubhex := suite.Point()
20+
err = pubhex.UnmarshalBinary(pubkey)
21+
require.Nil(t, err)
22+
require.True(t, pair.Public.Equal(pubhex))
23+
24+
privhex := suite.Scalar()
25+
err = privhex.UnmarshalBinary(privkey)
26+
require.Nil(t, err)
27+
require.True(t, pair.Private.Equal(privhex))
28+
29+
require.Equal(t, "gnark.adapter", suite.String())
30+
}

0 commit comments

Comments
 (0)