Skip to content

Commit 66ee994

Browse files
fix: x/gov deposits querier (Initial Deposit) (cosmos#9288)
* copied from old PR * fix errors * add test * Update x/gov/client/utils/query.go Co-authored-by: Robert Zaremba <robert@zaremba.ch> * 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 <robert@zaremba.ch>
1 parent 90edeb6 commit 66ee994

File tree

6 files changed

+298
-14
lines changed

6 files changed

+298
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ if input key is empty, or input data contains empty key.
142142

143143
### Bug Fixes
144144

145+
* (x/gov) [\#8813](https://github.com/cosmos/cosmos-sdk/pull/8813) fix `GET /cosmos/gov/v1beta1/proposals/{proposal_id}/deposits` to include initial deposit
145146
* (gRPC) [\#8945](https://github.com/cosmos/cosmos-sdk/pull/8945) gRPC reflection now works correctly.
146147
* (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic`
147148
* (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger

x/gov/client/cli/query.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
366366

367367
// check to see if the proposal is in the store
368368
ctx := cmd.Context()
369-
_, err = queryClient.Proposal(
369+
proposalRes, err := queryClient.Proposal(
370370
ctx,
371371
&types.QueryProposalRequest{ProposalId: proposalID},
372372
)
@@ -379,25 +379,27 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk
379379
return err
380380
}
381381

382-
res, err := queryClient.Deposit(
383-
ctx,
384-
&types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]},
385-
)
386-
if err != nil {
387-
return err
388-
}
389-
390-
deposit := res.GetDeposit()
391-
if deposit.Empty() {
382+
var deposit types.Deposit
383+
propStatus := proposalRes.Proposal.Status
384+
if !(propStatus == types.StatusVotingPeriod || propStatus == types.StatusDepositPeriod) {
392385
params := types.NewQueryDepositParams(proposalID, depositorAddr)
393386
resByTxQuery, err := gcutils.QueryDepositByTxQuery(clientCtx, params)
394387
if err != nil {
395388
return err
396389
}
397390
clientCtx.JSONCodec.MustUnmarshalJSON(resByTxQuery, &deposit)
391+
return clientCtx.PrintProto(&deposit)
392+
}
393+
394+
res, err := queryClient.Deposit(
395+
ctx,
396+
&types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]},
397+
)
398+
if err != nil {
399+
return err
398400
}
399401

400-
return clientCtx.PrintProto(&deposit)
402+
return clientCtx.PrintProto(&res.Deposit)
401403
},
402404
}
403405

x/gov/client/testutil/cli_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,26 @@ package testutil
44

55
import (
66
"testing"
7+
"time"
78

89
"github.com/cosmos/cosmos-sdk/testutil/network"
10+
sdk "github.com/cosmos/cosmos-sdk/types"
11+
"github.com/cosmos/cosmos-sdk/x/gov/types"
912

13+
"github.com/stretchr/testify/require"
1014
"github.com/stretchr/testify/suite"
1115
)
1216

1317
func TestIntegrationTestSuite(t *testing.T) {
1418
cfg := network.DefaultConfig()
1519
cfg.NumValidators = 1
1620
suite.Run(t, NewIntegrationTestSuite(cfg))
21+
22+
genesisState := types.DefaultGenesisState()
23+
genesisState.DepositParams = types.NewDepositParams(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, types.DefaultMinDepositTokens)), time.Duration(15)*time.Second)
24+
genesisState.VotingParams = types.NewVotingParams(time.Duration(5) * time.Second)
25+
bz, err := cfg.Codec.MarshalJSON(genesisState)
26+
require.NoError(t, err)
27+
cfg.GenesisState["gov"] = bz
28+
suite.Run(t, NewDepositTestSuite(cfg))
1729
}

x/gov/client/testutil/deposits.go

Lines changed: 193 additions & 0 deletions
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

Lines changed: 12 additions & 0 deletions
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.NewCmdWeightedVote(), 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

Lines changed: 66 additions & 2 deletions
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
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
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
searchResult, err := combineEvents(
4154
clientCtx, defaultPage,
4255
// Query legacy Msgs event action
@@ -54,8 +67,6 @@ func QueryDepositsByTxQuery(clientCtx client.Context, params types.QueryProposal
5467
return nil, err
5568
}
5669

57-
var deposits []types.Deposit
58-
5970
for _, info := range searchResult.Txs {
6071
for _, msg := range info.GetTx().GetMsgs() {
6172
if depMsg, ok := msg.(*types.MsgDeposit); ok {
@@ -226,6 +237,22 @@ func QueryVoteByTxQuery(clientCtx client.Context, params types.QueryVoteParams)
226237
// QueryDepositByTxQuery will query for a single deposit via a direct txs tags
227238
// query.
228239
func QueryDepositByTxQuery(clientCtx client.Context, params types.QueryDepositParams) ([]byte, error) {
240+
241+
// initial deposit was submitted with proposal, so must be queried separately
242+
initialDeposit, err := queryInitialDepositByTxQuery(clientCtx, params.ProposalID)
243+
if err != nil {
244+
return nil, err
245+
}
246+
247+
if !initialDeposit.Amount.IsZero() {
248+
bz, err := clientCtx.JSONCodec.MarshalJSON(&initialDeposit)
249+
if err != nil {
250+
return nil, err
251+
}
252+
253+
return bz, nil
254+
}
255+
229256
searchResult, err := combineEvents(
230257
clientCtx, defaultPage,
231258
// Query legacy Msgs event action
@@ -338,3 +365,40 @@ func combineEvents(clientCtx client.Context, page int, eventGroups ...[]string)
338365

339366
return &sdk.SearchTxsResult{Txs: allTxs}, nil
340367
}
368+
369+
// queryInitialDepositByTxQuery will query for a initial deposit of a governance proposal by
370+
// ID.
371+
func queryInitialDepositByTxQuery(clientCtx client.Context, proposalID uint64) (types.Deposit, error) {
372+
searchResult, err := combineEvents(
373+
clientCtx, defaultPage,
374+
// Query legacy Msgs event action
375+
[]string{
376+
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, types.TypeMsgSubmitProposal),
377+
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
378+
},
379+
// Query proto Msgs event action
380+
[]string{
381+
fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, sdk.MsgTypeURL(&types.MsgSubmitProposal{})),
382+
fmt.Sprintf("%s.%s='%s'", types.EventTypeSubmitProposal, types.AttributeKeyProposalID, []byte(fmt.Sprintf("%d", proposalID))),
383+
},
384+
)
385+
386+
if err != nil {
387+
return types.Deposit{}, err
388+
}
389+
390+
for _, info := range searchResult.Txs {
391+
for _, msg := range info.GetTx().GetMsgs() {
392+
// there should only be a single proposal under the given conditions
393+
if subMsg, ok := msg.(*types.MsgSubmitProposal); ok {
394+
return types.Deposit{
395+
ProposalId: proposalID,
396+
Depositor: subMsg.Proposer,
397+
Amount: subMsg.InitialDeposit,
398+
}, nil
399+
}
400+
}
401+
}
402+
403+
return types.Deposit{}, sdkerrors.ErrNotFound.Wrapf("failed to find the initial deposit for proposalID %d", proposalID)
404+
}

0 commit comments

Comments
 (0)