From f02f7aa5a09d8fae4cae65fc387116eadd9055e0 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 19 Dec 2018 21:26:33 -0300 Subject: [PATCH] Add fees and memo to REST, updated CLI to receive coins as fees (#3069) --- PENDING.md | 13 +- client/flags.go | 19 +- client/lcd/lcd_test.go | 204 +++++++++++++++------- client/lcd/swagger-ui/swagger.yaml | 13 +- client/lcd/test_helpers.go | 157 ++++++----------- client/utils/rest.go | 134 +++++++------- client/utils/utils.go | 21 +-- client/utils/utils_test.go | 3 +- cmd/gaia/app/benchmarks/txsize_test.go | 4 +- cmd/gaia/cli_test/cli_test.go | 6 +- x/auth/ante.go | 2 +- x/auth/ante_test.go | 10 +- x/auth/client/cli/sign.go | 2 +- x/auth/client/rest/sign.go | 7 +- x/auth/client/txbuilder/txbuilder.go | 140 +++++++++------ x/auth/client/txbuilder/txbuilder_test.go | 22 +-- x/auth/stdtx.go | 2 +- x/bank/app_test.go | 2 +- x/bank/client/rest/sendtx.go | 11 +- x/gov/client/rest/rest.go | 27 +-- x/ibc/client/rest/transfer.go | 13 +- x/slashing/client/rest/tx.go | 11 +- x/stake/client/rest/tx.go | 33 ++-- x/stake/test_common.go | 2 +- 24 files changed, 461 insertions(+), 397 deletions(-) diff --git a/PENDING.md b/PENDING.md index a6e09a470d..80b2a473bd 100644 --- a/PENDING.md +++ b/PENDING.md @@ -3,11 +3,13 @@ BREAKING CHANGES * Gaia REST API (`gaiacli advanced rest-server`) + * [gaia-lite] [\#2182] Renamed and merged all redelegations endpoints into `/stake/redelegations` * Gaia CLI (`gaiacli`) * [\#810](https://github.com/cosmos/cosmos-sdk/issues/810) Don't fallback to any default values for chain ID. - - Users need to supply chain ID either via config file or the `--chain-id` flag. - - Change `chain_id` and `trust_node` in `gaiacli` configuration to `chain-id` and `trust-node` respectively. + * Users need to supply chain ID either via config file or the `--chain-id` flag. + * Change `chain_id` and `trust_node` in `gaiacli` configuration to `chain-id` and `trust-node` respectively. + * [\#3069](https://github.com/cosmos/cosmos-sdk/pull/3069) `--fee` flag renamed to `--fees` to support multiple coins * [\#3156](https://github.com/cosmos/cosmos-sdk/pull/3156) Remove unimplemented `gaiacli init` command * Gaia @@ -22,14 +24,13 @@ BREAKING CHANGES FEATURES * Gaia REST API (`gaiacli advanced rest-server`) - * [gaia-lite] [\#2182] Added LCD endpoint for querying redelegations - * [gov] [\#2479](https://github.com/cosmos/cosmos-sdk/issues/2479) Added governance parameter - query REST endpoints. + * [\#3067](https://github.com/cosmos/cosmos-sdk/issues/3067) Add support for fees on transactions + * [\#3069](https://github.com/cosmos/cosmos-sdk/pull/3069) Add a custom memo on transactions * Gaia CLI (`gaiacli`) + * \#2399 Implement `params` command to query slashing parameters. * Gaia - * [\#2182] [x/stake] Added querier for querying a single redelegation * SDK diff --git a/client/flags.go b/client/flags.go index 82e26ec852..7b37ec7154 100644 --- a/client/flags.go +++ b/client/flags.go @@ -1,6 +1,7 @@ package client import ( + "errors" "fmt" "strconv" @@ -29,7 +30,7 @@ const ( FlagAccountNumber = "account-number" FlagSequence = "sequence" FlagMemo = "memo" - FlagFee = "fee" + FlagFees = "fees" FlagAsync = "async" FlagJson = "json" FlagPrintResponse = "print-response" @@ -78,7 +79,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Uint64(FlagAccountNumber, 0, "AccountNumber number to sign the tx") c.Flags().Uint64(FlagSequence, 0, "Sequence number to sign the tx") c.Flags().String(FlagMemo, "", "Memo to send along with transaction") - c.Flags().String(FlagFee, "", "Fee to pay along with transaction") + c.Flags().String(FlagFees, "", "Fees to pay along with transaction; eg: 10stake,1atom") c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") c.Flags().String(FlagNode, "tcp://localhost:26657", ": to tendermint rpc interface for this chain") c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") @@ -135,7 +136,7 @@ func (v *GasSetting) Type() string { return "string" } // Set parses and sets the value of the --gas flag. func (v *GasSetting) Set(s string) (err error) { - v.Simulate, v.Gas, err = ReadGasFlag(s) + v.Simulate, v.Gas, err = ParseGas(s) return } @@ -146,17 +147,17 @@ func (v *GasSetting) String() string { return strconv.FormatUint(v.Gas, 10) } -// ParseGasFlag parses the value of the --gas flag. -func ReadGasFlag(s string) (simulate bool, gas uint64, err error) { - switch s { +// ParseGas parses the value of the gas option. +func ParseGas(gasStr string) (simulateAndExecute bool, gas uint64, err error) { + switch gasStr { case "": gas = DefaultGasLimit case GasFlagSimulate: - simulate = true + simulateAndExecute = true default: - gas, err = strconv.ParseUint(s, 10, 64) + gas, err = strconv.ParseUint(gasStr, 10, 64) if err != nil { - err = fmt.Errorf("gas must be either integer or %q", GasFlagSimulate) + err = errors.New("gas must be a positive integer") return } } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index a70ff643bb..b6b7a77175 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -35,10 +35,13 @@ const ( name1 = "test1" name2 = "test2" name3 = "test3" + memo = "LCD test tx" pw = app.DefaultKeyPass altPw = "12345678901" ) +var fees = sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 5)} + func init() { mintkey.BcryptSecurityParameter = 1 version.Version = os.Getenv("VERSION") @@ -160,7 +163,7 @@ func TestCoinSend(t *testing.T) { initialBalance := acc.GetCoins() // create TX - receiveAddr, resultTx := doTransfer(t, port, seed, name1, pw, addr) + receiveAddr, resultTx := doTransfer(t, port, seed, name1, memo, pw, addr, fees) tests.WaitForHeight(resultTx.Height+1, port) // check if tx was committed @@ -170,44 +173,52 @@ func TestCoinSend(t *testing.T) { // query sender acc = getAccount(t, port, addr) coins := acc.GetCoins() - mycoins := coins[0] + expectedBalance := initialBalance[0].Minus(fees[0]) - require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom) - require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount) + require.Equal(t, stakeTypes.DefaultBondDenom, coins[0].Denom) + require.Equal(t, expectedBalance.Amount.SubRaw(1), coins[0].Amount) + expectedBalance = coins[0] // query receiver - acc = getAccount(t, port, receiveAddr) - coins = acc.GetCoins() - mycoins = coins[0] - - require.Equal(t, stakeTypes.DefaultBondDenom, mycoins.Denom) - require.Equal(t, int64(1), mycoins.Amount.Int64()) + acc2 := getAccount(t, port, receiveAddr) + coins2 := acc2.GetCoins() + require.Equal(t, stakeTypes.DefaultBondDenom, coins2[0].Denom) + require.Equal(t, int64(1), coins2[0].Amount.Int64()) // test failure with too little gas - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, "100", 0, false, false) + res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, "100", 0, false, false, fees) require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) + require.Nil(t, err) - // test failure with negative gas - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, "-200", 0, false, false) + // test failure with negative adjustment + res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, "10000", -0.1, true, false, fees) require.Equal(t, http.StatusBadRequest, res.StatusCode, body) - // test failure with 0 gas - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, "0", 0, false, false) - require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) - - // test failure with wrong adjustment - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, "simulate", 0.1, false, false) - require.Equal(t, http.StatusInternalServerError, res.StatusCode, body) - // run simulation and test success with estimated gas - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, "", 0, true, false) + res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, "10000", 1.0, true, false, fees) require.Equal(t, http.StatusOK, res.StatusCode, body) var responseBody struct { GasEstimate int64 `json:"gas_estimate"` } require.Nil(t, json.Unmarshal([]byte(body), &responseBody)) - res, body, _ = doTransferWithGas(t, port, seed, name1, pw, addr, fmt.Sprintf("%v", responseBody.GasEstimate), 0, false, false) + + acc = getAccount(t, port, addr) + require.Equal(t, expectedBalance.Amount, acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)) + + res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, + fmt.Sprintf("%d", responseBody.GasEstimate), 1.0, false, false, fees) require.Equal(t, http.StatusOK, res.StatusCode, body) + + err = cdc.UnmarshalJSON([]byte(body), &resultTx) + require.Nil(t, err) + + tests.WaitForHeight(resultTx.Height+1, port) + require.Equal(t, uint32(0), resultTx.CheckTx.Code) + require.Equal(t, uint32(0), resultTx.DeliverTx.Code) + + acc = getAccount(t, port, addr) + expectedBalance = expectedBalance.Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(1), acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)) } func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { @@ -217,7 +228,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { acc := getAccount(t, port, addr) // generate TX - res, body, _ := doTransferWithGas(t, port, seed, name1, pw, addr, "simulate", 0, false, true) + res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, "200000", 1, false, true, fees) require.Equal(t, http.StatusOK, res.StatusCode, body) var msg auth.StdTx require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg)) @@ -225,7 +236,9 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { require.Equal(t, msg.Msgs[0].Route(), "bank") require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) require.Equal(t, 0, len(msg.Signatures)) - gasEstimate := msg.Fee.Gas + require.Equal(t, memo, msg.Memo) + + gasEstimate := int64(msg.Fee.Gas) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() @@ -265,8 +278,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { require.Nil(t, cdc.UnmarshalJSON([]byte(body), &resultTx)) require.Equal(t, uint32(0), resultTx.CheckTx.Code) require.Equal(t, uint32(0), resultTx.DeliverTx.Code) - require.Equal(t, gasEstimate, uint64(resultTx.DeliverTx.GasWanted)) - require.Equal(t, gasEstimate, uint64(resultTx.DeliverTx.GasUsed)) + require.Equal(t, gasEstimate, resultTx.DeliverTx.GasWanted) } func TestTxs(t *testing.T) { @@ -290,7 +302,7 @@ func TestTxs(t *testing.T) { require.Equal(t, emptyTxs, txs) // create tx - receiveAddr, resultTx := doTransfer(t, port, seed, name1, pw, addr) + receiveAddr, resultTx := doTransfer(t, port, seed, name1, memo, pw, addr, fees) tests.WaitForHeight(resultTx.Height+1, port) // check if tx is queryable @@ -301,6 +313,7 @@ func TestTxs(t *testing.T) { txs = getTransactions(t, port, fmt.Sprintf("sender=%s", addr.String())) require.Len(t, txs, 1) require.Equal(t, resultTx.Height, txs[0].Height) + fmt.Println(txs[0]) // query recipient txs = getTransactions(t, port, fmt.Sprintf("recipient=%s", receiveAddr.String())) @@ -371,8 +384,11 @@ func TestBonding(t *testing.T) { amt := sdk.NewDec(60) validator := getValidator(t, port, operAddrs[0]) + acc := getAccount(t, port, addr) + initialBalance := acc.GetCoins() + // create bond TX - resultTx := doDelegate(t, port, name1, pw, addr, operAddrs[0], 60) + resultTx := doDelegate(t, port, name1, pw, addr, operAddrs[0], 60, fees) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -386,10 +402,12 @@ func TestBonding(t *testing.T) { require.Len(t, txs, 1) require.Equal(t, resultTx.Height, txs[0].Height) - acc := getAccount(t, port, addr) + // verify balance + acc = getAccount(t, port, addr) coins := acc.GetCoins() - - require.Equal(t, int64(40), coins.AmountOf(stakeTypes.DefaultBondDenom).Int64()) + expectedBalance := initialBalance[0].Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(60), coins.AmountOf(stakeTypes.DefaultBondDenom)) + expectedBalance = coins[0] // query delegation bond := getDelegation(t, port, addr, operAddrs[0]) @@ -412,7 +430,7 @@ func TestBonding(t *testing.T) { require.Equal(t, operAddrs[0], bondedValidator.OperatorAddr) // testing unbonding - resultTx = doBeginUnbonding(t, port, name1, pw, addr, operAddrs[0], 30) + resultTx = doBeginUnbonding(t, port, name1, pw, addr, operAddrs[0], 30, fees) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) @@ -421,7 +439,13 @@ func TestBonding(t *testing.T) { // sender should have not received any coins as the unbonding has only just begun acc = getAccount(t, port, addr) coins = acc.GetCoins() - require.Equal(t, int64(40), coins.AmountOf(stakeTypes.DefaultBondDenom).Int64()) + expectedBalance = expectedBalance.Minus(fees[0]) + require.True(t, + expectedBalance.Amount.LT(coins.AmountOf(stakeTypes.DefaultBondDenom)) || + expectedBalance.Amount.Equal(coins.AmountOf(stakeTypes.DefaultBondDenom)), + "should get tokens back from automatic withdrawal after an unbonding delegation", + ) + expectedBalance = coins[0] // query tx txs = getTransactions(t, port, @@ -432,15 +456,24 @@ func TestBonding(t *testing.T) { require.Equal(t, resultTx.Height, txs[0].Height) unbonding := getUndelegation(t, port, addr, operAddrs[0]) - require.Equal(t, "30", unbonding.Balance.Amount.String()) + require.Equal(t, int64(30), unbonding.Balance.Amount.Int64()) // test redelegation - resultTx = doBeginRedelegation(t, port, name1, pw, addr, operAddrs[0], operAddrs[1], 30) + resultTx = doBeginRedelegation(t, port, name1, pw, addr, operAddrs[0], operAddrs[1], 30, fees) tests.WaitForHeight(resultTx.Height+1, port) require.Equal(t, uint32(0), resultTx.CheckTx.Code) require.Equal(t, uint32(0), resultTx.DeliverTx.Code) + // verify balance after paying fees + acc = getAccount(t, port, addr) + expectedBalance = expectedBalance.Minus(fees[0]) + require.True(t, + expectedBalance.Amount.LT(coins.AmountOf(stakeTypes.DefaultBondDenom)) || + expectedBalance.Amount.Equal(coins.AmountOf(stakeTypes.DefaultBondDenom)), + "should get tokens back from automatic withdrawal after an unbonding delegation", + ) + // query tx txs = getTransactions(t, port, fmt.Sprintf("action=begin_redelegate&delegator=%s", addr), @@ -497,8 +530,11 @@ func TestSubmitProposal(t *testing.T) { cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() + acc := getAccount(t, port, addr) + initialBalance := acc.GetCoins() + // create SubmitProposal TX - resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 5) + resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 5, fees) tests.WaitForHeight(resultTx.Height+1, port) // check if tx was committed @@ -508,6 +544,11 @@ func TestSubmitProposal(t *testing.T) { var proposalID uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID) + // verify balance + acc = getAccount(t, port, addr) + expectedBalance := initialBalance[0].Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(5), acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)) + // query proposal proposal := getProposal(t, port, proposalID) require.Equal(t, "Test", proposal.GetTitle()) @@ -523,8 +564,11 @@ func TestDeposit(t *testing.T) { cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() + acc := getAccount(t, port, addr) + initialBalance := acc.GetCoins() + // create SubmitProposal TX - resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 5) + resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 5, fees) tests.WaitForHeight(resultTx.Height+1, port) // check if tx was committed @@ -534,14 +578,26 @@ func TestDeposit(t *testing.T) { var proposalID uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID) + // verify balance + acc = getAccount(t, port, addr) + coins := acc.GetCoins() + expectedBalance := initialBalance[0].Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(5), coins.AmountOf(stakeTypes.DefaultBondDenom)) + expectedBalance = coins[0] + // query proposal proposal := getProposal(t, port, proposalID) require.Equal(t, "Test", proposal.GetTitle()) // create SubmitProposal TX - resultTx = doDeposit(t, port, seed, name1, pw, addr, proposalID, 5) + resultTx = doDeposit(t, port, seed, name1, pw, addr, proposalID, 5, fees) tests.WaitForHeight(resultTx.Height+1, port) + // verify balance after deposit and fee + acc = getAccount(t, port, addr) + expectedBalance = expectedBalance.Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(5), acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)) + // query tx txs := getTransactions(t, port, fmt.Sprintf("action=deposit&depositor=%s", addr)) require.Len(t, txs, 1) @@ -561,8 +617,11 @@ func TestVote(t *testing.T) { cleanup, _, operAddrs, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr}) defer cleanup() + acc := getAccount(t, port, addr) + initialBalance := acc.GetCoins() + // create SubmitProposal TX - resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 5) + resultTx := doSubmitProposal(t, port, seed, name1, pw, addr, 10, fees) tests.WaitForHeight(resultTx.Height+1, port) // check if tx was committed @@ -572,22 +631,29 @@ func TestVote(t *testing.T) { var proposalID uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID) + // verify balance + acc = getAccount(t, port, addr) + coins := acc.GetCoins() + expectedBalance := initialBalance[0].Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(10), coins.AmountOf(stakeTypes.DefaultBondDenom)) + expectedBalance = coins[0] + // query proposal proposal := getProposal(t, port, proposalID) require.Equal(t, "Test", proposal.GetTitle()) - - // deposit - resultTx = doDeposit(t, port, seed, name1, pw, addr, proposalID, 5) - tests.WaitForHeight(resultTx.Height+1, port) - - // query proposal - proposal = getProposal(t, port, proposalID) require.Equal(t, gov.StatusVotingPeriod, proposal.GetStatus()) // vote - resultTx = doVote(t, port, seed, name1, pw, addr, proposalID) + resultTx = doVote(t, port, seed, name1, pw, addr, proposalID, "Yes", fees) tests.WaitForHeight(resultTx.Height+1, port) + // verify balance after vote and fee + acc = getAccount(t, port, addr) + coins = acc.GetCoins() + expectedBalance = expectedBalance.Minus(fees[0]) + require.Equal(t, expectedBalance.Amount, coins.AmountOf(stakeTypes.DefaultBondDenom)) + expectedBalance = coins[0] + // query tx txs := getTransactions(t, port, fmt.Sprintf("action=vote&voter=%s", addr)) require.Len(t, txs, 1) @@ -601,15 +667,31 @@ func TestVote(t *testing.T) { require.Equal(t, sdk.ZeroDec(), tally.Yes, "tally should be 0 as the address is not bonded") // create bond TX - resultTx = doDelegate(t, port, name1, pw, addr, operAddrs[0], 60) + resultTx = doDelegate(t, port, name1, pw, addr, operAddrs[0], 60, fees) tests.WaitForHeight(resultTx.Height+1, port) - // vote - resultTx = doVote(t, port, seed, name1, pw, addr, proposalID) - tests.WaitForHeight(resultTx.Height+1, port) + // verify balance + acc = getAccount(t, port, addr) + coins = acc.GetCoins() + expectedBalance = expectedBalance.Minus(fees[0]) + require.Equal(t, expectedBalance.Amount.SubRaw(60), coins.AmountOf(stakeTypes.DefaultBondDenom)) + expectedBalance = coins[0] tally = getTally(t, port, proposalID) require.Equal(t, sdk.NewDec(60), tally.Yes, "tally should be equal to the amount delegated") + + // change vote option + resultTx = doVote(t, port, seed, name1, pw, addr, proposalID, "No", fees) + tests.WaitForHeight(resultTx.Height+1, port) + + // verify balance + acc = getAccount(t, port, addr) + expectedBalance = expectedBalance.Minus(fees[0]) + require.Equal(t, expectedBalance.Amount, acc.GetCoins().AmountOf(stakeTypes.DefaultBondDenom)) + + tally = getTally(t, port, proposalID) + require.Equal(t, sdk.ZeroDec(), tally.Yes, "tally should be 0 the user changed the option") + require.Equal(t, sdk.NewDec(60), tally.No, "tally should be equal to the amount delegated") } func TestUnjail(t *testing.T) { @@ -639,27 +721,27 @@ func TestProposalsQuery(t *testing.T) { getTallyingParam(t, port) // Addr1 proposes (and deposits) proposals #1 and #2 - resultTx := doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], halfMinDeposit) + resultTx := doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], halfMinDeposit, fees) var proposalID1 uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID1) tests.WaitForHeight(resultTx.Height+1, port) - resultTx = doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], halfMinDeposit) + resultTx = doSubmitProposal(t, port, seeds[0], names[0], passwords[0], addrs[0], halfMinDeposit, fees) var proposalID2 uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID2) tests.WaitForHeight(resultTx.Height+1, port) // Addr2 proposes (and deposits) proposals #3 - resultTx = doSubmitProposal(t, port, seeds[1], names[1], passwords[1], addrs[1], halfMinDeposit) + resultTx = doSubmitProposal(t, port, seeds[1], names[1], passwords[1], addrs[1], halfMinDeposit, fees) var proposalID3 uint64 cdc.MustUnmarshalBinaryLengthPrefixed(resultTx.DeliverTx.GetData(), &proposalID3) tests.WaitForHeight(resultTx.Height+1, port) // Addr2 deposits on proposals #2 & #3 - resultTx = doDeposit(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID2, halfMinDeposit) + resultTx = doDeposit(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID2, halfMinDeposit, fees) tests.WaitForHeight(resultTx.Height+1, port) - resultTx = doDeposit(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID3, halfMinDeposit) + resultTx = doDeposit(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID3, halfMinDeposit, fees) tests.WaitForHeight(resultTx.Height+1, port) // check deposits match proposal and individual deposits @@ -681,7 +763,7 @@ func TestProposalsQuery(t *testing.T) { require.Equal(t, deposit, deposits[0]) // increasing the amount of the deposit should update the existing one - resultTx = doDeposit(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID1, 1) + resultTx = doDeposit(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID1, 1, fees) tests.WaitForHeight(resultTx.Height+1, port) deposits = getDeposits(t, port, proposalID1) @@ -699,13 +781,13 @@ func TestProposalsQuery(t *testing.T) { require.Equal(t, proposalID3, proposals[1].GetProposalID()) // Addr1 votes on proposals #2 & #3 - resultTx = doVote(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID2) + resultTx = doVote(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID2, "Yes", fees) tests.WaitForHeight(resultTx.Height+1, port) - resultTx = doVote(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID3) + resultTx = doVote(t, port, seeds[0], names[0], passwords[0], addrs[0], proposalID3, "Yes", fees) tests.WaitForHeight(resultTx.Height+1, port) // Addr2 votes on proposal #3 - resultTx = doVote(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID3) + resultTx = doVote(t, port, seeds[1], names[1], passwords[1], addrs[1], proposalID3, "Yes", fees) tests.WaitForHeight(resultTx.Height+1, port) // Test query all proposals diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index 6d29d1d21a..27fdce75f8 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -834,7 +834,7 @@ paths: items: $ref: "#/definitions/Redelegation" 500: - description: Internal Server Error + description: Internal Server Error /stake/delegators/{delegatorAddr}/redelegations: parameters: - in: path @@ -2199,23 +2199,32 @@ definitions: properties: name: type: string + example: "my_name" password: type: string example: "12345678" + memo: + type: string + example: "Sent via Cosmos Voyager 🚀" chain_id: type: string + example: "Cosmos-Hub" account_number: type: string example: "0" sequence: type: string - example: "0" + example: "1" gas: type: string example: "200000" gas_adjustment: type: string example: "1.2" + fees: + type: array + items: + $ref: "#/definitions/Coin" generate_only: type: boolean example: false diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 1c7845c7f4..850b4b9570 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -678,8 +678,8 @@ type broadcastReq struct { // GET /bank/balances/{address} Get the account balances // POST /bank/accounts/{address}/transfers Send coins (build -> sign -> send) -func doTransfer(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { - res, body, receiveAddr := doTransferWithGas(t, port, seed, name, password, addr, "", 0, false, false) +func doTransfer(t *testing.T, port, seed, name, memo, password string, addr sdk.AccAddress, fees sdk.Coins) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) { + res, body, receiveAddr := doTransferWithGas(t, port, seed, name, memo, password, addr, "", 1.0, false, false, fees) require.Equal(t, http.StatusOK, res.StatusCode, body) err := cdc.UnmarshalJSON([]byte(body), &resultTx) @@ -688,8 +688,8 @@ func doTransfer(t *testing.T, port, seed, name, password string, addr sdk.AccAdd return receiveAddr, resultTx } -func doTransferWithGas(t *testing.T, port, seed, name, password string, addr sdk.AccAddress, gas string, - gasAdjustment float64, simulate, generateOnly bool) ( +func doTransferWithGas(t *testing.T, port, seed, name, memo, password string, addr sdk.AccAddress, gas string, + gasAdjustment float64, simulate, generateOnly bool, fees sdk.Coins) ( res *http.Response, body string, receiveAddr sdk.AccAddress) { // create receive address @@ -703,25 +703,14 @@ func doTransferWithGas(t *testing.T, port, seed, name, password string, addr sdk sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) + baseReq := utils.NewBaseReq(name, password, memo, chainID, gas, + fmt.Sprintf("%f", gasAdjustment), accnum, sequence, fees, + generateOnly, simulate, + ) + sr := sendReq{ - Amount: sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1)}, - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - Simulate: simulate, - GenerateOnly: generateOnly, - }, - } - - if len(gas) != 0 { - sr.BaseReq.Gas = gas - } - - if gasAdjustment > 0 { - sr.BaseReq.GasAdjustment = fmt.Sprintf("%f", gasAdjustment) + Amount: sdk.Coins{sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, 1)}, + BaseReq: baseReq, } req, err := cdc.MarshalJSON(sr) @@ -742,32 +731,28 @@ type sendReq struct { // POST /stake/delegators/{delegatorAddr}/delegations Submit delegation func doDelegate(t *testing.T, port, name, password string, - delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { - + delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) - ed := msgDelegationsInput{ - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + msg := msgDelegationsInput{ + BaseReq: baseReq, DelegatorAddr: delAddr, ValidatorAddr: valAddr, Delegation: sdk.NewInt64Coin(stakeTypes.DefaultBondDenom, amount), } - req, err := cdc.MarshalJSON(ed) + req, err := cdc.MarshalJSON(msg) require.NoError(t, err) res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delAddr.String()), req) require.Equal(t, http.StatusOK, res.StatusCode, body) - var results ctypes.ResultBroadcastTxCommit - err = cdc.UnmarshalJSON([]byte(body), &results) + + var result ctypes.ResultBroadcastTxCommit + err = cdc.UnmarshalJSON([]byte(body), &result) require.Nil(t, err) - return results + + return result } type msgDelegationsInput struct { @@ -779,35 +764,30 @@ type msgDelegationsInput struct { // POST /stake/delegators/{delegatorAddr}/delegations Submit delegation func doBeginUnbonding(t *testing.T, port, name, password string, - delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { + delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount int64, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) - ed := msgBeginUnbondingInput{ - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + msg := msgBeginUnbondingInput{ + BaseReq: baseReq, DelegatorAddr: delAddr, ValidatorAddr: valAddr, SharesAmount: sdk.NewDec(amount), } - req, err := cdc.MarshalJSON(ed) + req, err := cdc.MarshalJSON(msg) require.NoError(t, err) res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations", delAddr), req) require.Equal(t, http.StatusOK, res.StatusCode, body) - var results ctypes.ResultBroadcastTxCommit - err = cdc.UnmarshalJSON([]byte(body), &results) + var result ctypes.ResultBroadcastTxCommit + err = cdc.UnmarshalJSON([]byte(body), &result) require.Nil(t, err) - return results + return result } type msgBeginUnbondingInput struct { @@ -819,37 +799,33 @@ type msgBeginUnbondingInput struct { // POST /stake/delegators/{delegatorAddr}/delegations Submit delegation func doBeginRedelegation(t *testing.T, port, name, password string, - delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { + delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress, amount int64, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, delAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() chainID := viper.GetString(client.FlagChainID) - ed := msgBeginRedelegateInput{ - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + + msg := msgBeginRedelegateInput{ + BaseReq: baseReq, DelegatorAddr: delAddr, ValidatorSrcAddr: valSrcAddr, ValidatorDstAddr: valDstAddr, SharesAmount: sdk.NewDec(amount), } - req, err := cdc.MarshalJSON(ed) + req, err := cdc.MarshalJSON(msg) require.NoError(t, err) res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/redelegations", delAddr), req) require.Equal(t, http.StatusOK, res.StatusCode, body) - var results ctypes.ResultBroadcastTxCommit - err = cdc.UnmarshalJSON([]byte(body), &results) + var result ctypes.ResultBroadcastTxCommit + err = cdc.UnmarshalJSON([]byte(body), &result) require.Nil(t, err) - return results + return result } type msgBeginRedelegateInput struct { @@ -1051,26 +1027,20 @@ func getStakeParams(t *testing.T, port string) stake.Params { // ICS 22 - Gov // ---------------------------------------------------------------------- // POST /gov/proposals Submit a proposal -func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { - +func doSubmitProposal(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, amount int64, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, proposerAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() - chainID := viper.GetString(client.FlagChainID) + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + pr := postProposalReq{ Title: "Test", Description: "test", ProposalType: "Text", Proposer: proposerAddr, InitialDeposit: sdk.Coins{sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(amount))}, - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + BaseReq: baseReq, } req, err := cdc.MarshalJSON(pr) @@ -1152,23 +1122,18 @@ func getProposalsFilterStatus(t *testing.T, port string, status gov.ProposalStat } // POST /gov/proposals/{proposalId}/deposits Deposit tokens to a proposal -func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64, amount int64) (resultTx ctypes.ResultBroadcastTxCommit) { +func doDeposit(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64, amount int64, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { acc := getAccount(t, port, proposerAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() - chainID := viper.GetString(client.FlagChainID) + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + dr := depositReq{ Depositor: proposerAddr, Amount: sdk.Coins{sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(amount))}, - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + BaseReq: baseReq, } req, err := cdc.MarshalJSON(dr) @@ -1211,23 +1176,18 @@ func getTally(t *testing.T, port string, proposalID uint64) gov.TallyResult { } // POST /gov/proposals/{proposalId}/votes Vote a proposal -func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64) (resultTx ctypes.ResultBroadcastTxCommit) { +func doVote(t *testing.T, port, seed, name, password string, proposerAddr sdk.AccAddress, proposalID uint64, option string, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { // get the account to get the sequence acc := getAccount(t, port, proposerAddr) accnum := acc.GetAccountNumber() sequence := acc.GetSequence() - chainID := viper.GetString(client.FlagChainID) + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", accnum, sequence, fees, false, false) + vr := voteReq{ - Voter: proposerAddr, - Option: "Yes", - BaseReq: utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: accnum, - Sequence: sequence, - }, + Voter: proposerAddr, + Option: option, + BaseReq: baseReq, } req, err := cdc.MarshalJSON(vr) @@ -1340,16 +1300,13 @@ func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing. // TODO: Test this functionality, it is not currently in any of the tests // POST /slashing/validators/{validatorAddr}/unjail Unjail a jailed validator func doUnjail(t *testing.T, port, seed, name, password string, - valAddr sdk.ValAddress) (resultTx ctypes.ResultBroadcastTxCommit) { + valAddr sdk.ValAddress, fees sdk.Coins) (resultTx ctypes.ResultBroadcastTxCommit) { chainID := viper.GetString(client.FlagChainID) + baseReq := utils.NewBaseReq(name, password, "", chainID, "", "", 1, 1, fees, false, false) - ur := unjailReq{utils.BaseReq{ - Name: name, - Password: password, - ChainID: chainID, - AccountNumber: 1, - Sequence: 1, - }} + ur := unjailReq{ + BaseReq: baseReq, + } req, err := cdc.MarshalJSON(ur) require.NoError(t, err) res, body := Request(t, port, "POST", fmt.Sprintf("/slashing/validators/%s/unjail", valAddr.String()), req) diff --git a/client/utils/rest.go b/client/utils/rest.go index cd614cdbfa..e7e0f33714 100644 --- a/client/utils/rest.go +++ b/client/utils/rest.go @@ -101,30 +101,70 @@ func WriteGenerateStdTxResponse(w http.ResponseWriter, cdc *codec.Codec, txBldr // BaseReq defines a structure that can be embedded in other request structures // that all share common "base" fields. type BaseReq struct { - Name string `json:"name"` - Password string `json:"password"` - ChainID string `json:"chain_id"` - AccountNumber uint64 `json:"account_number"` - Sequence uint64 `json:"sequence"` - Gas string `json:"gas"` - GasAdjustment string `json:"gas_adjustment"` - GenerateOnly bool `json:"generate_only"` - Simulate bool `json:"simulate"` + Name string `json:"name"` + Password string `json:"password"` + Memo string `json:"memo"` + ChainID string `json:"chain_id"` + AccountNumber uint64 `json:"account_number"` + Sequence uint64 `json:"sequence"` + Fees sdk.Coins `json:"fees"` + Gas string `json:"gas"` + GasAdjustment string `json:"gas_adjustment"` + GenerateOnly bool `json:"generate_only"` + Simulate bool `json:"simulate"` +} + +// NewBaseReq creates a new basic request instance and sanitizes its values +func NewBaseReq( + name, password, memo, chainID string, gas, gasAdjustment string, + accNumber, seq uint64, fees sdk.Coins, genOnly, simulate bool) BaseReq { + + return BaseReq{ + Name: strings.TrimSpace(name), + Password: password, + Memo: strings.TrimSpace(memo), + ChainID: strings.TrimSpace(chainID), + Fees: fees, + Gas: strings.TrimSpace(gas), + GasAdjustment: strings.TrimSpace(gasAdjustment), + AccountNumber: accNumber, + Sequence: seq, + GenerateOnly: genOnly, + Simulate: simulate, + } } // Sanitize performs basic sanitization on a BaseReq object. func (br BaseReq) Sanitize() BaseReq { - return BaseReq{ - Name: strings.TrimSpace(br.Name), - Password: strings.TrimSpace(br.Password), - ChainID: strings.TrimSpace(br.ChainID), - Gas: strings.TrimSpace(br.Gas), - GasAdjustment: strings.TrimSpace(br.GasAdjustment), - AccountNumber: br.AccountNumber, - Sequence: br.Sequence, - GenerateOnly: br.GenerateOnly, - Simulate: br.Simulate, + newBr := NewBaseReq( + br.Name, br.Password, br.Memo, br.ChainID, br.Gas, br.GasAdjustment, + br.AccountNumber, br.Sequence, br.Fees, br.GenerateOnly, br.Simulate, + ) + return newBr +} + +// ValidateBasic performs basic validation of a BaseReq. If custom validation +// logic is needed, the implementing request handler should perform those +// checks manually. +func (br BaseReq) ValidateBasic(w http.ResponseWriter) bool { + if !br.GenerateOnly && !br.Simulate { + switch { + case len(br.Password) == 0: + WriteErrorResponse(w, http.StatusUnauthorized, "password required but not specified") + return false + case len(br.ChainID) == 0: + WriteErrorResponse(w, http.StatusUnauthorized, "chain-id required but not specified") + return false + case !br.Fees.IsValid(): + WriteErrorResponse(w, http.StatusPaymentRequired, "invalid or insufficient fees") + return false + } } + if len(br.Name) == 0 { + WriteErrorResponse(w, http.StatusUnauthorized, "name required but not specified") + return false + } + return true } /* @@ -156,27 +196,6 @@ func ReadRESTReq(w http.ResponseWriter, r *http.Request, cdc *codec.Codec, req i return nil } -// ValidateBasic performs basic validation of a BaseReq. If custom validation -// logic is needed, the implementing request handler should perform those -// checks manually. -func (br BaseReq) ValidateBasic(w http.ResponseWriter, cliCtx context.CLIContext) bool { - if !cliCtx.GenerateOnly && !cliCtx.Simulate { - switch { - case len(br.Password) == 0: - WriteErrorResponse(w, http.StatusUnauthorized, "password required but not specified") - return false - case len(br.ChainID) == 0: - WriteErrorResponse(w, http.StatusUnauthorized, "chain-id required but not specified") - return false - } - } - if len(br.Name) == 0 { - WriteErrorResponse(w, http.StatusUnauthorized, "name required but not specified") - return false - } - return true -} - // CompleteAndBroadcastTxREST implements a utility function that facilitates // sending a series of messages in a signed transaction given a TxBuilder and a // QueryContext. It ensures that the account exists, has a proper number and @@ -186,40 +205,37 @@ func (br BaseReq) ValidateBasic(w http.ResponseWriter, cliCtx context.CLIContext // NOTE: Also see CompleteAndBroadcastTxCli. // NOTE: Also see x/stake/client/rest/tx.go delegationsRequestHandlerFn. func CompleteAndBroadcastTxREST(w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext, baseReq BaseReq, msgs []sdk.Msg, cdc *codec.Codec) { - simulateGas, gas, err := client.ReadGasFlag(baseReq.Gas) + gasAdjustment, ok := ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment) + if !ok { + return + } + + simulateAndExecute, gas, err := client.ParseGas(baseReq.Gas) if err != nil { WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - adjustment, ok := ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment) - if !ok { - return - } + txBldr := authtxb.NewTxBuilder(GetTxEncoder(cdc), baseReq.AccountNumber, + baseReq.Sequence, gas, gasAdjustment, baseReq.Simulate, + baseReq.ChainID, baseReq.Memo, baseReq.Fees) - txBldr := authtxb.TxBuilder{ - TxEncoder: GetTxEncoder(cdc), - Gas: gas, - GasAdjustment: adjustment, - SimulateGas: simulateGas, - ChainID: baseReq.ChainID, - AccountNumber: baseReq.AccountNumber, - Sequence: baseReq.Sequence, - } + if baseReq.Simulate || simulateAndExecute { + if gasAdjustment < 0 { + WriteErrorResponse(w, http.StatusBadRequest, "gas adjustment must be a positive float") + return + } - if baseReq.Simulate || txBldr.SimulateGas { - newBldr, err := EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, msgs) + txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, msgs) if err != nil { WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } if baseReq.Simulate { - WriteSimulationResponse(w, newBldr.Gas) + WriteSimulationResponse(w, txBldr.GetGas()) return } - - txBldr = newBldr } if baseReq.GenerateOnly { diff --git a/client/utils/utils.go b/client/utils/utils.go index 2d928ddcc9..ad3f6a00d9 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -3,10 +3,11 @@ package utils import ( "bytes" "fmt" - "github.com/cosmos/cosmos-sdk/codec" "io" "os" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/libs/common" @@ -35,12 +36,12 @@ func CompleteAndBroadcastTxCli(txBldr authtxb.TxBuilder, cliCtx context.CLIConte return err } - if txBldr.SimulateGas || cliCtx.Simulate { + if txBldr.GetSimulateAndExecute() || cliCtx.Simulate { txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, name, msgs) if err != nil { return err } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.GetGas()) } if cliCtx.Simulate { return nil @@ -131,7 +132,7 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, "The generated transaction's intended signer does not match the given signer: %q", name) } - if !offline && txBldr.AccountNumber == 0 { + if !offline && txBldr.GetAccountNumber() == 0 { accNum, err := cliCtx.GetAccountNumber(addr) if err != nil { return signedStdTx, err @@ -139,7 +140,7 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, txBldr = txBldr.WithAccountNumber(accNum) } - if !offline && txBldr.Sequence == 0 { + if !offline && txBldr.GetSequence() == 0 { accSeq, err := cliCtx.GetAccountSequence(addr) if err != nil { return signedStdTx, err @@ -172,7 +173,7 @@ func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name stri if err != nil { return } - estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, txBldr.GasAdjustment) + estimated, adjusted, err = CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, txBldr.GetGasAdjustment()) return } @@ -200,7 +201,7 @@ func prepareTxBuilder(txBldr authtxb.TxBuilder, cliCtx context.CLIContext) (auth // TODO: (ref #1903) Allow for user supplied account number without // automatically doing a manual lookup. - if txBldr.AccountNumber == 0 { + if txBldr.GetAccountNumber() == 0 { accNum, err := cliCtx.GetAccountNumber(from) if err != nil { return txBldr, err @@ -210,7 +211,7 @@ func prepareTxBuilder(txBldr authtxb.TxBuilder, cliCtx context.CLIContext) (auth // TODO: (ref #1903) Allow for user supplied account sequence without // automatically doing a manual lookup. - if txBldr.Sequence == 0 { + if txBldr.GetSequence() == 0 { accSeq, err := cliCtx.GetAccountSequence(from) if err != nil { return txBldr, err @@ -231,7 +232,7 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg } func buildUnsignedStdTxOffline(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) { - if txBldr.SimulateGas { + if txBldr.GetSimulateAndExecute() { var name string name, err = cliCtx.GetFromName() if err != nil { @@ -242,7 +243,7 @@ func buildUnsignedStdTxOffline(txBldr authtxb.TxBuilder, cliCtx context.CLIConte if err != nil { return } - fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.Gas) + fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.GetGas()) } stdSignMsg, err := txBldr.Build(msgs) if err != nil { diff --git a/client/utils/utils_test.go b/client/utils/utils_test.go index bdd57ded0d..cd754d9c1d 100644 --- a/client/utils/utils_test.go +++ b/client/utils/utils_test.go @@ -3,11 +3,12 @@ package utils import ( "encoding/json" "errors" + "testing" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" - "testing" "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/libs/common" diff --git a/cmd/gaia/app/benchmarks/txsize_test.go b/cmd/gaia/app/benchmarks/txsize_test.go index d9862f22c9..2726dcd1bb 100644 --- a/cmd/gaia/app/benchmarks/txsize_test.go +++ b/cmd/gaia/app/benchmarks/txsize_test.go @@ -22,12 +22,12 @@ func ExampleTxSendSize() { addr1 := sdk.AccAddress(priv1.PubKey().Address()) priv2 := secp256k1.GenPrivKeySecp256k1([]byte{1}) addr2 := sdk.AccAddress(priv2.PubKey().Address()) - coins := []sdk.Coin{sdk.NewCoin("denom", sdk.NewInt(10))} + coins := sdk.Coins{sdk.NewCoin("denom", sdk.NewInt(10))} msg1 := bank.MsgSend{ Inputs: []bank.Input{bank.NewInput(addr1, coins)}, Outputs: []bank.Output{bank.NewOutput(addr2, coins)}, } - fee := auth.NewStdFee(gas, coins...) + fee := auth.NewStdFee(gas, coins) signBytes := auth.StdSignBytes("example-chain-ID", 1, 1, fee, []sdk.Msg{msg1}, "") sig, _ := priv1.Sign(signBytes) diff --git a/cmd/gaia/cli_test/cli_test.go b/cmd/gaia/cli_test/cli_test.go index 8c125ea6bf..ba92f838d8 100644 --- a/cmd/gaia/cli_test/cli_test.go +++ b/cmd/gaia/cli_test/cli_test.go @@ -78,7 +78,7 @@ func TestGaiaCLIFeesDeduction(t *testing.T) { // test simulation success := executeWrite(t, fmt.Sprintf( - "gaiacli tx send %v --amount=1000footoken --to=%s --from=foo --fee=1footoken --dry-run", flags, barAddr), app.DefaultKeyPass) + "gaiacli tx send %v --amount=1000footoken --to=%s --from=foo --fees=1footoken --dry-run", flags, barAddr), app.DefaultKeyPass) require.True(t, success) tests.WaitForNextNBlocksTM(1, port) // ensure state didn't change @@ -87,7 +87,7 @@ func TestGaiaCLIFeesDeduction(t *testing.T) { // insufficient funds (coins + fees) success = executeWrite(t, fmt.Sprintf( - "gaiacli tx send %v --amount=1000footoken --to=%s --from=foo --fee=1footoken", flags, barAddr), app.DefaultKeyPass) + "gaiacli tx send %v --amount=1000footoken --to=%s --from=foo --fees=1footoken", flags, barAddr), app.DefaultKeyPass) require.False(t, success) tests.WaitForNextNBlocksTM(1, port) // ensure state didn't change @@ -96,7 +96,7 @@ func TestGaiaCLIFeesDeduction(t *testing.T) { // test success (transfer = coins + fees) success = executeWrite(t, fmt.Sprintf( - "gaiacli tx send %v --fee=300footoken --amount=500footoken --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) + "gaiacli tx send %v --fees=300footoken --amount=500footoken --to=%s --from=foo", flags, barAddr), app.DefaultKeyPass) require.True(t, success) cleanupDirs(gaiadHome, gaiacliHome) } diff --git a/x/auth/ante.go b/x/auth/ante.go index 54ce8edc46..aafbd540ee 100644 --- a/x/auth/ante.go +++ b/x/auth/ante.go @@ -270,7 +270,7 @@ func EnsureSufficientMempoolFees(ctx sdk.Context, stdTx StdTx) sdk.Result { // - Make the gasPrice not a constant, and account for tx size. // - Make Gas an unsigned integer and use tx basic validation if stdTx.Fee.Gas <= 0 { - return sdk.ErrInternal(fmt.Sprintf("invalid gas supplied: %d", stdTx.Fee.Gas)).Result() + return sdk.ErrInternal(fmt.Sprintf("gas supplied must be a positive integer: %d", stdTx.Fee.Gas)).Result() } requiredFees := adjustFeesByGas(ctx.MinimumFees(), stdTx.Fee.Gas) diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index ba18ecf90d..902ee4c983 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -23,7 +23,7 @@ func newTestMsg(addrs ...sdk.AccAddress) *sdk.TestMsg { func newStdFee() StdFee { return NewStdFee(50000, - sdk.NewInt64Coin("atom", 150), + sdk.Coins{sdk.NewInt64Coin("atom", 150)}, ) } @@ -429,24 +429,24 @@ func TestAnteHandlerMemoGas(t *testing.T) { var tx sdk.Tx msg := newTestMsg(addr1) privs, accnums, seqs := []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0} - fee := NewStdFee(0, sdk.NewInt64Coin("atom", 0)) + fee := NewStdFee(0, sdk.Coins{sdk.NewInt64Coin("atom", 0)}) // tx does not have enough gas tx = newTestTx(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee) checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) // tx with memo doesn't have enough gas - fee = NewStdFee(801, sdk.NewInt64Coin("atom", 0)) + fee = NewStdFee(801, sdk.Coins{sdk.NewInt64Coin("atom", 0)}) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, "abcininasidniandsinasindiansdiansdinaisndiasndiadninsd") checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeOutOfGas) // memo too large - fee = NewStdFee(9000, sdk.NewInt64Coin("atom", 0)) + fee = NewStdFee(9000, sdk.Coins{sdk.NewInt64Coin("atom", 0)}) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, strings.Repeat("01234567890", 500)) checkInvalidTx(t, anteHandler, ctx, tx, false, sdk.CodeMemoTooLarge) // tx with memo has enough gas - fee = NewStdFee(9000, sdk.NewInt64Coin("atom", 0)) + fee = NewStdFee(9000, sdk.Coins{sdk.NewInt64Coin("atom", 0)}) tx = newTestTxWithMemo(ctx, []sdk.Msg{msg}, privs, accnums, seqs, fee, strings.Repeat("0123456789", 10)) checkValidTx(t, anteHandler, ctx, tx, false) } diff --git a/x/auth/client/cli/sign.go b/x/auth/client/cli/sign.go index 842299df87..94c2aa9325 100644 --- a/x/auth/client/cli/sign.go +++ b/x/auth/client/cli/sign.go @@ -75,7 +75,7 @@ func makeSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error txBldr := authtxb.NewTxBuilderFromCLI() if viper.GetBool(flagValidateSigs) { - if !printAndValidateSigs(cliCtx, txBldr.ChainID, stdTx, offline) { + if !printAndValidateSigs(cliCtx, txBldr.GetChainID(), stdTx, offline) { return fmt.Errorf("signatures validation failed") } diff --git a/x/auth/client/rest/sign.go b/x/auth/client/rest/sign.go index 0307db6c1a..41e95e322f 100644 --- a/x/auth/client/rest/sign.go +++ b/x/auth/client/rest/sign.go @@ -41,11 +41,8 @@ func SignTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha return } - txBldr := authtxb.TxBuilder{ - ChainID: m.ChainID, - AccountNumber: m.AccountNumber, - Sequence: m.Sequence, - } + txBldr := authtxb.NewTxBuilder(utils.GetTxEncoder(cdc), m.AccountNumber, + m.Sequence, m.Tx.Fee.Gas, 1.0, false, m.ChainID, m.Tx.GetMemo(), m.Tx.Fee.Amount) signedTx, err := txBldr.SignStdTx(m.LocalAccountName, m.Password, m.Tx, m.AppendSig) if keyerror.IsErrKeyNotFound(err) { diff --git a/x/auth/client/txbuilder/txbuilder.go b/x/auth/client/txbuilder/txbuilder.go index 207195c015..c94d0a1b1c 100644 --- a/x/auth/client/txbuilder/txbuilder.go +++ b/x/auth/client/txbuilder/txbuilder.go @@ -1,6 +1,8 @@ package context import ( + "strings" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/keys" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,102 +14,136 @@ import ( // TxBuilder implements a transaction context created in SDK modules. type TxBuilder struct { - TxEncoder sdk.TxEncoder - AccountNumber uint64 - Sequence uint64 - Gas uint64 - GasAdjustment float64 - SimulateGas bool - ChainID string - Memo string - Fee string + txEncoder sdk.TxEncoder + accountNumber uint64 + sequence uint64 + gas uint64 + gasAdjustment float64 + simulateAndExecute bool + chainID string + memo string + fees sdk.Coins +} + +// NewTxBuilder returns a new initialized TxBuilder +func NewTxBuilder(txEncoder sdk.TxEncoder, accNumber, seq, gas uint64, gasAdj float64, simulateAndExecute bool, chainID, memo string, fees sdk.Coins) TxBuilder { + return TxBuilder{ + txEncoder: txEncoder, + accountNumber: accNumber, + sequence: seq, + gas: gas, + gasAdjustment: gasAdj, + simulateAndExecute: simulateAndExecute, + chainID: chainID, + memo: memo, + fees: fees, + } } // NewTxBuilderFromCLI returns a new initialized TxBuilder with parameters from // the command line using Viper. func NewTxBuilderFromCLI() TxBuilder { - // if chain ID is not specified manually, read default chain ID - chainID := viper.GetString(client.FlagChainID) - - return TxBuilder{ - ChainID: chainID, - AccountNumber: uint64(viper.GetInt64(client.FlagAccountNumber)), - Gas: client.GasFlagVar.Gas, - GasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), - Sequence: uint64(viper.GetInt64(client.FlagSequence)), - SimulateGas: client.GasFlagVar.Simulate, - Fee: viper.GetString(client.FlagFee), - Memo: viper.GetString(client.FlagMemo), + txbldr := TxBuilder{ + accountNumber: uint64(viper.GetInt64(client.FlagAccountNumber)), + sequence: uint64(viper.GetInt64(client.FlagSequence)), + gas: client.GasFlagVar.Gas, + gasAdjustment: viper.GetFloat64(client.FlagGasAdjustment), + simulateAndExecute: client.GasFlagVar.Simulate, + chainID: viper.GetString(client.FlagChainID), + memo: viper.GetString(client.FlagMemo), } + return txbldr.WithFees(viper.GetString(client.FlagFees)) } -// WithCodec returns a copy of the context with an updated codec. +// GetTxEncoder returns the transaction encoder +func (bldr TxBuilder) GetTxEncoder() sdk.TxEncoder { return bldr.txEncoder } + +// GetAccountNumber returns the account number +func (bldr TxBuilder) GetAccountNumber() uint64 { return bldr.accountNumber } + +// GetSequence returns the transaction sequence +func (bldr TxBuilder) GetSequence() uint64 { return bldr.sequence } + +// GetGas returns the gas for the transaction +func (bldr TxBuilder) GetGas() uint64 { return bldr.gas } + +// GetGasAdjustment returns the gas adjustment +func (bldr TxBuilder) GetGasAdjustment() float64 { return bldr.gasAdjustment } + +// GetSimulateAndExecute returns the option to simulate and then execute the transaction +// using the gas from the simulation results +func (bldr TxBuilder) GetSimulateAndExecute() bool { return bldr.simulateAndExecute } + +// GetChainID returns the chain id +func (bldr TxBuilder) GetChainID() string { return bldr.chainID } + +// GetMemo returns the memo message +func (bldr TxBuilder) GetMemo() string { return bldr.memo } + +// GetFees returns the fees for the transaction +func (bldr TxBuilder) GetFees() sdk.Coins { return bldr.fees } + +// WithTxEncoder returns a copy of the context with an updated codec. func (bldr TxBuilder) WithTxEncoder(txEncoder sdk.TxEncoder) TxBuilder { - bldr.TxEncoder = txEncoder + bldr.txEncoder = txEncoder return bldr } // WithChainID returns a copy of the context with an updated chainID. func (bldr TxBuilder) WithChainID(chainID string) TxBuilder { - bldr.ChainID = chainID + bldr.chainID = chainID return bldr } // WithGas returns a copy of the context with an updated gas. func (bldr TxBuilder) WithGas(gas uint64) TxBuilder { - bldr.Gas = gas + bldr.gas = gas return bldr } -// WithFee returns a copy of the context with an updated fee. -func (bldr TxBuilder) WithFee(fee string) TxBuilder { - bldr.Fee = fee +// WithFees returns a copy of the context with an updated fee. +func (bldr TxBuilder) WithFees(fees string) TxBuilder { + parsedFees, err := sdk.ParseCoins(fees) + if err != nil { + panic(err) + } + bldr.fees = parsedFees return bldr } // WithSequence returns a copy of the context with an updated sequence number. func (bldr TxBuilder) WithSequence(sequence uint64) TxBuilder { - bldr.Sequence = sequence + bldr.sequence = sequence return bldr } // WithMemo returns a copy of the context with an updated memo. func (bldr TxBuilder) WithMemo(memo string) TxBuilder { - bldr.Memo = memo + bldr.memo = strings.TrimSpace(memo) return bldr } // WithAccountNumber returns a copy of the context with an account number. func (bldr TxBuilder) WithAccountNumber(accnum uint64) TxBuilder { - bldr.AccountNumber = accnum + bldr.accountNumber = accnum return bldr } // Build builds a single message to be signed from a TxBuilder given a set of // messages. It returns an error if a fee is supplied but cannot be parsed. func (bldr TxBuilder) Build(msgs []sdk.Msg) (StdSignMsg, error) { - chainID := bldr.ChainID + chainID := bldr.chainID if chainID == "" { return StdSignMsg{}, errors.Errorf("chain ID required but not specified") } - fee := sdk.Coin{} - if bldr.Fee != "" { - parsedFee, err := sdk.ParseCoin(bldr.Fee) - if err != nil { - return StdSignMsg{}, err - } - - fee = parsedFee - } - return StdSignMsg{ - ChainID: bldr.ChainID, - AccountNumber: bldr.AccountNumber, - Sequence: bldr.Sequence, - Memo: bldr.Memo, + ChainID: bldr.chainID, + AccountNumber: bldr.accountNumber, + Sequence: bldr.sequence, + Memo: bldr.memo, Msgs: msgs, - Fee: auth.NewStdFee(bldr.Gas, fee), + Fee: auth.NewStdFee(bldr.gas, bldr.fees), }, nil } @@ -119,7 +155,7 @@ func (bldr TxBuilder) Sign(name, passphrase string, msg StdSignMsg) ([]byte, err return nil, err } - return bldr.TxEncoder(auth.NewStdTx(msg.Msgs, msg.Fee, []auth.StdSignature{sig}, msg.Memo)) + return bldr.txEncoder(auth.NewStdTx(msg.Msgs, msg.Fee, []auth.StdSignature{sig}, msg.Memo)) } // BuildAndSign builds a single message to be signed, and signs a transaction @@ -158,16 +194,16 @@ func (bldr TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, erro PubKey: info.GetPubKey(), }} - return bldr.TxEncoder(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) + return bldr.txEncoder(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo)) } // SignStdTx appends a signature to a StdTx and returns a copy of a it. If append // is false, it replaces the signatures already attached with the new signature. func (bldr TxBuilder) SignStdTx(name, passphrase string, stdTx auth.StdTx, appendSig bool) (signedStdTx auth.StdTx, err error) { stdSignature, err := MakeSignature(name, passphrase, StdSignMsg{ - ChainID: bldr.ChainID, - AccountNumber: bldr.AccountNumber, - Sequence: bldr.Sequence, + ChainID: bldr.chainID, + AccountNumber: bldr.accountNumber, + Sequence: bldr.sequence, Fee: stdTx.Fee, Msgs: stdTx.GetMsgs(), Memo: stdTx.GetMemo(), diff --git a/x/auth/client/txbuilder/txbuilder_test.go b/x/auth/client/txbuilder/txbuilder_test.go index 1861c3e2af..f33c96be18 100644 --- a/x/auth/client/txbuilder/txbuilder_test.go +++ b/x/auth/client/txbuilder/txbuilder_test.go @@ -29,7 +29,7 @@ func TestTxBuilderBuild(t *testing.T) { SimulateGas bool ChainID string Memo string - Fee string + Fees sdk.Coins } defaultMsg := []sdk.Msg{sdk.NewTestMsg(addr)} tests := []struct { @@ -47,33 +47,23 @@ func TestTxBuilderBuild(t *testing.T) { GasAdjustment: 1.1, SimulateGas: false, ChainID: "test-chain", - Memo: "hello", - Fee: "1" + stakeTypes.DefaultBondDenom, + Memo: "hello from Voyager !", + Fees: sdk.Coins{sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(1))}, }, defaultMsg, StdSignMsg{ ChainID: "test-chain", AccountNumber: 1, Sequence: 1, - Memo: "hello", + Memo: "hello from Voyager !", Msgs: defaultMsg, - Fee: auth.NewStdFee(100, sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(1))), + Fee: auth.NewStdFee(100, sdk.Coins{sdk.NewCoin(stakeTypes.DefaultBondDenom, sdk.NewInt(1))}), }, false, }, } for i, tc := range tests { - bldr := TxBuilder{ - TxEncoder: tc.fields.TxEncoder, - AccountNumber: tc.fields.AccountNumber, - Sequence: tc.fields.Sequence, - Gas: tc.fields.Gas, - GasAdjustment: tc.fields.GasAdjustment, - SimulateGas: tc.fields.SimulateGas, - ChainID: tc.fields.ChainID, - Memo: tc.fields.Memo, - Fee: tc.fields.Fee, - } + bldr := NewTxBuilder(tc.fields.TxEncoder, tc.fields.AccountNumber, tc.fields.Sequence, tc.fields.Gas, tc.fields.GasAdjustment, tc.fields.SimulateGas, tc.fields.ChainID, tc.fields.Memo, tc.fields.Fees) got, err := bldr.Build(tc.msgs) require.Equal(t, tc.wantErr, (err != nil), "TxBuilder.Build() error = %v, wantErr %v, tc %d", err, tc.wantErr, i) if !reflect.DeepEqual(got, tc.want) { diff --git a/x/auth/stdtx.go b/x/auth/stdtx.go index 79abfce0a0..5b9561cf37 100644 --- a/x/auth/stdtx.go +++ b/x/auth/stdtx.go @@ -133,7 +133,7 @@ type StdFee struct { Gas uint64 `json:"gas"` } -func NewStdFee(gas uint64, amount ...sdk.Coin) StdFee { +func NewStdFee(gas uint64, amount sdk.Coins) StdFee { return StdFee{ Amount: amount, Gas: gas, diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 42796d6435..36e084b73a 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -43,7 +43,7 @@ var ( coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} halfCoins = sdk.Coins{sdk.NewInt64Coin("foocoin", 5)} manyCoins = sdk.Coins{sdk.NewInt64Coin("foocoin", 1), sdk.NewInt64Coin("barcoin", 1)} - freeFee = auth.NewStdFee(100000, sdk.Coins{sdk.NewInt64Coin("foocoin", 0)}...) + freeFee = auth.NewStdFee(100000, sdk.Coins{sdk.NewInt64Coin("foocoin", 0)}) sendMsg1 = MsgSend{ Inputs: []Input{NewInput(addr1, coins)}, diff --git a/x/bank/client/rest/sendtx.go b/x/bank/client/rest/sendtx.go index 27cbc043c7..d73d7e61e3 100644 --- a/x/bank/client/rest/sendtx.go +++ b/x/bank/client/rest/sendtx.go @@ -49,21 +49,18 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } msg := client.CreateMsg(sdk.AccAddress(info.GetPubKey().Address()), to, req.Amount) - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index 2cbc2b3374..39f01932fe 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -78,11 +78,8 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } @@ -100,7 +97,7 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } @@ -126,11 +123,8 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } @@ -142,7 +136,7 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } @@ -168,11 +162,8 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } @@ -190,7 +181,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } diff --git a/x/ibc/client/rest/transfer.go b/x/ibc/client/rest/transfer.go index 704b663e62..ab26b6e420 100644 --- a/x/ibc/client/rest/transfer.go +++ b/x/ibc/client/rest/transfer.go @@ -43,15 +43,12 @@ func TransferRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context. return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -59,10 +56,10 @@ func TransferRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context. packet := ibc.NewIBCPacket( sdk.AccAddress(info.GetPubKey().Address()), to, - req.Amount, baseReq.ChainID, destChainID, + req.Amount, req.BaseReq.ChainID, destChainID, ) msg := ibc.IBCTransferMsg{IBCPacket: packet} - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } diff --git a/x/slashing/client/rest/tx.go b/x/slashing/client/rest/tx.go index ec28f48ed6..add8c6665b 100644 --- a/x/slashing/client/rest/tx.go +++ b/x/slashing/client/rest/tx.go @@ -38,15 +38,12 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -64,6 +61,6 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL } msg := slashing.NewMsgUnjail(valAddr) - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } diff --git a/x/stake/client/rest/tx.go b/x/stake/client/rest/tx.go index bb2bc0e7fa..7fde46acbd 100644 --- a/x/stake/client/rest/tx.go +++ b/x/stake/client/rest/tx.go @@ -63,15 +63,12 @@ func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context. return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -89,7 +86,7 @@ func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context. return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } @@ -103,15 +100,12 @@ func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx contex return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -129,7 +123,7 @@ func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx contex return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } @@ -143,15 +137,12 @@ func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx return } - cliCtx = cliCtx.WithGenerateOnly(req.BaseReq.GenerateOnly) - cliCtx = cliCtx.WithSimulation(req.BaseReq.Simulate) - - baseReq := req.BaseReq.Sanitize() - if !baseReq.ValidateBasic(w, cliCtx) { + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { return } - info, err := kb.Get(baseReq.Name) + info, err := kb.Get(req.BaseReq.Name) if err != nil { utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error()) return @@ -169,6 +160,6 @@ func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx return } - utils.CompleteAndBroadcastTxREST(w, r, cliCtx, baseReq, []sdk.Msg{msg}, cdc) + utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc) } } diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 88077d18bc..c9389d6eb9 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -20,7 +20,7 @@ var ( coins = sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(10))} fee = auth.NewStdFee( 100000, - sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))}..., + sdk.Coins{sdk.NewCoin("foocoin", sdk.NewInt(0))}, ) commissionMsg = NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())