Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(bank): update InputOutputCoins arguments #15477

Merged
merged 6 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
refactor(bank): update InputOutputCoins arguments
  • Loading branch information
julienrbrt committed Mar 20, 2023
commit edf54b4447d2559cc8a292bac84553ec7912819f
40 changes: 18 additions & 22 deletions x/bank/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,14 @@ func (suite *KeeperTestSuite) TestInputOutputNewAccount() {
require.Empty(suite.bankKeeper.GetAllBalances(ctx, accAddrs[1]))

suite.mockInputOutputCoins([]sdk.AccountI{authtypes.NewBaseAccountWithAddress(accAddrs[0])}, []sdk.AccAddress{accAddrs[1]})
inputs := []banktypes.Input{
{Address: accAddrs[0].String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
input := banktypes.Input{
Address: accAddrs[0].String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10)),
}
outputs := []banktypes.Output{
{Address: accAddrs[1].String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
}

require.NoError(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10))
acc2Balances := suite.bankKeeper.GetAllBalances(ctx, accAddrs[1])
Expand All @@ -524,37 +524,35 @@ func (suite *KeeperTestSuite) TestInputOutputCoins() {
balances := sdk.NewCoins(newFooCoin(90), newBarCoin(30))

acc0 := authtypes.NewBaseAccountWithAddress(accAddrs[0])
inputs := []banktypes.Input{
{Address: accAddrs[0].String(), Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20))},
input := banktypes.Input{
Address: accAddrs[0].String(), Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20)),
}
outputs := []banktypes.Output{
{Address: accAddrs[1].String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
{Address: accAddrs[2].String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
}

require.Error(suite.bankKeeper.InputOutputCoins(ctx, inputs, []banktypes.Output{}))
require.Error(suite.bankKeeper.InputOutputCoins(ctx, input, []banktypes.Output{}))

suite.authKeeper.EXPECT().GetAccount(suite.ctx, accAddrs[0]).Return(acc0)
require.Error(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.Error(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

suite.mockFundAccount(accAddrs[0])
require.NoError(banktestutil.FundAccount(suite.bankKeeper, ctx, accAddrs[0], balances))

insufficientInputs := []banktypes.Input{
{
Address: accAddrs[0].String(),
Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)),
},
insufficientInput := banktypes.Input{
Address: accAddrs[0].String(),
Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)),
}
insufficientOutputs := []banktypes.Output{
{Address: accAddrs[1].String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
{Address: accAddrs[2].String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
}

require.Error(suite.bankKeeper.InputOutputCoins(ctx, insufficientInputs, insufficientOutputs))
require.Error(suite.bankKeeper.InputOutputCoins(ctx, insufficientInput, insufficientOutputs))

suite.mockInputOutputCoins([]sdk.AccountI{acc0}, accAddrs[1:3])
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

acc1Balances := suite.bankKeeper.GetAllBalances(ctx, accAddrs[0])
expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10))
Expand Down Expand Up @@ -762,19 +760,17 @@ func (suite *KeeperTestSuite) TestMsgMultiSendEvents() {
coins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50), sdk.NewInt64Coin(barDenom, 100))
newCoins := sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50))
newCoins2 := sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))
inputs := []banktypes.Input{
{
Address: accAddrs[0].String(),
Coins: coins,
},
input := banktypes.Input{
Address: accAddrs[0].String(),
Coins: coins,
}
outputs := []banktypes.Output{
{Address: accAddrs[2].String(), Coins: newCoins},
{Address: accAddrs[3].String(), Coins: newCoins2},
}

suite.authKeeper.EXPECT().GetAccount(suite.ctx, accAddrs[0]).Return(acc0)
require.Error(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.Error(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

events := ctx.EventManager().ABCIEvents()
require.Equal(0, len(events))
Expand All @@ -784,7 +780,7 @@ func (suite *KeeperTestSuite) TestMsgMultiSendEvents() {
require.NoError(banktestutil.FundAccount(suite.bankKeeper, ctx, accAddrs[0], sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50), sdk.NewInt64Coin(barDenom, 100))))

suite.mockInputOutputCoins([]sdk.AccountI{acc0}, accAddrs[2:4])
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

events = ctx.EventManager().ABCIEvents()
require.Equal(12, len(events)) // 12 events because account funding causes extra minting + coin_spent + coin_recv events
Expand All @@ -809,7 +805,7 @@ func (suite *KeeperTestSuite) TestMsgMultiSendEvents() {
newCoins2 = sdk.NewCoins(sdk.NewInt64Coin(barDenom, 100))

suite.mockInputOutputCoins([]sdk.AccountI{acc0}, accAddrs[2:4])
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, inputs, outputs))
require.NoError(suite.bankKeeper.InputOutputCoins(ctx, input, outputs))

events = ctx.EventManager().ABCIEvents()
require.Equal(30, len(events)) // 27 due to account funding + coin_spent + coin_recv events
Expand Down
2 changes: 1 addition & 1 deletion x/bank/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t
}
}

err := k.InputOutputCoins(ctx, msg.Inputs, msg.Outputs)
err := k.InputOutputCoins(ctx, msg.Inputs[0], msg.Outputs)
if err != nil {
return nil, err
}
Expand Down
42 changes: 20 additions & 22 deletions x/bank/keeper/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
type SendKeeper interface {
ViewKeeper

InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
InputOutputCoins(ctx sdk.Context, inputs types.Input, outputs []types.Output) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error

GetParams(ctx sdk.Context) types.Params
Expand Down Expand Up @@ -110,35 +110,33 @@ func (k BaseSendKeeper) SetParams(ctx sdk.Context, params types.Params) error {
return k.Params.Set(ctx, params)
}

// InputOutputCoins performs multi-send functionality. It accepts a series of
// inputs that correspond to a series of outputs. It returns an error if the
// inputs and outputs don't line up or if any single transfer of tokens fails.
func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error {
// InputOutputCoins performs multi-send functionality. It accepts an
// input that corresponds to a series of outputs. It returns an error if the
// input and outputs don't line up or if any single transfer of tokens fails.
func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, input types.Input, outputs []types.Output) error {
// Safety check ensuring that when sending coins the keeper must maintain the
// Check supply invariant and validity of Coins.
if err := types.ValidateInputsOutputs(inputs, outputs); err != nil {
if err := types.ValidateInputOutputs(input, outputs); err != nil {
return err
}

for _, in := range inputs {
inAddress, err := sdk.AccAddressFromBech32(in.Address)
if err != nil {
return err
}

err = k.subUnlockedCoins(ctx, inAddress, in.Coins)
if err != nil {
return err
}
inAddress, err := sdk.AccAddressFromBech32(input.Address)
if err != nil {
return err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(types.AttributeKeySender, in.Address),
),
)
err = k.subUnlockedCoins(ctx, inAddress, input.Coins)
if err != nil {
return err
}

ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(types.AttributeKeySender, input.Address),
),
)

for _, out := range outputs {
outAddress, err := sdk.AccAddressFromBech32(out.Address)
if err != nil {
Expand Down
14 changes: 6 additions & 8 deletions x/bank/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (msg MsgMultiSend) ValidateBasic() error {
return ErrNoOutputs
}

return ValidateInputsOutputs(msg.Inputs, msg.Outputs)
return ValidateInputOutputs(msg.Inputs[0], msg.Outputs)
}

// GetSignBytes Implements Msg.
Expand Down Expand Up @@ -152,17 +152,15 @@ func NewOutput(addr sdk.AccAddress, coins sdk.Coins) Output {
}
}

// ValidateInputsOutputs validates that each respective input and output is
// ValidateInputOutputs validates that each respective input and output is
// valid and that the sum of inputs is equal to the sum of outputs.
func ValidateInputsOutputs(inputs []Input, outputs []Output) error {
func ValidateInputOutputs(input Input, outputs []Output) error {
var totalIn, totalOut sdk.Coins

for _, in := range inputs {
if err := in.ValidateBasic(); err != nil {
return err
}
totalIn = totalIn.Add(in.Coins...)
if err := input.ValidateBasic(); err != nil {
return err
}
totalIn = input.Coins

for _, out := range outputs {
if err := out.ValidateBasic(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion x/gov/testutil/expected_keepers_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.