diff --git a/PENDING.md b/PENDING.md index d93d0adb3..0447beee0 100644 --- a/PENDING.md +++ b/PENDING.md @@ -23,6 +23,7 @@ * [\#3669] Ensure consistency in message naming, codec registration, and JSON tags. +* [\#3751] Disable (temporarily) support for ED25519 account key pairs. ### Tendermint diff --git a/x/auth/ante.go b/x/auth/ante.go index fc6e8f5ad..376f36018 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -188,7 +188,10 @@ func processSig( consumeSimSigGas(ctx.GasMeter(), pubKey, sig, params) } - consumeSigVerificationGas(ctx.GasMeter(), sig.Signature, pubKey, params) + if res := consumeSigVerificationGas(ctx.GasMeter(), sig.Signature, pubKey, params); !res.IsOK() { + return nil, res + } + if !simulate && !pubKey.VerifyBytes(signBytes, sig.Signature) { return nil, sdk.ErrUnauthorized("signature verification failed").Result() } @@ -256,14 +259,20 @@ func ProcessPubKey(acc Account, sig StdSignature, simulate bool) (crypto.PubKey, // by the concrete type. // // TODO: Design a cleaner and flexible way to match concrete public key types. -func consumeSigVerificationGas(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params Params) { +func consumeSigVerificationGas( + meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params Params, +) sdk.Result { + pubkeyType := strings.ToLower(fmt.Sprintf("%T", pubkey)) + switch { case strings.Contains(pubkeyType, "ed25519"): meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519") + return sdk.ErrInvalidPubKey("ED25519 public keys are unsupported").Result() case strings.Contains(pubkeyType, "secp256k1"): meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") + return sdk.Result{} case strings.Contains(pubkeyType, "multisigthreshold"): var multisignature multisig.Multisignature @@ -271,9 +280,10 @@ func consumeSigVerificationGas(meter sdk.GasMeter, sig []byte, pubkey crypto.Pub multisigPubKey := pubkey.(multisig.PubKeyMultisigThreshold) consumeMultisignatureVerificationGas(meter, multisignature, multisigPubKey, params) + return sdk.Result{} default: - panic(fmt.Sprintf("unrecognized signature type: %s", pubkeyType)) + return sdk.ErrInvalidPubKey(fmt.Sprintf("unrecognized public key type: %s", pubkeyType)).Result() } } diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index 9a554080a..8d1db6f1a 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -585,19 +585,21 @@ func TestConsumeSignatureVerificationGas(t *testing.T) { name string args args gasConsumed uint64 - wantPanic bool + shouldErr bool }{ - {"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, false}, + {"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostED25519, true}, {"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, DefaultSigVerifyCostSecp256k1, false}, {"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1.Marshal(), multisigKey1, params}, expectedCost1, false}, {"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if tt.wantPanic { - require.Panics(t, func() { consumeSigVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) }) + res := consumeSigVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) + + if tt.shouldErr { + require.False(t, res.IsOK()) } else { - consumeSigVerificationGas(tt.args.meter, tt.args.sig, tt.args.pubkey, tt.args.params) + require.True(t, res.IsOK()) require.Equal(t, tt.gasConsumed, tt.args.meter.GasConsumed(), fmt.Sprintf("%d != %d", tt.gasConsumed, tt.args.meter.GasConsumed())) } }) diff --git a/x/auth/test_utils.go b/x/auth/test_utils.go index 096b3897a..800622b42 100644 --- a/x/auth/test_utils.go +++ b/x/auth/test_utils.go @@ -4,7 +4,7 @@ package auth import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" @@ -67,7 +67,7 @@ func newCoins() sdk.Coins { } func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { - key := ed25519.GenPrivKey() + key := secp256k1.GenPrivKey() pub := key.PubKey() addr := sdk.AccAddress(pub.Address()) return key, pub, addr diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 824f48670..8703d71ec 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -11,7 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) type ( @@ -32,12 +32,12 @@ type ( ) var ( - priv1 = ed25519.GenPrivKey() + priv1 = secp256k1.GenPrivKey() addr1 = sdk.AccAddress(priv1.PubKey().Address()) - priv2 = ed25519.GenPrivKey() + priv2 = secp256k1.GenPrivKey() addr2 = sdk.AccAddress(priv2.PubKey().Address()) - addr3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) - priv4 = ed25519.GenPrivKey() + addr3 = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) + priv4 = secp256k1.GenPrivKey() addr4 = sdk.AccAddress(priv4.PubKey().Address()) coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} @@ -104,6 +104,36 @@ func getInitChainer(mapp *mock.App, keeper BaseKeeper) sdk.InitChainer { } } +func TestSendNotEnoughBalance(t *testing.T) { + mapp := getMockApp(t) + acc := &auth.BaseAccount{ + Address: addr1, + Coins: sdk.Coins{sdk.NewInt64Coin("foocoin", 67)}, + } + + mock.SetGenesis(mapp, []auth.Account{acc}) + + ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{}) + + res1 := mapp.AccountKeeper.GetAccount(ctxCheck, addr1) + require.NotNil(t, res1) + require.Equal(t, acc, res1.(*auth.BaseAccount)) + + origAccNum := res1.GetAccountNumber() + origSeq := res1.GetSequence() + + sendMsg := NewMsgSend(addr1, addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 100)}) + mock.SignCheckDeliver(t, mapp.Cdc, mapp.BaseApp, []sdk.Msg{sendMsg}, []uint64{origAccNum}, []uint64{origSeq}, false, false, priv1) + + mock.CheckBalance(t, mapp, addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 67)}) + + res2 := mapp.AccountKeeper.GetAccount(mapp.NewContext(true, abci.Header{}), addr1) + require.NotNil(t, res2) + + require.True(t, res2.GetAccountNumber() == origAccNum) + require.True(t, res2.GetSequence() == origSeq+1) +} + func TestMsgMultiSendWithAccounts(t *testing.T) { mapp := getMockApp(t) acc := &auth.BaseAccount{ diff --git a/x/ibc/app_test.go b/x/ibc/app_test.go index 626e9a5b0..0b1e7d9da 100644 --- a/x/ibc/app_test.go +++ b/x/ibc/app_test.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/mock" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) // initialize the mock application for this module @@ -36,7 +36,7 @@ func TestIBCMsgs(t *testing.T) { sourceChain := "source-chain" destChain := "dest-chain" - priv1 := ed25519.GenPrivKey() + priv1 := secp256k1.GenPrivKey() addr1 := sdk.AccAddress(priv1.PubKey().Address()) coins := sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} var emptyCoins sdk.Coins diff --git a/x/mock/app.go b/x/mock/app.go index a5dad50e6..3e24bee0d 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -177,7 +177,7 @@ func CreateGenAccounts(numAccs int, genCoins sdk.Coins) (genAccs []auth.Account, addrKeysSlice := AddrKeysSlice{} for i := 0; i < numAccs; i++ { - privKey := ed25519.GenPrivKey() + privKey := secp256k1.GenPrivKey() pubKey := privKey.PubKey() addr := sdk.AccAddress(pubKey.Address()) @@ -235,12 +235,12 @@ func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKe return auth.NewStdTx(msgs, fee, sigs, memo) } -// GeneratePrivKeys generates a total n Ed25519 private keys. +// GeneratePrivKeys generates a total n secp256k1 private keys. func GeneratePrivKeys(n int) (keys []crypto.PrivKey) { // TODO: Randomize this between ed25519 and secp256k1 keys = make([]crypto.PrivKey, n) for i := 0; i < n; i++ { - keys[i] = ed25519.GenPrivKey() + keys[i] = secp256k1.GenPrivKey() } return diff --git a/x/slashing/app_test.go b/x/slashing/app_test.go index 0ae91f424..6f15e4aee 100644 --- a/x/slashing/app_test.go +++ b/x/slashing/app_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -15,7 +15,7 @@ import ( ) var ( - priv1 = ed25519.GenPrivKey() + priv1 = secp256k1.GenPrivKey() addr1 = sdk.AccAddress(priv1.PubKey().Address()) coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} ) diff --git a/x/staking/test_common.go b/x/staking/test_common.go index 2ddc53447..62cee84db 100644 --- a/x/staking/test_common.go +++ b/x/staking/test_common.go @@ -2,7 +2,7 @@ package staking import ( "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" @@ -10,12 +10,12 @@ import ( ) var ( - priv1 = ed25519.GenPrivKey() + priv1 = secp256k1.GenPrivKey() addr1 = sdk.AccAddress(priv1.PubKey().Address()) - priv2 = ed25519.GenPrivKey() + priv2 = secp256k1.GenPrivKey() addr2 = sdk.AccAddress(priv2.PubKey().Address()) - addr3 = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) - priv4 = ed25519.GenPrivKey() + addr3 = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) + priv4 = secp256k1.GenPrivKey() addr4 = sdk.AccAddress(priv4.PubKey().Address()) coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))} fee = auth.NewStdFee(