Skip to content

Commit

Permalink
Replace BLS library with github.com/kilic/bn254 (#978)
Browse files Browse the repository at this point in the history
  • Loading branch information
igorcrevar committed Nov 30, 2022
1 parent 07ce7e6 commit e96eeda
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 235 deletions.
94 changes: 5 additions & 89 deletions consensus/polybft/signer/common.go
@@ -1,100 +1,16 @@
package bls

import (
"crypto/sha256"
"errors"
"math/big"

"github.com/0xPolygon/polygon-edge/helper/common"
bn256 "github.com/umbracle/go-eth-bn256"
"encoding/hex"
)

var (
zeroBigInt = *big.NewInt(0)
oneBigInt = *big.NewInt(1)
g2 = *new(bn256.G2).ScalarBaseMult(&oneBigInt) // Generator point of G2 group
zeroG1 = *new(bn256.G1).ScalarBaseMult(&zeroBigInt) // Zero point in G2 group
zeroG2 = *new(bn256.G2).ScalarBaseMult(&zeroBigInt) // Zero point in G2 group

// this is a copy of point p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
// TODO delete this point and use bn256.p
bn256P, _ = new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10)
domain, _ = hex.DecodeString("508e30424791cb9a71683381558c3da1979b6fa423b2d6db1396b1d94d7c4a78")
)

func sum(ints ...*big.Int) *big.Int {
acc := big.NewInt(0)
for _, num := range ints {
acc.Add(acc, num)
}

return acc
}

func product(ints ...*big.Int) *big.Int {
acc := big.NewInt(1)
for _, num := range ints {
acc.Mul(acc, num)
}

return acc
}

func mod(i, m *big.Int) *big.Int {
return new(big.Int).Mod(i, m)
}

// modSqrt returns square root of x mod p if such a square root exists. The
// modulus p must be an odd prime. If x is not a square mod p, function returns
// nil.
func modSqrt(x, p *big.Int) *big.Int {
return new(big.Int).ModSqrt(x, p)
}

// yFromX calculates and returns only one of the two possible Ys, by
// solving the curve equation for X, the two Ys can be distinguished by
// their parity.
func yFromX(x *big.Int) *big.Int {
return modSqrt(sum(product(x, x, x), big.NewInt(3)), bn256P)
}

// g1FromInts returns G1 point based on the provided x and y.
func g1FromInts(x *big.Int, y *big.Int) (*bn256.G1, error) {
const size = 32

if len(x.Bytes()) > size || len(y.Bytes()) > size {
return nil, errors.New("points on G1 are limited to 256-bit coordinates")
}

paddedX := common.PadLeftOrTrim(x.Bytes(), size)
paddedY := common.PadLeftOrTrim(y.Bytes(), size)

m := append(paddedX, paddedY...)

g1 := new(bn256.G1)

_, err := g1.Unmarshal(m)
if err != nil {
return nil, err
}

return g1, nil
}

// g1HashToPoint hashes the provided byte slice, maps it into a G1
// and returns it as a G1 point.
func g1HashToPoint(m []byte) (*bn256.G1, error) {
one := big.NewInt(1)
h := sha256.Sum256(m)
x := mod(new(big.Int).SetBytes(h[:]), bn256P)

for {
y := yFromX(x)
if y != nil {
return g1FromInts(x, y)
}

x.Add(x, one)
}
// Returns bls/bn254 domain
func GetDomain() []byte {
return domain
}

// colects public keys from the BlsKeys
Expand Down
22 changes: 15 additions & 7 deletions consensus/polybft/signer/private.go
@@ -1,11 +1,10 @@
package bls

import (
"math/big"

"errors"
"math/big"

bn256 "github.com/umbracle/go-eth-bn256"
"github.com/kilic/bn254"
)

type PrivateKey struct {
Expand All @@ -14,17 +13,26 @@ type PrivateKey struct {

// PublicKey returns the public key from the PrivateKey
func (p *PrivateKey) PublicKey() *PublicKey {
return &PublicKey{p: new(bn256.G2).ScalarBaseMult(p.p)}
g2 := bn254.NewG2()
public := g2.New()

g2.MulScalar(public, g2.One(), p.p)

return &PublicKey{p: public}
}

// Sign generates a simple BLS signature of the given message
func (p *PrivateKey) Sign(message []byte) (*Signature, error) {
hashPoint, err := g1HashToPoint(message)
g := bn254.NewG1()

signature, err := g.HashToCurveFT(message, GetDomain())
if err != nil {
return &Signature{}, err
return nil, err
}

return &Signature{p: new(bn256.G1).ScalarMult(hashPoint, p.p)}, nil
g.MulScalar(signature, signature, p.p)

return &Signature{signature}, nil
}

// MarshalJSON marshal the key to bytes.
Expand Down
57 changes: 37 additions & 20 deletions consensus/polybft/signer/public.go
Expand Up @@ -6,36 +6,46 @@ import (
"math/big"

"github.com/0xPolygon/polygon-edge/helper/common"
bn256 "github.com/umbracle/go-eth-bn256"
"github.com/kilic/bn254"
)

// PublicKey represents bls public key
type PublicKey struct {
p *bn256.G2
p *bn254.PointG2
}

// aggregate adds the given public keys
func (p *PublicKey) aggregate(onemore *PublicKey) *PublicKey {
var g2 *bn256.G2
if p.p == nil {
g2 = new(bn256.G2).Set(&zeroG2)
} else {
g2 = new(bn256.G2).Set(p.p)
func (p *PublicKey) aggregate(next *PublicKey) *PublicKey {
g := bn254.NewG2()

newp := new(bn254.PointG2)
newp.Zero()

if p.p != nil {
if next.p != nil {
g.Add(newp, p.p, next.p)
} else {
newp.Set(p.p)
}
} else if next.p != nil {
newp.Set(next.p)
}

g2.Add(g2, onemore.p)

return &PublicKey{p: g2}
return &PublicKey{p: newp}
}

// Marshal marshal the key to bytes.
func (p *PublicKey) Marshal() []byte {
return p.p.Marshal()
if p.p == nil {
return nil
}

return bn254.NewG2().ToBytes(p.p)
}

// MarshalJSON implements the json.Marshaler interface.
func (p *PublicKey) MarshalJSON() ([]byte, error) {
return json.Marshal(p.p.Marshal())
return json.Marshal(p.Marshal())
}

// UnmarshalJSON implements the json.Marshaler interface.
Expand Down Expand Up @@ -63,10 +73,12 @@ func UnmarshalPublicKey(raw []byte) (*PublicKey, error) {
return nil, errors.New("cannot unmarshal public key from empty slice")
}

p := new(bn256.G2)
_, err := p.Unmarshal(raw)
p, err := bn254.NewG2().FromBytes(raw)
if err != nil {
return nil, err
}

return &PublicKey{p: p}, err
return &PublicKey{p: p}, nil
}

// ToBigInt converts public key to 4 big ints
Expand Down Expand Up @@ -104,10 +116,15 @@ func UnmarshalPublicKeyFromBigInt(b [4]*big.Int) (*PublicKey, error) {

// aggregatePublicKeys calculates P1 + P2 + ...
func aggregatePublicKeys(pubs []*PublicKey) *PublicKey {
res := *new(bn256.G2).Set(&zeroG2)
for i := 0; i < len(pubs); i++ {
res.Add(&res, pubs[i].p)
g, newp := bn254.NewG2(), new(bn254.PointG2)

newp.Set(g.Zero())

for _, x := range pubs {
if x.p != nil {
g.Add(newp, newp, x.p)
}
}

return &PublicKey{p: &res}
return &PublicKey{p: newp}
}
63 changes: 38 additions & 25 deletions consensus/polybft/signer/signature.go
Expand Up @@ -4,26 +4,27 @@ import (
"errors"
"math/big"

bn256 "github.com/umbracle/go-eth-bn256"
"github.com/kilic/bn254"
)

// Signature represents bls signature which is point on the curve
type Signature struct {
p *bn256.G1
p *bn254.PointG1
}

// Verify checks the BLS signature of the message against the public key of its signer
func (s *Signature) Verify(publicKey *PublicKey, message []byte) bool {
hashPoint, err := g1HashToPoint(message)
e := bn254.NewEngine()
messagePoint, err := e.G1.HashToCurveFT(message, GetDomain())

if err != nil {
// this should never happen, probably need a log here
return false
}

a := []*bn256.G1{new(bn256.G1).Neg(s.p), hashPoint}
b := []*bn256.G2{&g2, publicKey.p}
e.AddPair(messagePoint, publicKey.p)
e.AddPairInv(s.p, e.G2.One())

return bn256.PairingCheck(a, b)
return e.Check()
}

// VerifyAggregated checks the BLS signature of the message against the aggregated public keys of its signers
Expand All @@ -34,17 +35,23 @@ func (s *Signature) VerifyAggregated(publicKeys []*PublicKey, msg []byte) bool {
}

// Aggregate adds the given signatures
func (s *Signature) Aggregate(onemore *Signature) *Signature {
var p *bn256.G1
if s.p == nil {
p = new(bn256.G1).Set(&zeroG1)
} else {
p = new(bn256.G1).Set(s.p)
func (s *Signature) Aggregate(next *Signature) *Signature {
g := bn254.NewG1()

newp := new(bn254.PointG1)
newp.Zero()

if s.p != nil {
if next.p != nil {
g.Add(newp, s.p, next.p)
} else {
newp.Set(s.p)
}
} else if next.p != nil {
newp.Set(next.p)
}

p.Add(p, onemore.p)

return &Signature{p: p}
return &Signature{p: newp}
}

// Marshal the signature to bytes.
Expand All @@ -53,7 +60,7 @@ func (s *Signature) Marshal() ([]byte, error) {
return nil, errors.New("cannot marshal empty signature")
}

return s.p.Marshal(), nil
return bn254.NewG1().ToBytes(s.p), nil
}

// UnmarshalSignature reads the signature from the given byte array
Expand All @@ -62,10 +69,12 @@ func UnmarshalSignature(raw []byte) (*Signature, error) {
return nil, errors.New("cannot unmarshal signature from empty slice")
}

p := new(bn256.G1)
_, err := p.Unmarshal(raw)
p, err := bn254.NewG1().FromBytes(raw)
if err != nil {
return nil, err
}

return &Signature{p: p}, err
return &Signature{p: p}, nil
}

// ToBigInt marshalls signature (which is point) to 2 big ints - one for each coordinate
Expand All @@ -88,11 +97,15 @@ type Signatures []*Signature

// Aggregate sums the given array of signatures
func (s Signatures) Aggregate() *Signature {
p := *new(bn256.G1).Set(&zeroG1)
for _, sig := range s {
point := new(bn256.G1).Set(sig.p)
p.Add(&p, point)
g, newp := bn254.NewG1(), new(bn254.PointG1)

newp.Set(g.Zero())

for _, x := range s {
if x.p != nil {
g.Add(newp, newp, x.p)
}
}

return &Signature{p: &p}
return &Signature{p: newp}
}

0 comments on commit e96eeda

Please sign in to comment.