From 4ff9cb51823cf218d0db6011b89f94bec6128f5b Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Tue, 1 Jun 2021 21:41:32 -0500 Subject: [PATCH 1/9] feat: added element_fuzz.go with build tag gofuzz to expose non-asm (generic) impl for fuzz testing --- ecc/bls12-377/fp/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bls12-377/fr/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bls12-381/fp/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bls12-381/fr/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bn254/fp/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bn254/fr/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bw6-761/fp/element_fuzz.go | 54 ++++++++++++++++++++++++ ecc/bw6-761/fr/element_fuzz.go | 54 ++++++++++++++++++++++++ field/generator/generator.go | 17 ++++++-- field/internal/templates/element/fuzz.go | 42 ++++++++++++++++++ 10 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 ecc/bls12-377/fp/element_fuzz.go create mode 100644 ecc/bls12-377/fr/element_fuzz.go create mode 100644 ecc/bls12-381/fp/element_fuzz.go create mode 100644 ecc/bls12-381/fr/element_fuzz.go create mode 100644 ecc/bn254/fp/element_fuzz.go create mode 100644 ecc/bn254/fr/element_fuzz.go create mode 100644 ecc/bw6-761/fp/element_fuzz.go create mode 100644 ecc/bw6-761/fr/element_fuzz.go create mode 100644 field/internal/templates/element/fuzz.go diff --git a/ecc/bls12-377/fp/element_fuzz.go b/ecc/bls12-377/fp/element_fuzz.go new file mode 100644 index 000000000..0ed04dbb0 --- /dev/null +++ b/ecc/bls12-377/fp/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bls12-377/fr/element_fuzz.go b/ecc/bls12-377/fr/element_fuzz.go new file mode 100644 index 000000000..1b0c32ac8 --- /dev/null +++ b/ecc/bls12-377/fr/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bls12-381/fp/element_fuzz.go b/ecc/bls12-381/fp/element_fuzz.go new file mode 100644 index 000000000..0ed04dbb0 --- /dev/null +++ b/ecc/bls12-381/fp/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bls12-381/fr/element_fuzz.go b/ecc/bls12-381/fr/element_fuzz.go new file mode 100644 index 000000000..1b0c32ac8 --- /dev/null +++ b/ecc/bls12-381/fr/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bn254/fp/element_fuzz.go b/ecc/bn254/fp/element_fuzz.go new file mode 100644 index 000000000..0ed04dbb0 --- /dev/null +++ b/ecc/bn254/fp/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bn254/fr/element_fuzz.go b/ecc/bn254/fr/element_fuzz.go new file mode 100644 index 000000000..1b0c32ac8 --- /dev/null +++ b/ecc/bn254/fr/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bw6-761/fp/element_fuzz.go b/ecc/bw6-761/fp/element_fuzz.go new file mode 100644 index 000000000..0ed04dbb0 --- /dev/null +++ b/ecc/bw6-761/fp/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fp + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/ecc/bw6-761/fr/element_fuzz.go b/ecc/bw6-761/fr/element_fuzz.go new file mode 100644 index 000000000..1b0c32ac8 --- /dev/null +++ b/ecc/bw6-761/fr/element_fuzz.go @@ -0,0 +1,54 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fr + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z, x, y *Element) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *Element) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *Element) { + _addGeneric(z, x, y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *Element) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *Element) { + _subGeneric(z, x, y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *Element) { + _negGeneric(z, x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *Element) { + _reduceGeneric(z) +} diff --git a/field/generator/generator.go b/field/generator/generator.go index a460c321c..86e9fd97a 100644 --- a/field/generator/generator.go +++ b/field/generator/generator.go @@ -26,7 +26,7 @@ import ( // generator.GenerateFF(fp, filepath.Join(baseDir, "fp")) func GenerateFF(F *field.Field, outputDir string) error { // source file templates - src := []string{ + sourceFiles := []string{ element.Base, element.Reduce, element.Exp, @@ -38,7 +38,7 @@ func GenerateFF(F *field.Field, outputDir string) error { } // test file templates - tst := []string{ + testFiles := []string{ element.MulCIOS, element.MulNoCarry, element.Reduce, @@ -51,6 +51,7 @@ func GenerateFF(F *field.Field, outputDir string) error { pathSrc := filepath.Join(outputDir, eName+".go") pathSrcArith := filepath.Join(outputDir, "arith.go") pathTest := filepath.Join(outputDir, eName+"_test.go") + pathFuzz := filepath.Join(outputDir, eName+"_fuzz.go") // remove old format generated files oldFiles := []string{"_mul.go", "_mul_amd64.go", @@ -67,7 +68,7 @@ func GenerateFF(F *field.Field, outputDir string) error { } // generate source file - if err := bavard.GenerateFromString(pathSrc, src, F, bavardOpts...); err != nil { + if err := bavard.GenerateFromString(pathSrc, sourceFiles, F, bavardOpts...); err != nil { return err } // generate arithmetics source file @@ -75,8 +76,16 @@ func GenerateFF(F *field.Field, outputDir string) error { return err } + // generate fuzz file + bopts := make([]func(*bavard.Bavard) error, len(bavardOpts)) + copy(bopts, bavardOpts) + bopts = append(bopts, bavard.BuildTag("gofuzz")) + if err := bavard.GenerateFromString(pathFuzz, []string{element.Fuzz}, F, bopts...); err != nil { + return err + } + // generate test file - if err := bavard.GenerateFromString(pathTest, tst, F, bavardOpts...); err != nil { + if err := bavard.GenerateFromString(pathTest, testFiles, F, bavardOpts...); err != nil { return err } diff --git a/field/internal/templates/element/fuzz.go b/field/internal/templates/element/fuzz.go new file mode 100644 index 000000000..8e9e01d77 --- /dev/null +++ b/field/internal/templates/element/fuzz.go @@ -0,0 +1,42 @@ +package element + +// Fuzz when build tag is provided, we expose Generic methods to be used by ecc/ package fuzzing functions +const Fuzz = ` + +// MulGeneric is a wrapper exposed and used for fuzzing purposes only +func MulGeneric(z,x,y *{{.ElementName}}) { + _mulGeneric(z, x, y) +} + +// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only +func FromMontGeneric(z *{{.ElementName}}) { + _fromMontGeneric(z) +} + +// AddGeneric is a wrapper exposed and used for fuzzing purposes only +func AddGeneric(z, x, y *{{.ElementName}}) { + _addGeneric(z, x,y) +} + +// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only +func DoubleGeneric(z, x *{{.ElementName}}) { + _doubleGeneric(z, x) +} + +// SubGeneric is a wrapper exposed and used for fuzzing purposes only +func SubGeneric(z, x, y *{{.ElementName}}) { + _subGeneric(z,x,y) +} + +// NegGeneric is a wrapper exposed and used for fuzzing purposes only +func NegGeneric(z, x *{{.ElementName}}) { + _negGeneric(z,x) +} + +// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only +func ReduceGeneric(z *{{.ElementName}}) { + _reduceGeneric(z) +} + + +` From 80de0e15726419e9a0222d84720761a748028192 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Tue, 1 Jun 2021 21:58:43 -0500 Subject: [PATCH 2/9] feat: added curve level go-fuzz fuzz function --- ecc/bls12-377/fuzz.go | 72 +++++++++++++++++++ ecc/bls12-377/fuzz_test.go | 57 +++++++++++++++ ecc/bls12-381/fuzz.go | 72 +++++++++++++++++++ ecc/bls12-381/fuzz_test.go | 57 +++++++++++++++ ecc/bn254/fuzz.go | 72 +++++++++++++++++++ ecc/bn254/fuzz_test.go | 57 +++++++++++++++ ecc/bw6-761/fuzz.go | 72 +++++++++++++++++++ ecc/bw6-761/fuzz_test.go | 57 +++++++++++++++ internal/generator/ecc/generate.go | 9 +++ internal/generator/ecc/template/fuzz.go.tmpl | 61 ++++++++++++++++ .../generator/ecc/template/tests/fuzz.go.tmpl | 37 ++++++++++ 11 files changed, 623 insertions(+) create mode 100644 ecc/bls12-377/fuzz.go create mode 100644 ecc/bls12-377/fuzz_test.go create mode 100644 ecc/bls12-381/fuzz.go create mode 100644 ecc/bls12-381/fuzz_test.go create mode 100644 ecc/bn254/fuzz.go create mode 100644 ecc/bn254/fuzz_test.go create mode 100644 ecc/bw6-761/fuzz.go create mode 100644 ecc/bw6-761/fuzz_test.go create mode 100644 internal/generator/ecc/template/fuzz.go.tmpl create mode 100644 internal/generator/ecc/template/tests/fuzz.go.tmpl diff --git a/ecc/bls12-377/fuzz.go b/ecc/bls12-377/fuzz.go new file mode 100644 index 000000000..e602e4e20 --- /dev/null +++ b/ecc/bls12-377/fuzz.go @@ -0,0 +1,72 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls12377 + +import ( + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton + // in assembly and generic impl + middle := len(data) / 2 + // fr.Element + { + var a, b, c fr.Element + var _a, _b, _c fr.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fr.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bls12-377/fr") + } + } + + // fp.Element + { + var a, b, c fp.Element + var _a, _b, _c fp.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fp.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bls12-377/fp") + } + } + + return fuzzNormal + +} diff --git a/ecc/bls12-377/fuzz_test.go b/ecc/bls12-377/fuzz_test.go new file mode 100644 index 000000000..fb140b15d --- /dev/null +++ b/ecc/bls12-377/fuzz_test.go @@ -0,0 +1,57 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls12377 + +import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "io" + "math/rand" + "testing" + "time" +) + +func TestCSFuzzed(t *testing.T) { + const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + if Fuzz(bytes[:i]) != fuzzNormal { + t.Fatal("bls12-377 fuzz failed") + } + } + } + +} diff --git a/ecc/bls12-381/fuzz.go b/ecc/bls12-381/fuzz.go new file mode 100644 index 000000000..93fe48cd7 --- /dev/null +++ b/ecc/bls12-381/fuzz.go @@ -0,0 +1,72 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls12381 + +import ( + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton + // in assembly and generic impl + middle := len(data) / 2 + // fr.Element + { + var a, b, c fr.Element + var _a, _b, _c fr.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fr.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bls12-381/fr") + } + } + + // fp.Element + { + var a, b, c fp.Element + var _a, _b, _c fp.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fp.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bls12-381/fp") + } + } + + return fuzzNormal + +} diff --git a/ecc/bls12-381/fuzz_test.go b/ecc/bls12-381/fuzz_test.go new file mode 100644 index 000000000..838dc553d --- /dev/null +++ b/ecc/bls12-381/fuzz_test.go @@ -0,0 +1,57 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bls12381 + +import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "io" + "math/rand" + "testing" + "time" +) + +func TestCSFuzzed(t *testing.T) { + const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + if Fuzz(bytes[:i]) != fuzzNormal { + t.Fatal("bls12-381 fuzz failed") + } + } + } + +} diff --git a/ecc/bn254/fuzz.go b/ecc/bn254/fuzz.go new file mode 100644 index 000000000..452eb59c3 --- /dev/null +++ b/ecc/bn254/fuzz.go @@ -0,0 +1,72 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bn254 + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton + // in assembly and generic impl + middle := len(data) / 2 + // fr.Element + { + var a, b, c fr.Element + var _a, _b, _c fr.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fr.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bn254/fr") + } + } + + // fp.Element + { + var a, b, c fp.Element + var _a, _b, _c fp.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fp.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bn254/fp") + } + } + + return fuzzNormal + +} diff --git a/ecc/bn254/fuzz_test.go b/ecc/bn254/fuzz_test.go new file mode 100644 index 000000000..d6fa8f5c7 --- /dev/null +++ b/ecc/bn254/fuzz_test.go @@ -0,0 +1,57 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bn254 + +import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "io" + "math/rand" + "testing" + "time" +) + +func TestCSFuzzed(t *testing.T) { + const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + if Fuzz(bytes[:i]) != fuzzNormal { + t.Fatal("bn254 fuzz failed") + } + } + } + +} diff --git a/ecc/bw6-761/fuzz.go b/ecc/bw6-761/fuzz.go new file mode 100644 index 000000000..4c5054d8c --- /dev/null +++ b/ecc/bw6-761/fuzz.go @@ -0,0 +1,72 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bw6761 + +import ( + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton + // in assembly and generic impl + middle := len(data) / 2 + // fr.Element + { + var a, b, c fr.Element + var _a, _b, _c fr.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fr.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bw6-761/fr") + } + } + + // fp.Element + { + var a, b, c fp.Element + var _a, _b, _c fp.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fp.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on bw6-761/fp") + } + } + + return fuzzNormal + +} diff --git a/ecc/bw6-761/fuzz_test.go b/ecc/bw6-761/fuzz_test.go new file mode 100644 index 000000000..df243696c --- /dev/null +++ b/ecc/bw6-761/fuzz_test.go @@ -0,0 +1,57 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package bw6761 + +import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "io" + "math/rand" + "testing" + "time" +) + +func TestCSFuzzed(t *testing.T) { + const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + if Fuzz(bytes[:i]) != fuzzNormal { + t.Fatal("bw6-761 fuzz failed") + } + } + } + +} diff --git a/internal/generator/ecc/generate.go b/internal/generator/ecc/generate.go index 8cd38585c..6b887a4ef 100644 --- a/internal/generator/ecc/generate.go +++ b/internal/generator/ecc/generate.go @@ -26,6 +26,15 @@ func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) er return err } + // fuzz testing + entries = []bavard.Entry{ + {File: filepath.Join(baseDir, "fuzz.go"), Templates: []string{"fuzz.go.tmpl"}, BuildTag: "gofuzz"}, + {File: filepath.Join(baseDir, "fuzz_test.go"), Templates: []string{"tests/fuzz.go.tmpl"}, BuildTag: "gofuzz"}, + } + if err := bgen.Generate(conf, packageName, "./ecc/template", entries...); err != nil { + return err + } + // G1 entries = []bavard.Entry{ {File: filepath.Join(baseDir, "g1.go"), Templates: []string{"point.go.tmpl"}}, diff --git a/internal/generator/ecc/template/fuzz.go.tmpl b/internal/generator/ecc/template/fuzz.go.tmpl new file mode 100644 index 000000000..a0830bfd3 --- /dev/null +++ b/internal/generator/ecc/template/fuzz.go.tmpl @@ -0,0 +1,61 @@ +{{ $G1TAffine := print (toUpper .G1.PointName) "Affine" }} +{{ $G1TJacobian := print (toUpper .G1.PointName) "Jac" }} +{{ $G1TJacobianExtended := print (toLower .G1.PointName) "JacExtended" }} + +{{ $G2TAffine := print (toUpper .G2.PointName) "Affine" }} +{{ $G2TJacobian := print (toUpper .G2.PointName) "Jac" }} +{{ $G2TJacobianExtended := print (toLower .G2.PointName) "JacExtended" }} + + +import ( + "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" + "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton + // in assembly and generic impl + middle := len(data) / 2 + // fr.Element + { + var a, b, c fr.Element + var _a, _b, _c fr.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fr.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on {{.Name}}/fr") + } + } + + // fp.Element + { + var a, b, c fp.Element + var _a, _b, _c fp.Element + a.SetBytes(data[:middle]) + _a.SetBytes(data[:middle]) + b.SetBytes(data[middle:]) + _b.SetBytes(data[middle:]) + + c.Mul(&a, &b) + fp.MulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on {{.Name}}/fp") + } + } + + return fuzzNormal + +} \ No newline at end of file diff --git a/internal/generator/ecc/template/tests/fuzz.go.tmpl b/internal/generator/ecc/template/tests/fuzz.go.tmpl new file mode 100644 index 000000000..673d0e031 --- /dev/null +++ b/internal/generator/ecc/template/tests/fuzz.go.tmpl @@ -0,0 +1,37 @@ +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" + "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" + "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" +) + +func TestCSFuzzed(t *testing.T) { + const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + if Fuzz(bytes[:i]) != fuzzNormal { + t.Fatal("{{.Name}} fuzz failed") + } + } + } + +} \ No newline at end of file From 56ec31c0460d08ed177c445a527b39d27223619e Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Wed, 2 Jun 2021 15:26:56 -0500 Subject: [PATCH 3/9] feat: added Fuzz() for fft pacakge --- ecc/bls12-377/fp/element_fuzz.go | 147 ++++++++++--- ecc/bls12-377/fr/element_fuzz.go | 131 +++++++++--- ecc/bls12-377/fr/fft/fuzz.go | 70 +++++++ ecc/bls12-377/fr/fft/fuzz_test.go | 53 +++++ ecc/bls12-377/fuzz.go | 40 +--- ecc/bls12-377/fuzz_test.go | 6 +- ecc/bls12-381/fp/element_fuzz.go | 147 ++++++++++--- ecc/bls12-381/fr/element_fuzz.go | 131 +++++++++--- ecc/bls12-381/fr/fft/fuzz.go | 70 +++++++ ecc/bls12-381/fr/fft/fuzz_test.go | 53 +++++ ecc/bls12-381/fuzz.go | 40 +--- ecc/bls12-381/fuzz_test.go | 6 +- ecc/bn254/fp/element_fuzz.go | 131 +++++++++--- ecc/bn254/fr/element_fuzz.go | 131 +++++++++--- ecc/bn254/fr/fft/fuzz.go | 70 +++++++ ecc/bn254/fr/fft/fuzz_test.go | 53 +++++ ecc/bn254/fuzz.go | 40 +--- ecc/bn254/fuzz_test.go | 6 +- ecc/bw6-761/fp/element_fuzz.go | 195 +++++++++++++++--- ecc/bw6-761/fr/element_fuzz.go | 147 ++++++++++--- ecc/bw6-761/fr/fft/fuzz.go | 70 +++++++ ecc/bw6-761/fr/fft/fuzz_test.go | 53 +++++ ecc/bw6-761/fuzz.go | 40 +--- ecc/bw6-761/fuzz_test.go | 6 +- field/internal/templates/element/fuzz.go | 121 ++++++++--- internal/generator/ecc/template/fuzz.go.tmpl | 40 +--- .../generator/ecc/template/tests/fuzz.go.tmpl | 6 +- internal/generator/fft/generate.go | 2 + internal/generator/fft/template/fuzz.go.tmpl | 50 +++++ .../generator/fft/template/tests/fuzz.go.tmpl | 33 +++ 30 files changed, 1652 insertions(+), 436 deletions(-) create mode 100644 ecc/bls12-377/fr/fft/fuzz.go create mode 100644 ecc/bls12-377/fr/fft/fuzz_test.go create mode 100644 ecc/bls12-381/fr/fft/fuzz.go create mode 100644 ecc/bls12-381/fr/fft/fuzz_test.go create mode 100644 ecc/bn254/fr/fft/fuzz.go create mode 100644 ecc/bn254/fr/fft/fuzz_test.go create mode 100644 ecc/bw6-761/fr/fft/fuzz.go create mode 100644 ecc/bw6-761/fr/fft/fuzz_test.go create mode 100644 internal/generator/fft/template/fuzz.go.tmpl create mode 100644 internal/generator/fft/template/tests/fuzz.go.tmpl diff --git a/ecc/bls12-377/fp/element_fuzz.go b/ecc/bls12-377/fp/element_fuzz.go index 0ed04dbb0..89f191b6a 100644 --- a/ecc/bls12-377/fp/element_fuzz.go +++ b/ecc/bls12-377/fp/element_fuzz.go @@ -18,37 +18,134 @@ package fp -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[5] %= qElement[5] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + z[4], b = bits.Sub64(z[4], qElement[4], b) + z[5], b = bits.Sub64(z[5], qElement[5], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[5] > qElement[5] { + return true + } + if z[5] < qElement[5] { + return false + } + + if z[4] > qElement[4] { + return true + } + if z[4] < qElement[4] { + return false + } + + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bls12-377/fr/element_fuzz.go b/ecc/bls12-377/fr/element_fuzz.go index 1b0c32ac8..e8604bb0b 100644 --- a/ecc/bls12-377/fr/element_fuzz.go +++ b/ecc/bls12-377/fr/element_fuzz.go @@ -18,37 +18,118 @@ package fr -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[3] %= qElement[3] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bls12-377/fr/fft/fuzz.go b/ecc/bls12-377/fr/fft/fuzz.go new file mode 100644 index 000000000..684aa9b72 --- /dev/null +++ b/ecc/bls12-377/fr/fft/fuzz.go @@ -0,0 +1,70 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "bytes" + "fmt" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + r := bytes.NewReader(data) + + // random polynomial + size := len(data) / 8 + if size == 0 { + return fuzzDiscard + } + if size > (1 << 15) { + size = 1 << 15 + } + paddedSize := nextPowerOfTwo(uint64(size)) + p1 := make([]fr.Element, paddedSize) + p2 := make([]fr.Element, paddedSize) + for i := 0; i < len(p1); i++ { + p1[i].SetRawBytes(r) + } + copy(p2, p1) + + // fft domain + domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) + domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + + // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, 0) + domainWOPrecompute.FFTInverse(p1, DIF, 0) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } + } + + return fuzzNormal +} diff --git a/ecc/bls12-377/fr/fft/fuzz_test.go b/ecc/bls12-377/fr/fft/fuzz_test.go new file mode 100644 index 000000000..7ece24c90 --- /dev/null +++ b/ecc/bls12-377/fr/fft/fuzz_test.go @@ -0,0 +1,53 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bls12-377/fuzz.go b/ecc/bls12-377/fuzz.go index e602e4e20..54c885ce3 100644 --- a/ecc/bls12-377/fuzz.go +++ b/ecc/bls12-377/fuzz.go @@ -30,43 +30,7 @@ const ( ) func Fuzz(data []byte) int { - // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton - // in assembly and generic impl - middle := len(data) / 2 - // fr.Element - { - var a, b, c fr.Element - var _a, _b, _c fr.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fr.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bls12-377/fr") - } - } - - // fp.Element - { - var a, b, c fp.Element - var _a, _b, _c fp.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fp.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bls12-377/fp") - } - } - + fr.Fuzz(data) + fp.Fuzz(data) return fuzzNormal - } diff --git a/ecc/bls12-377/fuzz_test.go b/ecc/bls12-377/fuzz_test.go index fb140b15d..9078e334b 100644 --- a/ecc/bls12-377/fuzz_test.go +++ b/ecc/bls12-377/fuzz_test.go @@ -28,7 +28,7 @@ import ( "time" ) -func TestCSFuzzed(t *testing.T) { +func TestFuzz(t *testing.T) { const maxBytes = (fp.Bytes + fr.Bytes) * 2 const testCount = 7 var bytes [maxBytes]byte @@ -48,9 +48,7 @@ func TestCSFuzzed(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - if Fuzz(bytes[:i]) != fuzzNormal { - t.Fatal("bls12-377 fuzz failed") - } + Fuzz(bytes[:i]) } } diff --git a/ecc/bls12-381/fp/element_fuzz.go b/ecc/bls12-381/fp/element_fuzz.go index 0ed04dbb0..89f191b6a 100644 --- a/ecc/bls12-381/fp/element_fuzz.go +++ b/ecc/bls12-381/fp/element_fuzz.go @@ -18,37 +18,134 @@ package fp -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[5] %= qElement[5] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + z[4], b = bits.Sub64(z[4], qElement[4], b) + z[5], b = bits.Sub64(z[5], qElement[5], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[5] > qElement[5] { + return true + } + if z[5] < qElement[5] { + return false + } + + if z[4] > qElement[4] { + return true + } + if z[4] < qElement[4] { + return false + } + + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bls12-381/fr/element_fuzz.go b/ecc/bls12-381/fr/element_fuzz.go index 1b0c32ac8..e8604bb0b 100644 --- a/ecc/bls12-381/fr/element_fuzz.go +++ b/ecc/bls12-381/fr/element_fuzz.go @@ -18,37 +18,118 @@ package fr -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[3] %= qElement[3] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bls12-381/fr/fft/fuzz.go b/ecc/bls12-381/fr/fft/fuzz.go new file mode 100644 index 000000000..bcc512fde --- /dev/null +++ b/ecc/bls12-381/fr/fft/fuzz.go @@ -0,0 +1,70 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "bytes" + "fmt" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + r := bytes.NewReader(data) + + // random polynomial + size := len(data) / 8 + if size == 0 { + return fuzzDiscard + } + if size > (1 << 15) { + size = 1 << 15 + } + paddedSize := nextPowerOfTwo(uint64(size)) + p1 := make([]fr.Element, paddedSize) + p2 := make([]fr.Element, paddedSize) + for i := 0; i < len(p1); i++ { + p1[i].SetRawBytes(r) + } + copy(p2, p1) + + // fft domain + domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) + domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + + // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, 0) + domainWOPrecompute.FFTInverse(p1, DIF, 0) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } + } + + return fuzzNormal +} diff --git a/ecc/bls12-381/fr/fft/fuzz_test.go b/ecc/bls12-381/fr/fft/fuzz_test.go new file mode 100644 index 000000000..7ece24c90 --- /dev/null +++ b/ecc/bls12-381/fr/fft/fuzz_test.go @@ -0,0 +1,53 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bls12-381/fuzz.go b/ecc/bls12-381/fuzz.go index 93fe48cd7..2d66f91dc 100644 --- a/ecc/bls12-381/fuzz.go +++ b/ecc/bls12-381/fuzz.go @@ -30,43 +30,7 @@ const ( ) func Fuzz(data []byte) int { - // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton - // in assembly and generic impl - middle := len(data) / 2 - // fr.Element - { - var a, b, c fr.Element - var _a, _b, _c fr.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fr.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bls12-381/fr") - } - } - - // fp.Element - { - var a, b, c fp.Element - var _a, _b, _c fp.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fp.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bls12-381/fp") - } - } - + fr.Fuzz(data) + fp.Fuzz(data) return fuzzNormal - } diff --git a/ecc/bls12-381/fuzz_test.go b/ecc/bls12-381/fuzz_test.go index 838dc553d..1a9f4d006 100644 --- a/ecc/bls12-381/fuzz_test.go +++ b/ecc/bls12-381/fuzz_test.go @@ -28,7 +28,7 @@ import ( "time" ) -func TestCSFuzzed(t *testing.T) { +func TestFuzz(t *testing.T) { const maxBytes = (fp.Bytes + fr.Bytes) * 2 const testCount = 7 var bytes [maxBytes]byte @@ -48,9 +48,7 @@ func TestCSFuzzed(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - if Fuzz(bytes[:i]) != fuzzNormal { - t.Fatal("bls12-381 fuzz failed") - } + Fuzz(bytes[:i]) } } diff --git a/ecc/bn254/fp/element_fuzz.go b/ecc/bn254/fp/element_fuzz.go index 0ed04dbb0..c56f81687 100644 --- a/ecc/bn254/fp/element_fuzz.go +++ b/ecc/bn254/fp/element_fuzz.go @@ -18,37 +18,118 @@ package fp -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[3] %= qElement[3] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bn254/fr/element_fuzz.go b/ecc/bn254/fr/element_fuzz.go index 1b0c32ac8..e8604bb0b 100644 --- a/ecc/bn254/fr/element_fuzz.go +++ b/ecc/bn254/fr/element_fuzz.go @@ -18,37 +18,118 @@ package fr -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[3] %= qElement[3] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bn254/fr/fft/fuzz.go b/ecc/bn254/fr/fft/fuzz.go new file mode 100644 index 000000000..063f1e7ec --- /dev/null +++ b/ecc/bn254/fr/fft/fuzz.go @@ -0,0 +1,70 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "bytes" + "fmt" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + r := bytes.NewReader(data) + + // random polynomial + size := len(data) / 8 + if size == 0 { + return fuzzDiscard + } + if size > (1 << 15) { + size = 1 << 15 + } + paddedSize := nextPowerOfTwo(uint64(size)) + p1 := make([]fr.Element, paddedSize) + p2 := make([]fr.Element, paddedSize) + for i := 0; i < len(p1); i++ { + p1[i].SetRawBytes(r) + } + copy(p2, p1) + + // fft domain + domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) + domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + + // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, 0) + domainWOPrecompute.FFTInverse(p1, DIF, 0) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } + } + + return fuzzNormal +} diff --git a/ecc/bn254/fr/fft/fuzz_test.go b/ecc/bn254/fr/fft/fuzz_test.go new file mode 100644 index 000000000..7ece24c90 --- /dev/null +++ b/ecc/bn254/fr/fft/fuzz_test.go @@ -0,0 +1,53 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bn254/fuzz.go b/ecc/bn254/fuzz.go index 452eb59c3..04e63e389 100644 --- a/ecc/bn254/fuzz.go +++ b/ecc/bn254/fuzz.go @@ -30,43 +30,7 @@ const ( ) func Fuzz(data []byte) int { - // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton - // in assembly and generic impl - middle := len(data) / 2 - // fr.Element - { - var a, b, c fr.Element - var _a, _b, _c fr.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fr.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bn254/fr") - } - } - - // fp.Element - { - var a, b, c fp.Element - var _a, _b, _c fp.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fp.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bn254/fp") - } - } - + fr.Fuzz(data) + fp.Fuzz(data) return fuzzNormal - } diff --git a/ecc/bn254/fuzz_test.go b/ecc/bn254/fuzz_test.go index d6fa8f5c7..703f82c23 100644 --- a/ecc/bn254/fuzz_test.go +++ b/ecc/bn254/fuzz_test.go @@ -28,7 +28,7 @@ import ( "time" ) -func TestCSFuzzed(t *testing.T) { +func TestFuzz(t *testing.T) { const maxBytes = (fp.Bytes + fr.Bytes) * 2 const testCount = 7 var bytes [maxBytes]byte @@ -48,9 +48,7 @@ func TestCSFuzzed(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - if Fuzz(bytes[:i]) != fuzzNormal { - t.Fatal("bn254 fuzz failed") - } + Fuzz(bytes[:i]) } } diff --git a/ecc/bw6-761/fp/element_fuzz.go b/ecc/bw6-761/fp/element_fuzz.go index 0ed04dbb0..32e7f0a3a 100644 --- a/ecc/bw6-761/fp/element_fuzz.go +++ b/ecc/bw6-761/fp/element_fuzz.go @@ -18,37 +18,182 @@ package fp -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[11] %= qElement[11] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + z[4], b = bits.Sub64(z[4], qElement[4], b) + z[5], b = bits.Sub64(z[5], qElement[5], b) + z[6], b = bits.Sub64(z[6], qElement[6], b) + z[7], b = bits.Sub64(z[7], qElement[7], b) + z[8], b = bits.Sub64(z[8], qElement[8], b) + z[9], b = bits.Sub64(z[9], qElement[9], b) + z[10], b = bits.Sub64(z[10], qElement[10], b) + z[11], b = bits.Sub64(z[11], qElement[11], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[11] > qElement[11] { + return true + } + if z[11] < qElement[11] { + return false + } + + if z[10] > qElement[10] { + return true + } + if z[10] < qElement[10] { + return false + } + + if z[9] > qElement[9] { + return true + } + if z[9] < qElement[9] { + return false + } + + if z[8] > qElement[8] { + return true + } + if z[8] < qElement[8] { + return false + } + + if z[7] > qElement[7] { + return true + } + if z[7] < qElement[7] { + return false + } + + if z[6] > qElement[6] { + return true + } + if z[6] < qElement[6] { + return false + } + + if z[5] > qElement[5] { + return true + } + if z[5] < qElement[5] { + return false + } + + if z[4] > qElement[4] { + return true + } + if z[4] < qElement[4] { + return false + } + + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bw6-761/fr/element_fuzz.go b/ecc/bw6-761/fr/element_fuzz.go index 1b0c32ac8..0c47bddd4 100644 --- a/ecc/bw6-761/fr/element_fuzz.go +++ b/ecc/bw6-761/fr/element_fuzz.go @@ -18,37 +18,134 @@ package fr -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z, x, y *Element) { - _mulGeneric(z, x, y) -} +import ( + "bytes" + "encoding/binary" + "io" + "math/big" + "math/bits" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *Element) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *Element) { - _addGeneric(z, x, y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *Element) { - _doubleGeneric(z, x) -} + var e1, e2 Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + // mul assembly + + var c, _c Element + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on Element") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *Element) { - _subGeneric(z, x, y) } -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *Element) { - _negGeneric(z, x) +// SetRawBytes reads up to Bytes (bytes needed to represent Element) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *Element) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[5] %= qElement[5] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], qElement[0], 0) + z[1], b = bits.Sub64(z[1], qElement[1], b) + z[2], b = bits.Sub64(z[2], qElement[2], b) + z[3], b = bits.Sub64(z[3], qElement[3], b) + z[4], b = bits.Sub64(z[4], qElement[4], b) + z[5], b = bits.Sub64(z[5], qElement[5], b) + } + + return } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *Element) { - _reduceGeneric(z) +func (z *Element) BiggerModulus() bool { + if z[5] > qElement[5] { + return true + } + if z[5] < qElement[5] { + return false + } + + if z[4] > qElement[4] { + return true + } + if z[4] < qElement[4] { + return false + } + + if z[3] > qElement[3] { + return true + } + if z[3] < qElement[3] { + return false + } + + if z[2] > qElement[2] { + return true + } + if z[2] < qElement[2] { + return false + } + + if z[1] > qElement[1] { + return true + } + if z[1] < qElement[1] { + return false + } + + return z[0] >= qElement[0] } diff --git a/ecc/bw6-761/fr/fft/fuzz.go b/ecc/bw6-761/fr/fft/fuzz.go new file mode 100644 index 000000000..16acf4f61 --- /dev/null +++ b/ecc/bw6-761/fr/fft/fuzz.go @@ -0,0 +1,70 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "bytes" + "fmt" + + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + r := bytes.NewReader(data) + + // random polynomial + size := len(data) / 8 + if size == 0 { + return fuzzDiscard + } + if size > (1 << 15) { + size = 1 << 15 + } + paddedSize := nextPowerOfTwo(uint64(size)) + p1 := make([]fr.Element, paddedSize) + p2 := make([]fr.Element, paddedSize) + for i := 0; i < len(p1); i++ { + p1[i].SetRawBytes(r) + } + copy(p2, p1) + + // fft domain + domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) + domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + + // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, 0) + domainWOPrecompute.FFTInverse(p1, DIF, 0) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } + } + + return fuzzNormal +} diff --git a/ecc/bw6-761/fr/fft/fuzz_test.go b/ecc/bw6-761/fr/fft/fuzz_test.go new file mode 100644 index 000000000..7ece24c90 --- /dev/null +++ b/ecc/bw6-761/fr/fft/fuzz_test.go @@ -0,0 +1,53 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package fft + +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bw6-761/fuzz.go b/ecc/bw6-761/fuzz.go index 4c5054d8c..45870ed29 100644 --- a/ecc/bw6-761/fuzz.go +++ b/ecc/bw6-761/fuzz.go @@ -30,43 +30,7 @@ const ( ) func Fuzz(data []byte) int { - // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton - // in assembly and generic impl - middle := len(data) / 2 - // fr.Element - { - var a, b, c fr.Element - var _a, _b, _c fr.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fr.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bw6-761/fr") - } - } - - // fp.Element - { - var a, b, c fp.Element - var _a, _b, _c fp.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fp.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on bw6-761/fp") - } - } - + fr.Fuzz(data) + fp.Fuzz(data) return fuzzNormal - } diff --git a/ecc/bw6-761/fuzz_test.go b/ecc/bw6-761/fuzz_test.go index df243696c..bd38e4df8 100644 --- a/ecc/bw6-761/fuzz_test.go +++ b/ecc/bw6-761/fuzz_test.go @@ -28,7 +28,7 @@ import ( "time" ) -func TestCSFuzzed(t *testing.T) { +func TestFuzz(t *testing.T) { const maxBytes = (fp.Bytes + fr.Bytes) * 2 const testCount = 7 var bytes [maxBytes]byte @@ -48,9 +48,7 @@ func TestCSFuzzed(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - if Fuzz(bytes[:i]) != fuzzNormal { - t.Fatal("bw6-761 fuzz failed") - } + Fuzz(bytes[:i]) } } diff --git a/field/internal/templates/element/fuzz.go b/field/internal/templates/element/fuzz.go index 8e9e01d77..83fe41234 100644 --- a/field/internal/templates/element/fuzz.go +++ b/field/internal/templates/element/fuzz.go @@ -3,40 +3,109 @@ package element // Fuzz when build tag is provided, we expose Generic methods to be used by ecc/ package fuzzing functions const Fuzz = ` -// MulGeneric is a wrapper exposed and used for fuzzing purposes only -func MulGeneric(z,x,y *{{.ElementName}}) { - _mulGeneric(z, x, y) -} +import ( + "encoding/binary" + "io" + "math/bits" + "math/big" + "bytes" +) -// FromMontGeneric is a wrapper exposed and used for fuzzing purposes only -func FromMontGeneric(z *{{.ElementName}}) { - _fromMontGeneric(z) -} +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) -// AddGeneric is a wrapper exposed and used for fuzzing purposes only -func AddGeneric(z, x, y *{{.ElementName}}) { - _addGeneric(z, x,y) -} +// Fuzz arithmetic operations fuzzer +func Fuzz(data []byte) int { + r := bytes.NewReader(data) -// DoubleGeneric is a wrapper exposed and used for fuzzing purposes only -func DoubleGeneric(z, x *{{.ElementName}}) { - _doubleGeneric(z, x) -} + var e1, e2 {{.ElementName}} + e1.SetRawBytes(r) + e2.SetRawBytes(r) -// SubGeneric is a wrapper exposed and used for fuzzing purposes only -func SubGeneric(z, x, y *{{.ElementName}}) { - _subGeneric(z,x,y) -} + { + // mul assembly + + var c, _c {{.ElementName}} + a, _a, b, _b := e1, e1, e2, e2 + c.Mul(&a, &b) + _mulGeneric(&_c, &_a, &_b) + + if !c.Equal(&_c) { + panic("mul asm != mul generic on {{.ElementName}}") + } + } + + { + // inverse + inv := e1 + inv.Inverse(&inv) + + var bInv, b1, b2 big.Int + e1.ToBigIntRegular(&b1) + bInv.ModInverse(&b1, Modulus()) + inv.ToBigIntRegular(&b2) + + if b2.Cmp(&bInv) != 0 { + panic("inverse operation doesn't match big int result") + } + } + + { + // a + -a == 0 + a, b := e1, e1 + b.Neg(&b) + a.Add(&a, &b) + if !a.IsZero() { + panic("a + -a != 0") + } + } + + return fuzzNormal -// NegGeneric is a wrapper exposed and used for fuzzing purposes only -func NegGeneric(z, x *{{.ElementName}}) { - _negGeneric(z,x) } -// ReduceGeneric is a wrapper exposed and used for fuzzing purposes only -func ReduceGeneric(z *{{.ElementName}}) { - _reduceGeneric(z) +// SetRawBytes reads up to Bytes (bytes needed to represent {{.ElementName}}) from reader +// and interpret it as big endian uint64 +// used for fuzzing purposes only +func (z *{{.ElementName}}) SetRawBytes(r io.Reader) { + + buf := make([]byte, 8) + + for i := 0; i < len(z); i++ { + if _, err := io.ReadFull(r, buf); err != nil { + goto eof + } + z[i] = binary.BigEndian.Uint64(buf[:]) + } +eof: + z[{{.NbWordsLastIndex}}] %= q{{.ElementName}}[{{.NbWordsLastIndex}}] + + if z.BiggerModulus() { + var b uint64 + z[0], b = bits.Sub64(z[0], q{{$.ElementName}}[0], 0) + {{- range $i := .NbWordsIndexesNoZero}} + z[{{$i}}], b = bits.Sub64(z[{{$i}}], q{{$.ElementName}}[{{$i}}], b) + {{- end}} + } + + return } +func (z *{{.ElementName}}) BiggerModulus() bool { + {{- range $i := reverse .NbWordsIndexesNoZero}} + if z[{{$i}}] > q{{$.ElementName}}[{{$i}}] { + return true + } + if z[{{$i}}] < q{{$.ElementName}}[{{$i}}] { + return false + } + {{end}} + + return z[0] >= q{{.ElementName}}[0] +} + ` diff --git a/internal/generator/ecc/template/fuzz.go.tmpl b/internal/generator/ecc/template/fuzz.go.tmpl index a0830bfd3..4b6fd0f56 100644 --- a/internal/generator/ecc/template/fuzz.go.tmpl +++ b/internal/generator/ecc/template/fuzz.go.tmpl @@ -19,43 +19,7 @@ const ( ) func Fuzz(data []byte) int { - // wip, to test continuous fuzzing infra, we compare the result of field element multiplicaiton - // in assembly and generic impl - middle := len(data) / 2 - // fr.Element - { - var a, b, c fr.Element - var _a, _b, _c fr.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fr.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on {{.Name}}/fr") - } - } - - // fp.Element - { - var a, b, c fp.Element - var _a, _b, _c fp.Element - a.SetBytes(data[:middle]) - _a.SetBytes(data[:middle]) - b.SetBytes(data[middle:]) - _b.SetBytes(data[middle:]) - - c.Mul(&a, &b) - fp.MulGeneric(&_c, &_a, &_b) - - if !c.Equal(&_c) { - panic("mul asm != mul generic on {{.Name}}/fp") - } - } - + fr.Fuzz(data) + fp.Fuzz(data) return fuzzNormal - } \ No newline at end of file diff --git a/internal/generator/ecc/template/tests/fuzz.go.tmpl b/internal/generator/ecc/template/tests/fuzz.go.tmpl index 673d0e031..e58bd5cb6 100644 --- a/internal/generator/ecc/template/tests/fuzz.go.tmpl +++ b/internal/generator/ecc/template/tests/fuzz.go.tmpl @@ -8,7 +8,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" ) -func TestCSFuzzed(t *testing.T) { +func TestFuzz(t *testing.T) { const maxBytes = (fp.Bytes + fr.Bytes) * 2 const testCount = 7 var bytes [maxBytes]byte @@ -28,9 +28,7 @@ func TestCSFuzzed(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - if Fuzz(bytes[:i]) != fuzzNormal { - t.Fatal("{{.Name}} fuzz failed") - } + Fuzz(bytes[:i]) } } diff --git a/internal/generator/fft/generate.go b/internal/generator/fft/generate.go index 7fc01f599..3e4e9efc0 100644 --- a/internal/generator/fft/generate.go +++ b/internal/generator/fft/generate.go @@ -15,6 +15,8 @@ func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) er {File: filepath.Join(baseDir, "domain.go"), Templates: []string{"domain.go.tmpl", "imports.go.tmpl"}}, {File: filepath.Join(baseDir, "fft_test.go"), Templates: []string{"tests/fft.go.tmpl", "imports.go.tmpl"}}, {File: filepath.Join(baseDir, "fft.go"), Templates: []string{"fft.go.tmpl", "imports.go.tmpl"}}, + {File: filepath.Join(baseDir, "fuzz.go"), Templates: []string{"fuzz.go.tmpl", "imports.go.tmpl"}, BuildTag: "gofuzz"}, + {File: filepath.Join(baseDir, "fuzz_test.go"), Templates: []string{"tests/fuzz.go.tmpl", "imports.go.tmpl"}, BuildTag: "gofuzz"}, } return bgen.Generate(conf, conf.Package, "./fft/template/", entries...) } diff --git a/internal/generator/fft/template/fuzz.go.tmpl b/internal/generator/fft/template/fuzz.go.tmpl new file mode 100644 index 000000000..2760145d6 --- /dev/null +++ b/internal/generator/fft/template/fuzz.go.tmpl @@ -0,0 +1,50 @@ +import ( + "bytes" + "fmt" + {{ template "import_fr" . }} +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + + +func Fuzz(data []byte) int { + r := bytes.NewReader(data) + + // random polynomial + size := len(data) / 8 + if size == 0 { + return fuzzDiscard + } + if size > (1 << 15) { + size = 1 << 15 + } + paddedSize := nextPowerOfTwo(uint64(size)) + p1 := make([]fr.Element, paddedSize) + p2 := make([]fr.Element, paddedSize) + for i := 0; i < len(p1); i++ { + p1[i].SetRawBytes(r) + } + copy(p2, p1) + + // fft domain + domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0]) % 3) , true) + domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0]) % 3) , false) + + // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, 0) + domainWOPrecompute.FFTInverse(p1, DIF, 0) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size) ) + } + } + + return fuzzNormal +} \ No newline at end of file diff --git a/internal/generator/fft/template/tests/fuzz.go.tmpl b/internal/generator/fft/template/tests/fuzz.go.tmpl new file mode 100644 index 000000000..5a23c0f77 --- /dev/null +++ b/internal/generator/fft/template/tests/fuzz.go.tmpl @@ -0,0 +1,33 @@ +import ( + "encoding/hex" + "io" + "math/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} \ No newline at end of file From 37d2eb5f4cfa2290c0b08935c6b623c6556dfbc4 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Wed, 2 Jun 2021 15:31:08 -0500 Subject: [PATCH 4/9] feat: added Fuzz for fft with cosets --- ecc/bls12-377/fr/fft/fuzz.go | 21 +++++++++------- ecc/bls12-381/fr/fft/fuzz.go | 21 +++++++++------- ecc/bn254/fr/fft/fuzz.go | 21 +++++++++------- ecc/bw6-761/fr/fft/fuzz.go | 21 +++++++++------- internal/generator/fft/template/fuzz.go.tmpl | 26 ++++++++++++-------- 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/ecc/bls12-377/fr/fft/fuzz.go b/ecc/bls12-377/fr/fft/fuzz.go index 684aa9b72..3ff9a72bc 100644 --- a/ecc/bls12-377/fr/fft/fuzz.go +++ b/ecc/bls12-377/fr/fft/fuzz.go @@ -51,18 +51,21 @@ func Fuzz(data []byte) int { copy(p2, p1) // fft domain - domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) - domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + nbCosets := uint64(uint8(data[0]) % 3) + domainWithPrecompute := NewDomain(paddedSize, nbCosets, true) + domainWOPrecompute := NewDomain(paddedSize, nbCosets, false) // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id - BitReverse(p1) - domainWithPrecompute.FFT(p1, DIT, 0) - domainWOPrecompute.FFTInverse(p1, DIF, 0) - BitReverse(p1) + for i := uint64(0); i < nbCosets; i++ { + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, i) + domainWOPrecompute.FFTInverse(p1, DIF, i) + BitReverse(p1) - for i := 0; i < len(p1); i++ { - if !p1[i].Equal(&p2[i]) { - panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } } } diff --git a/ecc/bls12-381/fr/fft/fuzz.go b/ecc/bls12-381/fr/fft/fuzz.go index bcc512fde..f5bd66fea 100644 --- a/ecc/bls12-381/fr/fft/fuzz.go +++ b/ecc/bls12-381/fr/fft/fuzz.go @@ -51,18 +51,21 @@ func Fuzz(data []byte) int { copy(p2, p1) // fft domain - domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) - domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + nbCosets := uint64(uint8(data[0]) % 3) + domainWithPrecompute := NewDomain(paddedSize, nbCosets, true) + domainWOPrecompute := NewDomain(paddedSize, nbCosets, false) // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id - BitReverse(p1) - domainWithPrecompute.FFT(p1, DIT, 0) - domainWOPrecompute.FFTInverse(p1, DIF, 0) - BitReverse(p1) + for i := uint64(0); i < nbCosets; i++ { + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, i) + domainWOPrecompute.FFTInverse(p1, DIF, i) + BitReverse(p1) - for i := 0; i < len(p1); i++ { - if !p1[i].Equal(&p2[i]) { - panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } } } diff --git a/ecc/bn254/fr/fft/fuzz.go b/ecc/bn254/fr/fft/fuzz.go index 063f1e7ec..07587a1fe 100644 --- a/ecc/bn254/fr/fft/fuzz.go +++ b/ecc/bn254/fr/fft/fuzz.go @@ -51,18 +51,21 @@ func Fuzz(data []byte) int { copy(p2, p1) // fft domain - domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) - domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + nbCosets := uint64(uint8(data[0]) % 3) + domainWithPrecompute := NewDomain(paddedSize, nbCosets, true) + domainWOPrecompute := NewDomain(paddedSize, nbCosets, false) // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id - BitReverse(p1) - domainWithPrecompute.FFT(p1, DIT, 0) - domainWOPrecompute.FFTInverse(p1, DIF, 0) - BitReverse(p1) + for i := uint64(0); i < nbCosets; i++ { + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, i) + domainWOPrecompute.FFTInverse(p1, DIF, i) + BitReverse(p1) - for i := 0; i < len(p1); i++ { - if !p1[i].Equal(&p2[i]) { - panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } } } diff --git a/ecc/bw6-761/fr/fft/fuzz.go b/ecc/bw6-761/fr/fft/fuzz.go index 16acf4f61..0c11236e9 100644 --- a/ecc/bw6-761/fr/fft/fuzz.go +++ b/ecc/bw6-761/fr/fft/fuzz.go @@ -51,18 +51,21 @@ func Fuzz(data []byte) int { copy(p2, p1) // fft domain - domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), true) - domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0])%3), false) + nbCosets := uint64(uint8(data[0]) % 3) + domainWithPrecompute := NewDomain(paddedSize, nbCosets, true) + domainWOPrecompute := NewDomain(paddedSize, nbCosets, false) // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id - BitReverse(p1) - domainWithPrecompute.FFT(p1, DIT, 0) - domainWOPrecompute.FFTInverse(p1, DIF, 0) - BitReverse(p1) + for i := uint64(0); i < nbCosets; i++ { + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, i) + domainWOPrecompute.FFTInverse(p1, DIF, i) + BitReverse(p1) - for i := 0; i < len(p1); i++ { - if !p1[i].Equal(&p2[i]) { - panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size)) + } } } diff --git a/internal/generator/fft/template/fuzz.go.tmpl b/internal/generator/fft/template/fuzz.go.tmpl index 2760145d6..8260a9906 100644 --- a/internal/generator/fft/template/fuzz.go.tmpl +++ b/internal/generator/fft/template/fuzz.go.tmpl @@ -31,20 +31,26 @@ func Fuzz(data []byte) int { copy(p2, p1) // fft domain - domainWithPrecompute := NewDomain(paddedSize, uint64(uint8(data[0]) % 3) , true) - domainWOPrecompute := NewDomain(paddedSize, uint64(uint8(data[0]) % 3) , false) + nbCosets := uint64(uint8(data[0]) % 3) + domainWithPrecompute := NewDomain(paddedSize, nbCosets , true) + domainWOPrecompute := NewDomain(paddedSize, nbCosets , false) // bitReverse(DIF FFT(DIT FFT (bitReverse))))==id - BitReverse(p1) - domainWithPrecompute.FFT(p1, DIT, 0) - domainWOPrecompute.FFTInverse(p1, DIF, 0) - BitReverse(p1) - - for i := 0; i < len(p1); i++ { - if !p1[i].Equal(&p2[i]) { - panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size) ) + for i := uint64(0); i < nbCosets;i++ { + BitReverse(p1) + domainWithPrecompute.FFT(p1, DIT, i) + domainWOPrecompute.FFTInverse(p1, DIF,i) + BitReverse(p1) + + for i := 0; i < len(p1); i++ { + if !p1[i].Equal(&p2[i]) { + panic(fmt.Sprintf("bitReverse(DIF FFT(DIT FFT (bitReverse)))) != id, size %d", size) ) + } } } + + + return fuzzNormal } \ No newline at end of file From 05eb1afc3ee0a8549956e3a65ea4752d3ad36043 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Wed, 2 Jun 2021 16:34:28 -0500 Subject: [PATCH 5/9] feat: added kzg Fuzz test --- ecc/bls12-377/fr/fft/domain.go | 3 +- ecc/bls12-377/fr/fft/fuzz_test.go | 2 + ecc/bls12-377/fr/mimc/fuzz.go | 33 +++++++ ecc/bls12-377/fr/polynomial/kzg/fuzz.go | 86 +++++++++++++++++++ ecc/bls12-377/fr/polynomial/kzg/fuzz_test.go | 55 ++++++++++++ ecc/bls12-377/fr/polynomial/kzg/kzg_test.go | 50 ++--------- ecc/bls12-377/fuzz.go | 2 + ecc/bls12-377/fuzz_test.go | 6 +- ecc/bls12-381/fr/fft/domain.go | 3 +- ecc/bls12-381/fr/fft/fuzz_test.go | 2 + ecc/bls12-381/fr/mimc/fuzz.go | 33 +++++++ ecc/bls12-381/fr/polynomial/kzg/fuzz.go | 86 +++++++++++++++++++ ecc/bls12-381/fr/polynomial/kzg/fuzz_test.go | 55 ++++++++++++ ecc/bls12-381/fr/polynomial/kzg/kzg_test.go | 50 ++--------- ecc/bls12-381/fuzz.go | 2 + ecc/bls12-381/fuzz_test.go | 6 +- ecc/bn254/fr/fft/domain.go | 3 +- ecc/bn254/fr/fft/fuzz_test.go | 2 + ecc/bn254/fr/mimc/fuzz.go | 33 +++++++ ecc/bn254/fr/polynomial/kzg/fuzz.go | 86 +++++++++++++++++++ ecc/bn254/fr/polynomial/kzg/fuzz_test.go | 55 ++++++++++++ ecc/bn254/fr/polynomial/kzg/kzg_test.go | 50 ++--------- ecc/bn254/fuzz.go | 2 + ecc/bn254/fuzz_test.go | 6 +- ecc/bw6-761/fr/fft/domain.go | 3 +- ecc/bw6-761/fr/fft/fuzz_test.go | 2 + ecc/bw6-761/fr/mimc/fuzz.go | 33 +++++++ ecc/bw6-761/fr/polynomial/kzg/fuzz.go | 86 +++++++++++++++++++ ecc/bw6-761/fr/polynomial/kzg/fuzz_test.go | 55 ++++++++++++ ecc/bw6-761/fr/polynomial/kzg/kzg_test.go | 50 ++--------- ecc/bw6-761/fuzz.go | 2 + ecc/bw6-761/fuzz_test.go | 6 +- .../generator/crypto/hash/mimc/generate.go | 1 + .../crypto/hash/mimc/template/fuzz.go.tmpl | 15 ++++ internal/generator/ecc/template/fuzz.go.tmpl | 2 + .../generator/ecc/template/tests/fuzz.go.tmpl | 8 +- .../generator/fft/template/domain.go.tmpl | 3 +- .../generator/fft/template/tests/fuzz.go.tmpl | 2 + internal/generator/polynomial/generate.go | 2 + .../template/commitment_kzg/fuzz.go.tmpl | 70 +++++++++++++++ .../template/commitment_kzg/fuzz.test.go.tmpl | 35 ++++++++ .../template/commitment_kzg/kzg.test.go.tmpl | 49 ++--------- 42 files changed, 910 insertions(+), 225 deletions(-) create mode 100644 ecc/bls12-377/fr/mimc/fuzz.go create mode 100644 ecc/bls12-377/fr/polynomial/kzg/fuzz.go create mode 100644 ecc/bls12-377/fr/polynomial/kzg/fuzz_test.go create mode 100644 ecc/bls12-381/fr/mimc/fuzz.go create mode 100644 ecc/bls12-381/fr/polynomial/kzg/fuzz.go create mode 100644 ecc/bls12-381/fr/polynomial/kzg/fuzz_test.go create mode 100644 ecc/bn254/fr/mimc/fuzz.go create mode 100644 ecc/bn254/fr/polynomial/kzg/fuzz.go create mode 100644 ecc/bn254/fr/polynomial/kzg/fuzz_test.go create mode 100644 ecc/bw6-761/fr/mimc/fuzz.go create mode 100644 ecc/bw6-761/fr/polynomial/kzg/fuzz.go create mode 100644 ecc/bw6-761/fr/polynomial/kzg/fuzz_test.go create mode 100644 internal/generator/crypto/hash/mimc/template/fuzz.go.tmpl create mode 100644 internal/generator/polynomial/template/commitment_kzg/fuzz.go.tmpl create mode 100644 internal/generator/polynomial/template/commitment_kzg/fuzz.test.go.tmpl diff --git a/ecc/bls12-377/fr/fft/domain.go b/ecc/bls12-377/fr/fft/domain.go index ad939c617..af9d69414 100644 --- a/ecc/bls12-377/fr/fft/domain.go +++ b/ecc/bls12-377/fr/fft/domain.go @@ -17,6 +17,7 @@ package fft import ( + "fmt" "io" "math/big" "math/bits" @@ -95,7 +96,7 @@ func NewDomain(m, depth uint64, precomputeReversedTable bool) *Domain { // find generator for Z/2^(log(m))Z and Z/2^(log(m)+cosets)Z logx := uint64(bits.TrailingZeros64(x)) if logx > maxOrderRoot { - panic("m is too big: the required root of unity does not exist") + panic(fmt.Sprintf("m (%d) is too big: the required root of unity does not exist", m)) } logGen := logx + depth if logGen > maxOrderRoot { diff --git a/ecc/bls12-377/fr/fft/fuzz_test.go b/ecc/bls12-377/fr/fft/fuzz_test.go index 7ece24c90..7f3da1257 100644 --- a/ecc/bls12-377/fr/fft/fuzz_test.go +++ b/ecc/bls12-377/fr/fft/fuzz_test.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "io" "math/rand" + "runtime/debug" "testing" "time" ) @@ -35,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bls12-377/fr/mimc/fuzz.go b/ecc/bls12-377/fr/mimc/fuzz.go new file mode 100644 index 000000000..8678a9ad6 --- /dev/null +++ b/ecc/bls12-377/fr/mimc/fuzz.go @@ -0,0 +1,33 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package mimc + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + var s []byte + h := NewMiMC(string(data)) + h.Write(data) + h.Sum(s) + return fuzzNormal +} diff --git a/ecc/bls12-377/fr/polynomial/kzg/fuzz.go b/ecc/bls12-377/fr/polynomial/kzg/fuzz.go new file mode 100644 index 000000000..0b33dd550 --- /dev/null +++ b/ecc/bls12-377/fr/polynomial/kzg/fuzz.go @@ -0,0 +1,86 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "bytes" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + bls12377_pol "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/polynomial" + "github.com/consensys/gnark-crypto/polynomial" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return fuzzDiscard + } + size := int(uint8(data[0])) + 2 // TODO fix min size in NewScheme + if size > (1 << 15) { + size = 1 << 15 + } + r := bytes.NewReader(data[1:]) + var alpha, point fr.Element + alpha.SetRawBytes(r) + point.SetRawBytes(r) + s := NewScheme(size, alpha) + + // create polynomials + f := make([]polynomial.Polynomial, size/2) + for i := 0; i < len(f); i++ { + _f := make(bls12377_pol.Polynomial, size) + for j := 0; j < len(_f); j++ { + _f[j].SetRawBytes(r) + } + f[i] = &_f + } + + // commit the polynomials + digests := make([]polynomial.Digest, size/2) + for i := 0; i < len(digests); i++ { + digests[i], _ = s.Commit(f[i]) + + } + + proof, err := s.BatchOpenSinglePoint(&point, digests, f) + if err != nil { + panic(err) + } + + // verify the claimed values + _proof := proof.(*BatchProofsSinglePoint) + for i := 0; i < len(f); i++ { + expectedClaim := f[i].Eval(point).(fr.Element) + if !expectedClaim.Equal(&_proof.ClaimedValues[i]) { + panic("inconsistant claimed values") + } + } + + // verify correct proof + err = s.BatchVerifySinglePoint(digests, proof) + if err != nil { + panic(err) + } + + return fuzzNormal +} diff --git a/ecc/bls12-377/fr/polynomial/kzg/fuzz_test.go b/ecc/bls12-377/fr/polynomial/kzg/fuzz_test.go new file mode 100644 index 000000000..1ed5922fc --- /dev/null +++ b/ecc/bls12-377/fr/polynomial/kzg/fuzz_test.go @@ -0,0 +1,55 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "encoding/hex" + "io" + "math/rand" + "runtime/debug" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Error(string(debug.Stack())) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go b/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go index 28f95316a..7233f9976 100644 --- a/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go @@ -36,38 +36,6 @@ func init() { _alphaSetup.SetString("1234") } -// NewKZG returns a new Scheme instance -// this is used for test purposes -func NewKZG(size int, alpha fr.Element) Scheme { - - var s Scheme - d := fft.NewDomain(uint64(size), 0, false) - s.Domain = *d - s.SRS.G1 = make([]bls12377.G1Affine, size) - - // generate the SRS - var alphaBigInt big.Int - alpha.ToBigIntRegular(&alphaBigInt) - - _, _, gen1Aff, gen2Aff := bls12377.Generators() - s.SRS.G1[0] = gen1Aff - s.SRS.G2[0] = gen2Aff - s.SRS.G2[1].ScalarMultiplication(&gen2Aff, &alphaBigInt) - - alphas := make([]fr.Element, size-1) - alphas[0] = alpha - for i := 1; i < len(alphas); i++ { - alphas[i].Mul(&alphas[i-1], &alpha) - } - for i := 0; i < len(alphas); i++ { - alphas[i].FromMont() - } - g1s := bls12377.BatchScalarMultiplicationG1(&gen1Aff, alphas) - copy(s.SRS.G1[1:], g1s) - - return s -} - func randomPolynomial(size int) bls12377_pol.Polynomial { f := make(bls12377_pol.Polynomial, size) for i := 0; i < size; i++ { @@ -121,7 +89,7 @@ func TestDividePolyByXminusA(t *testing.T) { func TestSerialization(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // serialize it... var buf bytes.Buffer @@ -147,7 +115,7 @@ func TestSerialization(t *testing.T) { func TestCommit(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := make(bls12377_pol.Polynomial, 60) @@ -183,7 +151,7 @@ func TestCommit(t *testing.T) { func TestVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := randomPolynomial(60) @@ -227,7 +195,7 @@ func TestVerifySinglePoint(t *testing.T) { func TestBatchVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create polynomials f := make([]polynomial.Polynomial, 10) @@ -279,7 +247,7 @@ const benchSize = 1 << 16 func BenchmarkKZGCommit(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -292,7 +260,7 @@ func BenchmarkKZGCommit(b *testing.B) { func BenchmarkKZGOpen(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -307,7 +275,7 @@ func BenchmarkKZGOpen(b *testing.B) { func BenchmarkKZGVerify(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -334,7 +302,7 @@ func BenchmarkKZGVerify(b *testing.B) { func BenchmarkKZGBatchOpen10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial @@ -360,7 +328,7 @@ func BenchmarkKZGBatchOpen10(b *testing.B) { func BenchmarkKZGBatchVerify10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial diff --git a/ecc/bls12-377/fuzz.go b/ecc/bls12-377/fuzz.go index 54c885ce3..0f06ec150 100644 --- a/ecc/bls12-377/fuzz.go +++ b/ecc/bls12-377/fuzz.go @@ -21,6 +21,7 @@ package bls12377 import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/mimc" ) const ( @@ -32,5 +33,6 @@ const ( func Fuzz(data []byte) int { fr.Fuzz(data) fp.Fuzz(data) + mimc.Fuzz(data) return fuzzNormal } diff --git a/ecc/bls12-377/fuzz_test.go b/ecc/bls12-377/fuzz_test.go index 9078e334b..d9f19fd82 100644 --- a/ecc/bls12-377/fuzz_test.go +++ b/ecc/bls12-377/fuzz_test.go @@ -20,16 +20,15 @@ package bls12377 import ( "encoding/hex" - "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" - "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "io" "math/rand" + "runtime/debug" "testing" "time" ) func TestFuzz(t *testing.T) { - const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const maxBytes = 1 << 10 const testCount = 7 var bytes [maxBytes]byte var i int @@ -37,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bls12-381/fr/fft/domain.go b/ecc/bls12-381/fr/fft/domain.go index af43749ec..02f7ba573 100644 --- a/ecc/bls12-381/fr/fft/domain.go +++ b/ecc/bls12-381/fr/fft/domain.go @@ -17,6 +17,7 @@ package fft import ( + "fmt" "io" "math/big" "math/bits" @@ -95,7 +96,7 @@ func NewDomain(m, depth uint64, precomputeReversedTable bool) *Domain { // find generator for Z/2^(log(m))Z and Z/2^(log(m)+cosets)Z logx := uint64(bits.TrailingZeros64(x)) if logx > maxOrderRoot { - panic("m is too big: the required root of unity does not exist") + panic(fmt.Sprintf("m (%d) is too big: the required root of unity does not exist", m)) } logGen := logx + depth if logGen > maxOrderRoot { diff --git a/ecc/bls12-381/fr/fft/fuzz_test.go b/ecc/bls12-381/fr/fft/fuzz_test.go index 7ece24c90..7f3da1257 100644 --- a/ecc/bls12-381/fr/fft/fuzz_test.go +++ b/ecc/bls12-381/fr/fft/fuzz_test.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "io" "math/rand" + "runtime/debug" "testing" "time" ) @@ -35,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bls12-381/fr/mimc/fuzz.go b/ecc/bls12-381/fr/mimc/fuzz.go new file mode 100644 index 000000000..8678a9ad6 --- /dev/null +++ b/ecc/bls12-381/fr/mimc/fuzz.go @@ -0,0 +1,33 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package mimc + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + var s []byte + h := NewMiMC(string(data)) + h.Write(data) + h.Sum(s) + return fuzzNormal +} diff --git a/ecc/bls12-381/fr/polynomial/kzg/fuzz.go b/ecc/bls12-381/fr/polynomial/kzg/fuzz.go new file mode 100644 index 000000000..8e241b5ca --- /dev/null +++ b/ecc/bls12-381/fr/polynomial/kzg/fuzz.go @@ -0,0 +1,86 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "bytes" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + bls12381_pol "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/polynomial" + "github.com/consensys/gnark-crypto/polynomial" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return fuzzDiscard + } + size := int(uint8(data[0])) + 2 // TODO fix min size in NewScheme + if size > (1 << 15) { + size = 1 << 15 + } + r := bytes.NewReader(data[1:]) + var alpha, point fr.Element + alpha.SetRawBytes(r) + point.SetRawBytes(r) + s := NewScheme(size, alpha) + + // create polynomials + f := make([]polynomial.Polynomial, size/2) + for i := 0; i < len(f); i++ { + _f := make(bls12381_pol.Polynomial, size) + for j := 0; j < len(_f); j++ { + _f[j].SetRawBytes(r) + } + f[i] = &_f + } + + // commit the polynomials + digests := make([]polynomial.Digest, size/2) + for i := 0; i < len(digests); i++ { + digests[i], _ = s.Commit(f[i]) + + } + + proof, err := s.BatchOpenSinglePoint(&point, digests, f) + if err != nil { + panic(err) + } + + // verify the claimed values + _proof := proof.(*BatchProofsSinglePoint) + for i := 0; i < len(f); i++ { + expectedClaim := f[i].Eval(point).(fr.Element) + if !expectedClaim.Equal(&_proof.ClaimedValues[i]) { + panic("inconsistant claimed values") + } + } + + // verify correct proof + err = s.BatchVerifySinglePoint(digests, proof) + if err != nil { + panic(err) + } + + return fuzzNormal +} diff --git a/ecc/bls12-381/fr/polynomial/kzg/fuzz_test.go b/ecc/bls12-381/fr/polynomial/kzg/fuzz_test.go new file mode 100644 index 000000000..1ed5922fc --- /dev/null +++ b/ecc/bls12-381/fr/polynomial/kzg/fuzz_test.go @@ -0,0 +1,55 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "encoding/hex" + "io" + "math/rand" + "runtime/debug" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Error(string(debug.Stack())) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go b/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go index 7a50eeeca..c0629f419 100644 --- a/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go @@ -36,38 +36,6 @@ func init() { _alphaSetup.SetString("1234") } -// NewKZG returns a new Scheme instance -// this is used for test purposes -func NewKZG(size int, alpha fr.Element) Scheme { - - var s Scheme - d := fft.NewDomain(uint64(size), 0, false) - s.Domain = *d - s.SRS.G1 = make([]bls12381.G1Affine, size) - - // generate the SRS - var alphaBigInt big.Int - alpha.ToBigIntRegular(&alphaBigInt) - - _, _, gen1Aff, gen2Aff := bls12381.Generators() - s.SRS.G1[0] = gen1Aff - s.SRS.G2[0] = gen2Aff - s.SRS.G2[1].ScalarMultiplication(&gen2Aff, &alphaBigInt) - - alphas := make([]fr.Element, size-1) - alphas[0] = alpha - for i := 1; i < len(alphas); i++ { - alphas[i].Mul(&alphas[i-1], &alpha) - } - for i := 0; i < len(alphas); i++ { - alphas[i].FromMont() - } - g1s := bls12381.BatchScalarMultiplicationG1(&gen1Aff, alphas) - copy(s.SRS.G1[1:], g1s) - - return s -} - func randomPolynomial(size int) bls12381_pol.Polynomial { f := make(bls12381_pol.Polynomial, size) for i := 0; i < size; i++ { @@ -121,7 +89,7 @@ func TestDividePolyByXminusA(t *testing.T) { func TestSerialization(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // serialize it... var buf bytes.Buffer @@ -147,7 +115,7 @@ func TestSerialization(t *testing.T) { func TestCommit(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := make(bls12381_pol.Polynomial, 60) @@ -183,7 +151,7 @@ func TestCommit(t *testing.T) { func TestVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := randomPolynomial(60) @@ -227,7 +195,7 @@ func TestVerifySinglePoint(t *testing.T) { func TestBatchVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create polynomials f := make([]polynomial.Polynomial, 10) @@ -279,7 +247,7 @@ const benchSize = 1 << 16 func BenchmarkKZGCommit(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -292,7 +260,7 @@ func BenchmarkKZGCommit(b *testing.B) { func BenchmarkKZGOpen(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -307,7 +275,7 @@ func BenchmarkKZGOpen(b *testing.B) { func BenchmarkKZGVerify(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -334,7 +302,7 @@ func BenchmarkKZGVerify(b *testing.B) { func BenchmarkKZGBatchOpen10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial @@ -360,7 +328,7 @@ func BenchmarkKZGBatchOpen10(b *testing.B) { func BenchmarkKZGBatchVerify10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial diff --git a/ecc/bls12-381/fuzz.go b/ecc/bls12-381/fuzz.go index 2d66f91dc..4f0af6e15 100644 --- a/ecc/bls12-381/fuzz.go +++ b/ecc/bls12-381/fuzz.go @@ -21,6 +21,7 @@ package bls12381 import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/mimc" ) const ( @@ -32,5 +33,6 @@ const ( func Fuzz(data []byte) int { fr.Fuzz(data) fp.Fuzz(data) + mimc.Fuzz(data) return fuzzNormal } diff --git a/ecc/bls12-381/fuzz_test.go b/ecc/bls12-381/fuzz_test.go index 1a9f4d006..6751f3a28 100644 --- a/ecc/bls12-381/fuzz_test.go +++ b/ecc/bls12-381/fuzz_test.go @@ -20,16 +20,15 @@ package bls12381 import ( "encoding/hex" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "io" "math/rand" + "runtime/debug" "testing" "time" ) func TestFuzz(t *testing.T) { - const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const maxBytes = 1 << 10 const testCount = 7 var bytes [maxBytes]byte var i int @@ -37,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bn254/fr/fft/domain.go b/ecc/bn254/fr/fft/domain.go index a842c30bb..bdd5a37cc 100644 --- a/ecc/bn254/fr/fft/domain.go +++ b/ecc/bn254/fr/fft/domain.go @@ -17,6 +17,7 @@ package fft import ( + "fmt" "io" "math/big" "math/bits" @@ -95,7 +96,7 @@ func NewDomain(m, depth uint64, precomputeReversedTable bool) *Domain { // find generator for Z/2^(log(m))Z and Z/2^(log(m)+cosets)Z logx := uint64(bits.TrailingZeros64(x)) if logx > maxOrderRoot { - panic("m is too big: the required root of unity does not exist") + panic(fmt.Sprintf("m (%d) is too big: the required root of unity does not exist", m)) } logGen := logx + depth if logGen > maxOrderRoot { diff --git a/ecc/bn254/fr/fft/fuzz_test.go b/ecc/bn254/fr/fft/fuzz_test.go index 7ece24c90..7f3da1257 100644 --- a/ecc/bn254/fr/fft/fuzz_test.go +++ b/ecc/bn254/fr/fft/fuzz_test.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "io" "math/rand" + "runtime/debug" "testing" "time" ) @@ -35,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bn254/fr/mimc/fuzz.go b/ecc/bn254/fr/mimc/fuzz.go new file mode 100644 index 000000000..8678a9ad6 --- /dev/null +++ b/ecc/bn254/fr/mimc/fuzz.go @@ -0,0 +1,33 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package mimc + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + var s []byte + h := NewMiMC(string(data)) + h.Write(data) + h.Sum(s) + return fuzzNormal +} diff --git a/ecc/bn254/fr/polynomial/kzg/fuzz.go b/ecc/bn254/fr/polynomial/kzg/fuzz.go new file mode 100644 index 000000000..f8a86dae0 --- /dev/null +++ b/ecc/bn254/fr/polynomial/kzg/fuzz.go @@ -0,0 +1,86 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "bytes" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + bn254_pol "github.com/consensys/gnark-crypto/ecc/bn254/fr/polynomial" + "github.com/consensys/gnark-crypto/polynomial" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return fuzzDiscard + } + size := int(uint8(data[0])) + 2 // TODO fix min size in NewScheme + if size > (1 << 15) { + size = 1 << 15 + } + r := bytes.NewReader(data[1:]) + var alpha, point fr.Element + alpha.SetRawBytes(r) + point.SetRawBytes(r) + s := NewScheme(size, alpha) + + // create polynomials + f := make([]polynomial.Polynomial, size/2) + for i := 0; i < len(f); i++ { + _f := make(bn254_pol.Polynomial, size) + for j := 0; j < len(_f); j++ { + _f[j].SetRawBytes(r) + } + f[i] = &_f + } + + // commit the polynomials + digests := make([]polynomial.Digest, size/2) + for i := 0; i < len(digests); i++ { + digests[i], _ = s.Commit(f[i]) + + } + + proof, err := s.BatchOpenSinglePoint(&point, digests, f) + if err != nil { + panic(err) + } + + // verify the claimed values + _proof := proof.(*BatchProofsSinglePoint) + for i := 0; i < len(f); i++ { + expectedClaim := f[i].Eval(point).(fr.Element) + if !expectedClaim.Equal(&_proof.ClaimedValues[i]) { + panic("inconsistant claimed values") + } + } + + // verify correct proof + err = s.BatchVerifySinglePoint(digests, proof) + if err != nil { + panic(err) + } + + return fuzzNormal +} diff --git a/ecc/bn254/fr/polynomial/kzg/fuzz_test.go b/ecc/bn254/fr/polynomial/kzg/fuzz_test.go new file mode 100644 index 000000000..1ed5922fc --- /dev/null +++ b/ecc/bn254/fr/polynomial/kzg/fuzz_test.go @@ -0,0 +1,55 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "encoding/hex" + "io" + "math/rand" + "runtime/debug" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Error(string(debug.Stack())) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bn254/fr/polynomial/kzg/kzg_test.go b/ecc/bn254/fr/polynomial/kzg/kzg_test.go index 61c3330fc..72d2e27f1 100644 --- a/ecc/bn254/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bn254/fr/polynomial/kzg/kzg_test.go @@ -36,38 +36,6 @@ func init() { _alphaSetup.SetString("1234") } -// NewKZG returns a new Scheme instance -// this is used for test purposes -func NewKZG(size int, alpha fr.Element) Scheme { - - var s Scheme - d := fft.NewDomain(uint64(size), 0, false) - s.Domain = *d - s.SRS.G1 = make([]bn254.G1Affine, size) - - // generate the SRS - var alphaBigInt big.Int - alpha.ToBigIntRegular(&alphaBigInt) - - _, _, gen1Aff, gen2Aff := bn254.Generators() - s.SRS.G1[0] = gen1Aff - s.SRS.G2[0] = gen2Aff - s.SRS.G2[1].ScalarMultiplication(&gen2Aff, &alphaBigInt) - - alphas := make([]fr.Element, size-1) - alphas[0] = alpha - for i := 1; i < len(alphas); i++ { - alphas[i].Mul(&alphas[i-1], &alpha) - } - for i := 0; i < len(alphas); i++ { - alphas[i].FromMont() - } - g1s := bn254.BatchScalarMultiplicationG1(&gen1Aff, alphas) - copy(s.SRS.G1[1:], g1s) - - return s -} - func randomPolynomial(size int) bn254_pol.Polynomial { f := make(bn254_pol.Polynomial, size) for i := 0; i < size; i++ { @@ -121,7 +89,7 @@ func TestDividePolyByXminusA(t *testing.T) { func TestSerialization(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // serialize it... var buf bytes.Buffer @@ -147,7 +115,7 @@ func TestSerialization(t *testing.T) { func TestCommit(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := make(bn254_pol.Polynomial, 60) @@ -183,7 +151,7 @@ func TestCommit(t *testing.T) { func TestVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := randomPolynomial(60) @@ -227,7 +195,7 @@ func TestVerifySinglePoint(t *testing.T) { func TestBatchVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create polynomials f := make([]polynomial.Polynomial, 10) @@ -279,7 +247,7 @@ const benchSize = 1 << 16 func BenchmarkKZGCommit(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -292,7 +260,7 @@ func BenchmarkKZGCommit(b *testing.B) { func BenchmarkKZGOpen(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -307,7 +275,7 @@ func BenchmarkKZGOpen(b *testing.B) { func BenchmarkKZGVerify(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -334,7 +302,7 @@ func BenchmarkKZGVerify(b *testing.B) { func BenchmarkKZGBatchOpen10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial @@ -360,7 +328,7 @@ func BenchmarkKZGBatchOpen10(b *testing.B) { func BenchmarkKZGBatchVerify10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial diff --git a/ecc/bn254/fuzz.go b/ecc/bn254/fuzz.go index 04e63e389..2b013e5ab 100644 --- a/ecc/bn254/fuzz.go +++ b/ecc/bn254/fuzz.go @@ -21,6 +21,7 @@ package bn254 import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" ) const ( @@ -32,5 +33,6 @@ const ( func Fuzz(data []byte) int { fr.Fuzz(data) fp.Fuzz(data) + mimc.Fuzz(data) return fuzzNormal } diff --git a/ecc/bn254/fuzz_test.go b/ecc/bn254/fuzz_test.go index 703f82c23..da81e318e 100644 --- a/ecc/bn254/fuzz_test.go +++ b/ecc/bn254/fuzz_test.go @@ -20,16 +20,15 @@ package bn254 import ( "encoding/hex" - "github.com/consensys/gnark-crypto/ecc/bn254/fp" - "github.com/consensys/gnark-crypto/ecc/bn254/fr" "io" "math/rand" + "runtime/debug" "testing" "time" ) func TestFuzz(t *testing.T) { - const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const maxBytes = 1 << 10 const testCount = 7 var bytes [maxBytes]byte var i int @@ -37,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bw6-761/fr/fft/domain.go b/ecc/bw6-761/fr/fft/domain.go index 42f3ebead..e3a04049f 100644 --- a/ecc/bw6-761/fr/fft/domain.go +++ b/ecc/bw6-761/fr/fft/domain.go @@ -17,6 +17,7 @@ package fft import ( + "fmt" "io" "math/big" "math/bits" @@ -95,7 +96,7 @@ func NewDomain(m, depth uint64, precomputeReversedTable bool) *Domain { // find generator for Z/2^(log(m))Z and Z/2^(log(m)+cosets)Z logx := uint64(bits.TrailingZeros64(x)) if logx > maxOrderRoot { - panic("m is too big: the required root of unity does not exist") + panic(fmt.Sprintf("m (%d) is too big: the required root of unity does not exist", m)) } logGen := logx + depth if logGen > maxOrderRoot { diff --git a/ecc/bw6-761/fr/fft/fuzz_test.go b/ecc/bw6-761/fr/fft/fuzz_test.go index 7ece24c90..7f3da1257 100644 --- a/ecc/bw6-761/fr/fft/fuzz_test.go +++ b/ecc/bw6-761/fr/fft/fuzz_test.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "io" "math/rand" + "runtime/debug" "testing" "time" ) @@ -35,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/ecc/bw6-761/fr/mimc/fuzz.go b/ecc/bw6-761/fr/mimc/fuzz.go new file mode 100644 index 000000000..8678a9ad6 --- /dev/null +++ b/ecc/bw6-761/fr/mimc/fuzz.go @@ -0,0 +1,33 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package mimc + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + var s []byte + h := NewMiMC(string(data)) + h.Write(data) + h.Sum(s) + return fuzzNormal +} diff --git a/ecc/bw6-761/fr/polynomial/kzg/fuzz.go b/ecc/bw6-761/fr/polynomial/kzg/fuzz.go new file mode 100644 index 000000000..cbca850c7 --- /dev/null +++ b/ecc/bw6-761/fr/polynomial/kzg/fuzz.go @@ -0,0 +1,86 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "bytes" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + bw6761_pol "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/polynomial" + "github.com/consensys/gnark-crypto/polynomial" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return fuzzDiscard + } + size := int(uint8(data[0])) + 2 // TODO fix min size in NewScheme + if size > (1 << 15) { + size = 1 << 15 + } + r := bytes.NewReader(data[1:]) + var alpha, point fr.Element + alpha.SetRawBytes(r) + point.SetRawBytes(r) + s := NewScheme(size, alpha) + + // create polynomials + f := make([]polynomial.Polynomial, size/2) + for i := 0; i < len(f); i++ { + _f := make(bw6761_pol.Polynomial, size) + for j := 0; j < len(_f); j++ { + _f[j].SetRawBytes(r) + } + f[i] = &_f + } + + // commit the polynomials + digests := make([]polynomial.Digest, size/2) + for i := 0; i < len(digests); i++ { + digests[i], _ = s.Commit(f[i]) + + } + + proof, err := s.BatchOpenSinglePoint(&point, digests, f) + if err != nil { + panic(err) + } + + // verify the claimed values + _proof := proof.(*BatchProofsSinglePoint) + for i := 0; i < len(f); i++ { + expectedClaim := f[i].Eval(point).(fr.Element) + if !expectedClaim.Equal(&_proof.ClaimedValues[i]) { + panic("inconsistant claimed values") + } + } + + // verify correct proof + err = s.BatchVerifySinglePoint(digests, proof) + if err != nil { + panic(err) + } + + return fuzzNormal +} diff --git a/ecc/bw6-761/fr/polynomial/kzg/fuzz_test.go b/ecc/bw6-761/fr/polynomial/kzg/fuzz_test.go new file mode 100644 index 000000000..1ed5922fc --- /dev/null +++ b/ecc/bw6-761/fr/polynomial/kzg/fuzz_test.go @@ -0,0 +1,55 @@ +// +build gofuzz + +// Copyright 2020 ConsenSys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by consensys/gnark-crypto DO NOT EDIT + +package kzg + +import ( + "encoding/hex" + "io" + "math/rand" + "runtime/debug" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + const maxBytes = 1 << 10 + const testCount = 7 + var bytes [maxBytes]byte + var i int + seed := time.Now().UnixNano() + defer func() { + if r := recover(); r != nil { + t.Error(r) + t.Error(string(debug.Stack())) + t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) + } + }() + r := rand.New(rand.NewSource(seed)) + + for i = 1; i < maxBytes; i++ { + for j := 0; j < testCount; j++ { + if _, err := io.ReadFull(r, bytes[:i]); err != nil { + t.Fatal("couldn't read random bytes", err) + } + + Fuzz(bytes[:i]) + } + } + +} diff --git a/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go b/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go index 1033af8ac..da679d4c7 100644 --- a/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go @@ -36,38 +36,6 @@ func init() { _alphaSetup.SetString("1234") } -// NewKZG returns a new Scheme instance -// this is used for test purposes -func NewKZG(size int, alpha fr.Element) Scheme { - - var s Scheme - d := fft.NewDomain(uint64(size), 0, false) - s.Domain = *d - s.SRS.G1 = make([]bw6761.G1Affine, size) - - // generate the SRS - var alphaBigInt big.Int - alpha.ToBigIntRegular(&alphaBigInt) - - _, _, gen1Aff, gen2Aff := bw6761.Generators() - s.SRS.G1[0] = gen1Aff - s.SRS.G2[0] = gen2Aff - s.SRS.G2[1].ScalarMultiplication(&gen2Aff, &alphaBigInt) - - alphas := make([]fr.Element, size-1) - alphas[0] = alpha - for i := 1; i < len(alphas); i++ { - alphas[i].Mul(&alphas[i-1], &alpha) - } - for i := 0; i < len(alphas); i++ { - alphas[i].FromMont() - } - g1s := bw6761.BatchScalarMultiplicationG1(&gen1Aff, alphas) - copy(s.SRS.G1[1:], g1s) - - return s -} - func randomPolynomial(size int) bw6761_pol.Polynomial { f := make(bw6761_pol.Polynomial, size) for i := 0; i < size; i++ { @@ -121,7 +89,7 @@ func TestDividePolyByXminusA(t *testing.T) { func TestSerialization(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // serialize it... var buf bytes.Buffer @@ -147,7 +115,7 @@ func TestSerialization(t *testing.T) { func TestCommit(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := make(bw6761_pol.Polynomial, 60) @@ -183,7 +151,7 @@ func TestCommit(t *testing.T) { func TestVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create a polynomial f := randomPolynomial(60) @@ -227,7 +195,7 @@ func TestVerifySinglePoint(t *testing.T) { func TestBatchVerifySinglePoint(t *testing.T) { // create a KZG scheme - s := NewKZG(64, _alphaSetup) + s := NewScheme(64, _alphaSetup) // create polynomials f := make([]polynomial.Polynomial, 10) @@ -279,7 +247,7 @@ const benchSize = 1 << 16 func BenchmarkKZGCommit(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -292,7 +260,7 @@ func BenchmarkKZGCommit(b *testing.B) { func BenchmarkKZGOpen(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -307,7 +275,7 @@ func BenchmarkKZGOpen(b *testing.B) { func BenchmarkKZGVerify(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // random polynomial p := randomPolynomial(benchSize / 2) @@ -334,7 +302,7 @@ func BenchmarkKZGVerify(b *testing.B) { func BenchmarkKZGBatchOpen10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial @@ -360,7 +328,7 @@ func BenchmarkKZGBatchOpen10(b *testing.B) { func BenchmarkKZGBatchVerify10(b *testing.B) { // kzg scheme - s := NewKZG(benchSize, _alphaSetup) + s := NewScheme(benchSize, _alphaSetup) // 10 random polynomials var ps [10]polynomial.Polynomial diff --git a/ecc/bw6-761/fuzz.go b/ecc/bw6-761/fuzz.go index 45870ed29..97f64919c 100644 --- a/ecc/bw6-761/fuzz.go +++ b/ecc/bw6-761/fuzz.go @@ -21,6 +21,7 @@ package bw6761 import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/mimc" ) const ( @@ -32,5 +33,6 @@ const ( func Fuzz(data []byte) int { fr.Fuzz(data) fp.Fuzz(data) + mimc.Fuzz(data) return fuzzNormal } diff --git a/ecc/bw6-761/fuzz_test.go b/ecc/bw6-761/fuzz_test.go index bd38e4df8..9bfb23bc5 100644 --- a/ecc/bw6-761/fuzz_test.go +++ b/ecc/bw6-761/fuzz_test.go @@ -20,16 +20,15 @@ package bw6761 import ( "encoding/hex" - "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" - "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "io" "math/rand" + "runtime/debug" "testing" "time" ) func TestFuzz(t *testing.T) { - const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const maxBytes = 1 << 10 const testCount = 7 var bytes [maxBytes]byte var i int @@ -37,6 +36,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/internal/generator/crypto/hash/mimc/generate.go b/internal/generator/crypto/hash/mimc/generate.go index c26a08452..b2dd056af 100644 --- a/internal/generator/crypto/hash/mimc/generate.go +++ b/internal/generator/crypto/hash/mimc/generate.go @@ -12,6 +12,7 @@ func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) er entries := []bavard.Entry{ {File: filepath.Join(baseDir, "doc.go"), Templates: []string{"doc.go.tmpl"}}, {File: filepath.Join(baseDir, "mimc.go"), Templates: []string{"mimc.go.tmpl"}}, + {File: filepath.Join(baseDir, "fuzz.go"), Templates: []string{"fuzz.go.tmpl"}, BuildTag: "gofuzz"}, } return bgen.Generate(conf, conf.Package, "./crypto/hash/mimc/template", entries...) diff --git a/internal/generator/crypto/hash/mimc/template/fuzz.go.tmpl b/internal/generator/crypto/hash/mimc/template/fuzz.go.tmpl new file mode 100644 index 000000000..8b27ab4ce --- /dev/null +++ b/internal/generator/crypto/hash/mimc/template/fuzz.go.tmpl @@ -0,0 +1,15 @@ + + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + var s []byte + h := NewMiMC(string(data)) + h.Write(data) + h.Sum(s) + return fuzzNormal +} \ No newline at end of file diff --git a/internal/generator/ecc/template/fuzz.go.tmpl b/internal/generator/ecc/template/fuzz.go.tmpl index 4b6fd0f56..3f0371f13 100644 --- a/internal/generator/ecc/template/fuzz.go.tmpl +++ b/internal/generator/ecc/template/fuzz.go.tmpl @@ -10,6 +10,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" + "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr/mimc" ) const ( @@ -21,5 +22,6 @@ const ( func Fuzz(data []byte) int { fr.Fuzz(data) fp.Fuzz(data) + mimc.Fuzz(data) return fuzzNormal } \ No newline at end of file diff --git a/internal/generator/ecc/template/tests/fuzz.go.tmpl b/internal/generator/ecc/template/tests/fuzz.go.tmpl index e58bd5cb6..f3f212962 100644 --- a/internal/generator/ecc/template/tests/fuzz.go.tmpl +++ b/internal/generator/ecc/template/tests/fuzz.go.tmpl @@ -4,12 +4,11 @@ import ( "math/rand" "testing" "time" - "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" - "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" + "runtime/debug" ) func TestFuzz(t *testing.T) { - const maxBytes = (fp.Bytes + fr.Bytes) * 2 + const maxBytes = 1 << 10 const testCount = 7 var bytes [maxBytes]byte var i int @@ -17,6 +16,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() @@ -28,7 +28,7 @@ func TestFuzz(t *testing.T) { t.Fatal("couldn't read random bytes", err) } - Fuzz(bytes[:i]) + Fuzz(bytes[:i]) } } diff --git a/internal/generator/fft/template/domain.go.tmpl b/internal/generator/fft/template/domain.go.tmpl index bfbf58d5b..07fe10c4c 100644 --- a/internal/generator/fft/template/domain.go.tmpl +++ b/internal/generator/fft/template/domain.go.tmpl @@ -4,6 +4,7 @@ import ( "runtime" "sync" "io" + "fmt" {{ template "import_fr" . }} {{ template "import_curve" . }} @@ -86,7 +87,7 @@ func NewDomain(m, depth uint64, precomputeReversedTable bool) *Domain { // find generator for Z/2^(log(m))Z and Z/2^(log(m)+cosets)Z logx := uint64(bits.TrailingZeros64(x)) if logx > maxOrderRoot { - panic("m is too big: the required root of unity does not exist") + panic(fmt.Sprintf("m (%d) is too big: the required root of unity does not exist", m)) } logGen := logx + depth if logGen > maxOrderRoot { diff --git a/internal/generator/fft/template/tests/fuzz.go.tmpl b/internal/generator/fft/template/tests/fuzz.go.tmpl index 5a23c0f77..f3f212962 100644 --- a/internal/generator/fft/template/tests/fuzz.go.tmpl +++ b/internal/generator/fft/template/tests/fuzz.go.tmpl @@ -4,6 +4,7 @@ import ( "math/rand" "testing" "time" + "runtime/debug" ) func TestFuzz(t *testing.T) { @@ -15,6 +16,7 @@ func TestFuzz(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error(r) + t.Error(string(debug.Stack())) t.Fatal("test panicked", i, hex.EncodeToString(bytes[:i]), "seed", seed) } }() diff --git a/internal/generator/polynomial/generate.go b/internal/generator/polynomial/generate.go index cf5bb0462..5f19aaba6 100644 --- a/internal/generator/polynomial/generate.go +++ b/internal/generator/polynomial/generate.go @@ -39,6 +39,8 @@ func Generate(conf config.Curve, baseDir string, bgen *bavard.BatchGenerator) er {File: filepath.Join(baseDir, "kzg", "kzg.go"), Templates: []string{"commitment_kzg/kzg.go.tmpl"}}, {File: filepath.Join(baseDir, "kzg", "kzg_test.go"), Templates: []string{"commitment_kzg/kzg.test.go.tmpl"}}, {File: filepath.Join(baseDir, "kzg", "util.go"), Templates: []string{"commitment_kzg/util.go.tmpl"}}, + {File: filepath.Join(baseDir, "kzg", "fuzz.go"), Templates: []string{"commitment_kzg/fuzz.go.tmpl"}, BuildTag: "gofuzz"}, + {File: filepath.Join(baseDir, "kzg", "fuzz_test.go"), Templates: []string{"commitment_kzg/fuzz.test.go.tmpl"}, BuildTag: "gofuzz"}, } if err := bgen.Generate(conf, conf.Package, "./polynomial/template/", entries...); err != nil { return err diff --git a/internal/generator/polynomial/template/commitment_kzg/fuzz.go.tmpl b/internal/generator/polynomial/template/commitment_kzg/fuzz.go.tmpl new file mode 100644 index 000000000..cddad7b64 --- /dev/null +++ b/internal/generator/polynomial/template/commitment_kzg/fuzz.go.tmpl @@ -0,0 +1,70 @@ +import ( + "bytes" + "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr" + {{ .CurvePackage }}_pol "github.com/consensys/gnark-crypto/ecc/{{ .Name }}/fr/polynomial" + "github.com/consensys/gnark-crypto/polynomial" +) + +const ( + fuzzInteresting = 1 + fuzzNormal = 0 + fuzzDiscard = -1 +) + +func Fuzz(data []byte) int { + if len(data) == 0 { + return fuzzDiscard + } + size := int(uint8(data[0])) + 2 // TODO fix min size in NewScheme + if size > (1 << 15) { + size = 1 << 15 + } + r := bytes.NewReader(data[1:]) + var alpha, point fr.Element + alpha.SetRawBytes(r) + point.SetRawBytes(r) + s := NewScheme(size, alpha) + + // create polynomials + f := make([]polynomial.Polynomial, size /2 ) + for i := 0; i < len(f); i++ { + _f := make({{ .CurvePackage }}_pol.Polynomial, size) + for j:=0;j Date: Wed, 2 Jun 2021 17:24:15 -0500 Subject: [PATCH 6/9] feat: added Fuzz pairing billinearity --- ecc/bls12-377/fuzz.go | 37 ++++++++++++++++++ ecc/bls12-381/fuzz.go | 37 ++++++++++++++++++ ecc/bn254/fuzz.go | 37 ++++++++++++++++++ ecc/bw6-761/fuzz.go | 37 ++++++++++++++++++ internal/generator/ecc/template/fuzz.go.tmpl | 40 ++++++++++++++++++++ 5 files changed, 188 insertions(+) diff --git a/ecc/bls12-377/fuzz.go b/ecc/bls12-377/fuzz.go index 0f06ec150..c4007d5c9 100644 --- a/ecc/bls12-377/fuzz.go +++ b/ecc/bls12-377/fuzz.go @@ -19,9 +19,11 @@ package bls12377 import ( + "bytes" "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/mimc" + "math/big" ) const ( @@ -31,8 +33,43 @@ const ( ) func Fuzz(data []byte) int { + // TODO separate in multiple FuzzXXX and update continuous fuzzer scripts + // else, we don't really benefits for fuzzer strategy. fr.Fuzz(data) fp.Fuzz(data) mimc.Fuzz(data) + + // fuzz pairing + r := bytes.NewReader(data) + var e1, e2 fr.Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + var r, r1, r2, r1r2, zero GT + var b1, b2, b1b2 big.Int + e1.ToBigIntRegular(&b1) + e2.ToBigIntRegular(&b2) + b1b2.Mul(&b1, &b2) + + var p1 G1Affine + var p2 G2Affine + + p1.ScalarMultiplication(&g1GenAff, &b1) + p2.ScalarMultiplication(&g2GenAff, &b2) + + r, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff}) + r1, _ = Pair([]G1Affine{p1}, []G2Affine{g2GenAff}) + r2, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{p2}) + + r1r2.Exp(&r, b1b2) + r1.Exp(&r1, b2) + r2.Exp(&r2, b1) + + if !(r1r2.Equal(&r1) && r1r2.Equal(&r2) && !r.Equal(&zero)) { + panic("pairing bilinearity check failed") + } + } + return fuzzNormal } diff --git a/ecc/bls12-381/fuzz.go b/ecc/bls12-381/fuzz.go index 4f0af6e15..7788b7604 100644 --- a/ecc/bls12-381/fuzz.go +++ b/ecc/bls12-381/fuzz.go @@ -19,9 +19,11 @@ package bls12381 import ( + "bytes" "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/mimc" + "math/big" ) const ( @@ -31,8 +33,43 @@ const ( ) func Fuzz(data []byte) int { + // TODO separate in multiple FuzzXXX and update continuous fuzzer scripts + // else, we don't really benefits for fuzzer strategy. fr.Fuzz(data) fp.Fuzz(data) mimc.Fuzz(data) + + // fuzz pairing + r := bytes.NewReader(data) + var e1, e2 fr.Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + var r, r1, r2, r1r2, zero GT + var b1, b2, b1b2 big.Int + e1.ToBigIntRegular(&b1) + e2.ToBigIntRegular(&b2) + b1b2.Mul(&b1, &b2) + + var p1 G1Affine + var p2 G2Affine + + p1.ScalarMultiplication(&g1GenAff, &b1) + p2.ScalarMultiplication(&g2GenAff, &b2) + + r, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff}) + r1, _ = Pair([]G1Affine{p1}, []G2Affine{g2GenAff}) + r2, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{p2}) + + r1r2.Exp(&r, b1b2) + r1.Exp(&r1, b2) + r2.Exp(&r2, b1) + + if !(r1r2.Equal(&r1) && r1r2.Equal(&r2) && !r.Equal(&zero)) { + panic("pairing bilinearity check failed") + } + } + return fuzzNormal } diff --git a/ecc/bn254/fuzz.go b/ecc/bn254/fuzz.go index 2b013e5ab..db43ad465 100644 --- a/ecc/bn254/fuzz.go +++ b/ecc/bn254/fuzz.go @@ -19,9 +19,11 @@ package bn254 import ( + "bytes" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" + "math/big" ) const ( @@ -31,8 +33,43 @@ const ( ) func Fuzz(data []byte) int { + // TODO separate in multiple FuzzXXX and update continuous fuzzer scripts + // else, we don't really benefits for fuzzer strategy. fr.Fuzz(data) fp.Fuzz(data) mimc.Fuzz(data) + + // fuzz pairing + r := bytes.NewReader(data) + var e1, e2 fr.Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + var r, r1, r2, r1r2, zero GT + var b1, b2, b1b2 big.Int + e1.ToBigIntRegular(&b1) + e2.ToBigIntRegular(&b2) + b1b2.Mul(&b1, &b2) + + var p1 G1Affine + var p2 G2Affine + + p1.ScalarMultiplication(&g1GenAff, &b1) + p2.ScalarMultiplication(&g2GenAff, &b2) + + r, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff}) + r1, _ = Pair([]G1Affine{p1}, []G2Affine{g2GenAff}) + r2, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{p2}) + + r1r2.Exp(&r, b1b2) + r1.Exp(&r1, b2) + r2.Exp(&r2, b1) + + if !(r1r2.Equal(&r1) && r1r2.Equal(&r2) && !r.Equal(&zero)) { + panic("pairing bilinearity check failed") + } + } + return fuzzNormal } diff --git a/ecc/bw6-761/fuzz.go b/ecc/bw6-761/fuzz.go index 97f64919c..89848ad68 100644 --- a/ecc/bw6-761/fuzz.go +++ b/ecc/bw6-761/fuzz.go @@ -19,9 +19,11 @@ package bw6761 import ( + "bytes" "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/mimc" + "math/big" ) const ( @@ -31,8 +33,43 @@ const ( ) func Fuzz(data []byte) int { + // TODO separate in multiple FuzzXXX and update continuous fuzzer scripts + // else, we don't really benefits for fuzzer strategy. fr.Fuzz(data) fp.Fuzz(data) mimc.Fuzz(data) + + // fuzz pairing + r := bytes.NewReader(data) + var e1, e2 fr.Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + var r, r1, r2, r1r2, zero GT + var b1, b2, b1b2 big.Int + e1.ToBigIntRegular(&b1) + e2.ToBigIntRegular(&b2) + b1b2.Mul(&b1, &b2) + + var p1 G1Affine + var p2 G2Affine + + p1.ScalarMultiplication(&g1GenAff, &b1) + p2.ScalarMultiplication(&g2GenAff, &b2) + + r, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff}) + r1, _ = Pair([]G1Affine{p1}, []G2Affine{g2GenAff}) + r2, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{p2}) + + r1r2.Exp(&r, b1b2) + r1.Exp(&r1, b2) + r2.Exp(&r2, b1) + + if !(r1r2.Equal(&r1) && r1r2.Equal(&r2) && !r.Equal(&zero)) { + panic("pairing bilinearity check failed") + } + } + return fuzzNormal } diff --git a/internal/generator/ecc/template/fuzz.go.tmpl b/internal/generator/ecc/template/fuzz.go.tmpl index 3f0371f13..8406c423b 100644 --- a/internal/generator/ecc/template/fuzz.go.tmpl +++ b/internal/generator/ecc/template/fuzz.go.tmpl @@ -8,6 +8,8 @@ import ( + "bytes" + "math/big" "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr/mimc" @@ -20,8 +22,46 @@ const ( ) func Fuzz(data []byte) int { + // TODO separate in multiple FuzzXXX and update continuous fuzzer scripts + // else, we don't really benefits for fuzzer strategy. fr.Fuzz(data) fp.Fuzz(data) mimc.Fuzz(data) + + // fuzz pairing + r := bytes.NewReader(data) + var e1, e2 fr.Element + e1.SetRawBytes(r) + e2.SetRawBytes(r) + + { + var r, r1, r2, r1r2, zero GT + var b1, b2, b1b2 big.Int + e1.ToBigIntRegular(&b1) + e2.ToBigIntRegular(&b2) + b1b2.Mul(&b1, &b2) + + var p1 {{$G1TAffine}} + var p2 {{$G2TAffine}} + + p1.ScalarMultiplication(&g1GenAff, &b1) + p2.ScalarMultiplication(&g2GenAff, &b2) + + r, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff}) + r1, _ = Pair([]G1Affine{p1}, []G2Affine{g2GenAff}) + r2, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{p2}) + + r1r2.Exp(&r, b1b2) + r1.Exp(&r1, b2) + r2.Exp(&r2, b1) + + if !(r1r2.Equal(&r1) && r1r2.Equal(&r2) && !r.Equal(&zero)) { + panic("pairing bilinearity check failed") + } + } + + + + return fuzzNormal } \ No newline at end of file From 3a7296e31d976a233bb320175a180ef353889074 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Wed, 2 Jun 2021 17:30:31 -0500 Subject: [PATCH 7/9] fix: kzg serilization test comparing address instead of value --- ecc/bls12-377/fr/polynomial/kzg/kzg_test.go | 2 +- ecc/bls12-381/fr/polynomial/kzg/kzg_test.go | 2 +- ecc/bn254/fr/polynomial/kzg/kzg_test.go | 2 +- ecc/bw6-761/fr/polynomial/kzg/kzg_test.go | 2 +- .../polynomial/template/commitment_kzg/kzg.test.go.tmpl | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go b/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go index 7233f9976..c2613f473 100644 --- a/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bls12-377/fr/polynomial/kzg/kzg_test.go @@ -106,7 +106,7 @@ func TestSerialization(t *testing.T) { } // compare - if !reflect.DeepEqual(&s, &_s) { + if !reflect.DeepEqual(s, &_s) { t.Fatal("scheme serialization failed") } diff --git a/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go b/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go index c0629f419..d3776ceca 100644 --- a/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bls12-381/fr/polynomial/kzg/kzg_test.go @@ -106,7 +106,7 @@ func TestSerialization(t *testing.T) { } // compare - if !reflect.DeepEqual(&s, &_s) { + if !reflect.DeepEqual(s, &_s) { t.Fatal("scheme serialization failed") } diff --git a/ecc/bn254/fr/polynomial/kzg/kzg_test.go b/ecc/bn254/fr/polynomial/kzg/kzg_test.go index 72d2e27f1..5b1392562 100644 --- a/ecc/bn254/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bn254/fr/polynomial/kzg/kzg_test.go @@ -106,7 +106,7 @@ func TestSerialization(t *testing.T) { } // compare - if !reflect.DeepEqual(&s, &_s) { + if !reflect.DeepEqual(s, &_s) { t.Fatal("scheme serialization failed") } diff --git a/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go b/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go index da679d4c7..374bd60f2 100644 --- a/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go +++ b/ecc/bw6-761/fr/polynomial/kzg/kzg_test.go @@ -106,7 +106,7 @@ func TestSerialization(t *testing.T) { } // compare - if !reflect.DeepEqual(&s, &_s) { + if !reflect.DeepEqual(s, &_s) { t.Fatal("scheme serialization failed") } diff --git a/internal/generator/polynomial/template/commitment_kzg/kzg.test.go.tmpl b/internal/generator/polynomial/template/commitment_kzg/kzg.test.go.tmpl index 7f5e76418..dc16bcf4e 100644 --- a/internal/generator/polynomial/template/commitment_kzg/kzg.test.go.tmpl +++ b/internal/generator/polynomial/template/commitment_kzg/kzg.test.go.tmpl @@ -90,7 +90,7 @@ func TestSerialization(t *testing.T) { } // compare - if !reflect.DeepEqual(&s, &_s) { + if !reflect.DeepEqual(s, &_s) { t.Fatal("scheme serialization failed") } From 94682878601719ac5cb403b421d61f92532bf07e Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Fri, 4 Jun 2021 16:36:23 -0500 Subject: [PATCH 8/9] feat: added Reference benchamrk for continuous benchmarking. fixes #54 --- ecc/bls12-377/fr/fft/fft_test.go | 32 ++++++++++++ ecc/bls12-377/multiexp_test.go | 50 +++++++++++++++++++ ecc/bls12-381/fr/fft/fft_test.go | 32 ++++++++++++ ecc/bls12-381/multiexp_test.go | 50 +++++++++++++++++++ ecc/bn254/fr/fft/fft_test.go | 32 ++++++++++++ ecc/bn254/multiexp_test.go | 50 +++++++++++++++++++ ecc/bw6-761/fr/fft/fft_test.go | 32 ++++++++++++ ecc/bw6-761/multiexp_test.go | 50 +++++++++++++++++++ .../ecc/template/tests/multiexp.go.tmpl | 26 ++++++++++ .../generator/fft/template/tests/fft.go.tmpl | 32 ++++++++++++ 10 files changed, 386 insertions(+) diff --git a/ecc/bls12-377/fr/fft/fft_test.go b/ecc/bls12-377/fr/fft/fft_test.go index ebd66639b..282a5bb4e 100644 --- a/ecc/bls12-377/fr/fft/fft_test.go +++ b/ecc/bls12-377/fr/fft/fft_test.go @@ -372,6 +372,38 @@ func BenchmarkFFT(b *testing.B) { } +func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 1, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIT, 1) + } +} + +func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 0, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIF, 0) + } +} + func evaluatePolynomial(pol []fr.Element, val fr.Element) fr.Element { var acc, res, tmp fr.Element res.Set(&pol[0]) diff --git a/ecc/bls12-377/multiexp_test.go b/ecc/bls12-377/multiexp_test.go index 53ae9a073..77918fd5f 100644 --- a/ecc/bls12-377/multiexp_test.go +++ b/ecc/bls12-377/multiexp_test.go @@ -649,6 +649,31 @@ func BenchmarkMultiExpG1(b *testing.B) { } } +func BenchmarkMultiExpG1Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G1Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g1GenAff + } + + var testPoint G1Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} + func TestMultiExpG2(t *testing.T) { parameters := gopter.DefaultTestParameters() @@ -1268,3 +1293,28 @@ func BenchmarkMultiExpG2(b *testing.B) { }) } } + +func BenchmarkMultiExpG2Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G2Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g2GenAff + } + + var testPoint G2Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} diff --git a/ecc/bls12-381/fr/fft/fft_test.go b/ecc/bls12-381/fr/fft/fft_test.go index 0ed6c7404..e91fc6261 100644 --- a/ecc/bls12-381/fr/fft/fft_test.go +++ b/ecc/bls12-381/fr/fft/fft_test.go @@ -372,6 +372,38 @@ func BenchmarkFFT(b *testing.B) { } +func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 1, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIT, 1) + } +} + +func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 0, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIF, 0) + } +} + func evaluatePolynomial(pol []fr.Element, val fr.Element) fr.Element { var acc, res, tmp fr.Element res.Set(&pol[0]) diff --git a/ecc/bls12-381/multiexp_test.go b/ecc/bls12-381/multiexp_test.go index 457bc1a96..c60819cf7 100644 --- a/ecc/bls12-381/multiexp_test.go +++ b/ecc/bls12-381/multiexp_test.go @@ -649,6 +649,31 @@ func BenchmarkMultiExpG1(b *testing.B) { } } +func BenchmarkMultiExpG1Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G1Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g1GenAff + } + + var testPoint G1Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} + func TestMultiExpG2(t *testing.T) { parameters := gopter.DefaultTestParameters() @@ -1268,3 +1293,28 @@ func BenchmarkMultiExpG2(b *testing.B) { }) } } + +func BenchmarkMultiExpG2Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G2Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g2GenAff + } + + var testPoint G2Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} diff --git a/ecc/bn254/fr/fft/fft_test.go b/ecc/bn254/fr/fft/fft_test.go index 57ffb6081..2df18705d 100644 --- a/ecc/bn254/fr/fft/fft_test.go +++ b/ecc/bn254/fr/fft/fft_test.go @@ -372,6 +372,38 @@ func BenchmarkFFT(b *testing.B) { } +func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 1, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIT, 1) + } +} + +func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 0, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIF, 0) + } +} + func evaluatePolynomial(pol []fr.Element, val fr.Element) fr.Element { var acc, res, tmp fr.Element res.Set(&pol[0]) diff --git a/ecc/bn254/multiexp_test.go b/ecc/bn254/multiexp_test.go index 4f7f4170f..902a6637c 100644 --- a/ecc/bn254/multiexp_test.go +++ b/ecc/bn254/multiexp_test.go @@ -649,6 +649,31 @@ func BenchmarkMultiExpG1(b *testing.B) { } } +func BenchmarkMultiExpG1Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G1Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g1GenAff + } + + var testPoint G1Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} + func TestMultiExpG2(t *testing.T) { parameters := gopter.DefaultTestParameters() @@ -1268,3 +1293,28 @@ func BenchmarkMultiExpG2(b *testing.B) { }) } } + +func BenchmarkMultiExpG2Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G2Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g2GenAff + } + + var testPoint G2Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} diff --git a/ecc/bw6-761/fr/fft/fft_test.go b/ecc/bw6-761/fr/fft/fft_test.go index 40d5e5262..33f68d93f 100644 --- a/ecc/bw6-761/fr/fft/fft_test.go +++ b/ecc/bw6-761/fr/fft/fft_test.go @@ -372,6 +372,38 @@ func BenchmarkFFT(b *testing.B) { } +func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 1, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIT, 1) + } +} + +func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 0, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIF, 0) + } +} + func evaluatePolynomial(pol []fr.Element, val fr.Element) fr.Element { var acc, res, tmp fr.Element res.Set(&pol[0]) diff --git a/ecc/bw6-761/multiexp_test.go b/ecc/bw6-761/multiexp_test.go index 07439c45d..fcb964bb3 100644 --- a/ecc/bw6-761/multiexp_test.go +++ b/ecc/bw6-761/multiexp_test.go @@ -289,6 +289,31 @@ func BenchmarkMultiExpG1(b *testing.B) { } } +func BenchmarkMultiExpG1Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G1Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g1GenAff + } + + var testPoint G1Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} + func TestMultiExpG2(t *testing.T) { parameters := gopter.DefaultTestParameters() @@ -548,3 +573,28 @@ func BenchmarkMultiExpG2(b *testing.B) { }) } } + +func BenchmarkMultiExpG2Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]G2Affine + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = g2GenAff + } + + var testPoint G2Affine + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} diff --git a/internal/generator/ecc/template/tests/multiexp.go.tmpl b/internal/generator/ecc/template/tests/multiexp.go.tmpl index f7d4e0c84..8ad79787e 100644 --- a/internal/generator/ecc/template/tests/multiexp.go.tmpl +++ b/internal/generator/ecc/template/tests/multiexp.go.tmpl @@ -207,4 +207,30 @@ func BenchmarkMultiExp{{ toUpper $.PointName }}(b *testing.B) { } +func BenchmarkMultiExp{{ toUpper $.PointName }}Reference(b *testing.B) { + // ensure every words of the scalars are filled + var mixer fr.Element + mixer.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") + + const nbSamples = 1 << 20 + + var samplePoints [nbSamples]{{ $.TAffine }} + var sampleScalars [nbSamples]fr.Element + + for i := 1; i <= nbSamples; i++ { + sampleScalars[i-1].SetUint64(uint64(i)). + Mul(&sampleScalars[i-1], &mixer). + FromMont() + samplePoints[i-1] = {{ toLower .PointName}}GenAff + } + + var testPoint {{ $.TAffine }} + + b.ResetTimer() + for j := 0; j < b.N; j++ { + testPoint.MultiExp(samplePoints[:], sampleScalars[:]) + } +} + + {{end }} \ No newline at end of file diff --git a/internal/generator/fft/template/tests/fft.go.tmpl b/internal/generator/fft/template/tests/fft.go.tmpl index 26e566630..c432f61f2 100644 --- a/internal/generator/fft/template/tests/fft.go.tmpl +++ b/internal/generator/fft/template/tests/fft.go.tmpl @@ -355,6 +355,38 @@ func BenchmarkFFT(b *testing.B) { } +func BenchmarkFFTDITCosetReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 1, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIT, 1) + } +} + +func BenchmarkFFTDIFReference(b *testing.B) { + const maxSize = 1 << 20 + + pol := make([]fr.Element, maxSize) + for i := uint64(0); i < maxSize; i++ { + pol[i].SetRandom() + } + + domain := NewDomain(uint64(maxSize), 0, false) + + b.ResetTimer() + for j := 0; j < b.N; j++ { + domain.FFT(pol, DIF, 0) + } +} + func evaluatePolynomial(pol []fr.Element, val fr.Element) fr.Element { var acc, res, tmp fr.Element res.Set(&pol[0]) From 0358592381aebed880b1fc00521fe24f54a31167 Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Fri, 4 Jun 2021 16:37:18 -0500 Subject: [PATCH 9/9] build: re-ran go genearte --- ecc/bls12-377/fr/fft/fft_test.go | 4 ++-- ecc/bls12-381/fr/fft/fft_test.go | 4 ++-- ecc/bn254/fr/fft/fft_test.go | 4 ++-- ecc/bw6-761/fr/fft/fft_test.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ecc/bls12-377/fr/fft/fft_test.go b/ecc/bls12-377/fr/fft/fft_test.go index 282a5bb4e..c43ce49fa 100644 --- a/ecc/bls12-377/fr/fft/fft_test.go +++ b/ecc/bls12-377/fr/fft/fft_test.go @@ -372,7 +372,7 @@ func BenchmarkFFT(b *testing.B) { } -func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { +func BenchmarkFFTDITCosetReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) @@ -388,7 +388,7 @@ func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { } } -func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { +func BenchmarkFFTDIFReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) diff --git a/ecc/bls12-381/fr/fft/fft_test.go b/ecc/bls12-381/fr/fft/fft_test.go index e91fc6261..6cac383c8 100644 --- a/ecc/bls12-381/fr/fft/fft_test.go +++ b/ecc/bls12-381/fr/fft/fft_test.go @@ -372,7 +372,7 @@ func BenchmarkFFT(b *testing.B) { } -func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { +func BenchmarkFFTDITCosetReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) @@ -388,7 +388,7 @@ func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { } } -func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { +func BenchmarkFFTDIFReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) diff --git a/ecc/bn254/fr/fft/fft_test.go b/ecc/bn254/fr/fft/fft_test.go index 2df18705d..15c88955e 100644 --- a/ecc/bn254/fr/fft/fft_test.go +++ b/ecc/bn254/fr/fft/fft_test.go @@ -372,7 +372,7 @@ func BenchmarkFFT(b *testing.B) { } -func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { +func BenchmarkFFTDITCosetReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) @@ -388,7 +388,7 @@ func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { } } -func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { +func BenchmarkFFTDIFReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) diff --git a/ecc/bw6-761/fr/fft/fft_test.go b/ecc/bw6-761/fr/fft/fft_test.go index 33f68d93f..56a232346 100644 --- a/ecc/bw6-761/fr/fft/fft_test.go +++ b/ecc/bw6-761/fr/fft/fft_test.go @@ -372,7 +372,7 @@ func BenchmarkFFT(b *testing.B) { } -func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { +func BenchmarkFFTDITCosetReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize) @@ -388,7 +388,7 @@ func BenchmarkFFTCosetNoPrecomputeDITReference(b *testing.B) { } } -func BenchmarkFFTNoPrecomputeDIFReference(b *testing.B) { +func BenchmarkFFTDIFReference(b *testing.B) { const maxSize = 1 << 20 pol := make([]fr.Element, maxSize)