diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 9c4fdf4c0..53660ff89 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -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 diff --git a/abci/types/pubkey.go b/abci/types/pubkey.go index 8530d9538..a0f746992 100644 --- a/abci/types/pubkey.go +++ b/abci/types/pubkey.go @@ -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, } diff --git a/crypto/encoding/codec.go b/crypto/encoding/codec.go index 3c552ed23..64e4e7c6f 100644 --- a/crypto/encoding/codec.go +++ b/crypto/encoding/codec.go @@ -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) } diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 76a93af5f..6b24a28fc 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -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") } diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 2bbe31fef..d70b8a902 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -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) { diff --git a/proto/tendermint/crypto/keys.pb.go b/proto/tendermint/crypto/keys.pb.go index 70cfe16e0..24c6c1b1b 100644 --- a/proto/tendermint/crypto/keys.pb.go +++ b/proto/tendermint/crypto/keys.pb.go @@ -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:]) diff --git a/proto/tendermint/crypto/keys.proto b/proto/tendermint/crypto/keys.proto index 16fd7adf3..d66f9fc0c 100644 --- a/proto/tendermint/crypto/keys.proto +++ b/proto/tendermint/crypto/keys.proto @@ -13,5 +13,6 @@ message PublicKey { oneof sum { bytes ed25519 = 1; bytes secp256k1 = 2; + bytes sr25519 = 3; } } diff --git a/types/params.go b/types/params.go index c6e070884..32d0f71c8 100644 --- a/types/params.go +++ b/types/params.go @@ -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 diff --git a/types/params_test.go b/types/params_test.go index 70a6a536e..8b69a81fc 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -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)) }