Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mf/convert validator voting keys to bls keys #522

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e7efd93
Add BLS signature utils.
mattfoley8 Apr 7, 2023
5d9abb1
Get tests passing.
mattfoley8 Apr 7, 2023
fdc2ff7
Update test dockerfile to install relic.
mattfoley8 Apr 7, 2023
1123964
Add relic + no relic files.
mattfoley8 Apr 7, 2023
d42ea74
Merge main. Resolve conflicts.
mattfoley8 May 5, 2023
9f14c21
Add more private key, public key, signature utils.
mattfoley8 May 5, 2023
f1baa27
Remove types_ filename prefix.
mattfoley8 May 5, 2023
b6da4c0
Install go v1.20 in the test.Dockerfile.
mattfoley8 May 5, 2023
96f4ef0
Dont apk add install go.
mattfoley8 May 5, 2023
5b476ad
Dont re-install flow-go.
mattfoley8 May 5, 2023
bb9ecc9
Add utils to aggregate + verify aggregate signatures.
mattfoley8 May 5, 2023
ce4076b
Add no relic version of aggregate BLS sig funcs.
mattfoley8 May 5, 2023
f0d71f0
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 5, 2023
b355375
Conver validator voting keys to BLS keys.
mattfoley8 May 5, 2023
3ca713e
Add copy funcs.
mattfoley8 May 8, 2023
8f83386
Merge upstream branch. Resolve conflicts.
mattfoley8 May 8, 2023
fb9e83c
Fix failing stake tests.
mattfoley8 May 8, 2023
3435fac
Validate validator voting signature block height.
mattfoley8 May 8, 2023
8dd40d9
Retrigger CI.
mattfoley8 May 8, 2023
3f9c743
Update no relic func signatures.
mattfoley8 May 8, 2023
e23252a
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
37edf0c
Add better edge-case handling for BLS types.
mattfoley8 May 8, 2023
5092bd2
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
35d354f
Merge upstream branch. Resolve conflicts.
mattfoley8 May 8, 2023
17ef0ec
Move BLS utils to own package.
mattfoley8 May 8, 2023
a61d8b4
Clean up naming conventions.
mattfoley8 May 8, 2023
793bb5e
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
4b4926d
Reference BLS utils from package.
mattfoley8 May 8, 2023
54d46bc
Expose NewPrivateKey().
mattfoley8 May 8, 2023
e3a69b1
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
ef66a2e
Incorporate new BLS package in tests.
mattfoley8 May 8, 2023
26748a4
Merge upstream branch. Resolve conflicts.
mattfoley8 May 8, 2023
5d8abfc
Dont error if parsing empty string or bytes.
mattfoley8 May 8, 2023
7efe861
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
aca9f66
Try non-recursive go test syntax.
mattfoley8 May 8, 2023
7ebd717
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 8, 2023
f7b1ae6
Retrigger CI.
mattfoley8 May 8, 2023
a09b653
Add bls package to Dockerfile.
mattfoley8 May 9, 2023
1cd2d86
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 9, 2023
f3aaff6
Test Copy() func.
mattfoley8 May 9, 2023
8cf3ec1
Merge branch 'mf/add-bls-signature-utils' into mf/convert-validator-v…
mattfoley8 May 9, 2023
869a21c
Add encoder/decoder wrappers.
mattfoley8 May 9, 2023
5620a83
Increase voting signature window from 60 to 300.
mattfoley8 May 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ quick_testing
dump_txns
compare_blocks.go
backend
core

.idea

Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ COPY go.sum .

RUN go mod download

COPY desohash desohash
COPY bls bls
COPY cmd cmd
COPY desohash desohash
COPY lib lib
COPY migrate migrate
COPY test_data test_data
Expand Down
237 changes: 237 additions & 0 deletions bls/signature.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
//go:build relic

package bls

import (
"bytes"
"crypto/rand"
"encoding/hex"
"errors"
flowCrypto "github.com/onflow/flow-go/crypto"
"strings"
)

const SigningAlgorithm = flowCrypto.BLSBLS12381

// TODO: what should the domainTag param be?
var HashingAlgorithm = flowCrypto.NewExpandMsgXOFKMAC128("deso-protocol")

func AggregateSignatures(signatures []*Signature) (*Signature, error) {
var flowSignatures []flowCrypto.Signature
for _, signature := range signatures {
flowSignatures = append(flowSignatures, signature.flowSignature)
}
aggregateFlowSignature, err := flowCrypto.AggregateBLSSignatures(flowSignatures)
if err != nil {
return nil, err
}
return &Signature{flowSignature: aggregateFlowSignature}, nil
}

func VerifyAggregateSignature(publicKeys []*PublicKey, signature *Signature, payloadBytes []byte) (bool, error) {
var flowPublicKeys []flowCrypto.PublicKey
for _, publicKey := range publicKeys {
flowPublicKeys = append(flowPublicKeys, publicKey.flowPublicKey)
}
return flowCrypto.VerifyBLSSignatureOneMessage(flowPublicKeys, signature.flowSignature, payloadBytes, HashingAlgorithm)
}

//
// TYPES: PrivateKey
//

type PrivateKey struct {
flowPrivateKey flowCrypto.PrivateKey
}

func NewPrivateKey() (*PrivateKey, error) {
randomBytes := make([]byte, 64)
_, err := rand.Read(randomBytes)
if err != nil {
return nil, err
}
flowPrivateKey, err := flowCrypto.GeneratePrivateKey(SigningAlgorithm, randomBytes)
if err != nil {
return nil, err
}
return &PrivateKey{flowPrivateKey: flowPrivateKey}, nil
}

func (privateKey *PrivateKey) Sign(payloadBytes []byte) (*Signature, error) {
if privateKey.flowPrivateKey == nil {
return nil, errors.New("bls.PrivateKey is nil")
}
flowSignature, err := privateKey.flowPrivateKey.Sign(payloadBytes, HashingAlgorithm)
if err != nil {
return nil, err
}
return &Signature{flowSignature: flowSignature}, nil
}

func (privateKey *PrivateKey) PublicKey() *PublicKey {
if privateKey.flowPrivateKey == nil {
return nil
}
return &PublicKey{flowPublicKey: privateKey.flowPrivateKey.PublicKey()}
}

func (privateKey *PrivateKey) ToString() string {
if privateKey.flowPrivateKey == nil {
return ""
}
return privateKey.flowPrivateKey.String()
}

func (privateKey *PrivateKey) FromString(privateKeyString string) (*PrivateKey, error) {
if privateKeyString == "" {
return nil, nil
}
// Chop off leading 0x, if exists. Otherwise, does nothing.
privateKeyStringCopy, _ := strings.CutPrefix(privateKeyString, "0x")
// Convert from hex string to byte slice.
privateKeyBytes, err := hex.DecodeString(privateKeyStringCopy)
if err != nil {
return nil, err
}
// Convert from byte slice to bls.PrivateKey.
privateKey.flowPrivateKey, err = flowCrypto.DecodePrivateKey(SigningAlgorithm, privateKeyBytes)
return privateKey, err
}

func (privateKey *PrivateKey) Eq(other *PrivateKey) bool {
if privateKey.flowPrivateKey == nil || other == nil {
return false
}
return privateKey.flowPrivateKey.Equals(other.flowPrivateKey)
}

//
// TYPES: PublicKey
//

type PublicKey struct {
flowPublicKey flowCrypto.PublicKey
}

func (publicKey *PublicKey) Verify(signature *Signature, input []byte) (bool, error) {
if publicKey.flowPublicKey == nil {
return false, errors.New("bls.PublicKey is nil")
}
return publicKey.flowPublicKey.Verify(signature.flowSignature, input, HashingAlgorithm)
}

func (publicKey *PublicKey) ToBytes() []byte {
var publicKeyBytes []byte
if publicKey.flowPublicKey != nil {
publicKeyBytes = publicKey.flowPublicKey.Encode()
}
return publicKeyBytes
}

func (publicKey *PublicKey) FromBytes(publicKeyBytes []byte) (*PublicKey, error) {
if len(publicKeyBytes) == 0 {
return nil, nil
}
var err error
publicKey.flowPublicKey, err = flowCrypto.DecodePublicKey(SigningAlgorithm, publicKeyBytes)
return publicKey, err
}

func (publicKey *PublicKey) ToString() string {
if publicKey.flowPublicKey == nil {
return ""
}
return publicKey.flowPublicKey.String()
}

func (publicKey *PublicKey) FromString(publicKeyString string) (*PublicKey, error) {
if publicKeyString == "" {
return nil, nil
}
// Chop off leading 0x, if exists. Otherwise, does nothing.
publicKeyStringCopy, _ := strings.CutPrefix(publicKeyString, "0x")
// Convert from hex string to byte slice.
publicKeyBytes, err := hex.DecodeString(publicKeyStringCopy)
if err != nil {
return nil, err
}
// Convert from byte slice to bls.PublicKey.
publicKey.flowPublicKey, err = flowCrypto.DecodePublicKey(SigningAlgorithm, publicKeyBytes)
return publicKey, err
}

func (publicKey *PublicKey) Eq(other *PublicKey) bool {
if publicKey.flowPublicKey == nil || other == nil {
return false
}
return publicKey.flowPublicKey.Equals(other.flowPublicKey)
}

func (publicKey *PublicKey) Copy() *PublicKey {
return &PublicKey{
flowPublicKey: publicKey.flowPublicKey,
}
}

//
// TYPES: Signature
//

type Signature struct {
flowSignature flowCrypto.Signature
}

func (signature *Signature) ToBytes() []byte {
var signatureBytes []byte
if signature.flowSignature != nil {
signatureBytes = signature.flowSignature.Bytes()
}
return signatureBytes
}

func (signature *Signature) FromBytes(signatureBytes []byte) (*Signature, error) {
if len(signatureBytes) == 0 {
return nil, nil
}
signature.flowSignature = signatureBytes
return signature, nil
}

func (signature *Signature) ToString() string {
if signature.flowSignature == nil {
return ""
}
return signature.flowSignature.String()
}

func (signature *Signature) FromString(signatureString string) (*Signature, error) {
if signatureString == "" {
return nil, nil
}
// Chop off leading 0x, if exists. Otherwise, does nothing.
signatureStringCopy, _ := strings.CutPrefix(signatureString, "0x")
// Convert from hex string to byte slice.
signatureBytes, err := hex.DecodeString(signatureStringCopy)
if err != nil {
return nil, err
}
// Convert from byte slice to bls.Signature.
signature.flowSignature = signatureBytes
return signature, nil
}

func (signature *Signature) Eq(other *Signature) bool {
if signature.flowSignature == nil || other == nil {
return false
}
return bytes.Equal(signature.ToBytes(), other.ToBytes())
}

func (signature *Signature) Copy() *Signature {
if signature.flowSignature == nil {
return &Signature{}
}
return &Signature{
flowSignature: append([]byte{}, signature.flowSignature.Bytes()...),
}
}
107 changes: 107 additions & 0 deletions bls/signature_no_relic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//go:build !relic

package bls

const BLSNoRelicError = "BLS keys can't be used without Relic installed"

func AggregateSignatures(signatures []*Signature) (*Signature, error) {
panic(BLSNoRelicError)
}

func VerifyAggregateSignature(publicKeys []*PublicKey, signature *Signature, payloadBytes []byte) (bool, error) {
panic(BLSNoRelicError)
}

//
// TYPES: PrivateKey
//

type PrivateKey struct{}

func NewPrivateKey() (*PrivateKey, error) {
panic(BLSNoRelicError)
}

func (privateKey *PrivateKey) Sign(payloadBytes []byte) (*Signature, error) {
panic(BLSNoRelicError)
}

func (privateKey *PrivateKey) PublicKey() *PublicKey {
panic(BLSNoRelicError)
}

func (privateKey *PrivateKey) ToString() string {
panic(BLSNoRelicError)
}

func (privateKey *PrivateKey) FromString(privateKeyString string) (*PrivateKey, error) {
panic(BLSNoRelicError)
}

func (privateKey *PrivateKey) Eq(other *PrivateKey) bool {
panic(BLSNoRelicError)
}

//
// TYPES: PublicKey
//

type PublicKey struct{}

func (publicKey *PublicKey) Verify(signature *Signature, input []byte) (bool, error) {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) ToBytes() []byte {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) FromBytes(publicKeyBytes []byte) (*PublicKey, error) {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) ToString() string {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) FromString(publicKeyString string) (*PublicKey, error) {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) Eq(other *PublicKey) bool {
panic(BLSNoRelicError)
}

func (publicKey *PublicKey) Copy() *PublicKey {
panic(BLSNoRelicError)
}

//
// TYPES: Signature
//

type Signature struct{}

func (signature *Signature) ToBytes() []byte {
panic(BLSNoRelicError)
}

func (signature *Signature) FromBytes(signatureBytes []byte) (*Signature, error) {
panic(BLSNoRelicError)
}

func (signature *Signature) ToString() string {
panic(BLSNoRelicError)
}

func (signature *Signature) FromString(signatureString string) (*Signature, error) {
panic(BLSNoRelicError)
}

func (signature *Signature) Eq(other *Signature) bool {
panic(BLSNoRelicError)
}

func (signature *Signature) Copy() *Signature {
panic(BLSNoRelicError)
}
15 changes: 15 additions & 0 deletions bls/signature_no_relic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build !relic

package bls

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestVerifyingBLSSignatures(t *testing.T) {
assert.Panics(t, func() { NewPrivateKey() })
assert.Panics(t, func() { (&PrivateKey{}).FromString("") })
assert.Panics(t, func() { (&PublicKey{}).FromString("") })
assert.Panics(t, func() { (&Signature{}).FromString("") })
}
Loading