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

feat(crypto): add blst #20296

Merged
merged 13 commits into from
Jun 11, 2024
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS)))
build_tags += boltdb
endif

# handle blst
ifeq (blst,$(findstring blst,$(COSMOS_BUILD_OPTIONS)))
CGO_ENABLED=1
build_tags += blst
endif

whitespace :=
whitespace += $(whitespace)
comma := ,
Expand Down
4 changes: 3 additions & 1 deletion crypto/codec/amino.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"github.com/cometbft/cometbft/crypto/sr25519"

"cosmossdk.io/core/legacy"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix import ordering as per project conventions.

- import (
-	"github.com/cometbft/cometbft/crypto/sr25519"
-	"cosmossdk.io/core/legacy"
-	bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
-	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
-	kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
-	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
-	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
- )
+ import (
+	"cosmossdk.io/core/legacy"
+	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
+	bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
+	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
+	kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
+	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
+	"github.com/cometbft/cometbft/crypto/sr25519"
+ )
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
"cosmossdk.io/core/legacy"
import (
"cosmossdk.io/core/legacy"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cometbft/cometbft/crypto/sr25519"
)
Tools
golangci-lint

6-6: File is not gci-ed with --skip-generated -s standard -s default -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) --custom-order (gci)


bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand All @@ -21,6 +21,7 @@ func RegisterCrypto(cdc legacy.Amino) {
ed25519.PubKeyName)
cdc.RegisterConcrete(&secp256k1.PubKey{},
secp256k1.PubKeyName)
cdc.RegisterConcrete(&bls12_381.PubKey{}, bls12_381.PubKeyName)
cdc.RegisterConcrete(&kmultisig.LegacyAminoPubKey{},
kmultisig.PubKeyAminoRoute)

Expand All @@ -31,4 +32,5 @@ func RegisterCrypto(cdc legacy.Amino) {
ed25519.PrivKeyName)
cdc.RegisterConcrete(&secp256k1.PrivKey{},
secp256k1.PrivKeyName)
cdc.RegisterConcrete(&bls12_381.PrivKey{}, bls12_381.PrivKeyName)
}
12 changes: 11 additions & 1 deletion crypto/codec/cmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/cometbft/cometbft/crypto/encoding"

"cosmossdk.io/errors"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reorder imports according to the Golang style guide.

import (
	cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1"
	cmtcrypto "github.com/cometbft/cometbft/crypto"
	"github.com/cometbft/cometbft/crypto/encoding"
	"cosmossdk.io/errors"
	bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
	"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
"cosmossdk.io/errors"
import (
cmtprotocrypto "github.com/cometbft/cometbft/api/cometbft/crypto/v1"
cmtcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cometbft/cometbft/crypto/encoding"
"cosmossdk.io/errors"
bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
Tools
golangci-lint

8-8: File is not gci-ed with --skip-generated -s standard -s default -s prefix(cosmossdk.io) -s prefix(github.com/cosmos/cosmos-sdk) --custom-order (gci)


bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
Expand All @@ -24,6 +24,10 @@ func FromCmtProtoPublicKey(protoPk cmtprotocrypto.PublicKey) (cryptotypes.PubKey
return &secp256k1.PubKey{
Key: protoPk.Secp256K1,
}, nil
case *cmtprotocrypto.PublicKey_Bls12381:
return &bls12_381.PubKey{
Key: protoPk.Bls12381,
}, nil
default:
return nil, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v from Tendermint public key", protoPk)
}
Expand All @@ -44,6 +48,12 @@ func ToCmtProtoPublicKey(pk cryptotypes.PubKey) (cmtprotocrypto.PublicKey, error
Secp256K1: pk.Key,
},
}, nil
case *bls12_381.PubKey:
return cmtprotocrypto.PublicKey{
Sum: &cmtprotocrypto.PublicKey_Bls12381{
Bls12381: pk.Key,
},
}, nil
default:
return cmtprotocrypto.PublicKey{}, errors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v to Tendermint public key", pk)
}
Expand Down
3 changes: 3 additions & 0 deletions crypto/codec/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package codec
import (
"cosmossdk.io/core/registry"

bls12_381 "github.com/cosmos/cosmos-sdk/crypto/keys/bls12_381"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
Expand All @@ -16,11 +17,13 @@ func RegisterInterfaces(registry registry.InterfaceRegistrar) {
registry.RegisterInterface("cosmos.crypto.PubKey", pk)
registry.RegisterImplementations(pk, &ed25519.PubKey{})
registry.RegisterImplementations(pk, &secp256k1.PubKey{})
registry.RegisterImplementations(pk, &bls12_381.PubKey{})
registry.RegisterImplementations(pk, &multisig.LegacyAminoPubKey{})

var priv *cryptotypes.PrivKey
registry.RegisterInterface("cosmos.crypto.PrivKey", priv)
registry.RegisterImplementations(priv, &secp256k1.PrivKey{})
registry.RegisterImplementations(priv, &ed25519.PrivKey{})
registry.RegisterImplementations(priv, &bls12_381.PrivKey{})
secp256r1.RegisterInterfaces(registry)
}
3 changes: 3 additions & 0 deletions crypto/hd/algo.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const (
// Ed25519Type represents the Ed25519Type signature system.
// It is currently not supported for end-user keys (wallets/ledgers).
Ed25519Type = PubKeyType("ed25519")
// Ed25519Type represents the Ed25519Type signature system.
// It is currently not supported for end-user keys (wallets/ledgers).
Bls12_381Type = PubKeyType("bls12_381")
// Sr25519Type represents the Sr25519Type signature system.
Sr25519Type = PubKeyType("sr25519")
)
Expand Down
20 changes: 20 additions & 0 deletions crypto/keys/bls12_381/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package bls12_381

const (
PrivKeyName = "cometbft/PrivKeyBls12_381"
PubKeyName = "cometbft/PubKeyBls12_381"
// PubKeySize is the size, in bytes, of public keys as used in this package.
PubKeySize = 32
// PrivKeySize is the size, in bytes, of private keys as used in this package.
PrivKeySize = 64
// SignatureLength defines the byte length of a BLS signature.
SignatureLength = 96
// SeedSize is the size, in bytes, of private key seeds. These are the
// private key representations used by RFC 8032.
SeedSize = 32

// MaxMsgLen defines the maximum length of the message bytes as passed to Sign.
MaxMsgLen = 32

KeyType = "bls12381"
)
131 changes: 131 additions & 0 deletions crypto/keys/bls12_381/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package bls12_381

import (
"bytes"
"errors"
"fmt"

"github.com/cometbft/cometbft/crypto"

"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)

// ===============================================================================================
// Private Key
// ===============================================================================================

// PrivKey is a wrapper around the Ethereum BLS12-381 private key type. This
// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum
// BLS12-381 private key type.

var (
_ cryptotypes.PrivKey = &PrivKey{}
_ codec.AminoMarshaler = &PrivKey{}
)

// NewPrivateKeyFromBytes build a new key from the given bytes.
func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}

// GenPrivKey generates a new key.
func GenPrivKey() (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}

// Bytes returns the byte representation of the Key.
func (privKey PrivKey) Bytes() []byte {
panic("not implemented, build flags are required to use bls12_381 keys")
}

// PubKey returns the private key's public key. If the privkey is not valid
// it returns a nil value.
func (privKey PrivKey) PubKey() cryptotypes.PubKey {
panic("not implemented, build flags are required to use bls12_381 keys")
}

// Equals returns true if two keys are equal and false otherwise.
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
panic("not implemented, build flags are required to use bls12_381 keys")
}

// Type returns the type.
func (PrivKey) Type() string {
return KeyType
}

// Sign signs the given byte array. If msg is larger than
// MaxMsgLen, SHA256 sum will be signed instead of the raw bytes.
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
Comment on lines +28 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All methods in PrivKey are not implemented and require build flags. This needs to be addressed for full functionality.

+ // TODO: Implement these methods or ensure appropriate build flags are set.
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// GenPrivKey generates a new key.
func GenPrivKey() (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Bytes returns the byte representation of the Key.
func (privKey PrivKey) Bytes() []byte {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// PubKey returns the private key's public key. If the privkey is not valid
// it returns a nil value.
func (privKey PrivKey) PubKey() cryptotypes.PubKey {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Equals returns true if two keys are equal and false otherwise.
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Type returns the type.
func (PrivKey) Type() string {
return KeyType
}
// Sign signs the given byte array. If msg is larger than
// MaxMsgLen, SHA256 sum will be signed instead of the raw bytes.
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
func NewPrivateKeyFromBytes(bz []byte) (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// GenPrivKey generates a new key.
func GenPrivKey() (PrivKey, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Bytes returns the byte representation of the Key.
func (privKey PrivKey) Bytes() []byte {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// PubKey returns the private key's public key. If the privkey is not valid
// it returns a nil value.
func (privKey PrivKey) PubKey() cryptotypes.PubKey {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Equals returns true if two keys are equal and false otherwise.
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// Type returns the type.
func (PrivKey) Type() string {
return KeyType
}
// Sign signs the given byte array. If msg is larger than
// MaxMsgLen, SHA256 sum will be signed instead of the raw bytes.
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
panic("not implemented, build flags are required to use bls12_381 keys")
}
// TODO: Implement these methods or ensure appropriate build flags are set.
Tools
golangci-lint

28-28: undefined: PrivKey (typecheck)


33-33: undefined: PrivKey (typecheck)


38-38: undefined: PrivKey (typecheck)


44-44: undefined: PrivKey (typecheck)


49-49: undefined: PrivKey (typecheck)


54-54: undefined: PrivKey (typecheck)


60-60: undefined: PrivKey (typecheck)


55-55: undefined: KeyType (typecheck)


// MarshalAmino overrides Amino binary marshaling.
func (privKey PrivKey) MarshalAmino() ([]byte, error) {
return privKey.Key, nil
}

// UnmarshalAmino overrides Amino binary marshaling.
func (privKey *PrivKey) UnmarshalAmino(bz []byte) error {
if len(bz) != PrivKeySize {
return errors.New("invalid privkey size")
}
privKey.Key = bz

return nil
}

// MarshalAminoJSON overrides Amino JSON marshaling.
func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) {
// When we marshal to Amino JSON, we don't marshal the "key" field itself,
// just its contents (i.e. the key bytes).
return privKey.MarshalAmino()
}

// UnmarshalAminoJSON overrides Amino JSON marshaling.
func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error {
return privKey.UnmarshalAmino(bz)
}

// ===============================================================================================
// Public Key
// ===============================================================================================

// Pubkey is a wrapper around the Ethereum BLS12-381 public key type. This
// wrapper conforms to crypto.Pubkey to allow for the use of the Ethereum
// BLS12-381 public key type.

var _ cryptotypes.PubKey = &PubKey{}

// Address returns the address of the key.
//
// The function will panic if the public key is invalid.
func (pubKey PubKey) Address() crypto.Address {
panic("not implemented, build flags are required to use bls12_381 keys")
Dismissed Show dismissed Hide dismissed
}

// VerifySignature verifies the given signature.
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
panic("not implemented, build flags are required to use bls12_381 keys")
}
Comment on lines +104 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The panic in Address method of PubKey could cause a chain halt in consensus methods. This needs to be handled more gracefully.

- panic("not implemented, build flags are required to use bls12_381 keys")
+ if len(pubKey.Key) == 0 {
+     return nil, errors.New("public key not initialized")
+ }

Committable suggestion was skipped due to low confidence.

Tools
golangci-lint

104-104: undefined: PubKey (typecheck)


109-109: undefined: PubKey (typecheck)

GitHub Check: CodeQL

[warning] 105-105: Panic in BeginBock or EndBlock consensus methods
Possible panics in BeginBock- or EndBlock-related consensus methods could cause a chain halt


// Bytes returns the byte format.
func (pubKey PubKey) Bytes() []byte {
return pubKey.Key
}

// Type returns the key's type.
func (PubKey) Type() string {
return KeyType
}

// Equals returns true if the other's type is the same and their bytes are deeply equal.
func (pubKey PubKey) Equals(other cryptotypes.PubKey) bool {
return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes())
}

// String returns Hex representation of a pubkey with it's type
func (pubKey PubKey) String() string {
return fmt.Sprintf("PubKeyBLS12_381{%X}", pubKey.Key)
}
Loading
Loading