diff --git a/crypto/codec/tm.go b/crypto/codec/tm.go index 6633f60c2377..8c841e96b3c7 100644 --- a/crypto/codec/tm.go +++ b/crypto/codec/tm.go @@ -6,6 +6,7 @@ import ( tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" "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" ) @@ -17,6 +18,10 @@ func FromTmProtoPublicKey(protoPk tmprotocrypto.PublicKey) (cryptotypes.PubKey, return &ed25519.PubKey{ Key: protoPk.Ed25519, }, nil + case *tmprotocrypto.PublicKey_Secp256K1: + return &secp256k1.PubKey{ + Key: protoPk.Secp256K1, + }, nil default: return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v from Tendermint public key", protoPk) } @@ -31,6 +36,12 @@ func ToTmProtoPublicKey(pk cryptotypes.PubKey) (tmprotocrypto.PublicKey, error) Ed25519: pk.Key, }, }, nil + case *secp256k1.PubKey: + return tmprotocrypto.PublicKey{ + Sum: &tmprotocrypto.PublicKey_Secp256K1{ + Secp256K1: pk.Key, + }, + }, nil default: return tmprotocrypto.PublicKey{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "cannot convert %v to Tendermint public key", pk) } diff --git a/crypto/keys/secp256k1/secp256k1_test.go b/crypto/keys/secp256k1/secp256k1_test.go index d96b1dc38216..56c67f594b0b 100644 --- a/crypto/keys/secp256k1/secp256k1_test.go +++ b/crypto/keys/secp256k1/secp256k1_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" + tmsecp256k1 "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" @@ -267,3 +268,56 @@ func TestMarshalAmino(t *testing.T) { }) } } + +func TestMarshalAmino_BackwardsCompatibility(t *testing.T) { + aminoCdc := codec.NewLegacyAmino() + // Create Tendermint keys. + tmPrivKey := tmsecp256k1.GenPrivKey() + tmPubKey := tmPrivKey.PubKey() + // Create our own keys, with the same private key as Tendermint's. + privKey := &secp256k1.PrivKey{Key: []byte(tmPrivKey)} + pubKey := privKey.PubKey().(*secp256k1.PubKey) + + testCases := []struct { + desc string + tmKey interface{} + ourKey interface{} + marshalFn func(o interface{}) ([]byte, error) + }{ + { + "secp256k1 private key, binary", + tmPrivKey, + privKey, + aminoCdc.MarshalBinaryBare, + }, + { + "secp256k1 private key, JSON", + tmPrivKey, + privKey, + aminoCdc.MarshalJSON, + }, + { + "secp256k1 public key, binary", + tmPubKey, + pubKey, + aminoCdc.MarshalBinaryBare, + }, + { + "secp256k1 public key, JSON", + tmPubKey, + pubKey, + aminoCdc.MarshalJSON, + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + // Make sure Amino encoding override is not breaking backwards compatibility. + bz1, err := tc.marshalFn(tc.tmKey) + require.NoError(t, err) + bz2, err := tc.marshalFn(tc.ourKey) + require.NoError(t, err) + require.Equal(t, bz1, bz2) + }) + } +} diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index 844fc779905b..c3bcc8ea3350 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -12,7 +12,9 @@ import ( tmtypes "github.com/tendermint/tendermint/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -181,6 +183,37 @@ func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) { tstaking.CreateValidator(addr, invalidPk, 10, false) } +func TestBothPubKeyTypesMsgCreateValidator(t *testing.T) { + app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, 1000, 2, 1000) + ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ + Validator: &tmproto.ValidatorParams{PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeEd25519, tmtypes.ABCIPubKeyTypeSecp256k1}}, + }) + + tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) + + testCases := []struct { + name string + addr sdk.ValAddress + pk cryptotypes.PubKey + }{ + { + "can create a validator with ed25519 pubkey", + valAddrs[0], + ed25519.GenPrivKey().PubKey(), + }, + { + "can create a validator with secp256k1 pubkey", + valAddrs[1], + secp256k1.GenPrivKey().PubKey(), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(*testing.T) { + tstaking.CreateValidator(tc.addr, tc.pk, 10, true) + }) + } +} + func TestLegacyValidatorDelegations(t *testing.T) { app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, 1000, 2, 100000000)