neo-go/pkg/core/native/crypto_blspoints.go
Anna Shaleva 71bcb8bade native: allow to use EQUAL opcode for BLS12-381 points comparison
That's the way how C# node handles equality checks for stackitem.Interop types
for these points. Ref. https://github.com/nspcc-dev/neo-go/issues/3002#issuecomment-1591220501.

Along the way, add GT case for CryptoLib's bls12381Equal method. It should be there since #2940.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2023-06-15 15:00:27 +03:00

104 lines
2.6 KiB
Go

package native
import (
"errors"
"fmt"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
// blsPoint is a wrapper around bls12381 point types that must be used as
// stackitem.Interop values and implement stackitem.Equatable interface.
type blsPoint struct {
point any
}
var _ = stackitem.Equatable(blsPoint{})
// Equals implements stackitem.Equatable interface.
func (p blsPoint) Equals(other stackitem.Equatable) bool {
res, err := p.EqualsCheckType(other)
return err == nil && res
}
// EqualsCheckType checks whether other is of the same type as p and returns an error if not.
// It also returns whether other and p are equal.
func (p blsPoint) EqualsCheckType(other stackitem.Equatable) (bool, error) {
b, ok := other.(blsPoint)
if !ok {
return false, errors.New("not a bls12-381 point")
}
var (
res bool
err error
)
switch x := p.point.(type) {
case *bls12381.G1Affine:
y, ok := b.point.(*bls12381.G1Affine)
if !ok {
err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G1Affine", y)
break
}
res = x.Equal(y)
case *bls12381.G1Jac:
y, ok := b.point.(*bls12381.G1Jac)
if !ok {
err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G1Jac", y)
break
}
res = x.Equal(y)
case *bls12381.G2Affine:
y, ok := b.point.(*bls12381.G2Affine)
if !ok {
err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G2Affine", y)
break
}
res = x.Equal(y)
case *bls12381.G2Jac:
y, ok := b.point.(*bls12381.G2Jac)
if !ok {
err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs G2Jac", y)
break
}
res = x.Equal(y)
case *bls12381.GT:
y, ok := b.point.(*bls12381.GT)
if !ok {
err = fmt.Errorf("equal: unexpected y bls12381 point type: %T vs GT", y)
break
}
res = x.Equal(y)
default:
err = fmt.Errorf("equal: unexpected x bls12381 point type: %T", x)
}
return res, err
}
// Bytes returns serialized representation of the provided point in compressed form.
func (p blsPoint) Bytes() []byte {
switch p := p.point.(type) {
case *bls12381.G1Affine:
compressed := p.Bytes()
return compressed[:]
case *bls12381.G1Jac:
g1Affine := new(bls12381.G1Affine)
g1Affine.FromJacobian(p)
compressed := g1Affine.Bytes()
return compressed[:]
case *bls12381.G2Affine:
compressed := p.Bytes()
return compressed[:]
case *bls12381.G2Jac:
g2Affine := new(bls12381.G2Affine)
g2Affine.FromJacobian(p)
compressed := g2Affine.Bytes()
return compressed[:]
case *bls12381.GT:
compressed := p.Bytes()
return compressed[:]
default:
panic(errors.New("unknown bls12381 point type"))
}
}