|
|
|
package bls
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/hex"
|
|
|
|
"math/big"
|
|
|
|
|
|
|
|
"github.com/harmony-one/bls/ffi/go/bls"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
emptyBLSPubKey = SerializedPublicKey{}
|
|
|
|
)
|
|
|
|
|
|
|
|
// PublicKeySizeInBytes ..
|
|
|
|
const (
|
|
|
|
PublicKeySizeInBytes = 48
|
|
|
|
BLSSignatureSizeInBytes = 96
|
|
|
|
)
|
|
|
|
|
|
|
|
// PrivateKeyWrapper combines the bls private key and the corresponding public key
|
|
|
|
type PrivateKeyWrapper struct {
|
|
|
|
Pri *bls.SecretKey
|
|
|
|
Pub *PublicKeyWrapper
|
|
|
|
}
|
|
|
|
|
|
|
|
// PublicKeyWrapper defines the bls public key in both serialized and
|
|
|
|
// deserialized form.
|
|
|
|
type PublicKeyWrapper struct {
|
|
|
|
Bytes SerializedPublicKey
|
|
|
|
Object *bls.PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
// WrapperFromPrivateKey makes a PrivateKeyWrapper from bls secret key
|
|
|
|
func WrapperFromPrivateKey(pri *bls.SecretKey) PrivateKeyWrapper {
|
|
|
|
pub := pri.GetPublicKey()
|
|
|
|
pubBytes := FromLibBLSPublicKeyUnsafe(pub)
|
|
|
|
return PrivateKeyWrapper{
|
|
|
|
Pri: pri,
|
|
|
|
Pub: &PublicKeyWrapper{
|
|
|
|
Bytes: *pubBytes,
|
|
|
|
Object: pub,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SerializedPublicKey defines the serialized bls public key
|
|
|
|
type SerializedPublicKey [PublicKeySizeInBytes]byte
|
|
|
|
|
|
|
|
// SerializedSignature defines the bls signature
|
|
|
|
type SerializedSignature [BLSSignatureSizeInBytes]byte
|
|
|
|
|
|
|
|
// Big ..
|
|
|
|
func (pk SerializedPublicKey) Big() *big.Int {
|
|
|
|
return new(big.Int).SetBytes(pk[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsEmpty returns whether the bls public key is empty 0 bytes
|
|
|
|
func (pk SerializedPublicKey) IsEmpty() bool {
|
|
|
|
return bytes.Equal(pk[:], emptyBLSPubKey[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hex returns the hex string of bls public key
|
|
|
|
func (pk SerializedPublicKey) Hex() string {
|
|
|
|
return hex.EncodeToString(pk[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalText so that we can use this as JSON printable when used as
|
|
|
|
// key in a map
|
|
|
|
func (pk SerializedPublicKey) MarshalText() (text []byte, err error) {
|
|
|
|
text = make([]byte, BLSSignatureSizeInBytes)
|
|
|
|
hex.Encode(text, pk[:])
|
|
|
|
return text, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromLibBLSPublicKeyUnsafe could give back nil, use only in cases when
|
|
|
|
// have invariant that return value won't be nil
|
|
|
|
func FromLibBLSPublicKeyUnsafe(key *bls.PublicKey) *SerializedPublicKey {
|
|
|
|
result := &SerializedPublicKey{}
|
|
|
|
if err := result.FromLibBLSPublicKey(key); err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromLibBLSPublicKey replaces the key contents with the given key,
|
|
|
|
func (pk *SerializedPublicKey) FromLibBLSPublicKey(key *bls.PublicKey) error {
|
|
|
|
bytes := key.Serialize()
|
|
|
|
if len(bytes) != len(pk) {
|
|
|
|
return errors.Errorf(
|
|
|
|
"key size (BLS) size mismatch, expected %d have %d", len(pk), len(bytes),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
copy(pk[:], bytes)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SeparateSigAndMask parse the commig signature data into signature and bitmap.
|
|
|
|
func SeparateSigAndMask(commitSigs []byte) ([]byte, []byte, error) {
|
|
|
|
if len(commitSigs) < BLSSignatureSizeInBytes {
|
|
|
|
return nil, nil, errors.New("no mask data found in commit sigs")
|
|
|
|
}
|
|
|
|
//#### Read payload data from committed msg
|
|
|
|
aggSig := make([]byte, BLSSignatureSizeInBytes)
|
|
|
|
bitmap := make([]byte, len(commitSigs)-BLSSignatureSizeInBytes)
|
|
|
|
offset := 0
|
|
|
|
copy(aggSig[:], commitSigs[offset:offset+BLSSignatureSizeInBytes])
|
|
|
|
offset += BLSSignatureSizeInBytes
|
|
|
|
copy(bitmap[:], commitSigs[offset:])
|
|
|
|
//#### END Read payload data from committed msg
|
|
|
|
return aggSig, bitmap, nil
|
|
|
|
}
|