cosmos-sdk/x/auth/middleware/tips_test.go

206 lines
7.1 KiB
Go
Raw Normal View History

feat: Add Tips middleware (#10208) <!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description R4R Closes: #9912 This PR introduces 1 new middleware: - `TipsMiddleware`: transfer tip from tipper to feePayer when relevant. It also makes sure in the DIRECT_AUX sign mode handler that the fee payer cannot use that sign mode. Depends on: - [x] #10028 - [x] #10268 - [x] #10322 - [x] #10346 <!-- Add a description of the changes that this PR introduces and the files that are the most critical to review. --> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-11-16 09:55:12 -08:00
package middleware_test
import (
"time"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
refactor: move legacy gov to v1beta1 (#10748) Ref: #9810 Moves all legacy gov code to `v1beta1`. This preserves all existing behavior (i.e. everything still uses v1beta1). It's merely moving things around to get everything in the right place logistically (hence the large diff still) --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-12-13 10:48:44 -08:00
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
feat: Add Tips middleware (#10208) <!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description R4R Closes: #9912 This PR introduces 1 new middleware: - `TipsMiddleware`: transfer tip from tipper to feePayer when relevant. It also makes sure in the DIRECT_AUX sign mode handler that the fee payer cannot use that sign mode. Depends on: - [x] #10028 - [x] #10268 - [x] #10322 - [x] #10346 <!-- Add a description of the changes that this PR introduces and the files that are the most critical to review. --> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-11-16 09:55:12 -08:00
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
)
var initialRegens = sdk.NewCoins(sdk.NewCoin("regen", sdk.NewInt(1000)))
var initialAtoms = sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(1000)))
// setupAcctsForTips sets up 2 accounts:
// - tipper has 1000 regens
// - feePayer has 1000 atoms and 1000 regens
func (s *MWTestSuite) setupAcctsForTips(ctx sdk.Context) (sdk.Context, []testAccount) {
accts := s.createTestAccounts(ctx, 2, initialRegens)
feePayer := accts[1]
err := s.app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, initialAtoms)
s.Require().NoError(err)
err = s.app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, feePayer.acc.GetAddress(), initialAtoms)
s.Require().NoError(err)
// Create dummy proposal for tipper to vote on.
prop, err := govtypes.NewProposal(govtypes.NewTextProposal("foo", "bar"), 1, time.Now(), time.Now().Add(time.Hour))
s.Require().NoError(err)
s.app.GovKeeper.SetProposal(ctx, prop)
s.app.GovKeeper.ActivateVotingPeriod(ctx, prop)
// Move to next block to commit previous data to state.
s.app.EndBlock(abci.RequestEndBlock{Height: ctx.BlockHeight()})
s.app.Commit()
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
s.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: ctx.BlockHeight()}})
return ctx, accts
}
func (s *MWTestSuite) TestTips() {
var msg sdk.Msg
testcases := []struct {
name string
tip sdk.Coins
fee sdk.Coins
gasLimit uint64
expErr bool
expErrStr string
}{
{
"wrong tip denom",
sdk.NewCoins(sdk.NewCoin("foobar", sdk.NewInt(1000))), initialAtoms, 200000,
true, "0foobar is smaller than 1000foobar: insufficient funds",
},
{
"insufficient tip from tipper",
sdk.NewCoins(sdk.NewCoin("regen", sdk.NewInt(5000))), initialAtoms, 200000,
true, "1000regen is smaller than 5000regen: insufficient funds",
},
{
"insufficient fees from feePayer",
initialRegens, sdk.NewCoins(sdk.NewCoin("atom", sdk.NewInt(5000))), 200000,
true, "1000atom is smaller than 5000atom: insufficient funds: insufficient funds",
},
{
"insufficient gas",
initialRegens, initialAtoms, 100,
true, "out of gas in location: ReadFlat; gasWanted: 100, gasUsed: 1000: out of gas",
},
{
"happy case",
initialRegens, initialAtoms, 200000,
false, "",
},
}
for _, tc := range testcases {
tc := tc
s.Run(tc.name, func() {
ctx := s.SetupTest(false) // reset
ctx, accts := s.setupAcctsForTips(ctx)
tipper, feePayer := accts[0], accts[1]
msg = govtypes.NewMsgVote(tipper.acc.GetAddress(), 1, govtypes.OptionYes)
auxSignerData := s.mkTipperAuxSignerData(tipper.priv, msg, tc.tip, signing.SignMode_SIGN_MODE_DIRECT_AUX, tipper.accNum, 0, ctx.ChainID())
feePayerTxBuilder := s.mkFeePayerTxBuilder(s.clientCtx, auxSignerData, feePayer.priv, signing.SignMode_SIGN_MODE_DIRECT, tx.Fee{Amount: tc.fee, GasLimit: tc.gasLimit}, feePayer.accNum, 0, ctx.ChainID())
_, res, err := s.app.SimDeliver(s.clientCtx.TxConfig.TxEncoder(), feePayerTxBuilder.GetTx())
if tc.expErr {
s.Require().Error(err)
s.Require().Contains(err.Error(), tc.expErrStr)
} else {
s.Require().NoError(err)
s.Require().NotNil(res)
// Move to next block to commit previous data to state.
s.app.EndBlock(abci.RequestEndBlock{Height: ctx.BlockHeight()})
s.app.Commit()
ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1)
s.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: ctx.BlockHeight()}})
// Make sure tip is correctly transferred to feepayer, and fee is paid.
expTipperRegens := initialRegens.Sub(tc.tip)
expFeePayerRegens := initialRegens.Add(tc.tip...)
expFeePayerAtoms := initialAtoms.Sub(tc.fee)
s.Require().True(expTipperRegens.AmountOf("regen").Equal(s.app.BankKeeper.GetBalance(ctx, tipper.acc.GetAddress(), "regen").Amount))
s.Require().True(expFeePayerRegens.AmountOf("regen").Equal(s.app.BankKeeper.GetBalance(ctx, feePayer.acc.GetAddress(), "regen").Amount))
s.Require().True(expFeePayerAtoms.AmountOf("atom").Equal(s.app.BankKeeper.GetBalance(ctx, feePayer.acc.GetAddress(), "atom").Amount))
// Make sure MsgVote has been submitted by tipper.
votes := s.app.GovKeeper.GetAllVotes(ctx)
s.Require().Len(votes, 1)
s.Require().Equal(tipper.acc.GetAddress().String(), votes[0].Voter)
}
})
}
}
func (s *MWTestSuite) mkTipperAuxSignerData(
tipperPriv cryptotypes.PrivKey, msg sdk.Msg, tip sdk.Coins,
signMode signing.SignMode, accNum, accSeq uint64, chainID string,
) tx.AuxSignerData {
tipperAddr := sdk.AccAddress(tipperPriv.PubKey().Address()).String()
b := clienttx.NewAuxTxBuilder()
b.SetAddress(tipperAddr)
b.SetAccountNumber(accNum)
b.SetSequence(accSeq)
err := b.SetMsgs(msg)
s.Require().NoError(err)
b.SetTip(&tx.Tip{Amount: tip, Tipper: tipperAddr})
err = b.SetSignMode(signMode)
s.Require().NoError(err)
b.SetSequence(accSeq)
err = b.SetPubKey(tipperPriv.PubKey())
s.Require().NoError(err)
b.SetChainID(chainID)
signBz, err := b.GetSignBytes()
s.Require().NoError(err)
sig, err := tipperPriv.Sign(signBz)
s.Require().NoError(err)
b.SetSignature(sig)
auxSignerData, err := b.GetAuxSignerData()
s.Require().NoError(err)
return auxSignerData
}
func (s *MWTestSuite) mkFeePayerTxBuilder(
clientCtx client.Context,
auxSignerData tx.AuxSignerData,
feePayerPriv cryptotypes.PrivKey, signMode signing.SignMode,
fee tx.Fee, accNum, accSeq uint64, chainID string,
) client.TxBuilder {
txBuilder := clientCtx.TxConfig.NewTxBuilder()
err := txBuilder.AddAuxSignerData(auxSignerData)
s.Require().NoError(err)
txBuilder.SetFeePayer(sdk.AccAddress(feePayerPriv.PubKey().Address()))
txBuilder.SetFeeAmount(fee.Amount)
txBuilder.SetGasLimit(fee.GasLimit)
// Calling SetSignatures with empty sig to populate AuthInfo.
tipperSigsV2, err := auxSignerData.GetSignatureV2()
s.Require().NoError(err)
feePayerSigV2 := signing.SignatureV2{
PubKey: feePayerPriv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: signMode,
Signature: nil,
}}
sigsV2 := append([]signing.SignatureV2{tipperSigsV2}, feePayerSigV2)
txBuilder.SetSignatures(sigsV2...)
// Actually sign the data.
signerData := authsigning.SignerData{
Address: sdk.AccAddress(feePayerPriv.PubKey().Address()).String(),
ChainID: chainID,
AccountNumber: accNum,
Sequence: accSeq,
refactor: Change SignerData.SignerIndex to PubKey (#10692) <!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description Closes: #10691 <!-- Add a description of the changes that this PR introduces and the files that are the most critical to review. --> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-12-08 03:43:15 -08:00
PubKey: feePayerPriv.PubKey(),
feat: Add Tips middleware (#10208) <!-- The default pull request template is for types feat, fix, or refactor. For other templates, add one of the following parameters to the url: - template=docs.md - template=other.md --> ## Description R4R Closes: #9912 This PR introduces 1 new middleware: - `TipsMiddleware`: transfer tip from tipper to feePayer when relevant. It also makes sure in the DIRECT_AUX sign mode handler that the fee payer cannot use that sign mode. Depends on: - [x] #10028 - [x] #10268 - [x] #10322 - [x] #10346 <!-- Add a description of the changes that this PR introduces and the files that are the most critical to review. --> --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-11-16 09:55:12 -08:00
}
feePayerSigV2, err = clienttx.SignWithPrivKey(
signMode, signerData,
txBuilder, feePayerPriv, clientCtx.TxConfig, accSeq)
s.Require().NoError(err)
sigsV2 = append([]signing.SignatureV2{tipperSigsV2}, feePayerSigV2)
err = txBuilder.SetSignatures(sigsV2...)
s.Require().NoError(err)
return txBuilder
}