Browse Source

crypto: add sr25519 as a validator key (#6376)

## Description

Add sr25519 as a validator key option. We support the crypto in tendermint and added batch verification recently.
pull/6387/head
Marko 3 years ago
committed by GitHub
parent
commit
990504cd07
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 196 additions and 14 deletions
  1. +2
    -1
      CHANGELOG_PENDING.md
  2. +11
    -2
      abci/types/pubkey.go
  3. +15
    -0
      crypto/encoding/codec.go
  4. +2
    -0
      p2p/conn/secret_connection.go
  5. +2
    -3
      p2p/conn/secret_connection_test.go
  6. +141
    -8
      proto/tendermint/crypto/keys.pb.go
  7. +1
    -0
      proto/tendermint/crypto/keys.proto
  8. +3
    -0
      types/params.go
  9. +19
    -0
      types/params_test.go

+ 2
- 1
CHANGELOG_PENDING.md View File

@ -53,7 +53,8 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi
### FEATURES
- [config] Add `--mode` flag and config variable. See [ADR-52](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-052-tendermint-mode.md) @dongsam
- [rpc] /#6329 Don't cap page size in unsafe mode (@gotjoshua, @cmwaters)
- [rpc] \#6329 Don't cap page size in unsafe mode (@gotjoshua, @cmwaters)
- [crypto] \#6376 Enable sr25519 as a validator key
### IMPROVEMENTS


+ 11
- 2
abci/types/pubkey.go View File

@ -6,6 +6,7 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
cryptoenc "github.com/tendermint/tendermint/crypto/encoding"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/sr25519"
)
func Ed25519ValidatorUpdate(pk []byte, power int64) ValidatorUpdate {
@ -17,7 +18,6 @@ func Ed25519ValidatorUpdate(pk []byte, power int64) ValidatorUpdate {
}
return ValidatorUpdate{
// Address:
PubKey: pkp,
Power: power,
}
@ -34,7 +34,16 @@ func UpdateValidator(pk []byte, power int64, keyType string) ValidatorUpdate {
panic(err)
}
return ValidatorUpdate{
// Address:
PubKey: pkp,
Power: power,
}
case sr25519.KeyType:
pke := sr25519.PubKey(pk)
pkp, err := cryptoenc.PubKeyToProto(pke)
if err != nil {
panic(err)
}
return ValidatorUpdate{
PubKey: pkp,
Power: power,
}


+ 15
- 0
crypto/encoding/codec.go View File

@ -6,6 +6,7 @@ import (
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/sr25519"
"github.com/tendermint/tendermint/libs/json"
pc "github.com/tendermint/tendermint/proto/tendermint/crypto"
)
@ -32,6 +33,12 @@ func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) {
Secp256K1: k,
},
}
case sr25519.PubKey:
kp = pc.PublicKey{
Sum: &pc.PublicKey_Sr25519{
Sr25519: k,
},
}
default:
return kp, fmt.Errorf("toproto: key type %v is not supported", k)
}
@ -57,6 +64,14 @@ func PubKeyFromProto(k pc.PublicKey) (crypto.PubKey, error) {
pk := make(secp256k1.PubKey, secp256k1.PubKeySize)
copy(pk, k.Secp256K1)
return pk, nil
case *pc.PublicKey_Sr25519:
if len(k.Sr25519) != sr25519.PubKeySize {
return nil, fmt.Errorf("invalid size for PubKeySr25519. Got %d, expected %d",
len(k.Sr25519), sr25519.PubKeySize)
}
pk := make(sr25519.PubKey, sr25519.PubKeySize)
copy(pk, k.Sr25519)
return pk, nil
default:
return nil, fmt.Errorf("fromproto: key type %v is not supported", k)
}


+ 2
- 0
p2p/conn/secret_connection.go View File

@ -167,9 +167,11 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
}
remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig
if _, ok := remPubKey.(ed25519.PubKey); !ok {
return nil, fmt.Errorf("expected ed25519 pubkey, got %T", remPubKey)
}
if !remPubKey.VerifySignature(challenge[:], remSignature) {
return nil, errors.New("challenge verification failed")
}


+ 2
- 3
p2p/conn/secret_connection_test.go View File

@ -276,11 +276,10 @@ func TestNonEd25519Pubkey(t *testing.T) {
var fooPrvKey = ed25519.GenPrivKey()
var barPrvKey = sr25519.GenPrivKey()
go MakeSecretConnection(fooConn, fooPrvKey) //nolint:errcheck // ignore for tests
go MakeSecretConnection(barConn, barPrvKey) //nolint:errcheck // ignore for tests
_, err := MakeSecretConnection(barConn, barPrvKey)
_, err := MakeSecretConnection(fooConn, fooPrvKey)
require.Error(t, err)
assert.Contains(t, err.Error(), "is not supported")
}
func writeLots(t *testing.T, wg *sync.WaitGroup, conn io.Writer, txt string, n int) {


+ 141
- 8
proto/tendermint/crypto/keys.pb.go View File

@ -29,6 +29,7 @@ type PublicKey struct {
// Types that are valid to be assigned to Sum:
// *PublicKey_Ed25519
// *PublicKey_Secp256K1
// *PublicKey_Sr25519
Sum isPublicKey_Sum `protobuf_oneof:"sum"`
}
@ -79,9 +80,13 @@ type PublicKey_Ed25519 struct {
type PublicKey_Secp256K1 struct {
Secp256K1 []byte `protobuf:"bytes,2,opt,name=secp256k1,proto3,oneof" json:"secp256k1,omitempty"`
}
type PublicKey_Sr25519 struct {
Sr25519 []byte `protobuf:"bytes,3,opt,name=sr25519,proto3,oneof" json:"sr25519,omitempty"`
}
func (*PublicKey_Ed25519) isPublicKey_Sum() {}
func (*PublicKey_Secp256K1) isPublicKey_Sum() {}
func (*PublicKey_Sr25519) isPublicKey_Sum() {}
func (m *PublicKey) GetSum() isPublicKey_Sum {
if m != nil {
@ -104,11 +109,19 @@ func (m *PublicKey) GetSecp256K1() []byte {
return nil
}
func (m *PublicKey) GetSr25519() []byte {
if x, ok := m.GetSum().(*PublicKey_Sr25519); ok {
return x.Sr25519
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*PublicKey) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*PublicKey_Ed25519)(nil),
(*PublicKey_Secp256K1)(nil),
(*PublicKey_Sr25519)(nil),
}
}
@ -119,20 +132,21 @@ func init() {
func init() { proto.RegisterFile("tendermint/crypto/keys.proto", fileDescriptor_cb048658b234868c) }
var fileDescriptor_cb048658b234868c = []byte{
// 199 bytes of a gzipped FileDescriptorProto
// 210 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x49, 0xcd, 0x4b,
0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e,
0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x44, 0xc8, 0xea, 0x41, 0x64, 0xa5,
0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x52, 0x04, 0x17, 0x67,
0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xb2, 0xfa, 0x20, 0x16, 0x44, 0xa1, 0x52, 0x09, 0x17, 0x67,
0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, 0x7b, 0x6a, 0x8a, 0x91,
0xa9, 0xa9, 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0x40, 0x48,
0x8e, 0x8b, 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x82, 0x09, 0x2a, 0x8b,
0x10, 0xb2, 0xe2, 0x78, 0xb1, 0x40, 0x9e, 0xf1, 0xc5, 0x42, 0x79, 0x46, 0x27, 0x56, 0x2e, 0xe6,
0xe2, 0xd2, 0x5c, 0xa7, 0xa0, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48,
0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xb2,
0x48, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x47, 0xf2, 0x05, 0x12, 0x13,
0xe2, 0x4c, 0x0c, 0x1f, 0x26, 0xb1, 0x81, 0x25, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe8,
0x1d, 0x1e, 0xe2, 0xfd, 0x00, 0x00, 0x00,
0x10, 0x02, 0xe9, 0x2d, 0x2e, 0x82, 0xe8, 0x65, 0x86, 0xe9, 0x85, 0x0a, 0x58, 0x71, 0xbc, 0x58,
0x20, 0xcf, 0xf8, 0x62, 0xa1, 0x3c, 0xa3, 0x13, 0x2b, 0x17, 0x73, 0x71, 0x69, 0xae, 0x53, 0xd0,
0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c,
0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x59, 0xa4, 0x67, 0x96, 0x64, 0x94,
0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x23, 0xf9, 0x10, 0x89, 0x09, 0xf1, 0x02, 0x86, 0xef, 0x93,
0xd8, 0xc0, 0x12, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x12, 0x2c, 0x35, 0x19, 0x01,
0x00, 0x00,
}
func (this *PublicKey) Compare(that interface{}) int {
@ -173,6 +187,8 @@ func (this *PublicKey) Compare(that interface{}) int {
thisType = 0
case *PublicKey_Secp256K1:
thisType = 1
case *PublicKey_Sr25519:
thisType = 2
default:
panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.Sum))
}
@ -182,6 +198,8 @@ func (this *PublicKey) Compare(that interface{}) int {
that1Type = 0
case *PublicKey_Secp256K1:
that1Type = 1
case *PublicKey_Sr25519:
that1Type = 2
default:
panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.Sum))
}
@ -257,6 +275,36 @@ func (this *PublicKey_Secp256K1) Compare(that interface{}) int {
}
return 0
}
func (this *PublicKey_Sr25519) Compare(that interface{}) int {
if that == nil {
if this == nil {
return 0
}
return 1
}
that1, ok := that.(*PublicKey_Sr25519)
if !ok {
that2, ok := that.(PublicKey_Sr25519)
if ok {
that1 = &that2
} else {
return 1
}
}
if that1 == nil {
if this == nil {
return 0
}
return 1
} else if this == nil {
return -1
}
if c := bytes.Compare(this.Sr25519, that1.Sr25519); c != 0 {
return c
}
return 0
}
func (this *PublicKey) Equal(that interface{}) bool {
if that == nil {
return this == nil
@ -335,6 +383,30 @@ func (this *PublicKey_Secp256K1) Equal(that interface{}) bool {
}
return true
}
func (this *PublicKey_Sr25519) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*PublicKey_Sr25519)
if !ok {
that2, ok := that.(PublicKey_Sr25519)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if !bytes.Equal(this.Sr25519, that1.Sr25519) {
return false
}
return true
}
func (m *PublicKey) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -399,6 +471,22 @@ func (m *PublicKey_Secp256K1) MarshalToSizedBuffer(dAtA []byte) (int, error) {
}
return len(dAtA) - i, nil
}
func (m *PublicKey_Sr25519) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PublicKey_Sr25519) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
if m.Sr25519 != nil {
i -= len(m.Sr25519)
copy(dAtA[i:], m.Sr25519)
i = encodeVarintKeys(dAtA, i, uint64(len(m.Sr25519)))
i--
dAtA[i] = 0x1a
}
return len(dAtA) - i, nil
}
func encodeVarintKeys(dAtA []byte, offset int, v uint64) int {
offset -= sovKeys(v)
base := offset
@ -446,6 +534,18 @@ func (m *PublicKey_Secp256K1) Size() (n int) {
}
return n
}
func (m *PublicKey_Sr25519) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Sr25519 != nil {
l = len(m.Sr25519)
n += 1 + l + sovKeys(uint64(l))
}
return n
}
func sovKeys(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
@ -548,6 +648,39 @@ func (m *PublicKey) Unmarshal(dAtA []byte) error {
copy(v, dAtA[iNdEx:postIndex])
m.Sum = &PublicKey_Secp256K1{v}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Sr25519", 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
}
v := make([]byte, postIndex-iNdEx)
copy(v, dAtA[iNdEx:postIndex])
m.Sum = &PublicKey_Sr25519{v}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipKeys(dAtA[iNdEx:])


+ 1
- 0
proto/tendermint/crypto/keys.proto View File

@ -13,5 +13,6 @@ message PublicKey {
oneof sum {
bytes ed25519 = 1;
bytes secp256k1 = 2;
bytes sr25519 = 3;
}
}

+ 3
- 0
types/params.go View File

@ -7,6 +7,7 @@ import (
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
"github.com/tendermint/tendermint/crypto/sr25519"
"github.com/tendermint/tendermint/crypto/tmhash"
tmstrings "github.com/tendermint/tendermint/libs/strings"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@ -24,11 +25,13 @@ const (
ABCIPubKeyTypeEd25519 = ed25519.KeyType
ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType
ABCIPubKeyTypeSr25519 = sr25519.KeyType
)
var ABCIPubKeyTypesToNames = map[string]string{
ABCIPubKeyTypeEd25519: ed25519.PubKeyName,
ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName,
ABCIPubKeyTypeSr25519: sr25519.PubKeyName,
}
// ConsensusParams contains consensus critical parameters that determine the


+ 19
- 0
types/params_test.go View File

@ -14,6 +14,7 @@ import (
var (
valEd25519 = []string{ABCIPubKeyTypeEd25519}
valSecp256k1 = []string{ABCIPubKeyTypeSecp256k1}
valSr25519 = []string{ABCIPubKeyTypeSr25519}
)
func TestConsensusParamsValidation(t *testing.T) {
@ -129,7 +130,25 @@ func TestConsensusParamsUpdate(t *testing.T) {
},
makeParams(100, 200, 300, 50, valSecp256k1),
},
{
makeParams(1, 2, 3, 0, valEd25519),
&tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxBytes: 100,
MaxGas: 200,
},
Evidence: &tmproto.EvidenceParams{
MaxAgeNumBlocks: 300,
MaxAgeDuration: time.Duration(300),
MaxBytes: 50,
},
Validator: &tmproto.ValidatorParams{
PubKeyTypes: valSr25519,
},
}, makeParams(100, 200, 300, 50, valSr25519),
},
}
for _, tc := range testCases {
assert.Equal(t, tc.updatedParams, tc.params.UpdateConsensusParams(tc.updates))
}


Loading…
Cancel
Save