Skip to content

Commit 1203c6a

Browse files
authored
crypto/bn256: full switchover to cloudflare's code (#16301)
* crypto/bn256: full switchover to cloudflare's code * crypto/bn256: only use cloudflare for optimized architectures * crypto/bn256: upstream fallback for non-optimized code * .travis, build: drop support for Go 1.8 (need type aliases) * crypto/bn256/cloudflare: enable curve mul lattice optimization
1 parent 0965761 commit 1203c6a

22 files changed

+783
-174
lines changed

.travis.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,6 @@ go_import_path: github.com/ethereum/go-ethereum
33
sudo: false
44
matrix:
55
include:
6-
- os: linux
7-
dist: trusty
8-
sudo: required
9-
go: 1.8.x
10-
script:
11-
- sudo modprobe fuse
12-
- sudo chmod 666 /dev/fuse
13-
- sudo chown root:$USER /etc/fuse.conf
14-
- go run build/ci.go install
15-
- go run build/ci.go test -coverage
16-
176
- os: linux
187
dist: trusty
198
sudo: required

build/ci.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -182,13 +182,13 @@ func doInstall(cmdline []string) {
182182
// Check Go version. People regularly open issues about compilation
183183
// failure with outdated Go. This should save them the trouble.
184184
if !strings.Contains(runtime.Version(), "devel") {
185-
// Figure out the minor version number since we can't textually compare (1.10 < 1.8)
185+
// Figure out the minor version number since we can't textually compare (1.10 < 1.9)
186186
var minor int
187187
fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
188188

189-
if minor < 8 {
189+
if minor < 9 {
190190
log.Println("You have Go version", runtime.Version())
191-
log.Println("go-ethereum requires at least Go version 1.8 and cannot")
191+
log.Println("go-ethereum requires at least Go version 1.9 and cannot")
192192
log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
193193
os.Exit(1)
194194
}
@@ -262,16 +262,6 @@ func goTool(subcmd string, args ...string) *exec.Cmd {
262262

263263
func goToolArch(arch string, cc string, subcmd string, args ...string) *exec.Cmd {
264264
cmd := build.GoTool(subcmd, args...)
265-
if subcmd == "build" || subcmd == "install" || subcmd == "test" {
266-
// Go CGO has a Windows linker error prior to 1.8 (https://github.com/golang/go/issues/8756).
267-
// Work around issue by allowing multiple definitions for <1.8 builds.
268-
var minor int
269-
fmt.Sscanf(strings.TrimPrefix(runtime.Version(), "go1."), "%d", &minor)
270-
271-
if runtime.GOOS == "windows" && minor < 8 {
272-
cmd.Args = append(cmd.Args, []string{"-ldflags", "-extldflags -Wl,--allow-multiple-definition"}...)
273-
}
274-
}
275265
cmd.Env = []string{"GOPATH=" + build.GOPATH()}
276266
if arch == "" || arch == runtime.GOARCH {
277267
cmd.Env = append(cmd.Env, "GOBIN="+GOBIN)

crypto/bn256/bn256_other.go renamed to crypto/bn256/bn256_fast.go

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,22 @@
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616

17-
// +build !amd64 appengine gccgo
17+
// +build amd64 arm64
1818

1919
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
2020
package bn256
2121

22-
import (
23-
"math/big"
24-
25-
"github.com/ethereum/go-ethereum/crypto/bn256/google"
26-
)
22+
import "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
2723

2824
// G1 is an abstract cyclic group. The zero value is suitable for use as the
2925
// output of an operation, but cannot be used as an input.
30-
type G1 struct {
31-
bn256.G1
32-
}
33-
34-
// Add sets e to a+b and then returns e.
35-
func (e *G1) Add(a, b *G1) *G1 {
36-
e.G1.Add(&a.G1, &b.G1)
37-
return e
38-
}
39-
40-
// ScalarMult sets e to a*k and then returns e.
41-
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
42-
e.G1.ScalarMult(&a.G1, k)
43-
return e
44-
}
26+
type G1 = bn256.G1
4527

4628
// G2 is an abstract cyclic group. The zero value is suitable for use as the
4729
// output of an operation, but cannot be used as an input.
48-
type G2 struct {
49-
bn256.G2
50-
}
30+
type G2 = bn256.G2
5131

5232
// PairingCheck calculates the Optimal Ate pairing for a set of points.
5333
func PairingCheck(a []*G1, b []*G2) bool {
54-
as := make([]*bn256.G1, len(a))
55-
for i, p := range a {
56-
as[i] = &p.G1
57-
}
58-
bs := make([]*bn256.G2, len(b))
59-
for i, p := range b {
60-
bs[i] = &p.G2
61-
}
62-
return bn256.PairingCheck(as, bs)
34+
return bn256.PairingCheck(a, b)
6335
}

crypto/bn256/bn256_fuzz.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2018 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
// +build gofuzz
18+
19+
package bn256
20+
21+
import (
22+
"bytes"
23+
"math/big"
24+
25+
cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
26+
google "github.com/ethereum/go-ethereum/crypto/bn256/google"
27+
)
28+
29+
// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
30+
func FuzzAdd(data []byte) int {
31+
// Ensure we have enough data in the first place
32+
if len(data) != 128 {
33+
return 0
34+
}
35+
// Ensure both libs can parse the first curve point
36+
xc := new(cloudflare.G1)
37+
_, errc := xc.Unmarshal(data[:64])
38+
39+
xg := new(google.G1)
40+
_, errg := xg.Unmarshal(data[:64])
41+
42+
if (errc == nil) != (errg == nil) {
43+
panic("parse mismatch")
44+
} else if errc != nil {
45+
return 0
46+
}
47+
// Ensure both libs can parse the second curve point
48+
yc := new(cloudflare.G1)
49+
_, errc = yc.Unmarshal(data[64:])
50+
51+
yg := new(google.G1)
52+
_, errg = yg.Unmarshal(data[64:])
53+
54+
if (errc == nil) != (errg == nil) {
55+
panic("parse mismatch")
56+
} else if errc != nil {
57+
return 0
58+
}
59+
// Add the two points and ensure they result in the same output
60+
rc := new(cloudflare.G1)
61+
rc.Add(xc, yc)
62+
63+
rg := new(google.G1)
64+
rg.Add(xg, yg)
65+
66+
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
67+
panic("add mismatch")
68+
}
69+
return 0
70+
}
71+
72+
// FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
73+
// libraries.
74+
func FuzzMul(data []byte) int {
75+
// Ensure we have enough data in the first place
76+
if len(data) != 96 {
77+
return 0
78+
}
79+
// Ensure both libs can parse the curve point
80+
pc := new(cloudflare.G1)
81+
_, errc := pc.Unmarshal(data[:64])
82+
83+
pg := new(google.G1)
84+
_, errg := pg.Unmarshal(data[:64])
85+
86+
if (errc == nil) != (errg == nil) {
87+
panic("parse mismatch")
88+
} else if errc != nil {
89+
return 0
90+
}
91+
// Add the two points and ensure they result in the same output
92+
rc := new(cloudflare.G1)
93+
rc.ScalarMult(pc, new(big.Int).SetBytes(data[64:]))
94+
95+
rg := new(google.G1)
96+
rg.ScalarMult(pg, new(big.Int).SetBytes(data[64:]))
97+
98+
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
99+
panic("scalar mul mismatch")
100+
}
101+
return 0
102+
}
103+
104+
func FuzzPair(data []byte) int {
105+
// Ensure we have enough data in the first place
106+
if len(data) != 192 {
107+
return 0
108+
}
109+
// Ensure both libs can parse the curve point
110+
pc := new(cloudflare.G1)
111+
_, errc := pc.Unmarshal(data[:64])
112+
113+
pg := new(google.G1)
114+
_, errg := pg.Unmarshal(data[:64])
115+
116+
if (errc == nil) != (errg == nil) {
117+
panic("parse mismatch")
118+
} else if errc != nil {
119+
return 0
120+
}
121+
// Ensure both libs can parse the twist point
122+
tc := new(cloudflare.G2)
123+
_, errc = tc.Unmarshal(data[64:])
124+
125+
tg := new(google.G2)
126+
_, errg = tg.Unmarshal(data[64:])
127+
128+
if (errc == nil) != (errg == nil) {
129+
panic("parse mismatch")
130+
} else if errc != nil {
131+
return 0
132+
}
133+
// Pair the two points and ensure thet result in the same output
134+
if cloudflare.PairingCheck([]*cloudflare.G1{pc}, []*cloudflare.G2{tc}) != google.PairingCheck([]*google.G1{pg}, []*google.G2{tg}) {
135+
panic("pair mismatch")
136+
}
137+
return 0
138+
}

crypto/bn256/bn256_amd64.go renamed to crypto/bn256/bn256_slow.go

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,22 @@
1414
// You should have received a copy of the GNU Lesser General Public License
1515
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616

17-
// +build amd64,!appengine,!gccgo
17+
// +build !amd64,!arm64
1818

1919
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
2020
package bn256
2121

22-
import (
23-
"math/big"
24-
25-
"github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
26-
)
22+
import "github.com/ethereum/go-ethereum/crypto/bn256/google"
2723

2824
// G1 is an abstract cyclic group. The zero value is suitable for use as the
2925
// output of an operation, but cannot be used as an input.
30-
type G1 struct {
31-
bn256.G1
32-
}
33-
34-
// Add sets e to a+b and then returns e.
35-
func (e *G1) Add(a, b *G1) *G1 {
36-
e.G1.Add(&a.G1, &b.G1)
37-
return e
38-
}
39-
40-
// ScalarMult sets e to a*k and then returns e.
41-
func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 {
42-
e.G1.ScalarMult(&a.G1, k)
43-
return e
44-
}
26+
type G1 = bn256.G1
4527

4628
// G2 is an abstract cyclic group. The zero value is suitable for use as the
4729
// output of an operation, but cannot be used as an input.
48-
type G2 struct {
49-
bn256.G2
50-
}
30+
type G2 = bn256.G2
5131

5232
// PairingCheck calculates the Optimal Ate pairing for a set of points.
5333
func PairingCheck(a []*G1, b []*G2) bool {
54-
as := make([]*bn256.G1, len(a))
55-
for i, p := range a {
56-
as[i] = &p.G1
57-
}
58-
bs := make([]*bn256.G2, len(b))
59-
for i, p := range b {
60-
bs[i] = &p.G2
61-
}
62-
return bn256.PairingCheck(as, bs)
34+
return bn256.PairingCheck(a, b)
6335
}

crypto/bn256/cloudflare/bn256_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// +build amd64,!appengine,!gccgo
2-
31
package bn256
42

53
import (

crypto/bn256/cloudflare/curve.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,24 @@ func (c *curvePoint) Double(a *curvePoint) {
183183
}
184184

185185
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int) {
186-
sum, t := &curvePoint{}, &curvePoint{}
186+
precomp := [1 << 2]*curvePoint{nil, {}, {}, {}}
187+
precomp[1].Set(a)
188+
precomp[2].Set(a)
189+
gfpMul(&precomp[2].x, &precomp[2].x, xiTo2PSquaredMinus2Over3)
190+
precomp[3].Add(precomp[1], precomp[2])
191+
192+
multiScalar := curveLattice.Multi(scalar)
193+
194+
sum := &curvePoint{}
187195
sum.SetInfinity()
196+
t := &curvePoint{}
188197

189-
for i := scalar.BitLen(); i >= 0; i-- {
198+
for i := len(multiScalar) - 1; i >= 0; i-- {
190199
t.Double(sum)
191-
if scalar.Bit(i) != 0 {
192-
sum.Add(t, a)
193-
} else {
200+
if multiScalar[i] == 0 {
194201
sum.Set(t)
202+
} else {
203+
sum.Add(t, precomp[multiScalar[i]])
195204
}
196205
}
197206
c.Set(sum)

crypto/bn256/cloudflare/example_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build amd64,!appengine,!gccgo
6-
75
package bn256
86

97
import (

crypto/bn256/cloudflare/gfp.h

Lines changed: 0 additions & 32 deletions
This file was deleted.

crypto/bn256/cloudflare/gfp_amd64.go

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)