Skip to content

Commit

Permalink
[CI] Fix device race in golang tests (#612)
Browse files Browse the repository at this point in the history
- Update golang tests to include a suite that allows us to wrap
each test in a function that will handle calling runtime.SetDevice.
- Add zero checks on affine to projective in Go and Rust
  • Loading branch information
jeremyfelder authored Sep 20, 2024
1 parent 58414e2 commit 9086ff1
Show file tree
Hide file tree
Showing 104 changed files with 3,036 additions and 1,509 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
with:
pr-number: ${{ github.event.pull_request.number }}

# TODO - add runtime tests to the workflow
# TODO - add core tests to the workflow

build-curves-linux:
name: Build and test curves on Linux
runs-on: [self-hosted, Linux, X64, icicle]
Expand Down
4 changes: 4 additions & 0 deletions wrappers/golang/core/internal/mock_curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func (a *MockAffine) Zero() MockAffine {
return *a
}

func (a *MockAffine) IsZero() bool {
return a.X.IsZero() && a.Y.IsZero()
}

func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine {
a.X.FromLimbs(x)
a.Y.FromLimbs(y)
Expand Down
10 changes: 10 additions & 0 deletions wrappers/golang/core/internal/mock_field.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ func (f *MockBaseField) Zero() MockBaseField {
return *f
}

func (f *MockBaseField) IsZero() bool {
for _, limb := range f.limbs {
if limb != 0 {
return false
}
}

return true
}

func (f *MockBaseField) One() MockBaseField {
for i := range f.limbs {
f.limbs[i] = 0
Expand Down
10 changes: 10 additions & 0 deletions wrappers/golang/curves/bls12377/base_field.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ func (f *BaseField) Zero() BaseField {
return *f
}

func (f *BaseField) IsZero() bool {
for _, limb := range f.limbs {
if limb != 0 {
return false
}
}

return true
}

func (f *BaseField) One() BaseField {
for i := range f.limbs {
f.limbs[i] = 0
Expand Down
20 changes: 17 additions & 3 deletions wrappers/golang/curves/bls12377/curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ func (a *Affine) Zero() Affine {
return *a
}

func (a *Affine) IsZero() bool {
return a.X.IsZero() && a.Y.IsZero()
}

func (a *Affine) FromLimbs(x, y []uint32) Affine {
a.X.FromLimbs(x)
a.Y.FromLimbs(y)
Expand All @@ -106,9 +110,19 @@ func (a *Affine) FromLimbs(x, y []uint32) Affine {
func (a Affine) ToProjective() Projective {
var p Projective

cA := (*C.affine_t)(unsafe.Pointer(&a))
cP := (*C.projective_t)(unsafe.Pointer(&p))
C.bls12_377_from_affine(cA, cP)
// TODO - Figure out why this sometimes returns an empty projective point, i.e. {x:0, y:0, z:0}
// cA := (*C.affine_t)(unsafe.Pointer(&a))
// cP := (*C.projective_t)(unsafe.Pointer(&p))
// C.bls12_377_from_affine(cA, cP)

if a.IsZero() {
p.Zero()
} else {
p.X = a.X
p.Y = a.Y
p.Z.One()
}

return p
}

Expand Down
20 changes: 17 additions & 3 deletions wrappers/golang/curves/bls12377/g2/curve.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ func (a *G2Affine) Zero() G2Affine {
return *a
}

func (a *G2Affine) IsZero() bool {
return a.X.IsZero() && a.Y.IsZero()
}

func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine {
a.X.FromLimbs(x)
a.Y.FromLimbs(y)
Expand All @@ -106,9 +110,19 @@ func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine {
func (a G2Affine) ToProjective() G2Projective {
var p G2Projective

cA := (*C.g2_affine_t)(unsafe.Pointer(&a))
cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
C.bls12_377_g2_from_affine(cA, cP)
// TODO - Figure out why this sometimes returns an empty projective point, i.e. {x:0, y:0, z:0}
// cA := (*C.g2_affine_t)(unsafe.Pointer(&a))
// cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
// C.bls12_377_g2_from_affine(cA, cP)

if a.IsZero() {
p.Zero()
} else {
p.X = a.X
p.Y = a.Y
p.Z.One()
}

return p
}

Expand Down
10 changes: 10 additions & 0 deletions wrappers/golang/curves/bls12377/g2/g2base_field.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ func (f *G2BaseField) Zero() G2BaseField {
return *f
}

func (f *G2BaseField) IsZero() bool {
for _, limb := range f.limbs {
if limb != 0 {
return false
}
}

return true
}

func (f *G2BaseField) One() G2BaseField {
for i := range f.limbs {
f.limbs[i] = 0
Expand Down
10 changes: 10 additions & 0 deletions wrappers/golang/curves/bls12377/scalar_field.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ func (f *ScalarField) Zero() ScalarField {
return *f
}

func (f *ScalarField) IsZero() bool {
for _, limb := range f.limbs {
if limb != 0 {
return false
}
}

return true
}

func (f *ScalarField) One() ScalarField {
for i := range f.limbs {
f.limbs[i] = 0
Expand Down
60 changes: 40 additions & 20 deletions wrappers/golang/curves/bls12377/tests/base_field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,105 @@ import (

bls12_377 "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/v3/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

const (
BASE_LIMBS = bls12_377.BASE_LIMBS
)

func TestBaseFieldFromLimbs(t *testing.T) {
func testBaseFieldFromLimbs(suite suite.Suite) {
emptyField := bls12_377.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
suite.ElementsMatch(randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
suite.NotEqual(randLimbs, emptyField.GetLimbs())
}

func TestBaseFieldGetLimbs(t *testing.T) {
func testBaseFieldGetLimbs(suite suite.Suite) {
emptyField := bls12_377.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])

assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
suite.ElementsMatch(randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
}

func TestBaseFieldOne(t *testing.T) {
func testBaseFieldOne(suite suite.Suite) {
var emptyField bls12_377.BaseField
emptyField.One()
limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
suite.ElementsMatch(emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")

randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])

emptyField.One()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work")
suite.ElementsMatch(emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work")
}

func TestBaseFieldZero(t *testing.T) {
func testBaseFieldZero(suite suite.Suite) {
var emptyField bls12_377.BaseField
emptyField.Zero()
limbsZero := make([]uint32, BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
suite.ElementsMatch(emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")

randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])

emptyField.Zero()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed")
suite.ElementsMatch(emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed")
}

func TestBaseFieldSize(t *testing.T) {
func testBaseFieldSize(suite suite.Suite) {
var emptyField bls12_377.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])

assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
suite.Equal(len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}

func TestBaseFieldAsPointer(t *testing.T) {
func testBaseFieldAsPointer(suite suite.Suite) {
var emptyField bls12_377.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])

assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
suite.Equal(randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}

func TestBaseFieldFromBytes(t *testing.T) {
func testBaseFieldFromBytes(suite suite.Suite) {
var emptyField bls12_377.BaseField
bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS))

emptyField.FromBytesLittleEndian(bytes)

assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
suite.ElementsMatch(emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}

func TestBaseFieldToBytes(t *testing.T) {
func testBaseFieldToBytes(suite suite.Suite) {
var emptyField bls12_377.BaseField
expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS))
emptyField.FromLimbs(limbs)

assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
suite.ElementsMatch(emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}

type BaseFieldTestSuite struct {
suite.Suite
}

func (s *BaseFieldTestSuite) TestBaseField() {
s.Run("TestBaseFieldFromLimbs", testWrapper(s.Suite, testBaseFieldFromLimbs))
s.Run("TestBaseFieldGetLimbs", testWrapper(s.Suite, testBaseFieldGetLimbs))
s.Run("TestBaseFieldOne", testWrapper(s.Suite, testBaseFieldOne))
s.Run("TestBaseFieldZero", testWrapper(s.Suite, testBaseFieldZero))
s.Run("TestBaseFieldSize", testWrapper(s.Suite, testBaseFieldSize))
s.Run("TestBaseFieldAsPointer", testWrapper(s.Suite, testBaseFieldAsPointer))
s.Run("TestBaseFieldFromBytes", testWrapper(s.Suite, testBaseFieldFromBytes))
s.Run("TestBaseFieldToBytes", testWrapper(s.Suite, testBaseFieldToBytes))

}

func TestSuiteBaseField(t *testing.T) {
suite.Run(t, new(BaseFieldTestSuite))
}
Loading

0 comments on commit 9086ff1

Please sign in to comment.