diff --git a/.pending/breaking/gaia/3463-Revert-bank-module-handler-fork-re-enables-transfers b/.pending/breaking/gaia/3463-Revert-bank-module-handler-fork-re-enables-transfers new file mode 100644 index 000000000..02589d311 --- /dev/null +++ b/.pending/breaking/gaia/3463-Revert-bank-module-handler-fork-re-enables-transfers @@ -0,0 +1 @@ +#3463 Revert bank module handler fork (re-enables transfers) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index bd2c3d92b..d0925a158 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -11,9 +11,6 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - // TODO: Remove once transfers are enabled. - gaiabank "github.com/cosmos/cosmos-sdk/cmd/gaia/app/x/bank" - bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -169,10 +166,8 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest, staking.RegisterInvariants(&app.crisisKeeper, app.stakingKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper) // register message routes - // - // TODO: Use standard bank router once transfers are enabled. app.Router(). - AddRoute(bank.RouterKey, gaiabank.NewHandler(app.bankKeeper)). + AddRoute(bank.RouterKey, bank.NewHandler(app.bankKeeper)). AddRoute(staking.RouterKey, staking.NewHandler(app.stakingKeeper)). AddRoute(distr.RouterKey, distr.NewHandler(app.distrKeeper)). AddRoute(slashing.RouterKey, slashing.NewHandler(app.slashingKeeper)). diff --git a/cmd/gaia/app/x/bank/handler.go b/cmd/gaia/app/x/bank/handler.go deleted file mode 100644 index d3aa3415d..000000000 --- a/cmd/gaia/app/x/bank/handler.go +++ /dev/null @@ -1,100 +0,0 @@ -// Package bank contains a forked version of the bank module. It only contains -// a modified message handler to support a very limited form of transfers during -// mainnet launch -- MsgMultiSend messages. -// -// NOTE: This fork should be removed entirely once transfers are enabled and -// the Gaia router should be reset to using the original bank module handler. -package bank - -import ( - "github.com/tendermint/tendermint/crypto" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank" -) - -var ( - uatomDenom = "uatom" - atomsToUatoms = int64(1000000) - - // BurnedCoinsAccAddr represents the burn account address used for - // MsgMultiSend message during the period for which transfers are disabled. - // Its Bech32 address is cosmos1x4p90uuy63fqzsheamn48vq88q3eusykf0a69v. - BurnedCoinsAccAddr = sdk.AccAddress(crypto.AddressHash([]byte("bankBurnedCoins"))) -) - -// NewHandler returns a handler for "bank" type messages. -func NewHandler(k bank.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - switch msg := msg.(type) { - case bank.MsgSend: - return handleMsgSend(ctx, k, msg) - - case bank.MsgMultiSend: - return handleMsgMultiSend(ctx, k, msg) - - default: - errMsg := "Unrecognized bank Msg type: %s" + msg.Type() - return sdk.ErrUnknownRequest(errMsg).Result() - } - } -} - -// handleMsgSend implements a MsgSend message handler. It operates no differently -// than the standard bank module MsgSend message handler in that it transfers -// an amount from one account to another under the condition of transfers being -// enabled. -func handleMsgSend(ctx sdk.Context, k bank.Keeper, msg bank.MsgSend) sdk.Result { - // No need to modify handleMsgSend as the forked module requires no changes, - // so we can just call the standard bank modules handleMsgSend since we know - // the message is of type MsgSend. - return bank.NewHandler(k)(ctx, msg) -} - -// handleMsgMultiSend implements a modified forked version of a MsgMultiSend -// message handler. If transfers are disabled, a modified version of MsgMultiSend -// is allowed where there must be a single input and only two outputs. The first -// of the two outputs must be to a specific burn address defined by -// burnedCoinsAccAddr. In addition, the output amounts must be of 9atom and -// 1uatom respectively. -func handleMsgMultiSend(ctx sdk.Context, k bank.Keeper, msg bank.MsgMultiSend) sdk.Result { - // NOTE: totalIn == totalOut should already have been checked - if !k.GetSendEnabled(ctx) { - if !validateMultiSendTransfersDisabled(msg) { - return bank.ErrSendDisabled(k.Codespace()).Result() - } - } - - tags, err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) - if err != nil { - return err.Result() - } - - return sdk.Result{ - Tags: tags, - } -} - -func validateMultiSendTransfersDisabled(msg bank.MsgMultiSend) bool { - nineAtoms := sdk.Coins{sdk.NewInt64Coin(uatomDenom, 9*atomsToUatoms)} - oneAtom := sdk.Coins{sdk.NewInt64Coin(uatomDenom, 1*atomsToUatoms)} - - if len(msg.Inputs) != 1 { - return false - } - if len(msg.Outputs) != 2 { - return false - } - - if !msg.Outputs[0].Address.Equals(BurnedCoinsAccAddr) { - return false - } - if !msg.Outputs[0].Coins.IsEqual(nineAtoms) { - return false - } - if !msg.Outputs[1].Coins.IsEqual(oneAtom) { - return false - } - - return true -} diff --git a/cmd/gaia/app/x/bank/handler_test.go b/cmd/gaia/app/x/bank/handler_test.go deleted file mode 100644 index c799e03f8..000000000 --- a/cmd/gaia/app/x/bank/handler_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package bank - -import ( - "testing" - "time" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/secp256k1" - dbm "github.com/tendermint/tendermint/libs/db" - "github.com/tendermint/tendermint/libs/log" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/params" -) - -var ( - addrs = []sdk.AccAddress{ - sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()), - sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()), - sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()), - } - - initAmt = sdk.NewInt(atomsToUatoms * 100) -) - -type testInput struct { - ctx sdk.Context - accKeeper auth.AccountKeeper - bankKeeper bank.Keeper -} - -func newTestCodec() *codec.Codec { - cdc := codec.New() - - bank.RegisterCodec(cdc) - auth.RegisterCodec(cdc) - sdk.RegisterCodec(cdc) - codec.RegisterCrypto(cdc) - - return cdc -} - -func createTestInput(t *testing.T) testInput { - keyAcc := sdk.NewKVStoreKey(auth.StoreKey) - keyParams := sdk.NewKVStoreKey(params.StoreKey) - tKeyParams := sdk.NewTransientStoreKey(params.TStoreKey) - - cdc := newTestCodec() - db := dbm.NewMemDB() - ms := store.NewCommitMultiStore(db) - ctx := sdk.NewContext(ms, abci.Header{Time: time.Now().UTC()}, false, log.NewNopLogger()) - - ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db) - ms.MountStoreWithDB(tKeyParams, sdk.StoreTypeTransient, db) - ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db) - - require.NoError(t, ms.LoadLatestVersion()) - - paramsKeeper := params.NewKeeper(cdc, keyParams, tKeyParams) - accKeeper := auth.NewAccountKeeper( - cdc, - keyAcc, - paramsKeeper.Subspace(auth.DefaultParamspace), - auth.ProtoBaseAccount, - ) - - bankKeeper := bank.NewBaseKeeper( - accKeeper, - paramsKeeper.Subspace(bank.DefaultParamspace), - bank.DefaultCodespace, - ) - - for _, addr := range addrs { - _, _, err := bankKeeper.AddCoins(ctx, addr, sdk.Coins{sdk.NewCoin(uatomDenom, initAmt)}) - require.NoError(t, err) - } - - return testInput{ctx, accKeeper, bankKeeper} -} - -func TestHandlerMsgSendTransfersDisabled(t *testing.T) { - input := createTestInput(t) - input.bankKeeper.SetSendEnabled(input.ctx, false) - - handler := NewHandler(input.bankKeeper) - amt := sdk.NewInt(atomsToUatoms * 5) - msg := bank.NewMsgSend(addrs[0], addrs[1], sdk.Coins{sdk.NewCoin(uatomDenom, amt)}) - - res := handler(input.ctx, msg) - require.False(t, res.IsOK(), "expected failed message execution: %v", res.Log) - - from := input.accKeeper.GetAccount(input.ctx, addrs[0]) - require.Equal(t, from.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, initAmt)}) - - to := input.accKeeper.GetAccount(input.ctx, addrs[1]) - require.Equal(t, to.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, initAmt)}) -} - -func TestHandlerMsgSendTransfersEnabled(t *testing.T) { - input := createTestInput(t) - input.bankKeeper.SetSendEnabled(input.ctx, true) - - handler := NewHandler(input.bankKeeper) - amt := sdk.NewInt(atomsToUatoms * 5) - msg := bank.NewMsgSend(addrs[0], addrs[1], sdk.Coins{sdk.NewCoin(uatomDenom, amt)}) - - res := handler(input.ctx, msg) - require.True(t, res.IsOK(), "expected successful message execution: %v", res.Log) - - from := input.accKeeper.GetAccount(input.ctx, addrs[0]) - balance := initAmt.Sub(amt) - require.Equal(t, from.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) - - to := input.accKeeper.GetAccount(input.ctx, addrs[1]) - balance = initAmt.Add(amt) - require.Equal(t, to.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) -} - -func TestHandlerMsgMultiSendTransfersDisabledBurn(t *testing.T) { - input := createTestInput(t) - input.bankKeeper.SetSendEnabled(input.ctx, false) - - handler := NewHandler(input.bankKeeper) - totalAmt := sdk.NewInt(10 * atomsToUatoms) - burnAmt := sdk.NewInt(9 * atomsToUatoms) - transAmt := sdk.NewInt(1 * atomsToUatoms) - msg := bank.NewMsgMultiSend( - []bank.Input{ - bank.NewInput(addrs[0], sdk.Coins{sdk.NewCoin(uatomDenom, totalAmt)}), - }, - []bank.Output{ - bank.NewOutput(BurnedCoinsAccAddr, sdk.Coins{sdk.NewCoin(uatomDenom, burnAmt)}), - bank.NewOutput(addrs[1], sdk.Coins{sdk.NewCoin(uatomDenom, transAmt)}), - }, - ) - - res := handler(input.ctx, msg) - require.True(t, res.IsOK(), "expected successful message execution: %v", res.Log) - - from := input.accKeeper.GetAccount(input.ctx, addrs[0]) - balance := initAmt.Sub(totalAmt) - require.Equal(t, from.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) - - to := input.accKeeper.GetAccount(input.ctx, addrs[1]) - balance = initAmt.Add(transAmt) - require.Equal(t, to.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) - - burn := input.accKeeper.GetAccount(input.ctx, BurnedCoinsAccAddr) - require.Equal(t, burn.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, burnAmt)}) -} - -func TestHandlerMsgMultiSendTransfersDisabledInvalidBurn(t *testing.T) { - input := createTestInput(t) - input.bankKeeper.SetSendEnabled(input.ctx, false) - - handler := NewHandler(input.bankKeeper) - totalAmt := sdk.NewInt(15 * atomsToUatoms) - burnAmt := sdk.NewInt(10 * atomsToUatoms) - transAmt := sdk.NewInt(5 * atomsToUatoms) - msg := bank.NewMsgMultiSend( - []bank.Input{ - bank.NewInput(addrs[0], sdk.Coins{sdk.NewCoin(uatomDenom, totalAmt)}), - }, - []bank.Output{ - bank.NewOutput(BurnedCoinsAccAddr, sdk.Coins{sdk.NewCoin(uatomDenom, burnAmt)}), - bank.NewOutput(addrs[1], sdk.Coins{sdk.NewCoin(uatomDenom, transAmt)}), - }, - ) - - res := handler(input.ctx, msg) - require.False(t, res.IsOK(), "expected failed message execution: %v", res.Log) - - from := input.accKeeper.GetAccount(input.ctx, addrs[0]) - require.Equal(t, from.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, initAmt)}) - - to := input.accKeeper.GetAccount(input.ctx, addrs[1]) - require.Equal(t, to.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, initAmt)}) -} - -func TestHandlerMsgMultiSendTransfersEnabled(t *testing.T) { - input := createTestInput(t) - input.bankKeeper.SetSendEnabled(input.ctx, true) - - handler := NewHandler(input.bankKeeper) - totalAmt := sdk.NewInt(10 * atomsToUatoms) - outAmt := sdk.NewInt(5 * atomsToUatoms) - msg := bank.NewMsgMultiSend( - []bank.Input{ - bank.NewInput(addrs[0], sdk.Coins{sdk.NewCoin(uatomDenom, totalAmt)}), - }, - []bank.Output{ - bank.NewOutput(addrs[1], sdk.Coins{sdk.NewCoin(uatomDenom, outAmt)}), - bank.NewOutput(addrs[2], sdk.Coins{sdk.NewCoin(uatomDenom, outAmt)}), - }, - ) - - res := handler(input.ctx, msg) - require.True(t, res.IsOK(), "expected successful message execution: %v", res.Log) - - from := input.accKeeper.GetAccount(input.ctx, addrs[0]) - balance := initAmt.Sub(totalAmt) - require.Equal(t, from.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) - - out1 := input.accKeeper.GetAccount(input.ctx, addrs[1]) - balance = initAmt.Add(outAmt) - require.Equal(t, out1.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) - - out2 := input.accKeeper.GetAccount(input.ctx, addrs[2]) - balance = initAmt.Add(outAmt) - require.Equal(t, out2.GetCoins(), sdk.Coins{sdk.NewCoin(uatomDenom, balance)}) -}