Skip to content

Commit e79fa63

Browse files
fix: x/gov deposits querier (Initial Deposit) (backport #9288) (#9453)
* fix: x/gov deposits querier (Initial Deposit) (#9288) * copied from old PR * fix errors * add test * Update x/gov/client/utils/query.go Co-authored-by: Robert Zaremba <[email protected]> * fix tests * fix failing test * add test * update test * fix tests * fix deposit query * fix test * update tests * add more tests * address lint error * address lint error * review changes Co-authored-by: Robert Zaremba <[email protected]> (cherry picked from commit 66ee994) # Conflicts: # CHANGELOG.md # x/gov/client/cli/query.go # x/gov/client/testutil/cli_test.go # x/gov/client/utils/query.go * resolve conflicts Co-authored-by: MD Aleem <[email protected]> Co-authored-by: aleem1314 <[email protected]>
1 parent 850da8a commit e79fa63

File tree

6 files changed

+310
-16
lines changed

6 files changed

+310
-16
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,13 @@ Ref: https://keepachangelog.com/en/1.0.0/
4444

4545
### Features
4646

47-
4847
* [\#9383](https://github.com/cosmos/cosmos-sdk/pull/9383) New CLI command `query ibc-transfer escrow-address <port> <channel id>` to get the escrow address for a channel; can be used to then query balance of escrowed tokens
4948
* (baseapp, types) [#\9390](https://github.com/cosmos/cosmos-sdk/pull/9390) Add current block header hash to `Context`
5049

50+
### Bug Fixes
51+
52+
* (x/gov) [\#8813](https://github.com/cosmos/cosmos-sdk/pull/8813) fix `GET /cosmos/gov/v1beta1/proposals/{proposal_id}/deposits` to include initial deposit
53+
5154

5255
## [v0.42.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.5) - 2021-05-18
5356

x/gov/client/cli/query.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,9 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
364364
}
365365

366366
// check to see if the proposal is in the store
367-
_, err = queryClient.Proposal(
368-
context.Background(),
367+
ctx := cmd.Context()
368+
proposalRes, err := queryClient.Proposal(
369+
ctx,
369370
&types.QueryProposalRequest{ProposalId: proposalID},
370371
)
371372
if err != nil {
@@ -377,25 +378,27 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
377378
return err
378379
}
379380

380-
res, err := queryClient.Deposit(
381-
context.Background(),
382-
&types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]},
383-
)
384-
if err != nil {
385-
return err
386-
}
387-
388-
deposit := res.GetDeposit()
389-
if deposit.Empty() {
381+
var deposit types.Deposit
382+
propStatus := proposalRes.Proposal.Status
383+
if !(propStatus == types.StatusVotingPeriod || propStatus == types.StatusDepositPeriod) {
390384
params := types.NewQueryDepositParams(proposalID, depositorAddr)
391385
resByTxQuery, err := gcutils.QueryDepositByTxQuery(clientCtx, params)
392386
if err != nil {
393387
return err
394388
}
395389
clientCtx.JSONMarshaler.MustUnmarshalJSON(resByTxQuery, &deposit)
390+
return clientCtx.PrintProto(&deposit)
391+
}
392+
393+
res, err := queryClient.Deposit(
394+
ctx,
395+
&types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]},
396+
)
397+
if err != nil {
398+
return err
396399
}
397400

398-
return clientCtx.PrintProto(&deposit)
401+
return clientCtx.PrintProto(&res.Deposit)
399402
},
400403
}
401404

x/gov/client/testutil/cli_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// +build norace
2+
3+
package testutil
4+
5+
import (
6+
"testing"
7+
"time"
8+
9+
"github.com/cosmos/cosmos-sdk/testutil/network"
10+
sdk "github.com/cosmos/cosmos-sdk/types"
11+
"github.com/cosmos/cosmos-sdk/x/gov/types"
12+
13+
"github.com/stretchr/testify/require"
14+
"github.com/stretchr/testify/suite"
15+
)
16+
17+
func TestIntegrationTestSuite(t *testing.T) {
18+
cfg := network.DefaultConfig()
19+
cfg.NumValidators = 1
20+
genesisState := types.DefaultGenesisState()
21+
genesisState.DepositParams = types.NewDepositParams(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, types.DefaultMinDepositTokens)), time.Duration(15)*time.Second)
22+
genesisState.VotingParams = types.NewVotingParams(time.Duration(5) * time.Second)
23+
bz, err := cfg.Codec.MarshalJSON(genesisState)
24+
require.NoError(t, err)
25+
cfg.GenesisState["gov"] = bz
26+
suite.Run(t, NewDepositTestSuite(cfg))
27+
}

x/gov/client/testutil/deposits.go

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package testutil
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
8+
"github.com/cosmos/cosmos-sdk/testutil/network"
9+
sdk "github.com/cosmos/cosmos-sdk/types"
10+
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
11+
"github.com/cosmos/cosmos-sdk/x/gov/types"
12+
"github.com/stretchr/testify/suite"
13+
tmcli "github.com/tendermint/tendermint/libs/cli"
14+
)
15+
16+
type DepositTestSuite struct {
17+
suite.Suite
18+
19+
cfg network.Config
20+
network *network.Network
21+
fees string
22+
}
23+
24+
func NewDepositTestSuite(cfg network.Config) *DepositTestSuite {
25+
return &DepositTestSuite{cfg: cfg}
26+
}
27+
28+
func (s *DepositTestSuite) SetupSuite() {
29+
s.T().Log("setting up test suite")
30+
31+
s.network = network.New(s.T(), s.cfg)
32+
33+
_, err := s.network.WaitForHeight(1)
34+
s.Require().NoError(err)
35+
s.fees = sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20))).String()
36+
37+
}
38+
39+
func (s *DepositTestSuite) TearDownSuite() {
40+
s.T().Log("tearing down test suite")
41+
s.network.Cleanup()
42+
}
43+
44+
func (s *DepositTestSuite) TestQueryDepositsInitialDeposit() {
45+
val := s.network.Validators[0]
46+
clientCtx := val.ClientCtx
47+
initialDeposit := sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens.Sub(sdk.NewInt(20))).String()
48+
49+
// create a proposal with deposit
50+
_, err := MsgSubmitProposal(val.ClientCtx, val.Address.String(),
51+
"Text Proposal 1", "Where is the title!?", types.ProposalTypeText,
52+
fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit))
53+
s.Require().NoError(err)
54+
55+
// deposit more amount
56+
_, err = MsgDeposit(clientCtx, val.Address.String(), "1", sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(50)).String())
57+
s.Require().NoError(err)
58+
59+
// waiting for voting period to end
60+
time.Sleep(20 * time.Second)
61+
62+
// query deposit & verify initial deposit
63+
deposit := s.queryDeposit(val, "1", false)
64+
s.Require().Equal(deposit.Amount.String(), initialDeposit)
65+
66+
// query deposits
67+
deposits := s.queryDeposits(val, "1", false)
68+
s.Require().Equal(len(deposits), 2)
69+
// verify initial deposit
70+
s.Require().Equal(deposits[0].Amount.String(), initialDeposit)
71+
}
72+
73+
func (s *DepositTestSuite) TestQueryDepositsWithoutInitialDeposit() {
74+
val := s.network.Validators[0]
75+
clientCtx := val.ClientCtx
76+
77+
// create a proposal without deposit
78+
_, err := MsgSubmitProposal(val.ClientCtx, val.Address.String(),
79+
"Text Proposal 2", "Where is the title!?", types.ProposalTypeText)
80+
s.Require().NoError(err)
81+
82+
// deposit amount
83+
_, err = MsgDeposit(clientCtx, val.Address.String(), "2", sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens.Add(sdk.NewInt(50))).String())
84+
s.Require().NoError(err)
85+
86+
// waiting for voting period to end
87+
time.Sleep(20 * time.Second)
88+
89+
// query deposit
90+
deposit := s.queryDeposit(val, "2", false)
91+
s.Require().Equal(deposit.Amount.String(), sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens.Add(sdk.NewInt(50))).String())
92+
93+
// query deposits
94+
deposits := s.queryDeposits(val, "2", false)
95+
s.Require().Equal(len(deposits), 1)
96+
// verify initial deposit
97+
s.Require().Equal(deposits[0].Amount.String(), sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens.Add(sdk.NewInt(50))).String())
98+
}
99+
100+
func (s *DepositTestSuite) TestQueryProposalNotEnoughDeposits() {
101+
val := s.network.Validators[0]
102+
clientCtx := val.ClientCtx
103+
initialDeposit := sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens.Sub(sdk.NewInt(2000))).String()
104+
105+
// create a proposal with deposit
106+
_, err := MsgSubmitProposal(val.ClientCtx, val.Address.String(),
107+
"Text Proposal 3", "Where is the title!?", types.ProposalTypeText,
108+
fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit))
109+
s.Require().NoError(err)
110+
111+
// query proposal
112+
args := []string{"3", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
113+
cmd := cli.GetCmdQueryProposal()
114+
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
115+
s.Require().NoError(err)
116+
117+
// waiting for deposit period to end
118+
time.Sleep(20 * time.Second)
119+
120+
// query proposal
121+
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
122+
s.Require().Error(err)
123+
s.Require().Contains(err.Error(), "proposal 3 doesn't exist")
124+
}
125+
126+
func (s *DepositTestSuite) TestRejectedProposalDeposits() {
127+
val := s.network.Validators[0]
128+
clientCtx := val.ClientCtx
129+
initialDeposit := sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens)
130+
131+
// create a proposal with deposit
132+
_, err := MsgSubmitProposal(clientCtx, val.Address.String(),
133+
"Text Proposal 4", "Where is the title!?", types.ProposalTypeText,
134+
fmt.Sprintf("--%s=%s", cli.FlagDeposit, initialDeposit))
135+
s.Require().NoError(err)
136+
137+
// query deposits
138+
var deposits types.QueryDepositsResponse
139+
args := []string{"4", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
140+
cmd := cli.GetCmdQueryDeposits()
141+
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
142+
s.Require().NoError(err)
143+
s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(out.Bytes(), &deposits))
144+
s.Require().Equal(len(deposits.Deposits), 1)
145+
// verify initial deposit
146+
s.Require().Equal(deposits.Deposits[0].Amount.String(), sdk.NewCoin(s.cfg.BondDenom, types.DefaultMinDepositTokens).String())
147+
148+
// vote
149+
_, err = MsgVote(clientCtx, val.Address.String(), "4", "no")
150+
s.Require().NoError(err)
151+
152+
time.Sleep(20 * time.Second)
153+
154+
args = []string{"4", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
155+
cmd = cli.GetCmdQueryProposal()
156+
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
157+
s.Require().NoError(err)
158+
159+
// query deposits
160+
depositsRes := s.queryDeposits(val, "4", false)
161+
s.Require().Equal(len(depositsRes), 1)
162+
// verify initial deposit
163+
s.Require().Equal(depositsRes[0].Amount.String(), initialDeposit.String())
164+
165+
}
166+
167+
func (s *DepositTestSuite) queryDeposits(val *network.Validator, proposalID string, exceptErr bool) types.Deposits {
168+
args := []string{proposalID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
169+
var depositsRes types.Deposits
170+
cmd := cli.GetCmdQueryDeposits()
171+
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
172+
if exceptErr {
173+
s.Require().Error(err)
174+
return nil
175+
}
176+
s.Require().NoError(err)
177+
s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(out.Bytes(), &depositsRes))
178+
return depositsRes
179+
}
180+
181+
func (s *DepositTestSuite) queryDeposit(val *network.Validator, proposalID string, exceptErr bool) *types.Deposit {
182+
args := []string{proposalID, val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}
183+
var depositRes types.Deposit
184+
cmd := cli.GetCmdQueryDeposit()
185+
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args)
186+
if exceptErr {
187+
s.Require().Error(err)
188+
return nil
189+
}
190+
s.Require().NoError(err)
191+
s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(out.Bytes(), &depositRes))
192+
return &depositRes
193+
}

x/gov/client/testutil/helpers.go

+12
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,15 @@ func MsgVote(clientCtx client.Context, from, id, vote string, extraArgs ...strin
4343

4444
return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdVote(), args)
4545
}
46+
47+
func MsgDeposit(clientCtx client.Context, from, id, deposit string, extraArgs ...string) (testutil.BufferWriter, error) {
48+
args := append([]string{
49+
id,
50+
deposit,
51+
fmt.Sprintf("--%s=%s", flags.FlagFrom, from),
52+
}, commonArgs...)
53+
54+
args = append(args, extraArgs...)
55+
56+
return clitestutil.ExecTestCLICmd(clientCtx, govcli.NewCmdDeposit(), args)
57+
}

x/gov/client/utils/query.go

+58-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/cosmos/cosmos-sdk/client"
77
sdk "github.com/cosmos/cosmos-sdk/types"
8+
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
89
authclient "github.com/cosmos/cosmos-sdk/x/auth/client"
910
"github.com/cosmos/cosmos-sdk/x/gov/types"
1011
)
@@ -37,6 +38,18 @@ func (p Proposer) String() string {
3738
// NOTE: SearchTxs is used to facilitate the txs query which does not currently
3839
// support configurable pagination.
3940
func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposalParams) ([]byte, error) {
41+
var deposits []types.Deposit
42+
43+
// initial deposit was submitted with proposal, so must be queried separately
44+
initialDeposit, err := queryInitialDepositByTxQuery(clientCtx, params.ProposalID)
45+
if err != nil {
46+
return nil, err
47+
}
48+
49+
if !initialDeposit.Amount.IsZero() {
50+
deposits = append(deposits, initialDeposit)
51+
}
52+
4053
events := []string{
4154
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
4255
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
@@ -49,8 +62,6 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal
4962
return nil, err
5063
}
5164

52-
var deposits []types.Deposit
53-
5465
for _, info := range searchResult.Txs {
5566
for _, msg := range info.GetTx().GetMsgs() {
5667
if msg.Type() == types.TypeMsgDeposit {
@@ -167,6 +178,21 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams)
167178
// QueryDepositByTxQuery will query for a single deposit via a direct txs tags
168179
// query.
169180
func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositParams) ([]byte, error) {
181+
// initial deposit was submitted with proposal, so must be queried separately
182+
initialDeposit, err := queryInitialDepositByTxQuery(clientCtx, params.ProposalID)
183+
if err != nil {
184+
return nil, err
185+
}
186+
187+
if !initialDeposit.Amount.IsZero() {
188+
bz, err := clientCtx.JSONMarshaler.MarshalJSON(&initialDeposit)
189+
if err != nil {
190+
return nil, err
191+
}
192+
193+
return bz, nil
194+
}
195+
170196
events := []string{
171197
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgDeposit),
172198
fmt.Sprintf("%s.%s='%s'", types.EventTypeProposalDeposit, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", params.ProposalID))),
@@ -248,3 +274,33 @@ func QueryProposalByID(proposalID uint64, clientCtx client.Context, queryRoute s
248274

249275
return res, err
250276
}
277+
278+
// queryInitialDepositByTxQuery will query for a initial deposit of a governance proposal by
279+
// ID.
280+
func queryInitialDepositByTxQuery(clientCtx client.Context, proposalID uint64) (types.Deposit, error) {
281+
// Query legacy Msgs event action
282+
events := []string{
283+
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal),
284+
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
285+
}
286+
searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, defaultPage, defaultLimit, "")
287+
288+
if err != nil {
289+
return types.Deposit{}, err
290+
}
291+
292+
for _, info := range searchResult.Txs {
293+
for _, msg := range info.GetTx().GetMsgs() {
294+
// there should only be a single proposal under the given conditions
295+
if subMsg, ok := msg.(*types.MsgSubmitProposal); ok {
296+
return types.Deposit{
297+
ProposalId: proposalID,
298+
Depositor: subMsg.Proposer,
299+
Amount: subMsg.InitialDeposit,
300+
}, nil
301+
}
302+
}
303+
}
304+
305+
return types.Deposit{}, sdkerrors.Wrapf(sdkerrors.ErrKeyNotFound, "failed to find the initial deposit for proposalID %d", proposalID)
306+
}

0 commit comments

Comments
 (0)