feat(crypto): add blst (#20296)

Co-authored-by: itsdevbear <itsdevbear@berachain.com>
Co-authored-by: Akhil Kumar P <36399231+akhilkumarpilli@users.noreply.github.com>
This commit is contained in:
Marko 2024-06-11 19:16:07 +02:00 committed by GitHub
parent 78327f40c5
commit 05ff7a7cb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 932 additions and 32 deletions

View File

@ -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 := ,

View File

@ -4,7 +4,7 @@ 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"
@ -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)
@ -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)
}

View File

@ -6,7 +6,7 @@ import (
"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"
@ -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)
}
@ -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)
}

View File

@ -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"
@ -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)
}

View File

@ -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")
)

View File

@ -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"
)

View File

@ -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")
}
// 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")
}
// 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")
}
// 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)
}

View File

@ -0,0 +1,181 @@
//go:build ((linux && amd64) || (linux && arm64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && bls12381
package bls12_381
import (
"bytes"
"crypto/sha256"
"errors"
"fmt"
"github.com/cometbft/cometbft/crypto"
"github.com/cometbft/cometbft/crypto/tmhash"
bls12381 "github.com/cosmos/crypto/curves/bls12381"
"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) {
secretKey, err := bls12381.SecretKeyFromBytes(bz)
if err != nil {
return PrivKey{}, err
}
return secretKey.Marshal(), nil
}
// GenPrivKey generates a new key.
func GenPrivKey() (PrivKey, error) {
secretKey, err := bls12381.RandKey()
return PrivKey(secretKey.Marshal()), err
}
// Bytes returns the byte representation of the Key.
func (privKey PrivKey) Bytes() []byte {
return privKey.Key
}
// 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 {
secretKey, err := bls12381.SecretKeyFromBytes(privKey.Key)
if err != nil {
return nil
}
return PubKey(secretKey.PublicKey().Marshal())
}
// Equals returns true if two keys are equal and false otherwise.
func (privKey PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
return privKey.Type() == other.Type() && bytes.Equal(privKey.Bytes(), other.Bytes())
}
// 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) {
secretKey, err := bls12381.SecretKeyFromBytes(privKey.Key)
if err != nil {
return nil, err
}
if len(msg) > MaxMsgLen {
hash := sha256.Sum256(msg)
sig := secretKey.Sign(hash[:])
return sig.Marshal(), nil
}
sig := secretKey.Sign(msg)
return sig.Marshal(), nil
}
// 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 {
pk, _ := bls12381.PublicKeyFromBytes(pubKey.Key)
if len(pk.Marshal()) != PubKeySize {
panic("pubkey is incorrect size")
}
return crypto.Address(tmhash.SumTruncated(pubKey.Key))
}
// VerifySignature verifies the given signature.
func (pubKey PubKey) VerifySignature(msg, sig []byte) bool {
if len(sig) != SignatureLength {
return false
}
pubK, err := bls12381.PublicKeyFromBytes(pubKey.Key)
if err != nil { // invalid pubkey
return false
}
if len(msg) > MaxMsgLen {
hash := sha256.Sum256(msg)
msg = hash[:]
}
ok, err := bls12381.VerifySignature(sig, [MaxMsgLen]byte(msg[:MaxMsgLen]), pubK)
if err != nil { // bad signature
return false
}
return ok
}
// 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)
}

View File

@ -0,0 +1,504 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/crypto/bls12_381/keys.proto
package bls12_381
import (
fmt "fmt"
_ "github.com/cosmos/cosmos-sdk/types/tx/amino"
_ "github.com/cosmos/gogoproto/gogoproto"
proto "github.com/cosmos/gogoproto/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// PubKey is an ed25519 public key for handling Tendermint keys in SDK.
// It's needed for Any serialization and SDK compatibility.
// It must not be used in a non Tendermint key context because it doesn't implement
// ADR-28. Nevertheless, you will like to use ed25519 in app user level
// then you must create a new proto message and follow ADR-28 for Address construction.
type PubKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PubKey) Reset() { *m = PubKey{} }
func (*PubKey) ProtoMessage() {}
func (*PubKey) Descriptor() ([]byte, []int) {
return fileDescriptor_afa2b84d543bb80f, []int{0}
}
func (m *PubKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PubKey.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PubKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PubKey.Merge(m, src)
}
func (m *PubKey) XXX_Size() int {
return m.Size()
}
func (m *PubKey) XXX_DiscardUnknown() {
xxx_messageInfo_PubKey.DiscardUnknown(m)
}
var xxx_messageInfo_PubKey proto.InternalMessageInfo
func (m *PubKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
// PrivKey defines a ed25519 private key.
// NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context.
type PrivKey struct {
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
}
func (m *PrivKey) Reset() { *m = PrivKey{} }
func (m *PrivKey) String() string { return proto.CompactTextString(m) }
func (*PrivKey) ProtoMessage() {}
func (*PrivKey) Descriptor() ([]byte, []int) {
return fileDescriptor_afa2b84d543bb80f, []int{1}
}
func (m *PrivKey) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PrivKey.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PrivKey) XXX_Merge(src proto.Message) {
xxx_messageInfo_PrivKey.Merge(m, src)
}
func (m *PrivKey) XXX_Size() int {
return m.Size()
}
func (m *PrivKey) XXX_DiscardUnknown() {
xxx_messageInfo_PrivKey.DiscardUnknown(m)
}
var xxx_messageInfo_PrivKey proto.InternalMessageInfo
func (m *PrivKey) GetKey() []byte {
if m != nil {
return m.Key
}
return nil
}
func init() {
proto.RegisterType((*PubKey)(nil), "cosmos.crypto.bls12_381.PubKey")
proto.RegisterType((*PrivKey)(nil), "cosmos.crypto.bls12_381.PrivKey")
}
func init() {
proto.RegisterFile("cosmos/crypto/bls12_381/keys.proto", fileDescriptor_afa2b84d543bb80f)
}
var fileDescriptor_afa2b84d543bb80f = []byte{
// 244 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x4f, 0xca, 0x29, 0x36, 0x34, 0x8a,
0x37, 0xb6, 0x30, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12,
0x87, 0xa8, 0xd1, 0x83, 0xa8, 0xd1, 0x83, 0xab, 0x91, 0x12, 0x4c, 0xcc, 0xcd, 0xcc, 0xcb, 0xd7,
0x07, 0x93, 0x10, 0xb5, 0x52, 0x22, 0xe9, 0xf9, 0xe9, 0xf9, 0x60, 0xa6, 0x3e, 0x88, 0x05, 0x11,
0x55, 0xf2, 0xe6, 0x62, 0x0b, 0x28, 0x4d, 0xf2, 0x4e, 0xad, 0x14, 0x12, 0xe0, 0x62, 0xce, 0x4e,
0xad, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x02, 0x31, 0xad, 0xf4, 0x67, 0x2c, 0x90, 0x67,
0xe8, 0x7a, 0xbe, 0x41, 0x4b, 0x22, 0x39, 0x3f, 0x37, 0xb5, 0x24, 0x29, 0xad, 0x44, 0x1f, 0xa2,
0xd6, 0xc9, 0x27, 0x18, 0x62, 0xcf, 0xa4, 0xe7, 0x1b, 0xb4, 0x38, 0xb3, 0x53, 0x2b, 0xe3, 0xd3,
0x32, 0x53, 0x73, 0x52, 0x94, 0x3c, 0xb9, 0xd8, 0x03, 0x8a, 0x32, 0xcb, 0xb0, 0x9b, 0xa6, 0x03,
0x32, 0x49, 0x12, 0x61, 0x12, 0x44, 0x21, 0x0e, 0xa3, 0x9c, 0x7c, 0x4e, 0x3c, 0x92, 0x63, 0xbc,
0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63,
0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x28, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f,
0x57, 0x1f, 0x16, 0x44, 0x60, 0x4a, 0xb7, 0x38, 0x25, 0x1b, 0x16, 0x5a, 0xa0, 0x30, 0x42, 0x04,
0x59, 0x12, 0x1b, 0xd8, 0xb3, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x05, 0x13, 0x8a,
0x54, 0x01, 0x00, 0x00,
}
func (m *PubKey) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PubKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PrivKey) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PrivKey) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Key) > 0 {
i -= len(m.Key)
copy(dAtA[i:], m.Key)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Key)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintKeys(dAtA []byte, offset int, v uint64) int {
offset -= sovKeys(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *PubKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func (m *PrivKey) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Key)
if l > 0 {
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func sovKeys(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozKeys(x uint64) (n int) {
return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *PubKey) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PubKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthKeys
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthKeys
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PrivKey) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PrivKey: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PrivKey: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowKeys
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthKeys
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthKeys
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...)
if m.Key == nil {
m.Key = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthKeys
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipKeys(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowKeys
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthKeys
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupKeys
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthKeys
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthKeys = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowKeys = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupKeys = fmt.Errorf("proto: unexpected end of group")
)

View File

@ -34,7 +34,7 @@ const (
// private key representations used by RFC 8032.
SeedSize = 32
keyType = "ed25519"
KeyType = "ed25519"
)
var (
@ -92,7 +92,7 @@ func (privKey *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool {
}
func (privKey *PrivKey) Type() string {
return keyType
return KeyType
}
// MarshalAmino overrides Amino binary marshaling.
@ -193,7 +193,7 @@ func (pubKey *PubKey) String() string {
}
func (pubKey *PubKey) Type() string {
return keyType
return KeyType
}
func (pubKey *PubKey) Equals(other cryptotypes.PubKey) bool {

View File

@ -4,6 +4,7 @@ import (
"github.com/cometbft/cometbft/crypto/sr25519"
"github.com/cosmos/cosmos-sdk/codec"
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"
@ -27,6 +28,8 @@ func init() {
sr25519.PubKeyName)
AminoCdc.RegisterConcrete(&secp256k1.PubKey{},
secp256k1.PubKeyName)
AminoCdc.RegisterConcrete(&bls12_381.PubKey{},
bls12_381.PubKeyName)
AminoCdc.RegisterConcrete(&LegacyAminoPubKey{},
PubKeyAminoRoute)
}

2
go.mod
View File

@ -25,6 +25,7 @@ require (
github.com/cosmos/btcutil v1.0.5
github.com/cosmos/cosmos-db v1.0.2
github.com/cosmos/cosmos-proto v1.0.0-beta.5
github.com/cosmos/crypto v0.0.0-20240309083813-82ed2537802e
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/gogogateway v1.2.0
github.com/cosmos/gogoproto v1.5.0
@ -85,7 +86,6 @@ require (
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cometbft/cometbft-db v0.12.0 // indirect
github.com/cosmos/crypto v0.0.0-20240309083813-82ed2537802e // indirect
github.com/cosmos/iavl v1.1.4 // indirect
github.com/cosmos/ics23/go v0.10.0 // indirect
github.com/danieljoos/wincred v1.2.1 // indirect

View File

@ -292,7 +292,7 @@ func initTestnetFiles(
}
}
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig, args.algo)
if err != nil {
_ = os.RemoveAll(args.outputDir)
return err

View File

@ -49,6 +49,7 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/runtime"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
@ -446,7 +447,7 @@ func New(l Logger, baseDir string, cfg Config) (NetworkI, error) {
mnemonic = cfg.Mnemonics[i]
}
nodeID, pubKey, err := genutil.InitializeNodeValidatorFilesFromMnemonic(cmtCfg, mnemonic)
nodeID, pubKey, err := genutil.InitializeNodeValidatorFilesFromMnemonic(cmtCfg, mnemonic, ed25519.PrivKeyName)
if err != nil {
return nil, err
}

View File

@ -26,7 +26,12 @@ func CollectGenTxsCmd(genBalIterator types.GenesisBalancesIterator, validator ty
clientCtx := client.GetClientContextFromCmd(cmd)
cdc := clientCtx.Codec
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(config)
consensusKey, err := cmd.Flags().GetString(FlagConsensusKeyAlgo)
if err != nil {
return errors.Wrap(err, "Failed to get consensus key algo")
}
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(config, consensusKey)
if err != nil {
return errors.Wrap(err, "failed to initialize node validator files")
}
@ -55,7 +60,7 @@ func CollectGenTxsCmd(genBalIterator types.GenesisBalancesIterator, validator ty
return displayInfo(cmd.ErrOrStderr(), toPrint)
},
}
cmd.Flags().String(FlagConsensusKeyAlgo, "ed25519", "algorithm to use for the consensus key")
cmd.Flags().String(flagGenTxDir, "", "override default \"gentx\" directory from which collect and execute genesis transactions; default [--home]/config/gentx/")
return cmd

View File

@ -62,7 +62,12 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
}
cdc := clientCtx.Codec
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(config)
consensusKey, err := cmd.Flags().GetString(FlagConsensusKeyAlgo)
if err != nil {
return errors.Wrap(err, "Failed to get consensus key algo")
}
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(config, consensusKey)
if err != nil {
return errors.Wrap(err, "failed to initialize node validator files")
}
@ -212,6 +217,7 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
},
}
cmd.Flags().String(FlagConsensusKeyAlgo, "ed25519", "algorithm to use for the consensus key: ed25519 | secp256k1 | bls12_381 | sr25519 | multi")
cmd.Flags().String(flags.FlagOutputDocument, "", "Write the genesis transaction JSON document to the given file instead of the default location")
cmd.Flags().AddFlagSet(fsCreateValidator)
flags.AddTxFlagsToCmd(cmd)

View File

@ -9,14 +9,10 @@ import (
"os"
"path/filepath"
cfg "github.com/cometbft/cometbft/config"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/math/unsafe"
cfg "github.com/cometbft/cometbft/config"
cmttypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
@ -25,6 +21,8 @@ import (
"github.com/cosmos/cosmos-sdk/version"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
)
const (
@ -113,7 +111,12 @@ func InitCmd(mm *module.Manager) *cobra.Command {
initHeight = 1
}
nodeID, _, err := genutil.InitializeNodeValidatorFilesFromMnemonic(config, mnemonic)
consensusKey, err := cmd.Flags().GetString(FlagConsensusKeyAlgo)
if err != nil {
return errorsmod.Wrap(err, "Failed to get consensus key algo")
}
nodeID, _, err := genutil.InitializeNodeValidatorFilesFromMnemonic(config, mnemonic, consensusKey)
if err != nil {
return err
}
@ -163,10 +166,6 @@ func InitCmd(mm *module.Manager) *cobra.Command {
Params: cmttypes.DefaultConsensusParams(),
}
consensusKey, err := cmd.Flags().GetString(FlagConsensusKeyAlgo)
if err != nil {
return errorsmod.Wrap(err, "Failed to get consensus key algo")
}
appGenesis.Consensus.Params.Validator.PubKeyTypes = []string{consensusKey}
if err = genutil.ExportGenesisFile(appGenesis, genFile); err != nil {

View File

@ -22,6 +22,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/server"
servercmtlog "github.com/cosmos/cosmos-sdk/server/log"
"github.com/cosmos/cosmos-sdk/server/mock"
@ -243,7 +244,7 @@ func TestInitNodeValidatorFiles(t *testing.T) {
cfg, err := genutiltest.CreateDefaultCometConfig(home)
require.NoError(t, err)
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(cfg)
nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(cfg, ed25519.KeyType)
require.NoError(t, err)
require.NotEqual(t, "", nodeID)

View File

@ -8,6 +8,8 @@ import (
"time"
cfg "github.com/cometbft/cometbft/config"
cmtcrypto "github.com/cometbft/cometbft/crypto"
cmtbls12381 "github.com/cometbft/cometbft/crypto/bls12381"
tmed25519 "github.com/cometbft/cometbft/crypto/ed25519"
"github.com/cometbft/cometbft/p2p"
"github.com/cometbft/cometbft/privval"
@ -44,13 +46,13 @@ func ExportGenesisFileWithTime(genFile, chainID string, validators []cmttypes.Ge
}
// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
func InitializeNodeValidatorFiles(config *cfg.Config) (nodeID string, valPubKey cryptotypes.PubKey, err error) {
return InitializeNodeValidatorFilesFromMnemonic(config, "")
func InitializeNodeValidatorFiles(config *cfg.Config, keyType string) (nodeID string, valPubKey cryptotypes.PubKey, err error) {
return InitializeNodeValidatorFilesFromMnemonic(config, "", keyType)
}
// InitializeNodeValidatorFilesFromMnemonic creates private validator and p2p configuration files using the given mnemonic.
// If no valid mnemonic is given, a random one will be used instead.
func InitializeNodeValidatorFilesFromMnemonic(config *cfg.Config, mnemonic string) (nodeID string, valPubKey cryptotypes.PubKey, err error) {
func InitializeNodeValidatorFilesFromMnemonic(config *cfg.Config, mnemonic, keyType string) (nodeID string, valPubKey cryptotypes.PubKey, err error) {
if len(mnemonic) > 0 && !bip39.IsMnemonicValid(mnemonic) {
return "", nil, fmt.Errorf("invalid mnemonic")
}
@ -71,15 +73,38 @@ func InitializeNodeValidatorFilesFromMnemonic(config *cfg.Config, mnemonic strin
return "", nil, fmt.Errorf("could not create directory %q: %w", filepath.Dir(pvStateFile), err)
}
var filePV *privval.FilePV
var (
filePV *privval.FilePV
privKey cmtcrypto.PrivKey
)
if len(mnemonic) == 0 {
filePV = privval.LoadOrGenFilePV(pvKeyFile, pvStateFile)
switch keyType {
case "ed25519":
privKey = tmed25519.GenPrivKey()
case "bls12_381":
privKey, err = cmtbls12381.GenPrivKey()
if err != nil {
return "", nil, err
}
default:
privKey = tmed25519.GenPrivKey()
}
} else {
privKey := tmed25519.GenPrivKeyFromSecret([]byte(mnemonic))
filePV = privval.NewFilePV(privKey, pvKeyFile, pvStateFile)
filePV.Save()
switch keyType {
case "ed25519":
privKey = tmed25519.GenPrivKeyFromSecret([]byte(mnemonic))
case "bls12_381":
// TODO: need to add support for getting from mnemonic in Comet.
return "", nil, fmt.Errorf("BLS key type does not support mnemonic")
default:
privKey = tmed25519.GenPrivKeyFromSecret([]byte(mnemonic))
}
}
filePV = privval.NewFilePV(privKey, pvKeyFile, pvStateFile)
filePV.Save()
tmValPubKey, err := filePV.GetPubKey()
if err != nil {
return "", nil, err

View File

@ -53,7 +53,7 @@ func TestInitializeNodeValidatorFilesFromMnemonic(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
_, _, err := InitializeNodeValidatorFilesFromMnemonic(cfg, tt.mnemonic)
_, _, err := InitializeNodeValidatorFilesFromMnemonic(cfg, tt.mnemonic, "ed25519")
if tt.expError {
require.Error(t, err)