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

fix: revert proto changes from #12610 #12670

Merged
merged 9 commits into from
Jul 21, 2022
255 changes: 157 additions & 98 deletions api/cosmos/bank/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions proto/cosmos/bank/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ message MsgSend {
// MsgSendResponse defines the Msg/Send response type.
message MsgSendResponse {}

// MsgMultiSend represents a single input, multi-out send message.
// MsgMultiSend represents an arbitrary multi-in, multi-out send message.
message MsgMultiSend {
option (cosmos.msg.v1.signer) = "input";
option (cosmos.msg.v1.signer) = "inputs";

option (gogoproto.equal) = false;

Input input = 1 [(gogoproto.nullable) = false];
repeated Input inputs = 1 [(gogoproto.nullable) = false];
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
repeated Output outputs = 2 [(gogoproto.nullable) = false];
}

Expand Down
8 changes: 4 additions & 4 deletions x/bank/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,24 @@ var (
sendMsg1 = types.NewMsgSend(addr1, addr2, coins)

multiSendMsg1 = &types.MsgMultiSend{
likhita-809 marked this conversation as resolved.
Show resolved Hide resolved
Input: types.NewInput(addr1, coins),
Inputs: []types.Input{types.NewInput(addr1, coins)},
Outputs: []types.Output{types.NewOutput(addr2, coins)},
}
multiSendMsg2 = &types.MsgMultiSend{
Input: types.NewInput(addr1, coins),
Inputs: []types.Input{types.NewInput(addr1, coins)},
Outputs: []types.Output{
types.NewOutput(addr2, halfCoins),
types.NewOutput(addr3, halfCoins),
},
}
multiSendMsg3 = &types.MsgMultiSend{
Input: types.NewInput(addr2, coins),
Inputs: []types.Input{types.NewInput(addr2, coins)},
Outputs: []types.Output{
types.NewOutput(addr1, coins),
},
}
multiSendMsg4 = &types.MsgMultiSend{
Input: types.NewInput(addr1, coins),
Inputs: []types.Input{types.NewInput(addr1, coins)},
Outputs: []types.Output{
types.NewOutput(moduleAccAddr, coins),
},
Expand Down
2 changes: 1 addition & 1 deletion x/bank/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ When using '--dry-run' a key name cannot be used, only a bech32 address.
amount = coins.MulInt(totalAddrs)
}

msg := types.NewMsgMultiSend(types.NewInput(clientCtx.FromAddress, amount), output)
msg := types.NewMsgMultiSend([]types.Input{types.NewInput(clientCtx.FromAddress, amount)}, output)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
Expand Down
27 changes: 14 additions & 13 deletions x/bank/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,14 @@ func (suite *IntegrationTestSuite) TestInputOutputNewAccount() {
suite.Require().Nil(app.AccountKeeper.GetAccount(ctx, addr2))
suite.Require().Empty(app.BankKeeper.GetAllBalances(ctx, addr2))

input := types.Input{
Address: addr1.String(),
Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10)),
inputs := []types.Input{
{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
}
outputs := []types.Output{
{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
}

suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, input, outputs))
suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))

expected := sdk.NewCoins(newFooCoin(30), newBarCoin(10))
acc2Balances := app.BankKeeper.GetAllBalances(ctx, addr2)
Expand All @@ -393,9 +392,8 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() {
acc3 := app.AccountKeeper.NewAccountWithAddress(ctx, addr3)
app.AccountKeeper.SetAccount(ctx, acc3)

input := types.Input{
Address: addr1.String(),
Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20)),
input := []types.Input{
{Address: addr1.String(), Coins: sdk.NewCoins(newFooCoin(60), newBarCoin(20))},
}
outputs := []types.Output{
{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(30), newBarCoin(10))},
Expand All @@ -407,9 +405,11 @@ func (suite *IntegrationTestSuite) TestInputOutputCoins() {

suite.Require().NoError(testutil.FundAccount(app.BankKeeper, ctx, addr1, balances))

insufficientInput := types.Input{
Address: addr1.String(),
Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)),
insufficientInput := []types.Input{
{
Address: addr1.String(),
Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100)),
},
}
insufficientOutputs := []types.Output{
{Address: addr2.String(), Coins: sdk.NewCoins(newFooCoin(300), newBarCoin(100))},
Expand Down Expand Up @@ -613,9 +613,10 @@ func (suite *IntegrationTestSuite) 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))
input := types.Input{
Address: addr.String(),
Coins: coins,
input := []types.Input{
{Address: addr.String(),
Coins: coins,
},
}
outputs := []types.Output{
{Address: addr3.String(), Coins: newCoins},
Expand Down
8 changes: 5 additions & 3 deletions x/bank/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t
ctx := sdk.UnwrapSDKContext(goCtx)

// NOTE: totalIn == totalOut should already have been checked
if err := k.IsSendEnabledCoins(ctx, msg.Input.Coins...); err != nil {
return nil, err
for _, in := range msg.Inputs {
if err := k.IsSendEnabledCoins(ctx, in.Coins...); err != nil {
return nil, err
}
}

for _, out := range msg.Outputs {
Expand All @@ -88,7 +90,7 @@ func (k msgServer) MultiSend(goCtx context.Context, msg *types.MsgMultiSend) (*t
}
}

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

InputOutputCoins(ctx sdk.Context, input 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 @@ -120,30 +120,31 @@ func (k BaseSendKeeper) SetParams(ctx sdk.Context, params types.Params) error {
// 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, input types.Input, outputs []types.Output) error {
func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []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(input, outputs); err != nil {
if err := types.ValidateInputsOutputs(inputs, outputs); err != nil {
return err
}

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

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

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
98 changes: 55 additions & 43 deletions x/bank/simulation/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,25 +176,40 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
// random number of outputs between [1, 3]
// random number of inputs/outputs between [1, 3]
inputs := make([]types.Input, r.Intn(1)+1)
outputs := make([]types.Output, r.Intn(3)+1)

// collect signer privKeys
privs := make([]cryptotypes.PrivKey, len(inputs))

// use map to check if address already exists as input
usedAddrs := make(map[string]bool)

var totalSentCoins sdk.Coins
// generate random input fields, ignore to address
from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak)
for i := range inputs {
// generate random input fields, ignore to address
from, _, coins, skip := randomSendFields(r, ctx, accs, bk, ak)

// if coins slice is empty, we can not create valid types.MsgMultiSend
if len(coins) == 0 {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "empty coins slice"), nil, nil
}
// make sure account is fresh and not used in previous input
for usedAddrs[from.Address.String()] {
from, _, coins, skip = randomSendFields(r, ctx, accs, bk, ak)
}

if skip {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "skip all transfers"), nil, nil
}
if skip {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, "skip all transfers"), nil, nil
}

// set next input and accumulate total sent coins
input := types.NewInput(from.Address, coins)
totalSentCoins = totalSentCoins.Add(coins...)
// set input address in used address map
usedAddrs[from.Address.String()] = true

// set signer privkey
privs[i] = from.PrivKey

// set next input and accumulate total sent coins
inputs[i] = types.NewInput(from.Address, coins)
totalSentCoins = totalSentCoins.Add(coins...)
}

// Check send_enabled status of each sent coin denom
if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil {
Expand Down Expand Up @@ -231,10 +246,10 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope
}

msg := &types.MsgMultiSend{
Input: input,
Inputs: inputs,
Outputs: outputs,
}
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{from.PrivKey})
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
}
Expand All @@ -249,20 +264,22 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
inputs := make([]types.Input, 2)
outputs := make([]types.Output, moduleAccCount)

// collect signer privKeys
privs := make([]cryptotypes.PrivKey, len(inputs))
var totalSentCoins sdk.Coins

sender := accs[0]
spendable := bk.SpendableCoins(ctx, sender.Address)
coins := simtypes.RandSubsetCoins(r, spendable)
input := types.NewInput(sender.Address, coins)
totalSentCoins = totalSentCoins.Add(coins...)

for i := range inputs {
sender := accs[i]
privs[i] = sender.PrivKey
spendable := bk.SpendableCoins(ctx, sender.Address)
coins := simtypes.RandSubsetCoins(r, spendable)
inputs[i] = types.NewInput(sender.Address, coins)
totalSentCoins = totalSentCoins.Add(coins...)
}
if err := bk.IsSendEnabledCoins(ctx, totalSentCoins...); err != nil {
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgMultiSend, err.Error()), nil, nil
}

moduleAccounts := getModuleAccounts(ak, ctx, moduleAccCount)
for i := range outputs {
var outCoins sdk.Coins
Expand All @@ -275,12 +292,9 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe
outCoins = simtypes.RandSubsetCoins(r, totalSentCoins)
totalSentCoins = totalSentCoins.Sub(outCoins...)
}

outputs[i] = types.NewOutput(moduleAccounts[i].Address, outCoins)
}

// remove any output that has no coins

for i := 0; i < len(outputs); {
if outputs[i].Coins.Empty() {
outputs[i] = outputs[len(outputs)-1]
Expand All @@ -290,16 +304,14 @@ func SimulateMsgMultiSendToModuleAccount(ak types.AccountKeeper, bk keeper.Keepe
i++
}
}

msg := &types.MsgMultiSend{
Input: input,
Inputs: inputs,
Outputs: outputs,
}
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, []cryptotypes.PrivKey{sender.PrivKey})
err := sendMsgMultiSend(r, app, bk, ak, msg, ctx, chainID, privs)
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err
}

return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil
}
}
Expand All @@ -310,27 +322,29 @@ func sendMsgMultiSend(
r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper,
msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey,
) error {

addr := sdk.MustAccAddressFromBech32(msg.Input.Address)
acc := ak.GetAccount(ctx, addr)

accountNumbers := make([]uint64, len(msg.Inputs))
sequenceNumbers := make([]uint64, len(msg.Inputs))
for i := 0; i < len(msg.Inputs); i++ {
addr := sdk.MustAccAddressFromBech32(msg.Inputs[i].Address)
acc := ak.GetAccount(ctx, addr)
accountNumbers[i] = acc.GetAccountNumber()
sequenceNumbers[i] = acc.GetSequence()
}
var (
fees sdk.Coins
err error
)

addr := sdk.MustAccAddressFromBech32(msg.Inputs[0].Address)
// feePayer is the first signer, i.e. first input address
feePayer := ak.GetAccount(ctx, addr)
spendable := bk.SpendableCoins(ctx, feePayer.GetAddress())

coins, hasNeg := spendable.SafeSub(msg.Input.Coins...)
coins, hasNeg := spendable.SafeSub(msg.Inputs[0].Coins...)
if !hasNeg {
fees, err = simtypes.RandomFees(r, ctx, coins)
if err != nil {
return err
}
}

txGen := simappparams.MakeTestEncodingConfig().TxConfig
tx, err := simtestutil.GenSignedMockTx(
r,
Expand All @@ -339,19 +353,17 @@ func sendMsgMultiSend(
fees,
simtestutil.DefaultGenTxGas,
chainID,
[]uint64{acc.GetAccountNumber()},
[]uint64{acc.GetSequence()},
accountNumbers,
sequenceNumbers,
privkeys...,
)
if err != nil {
return err
}

_, _, err = app.SimDeliver(txGen.TxEncoder(), tx)
if err != nil {
return err
}

return nil
}

Expand Down
Loading