feat(cli): cancel gov proposal by proposer before voting period ends (#13010)

Co-authored-by: Anil Kumar Kammari <anil@vitwit.com>
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com>
Co-authored-by: Robert Zaremba <robert@zaremba.ch>
Co-authored-by: Marko <marbar3778@yahoo.com>
Closes https://github.com/cosmos/cosmos-sdk/issues/11554
This commit is contained in:
Sai Kumar
2023-01-20 13:07:09 +00:00
committed by GitHub
parent c8f2f1d594
commit a4cf8e8c6f
53 changed files with 3440 additions and 413 deletions
@@ -19,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/types"
qtypes "github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/version"
_ "github.com/cosmos/cosmos-sdk/x/distribution"
_ "github.com/cosmos/cosmos-sdk/x/gov"
)
+1 -1
View File
@@ -77,7 +77,7 @@ func (s *E2ETestSuite) TestGetProposalsGRPC() {
"valid request",
fmt.Sprintf("%s/cosmos/gov/v1/proposals", val.APIAddress),
map[string]string{},
3,
4,
false,
},
{
+4 -2
View File
@@ -23,7 +23,7 @@ func (s *E2ETestSuite) TestCmdParams() {
{
"json output",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
`{"voting_params":{"voting_period":"172800s"},"deposit_params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800s"},"tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800s","voting_period":"172800s","quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000","min_initial_deposit_ratio":"0.000000000000000000"}}`,
`{"voting_params":{"voting_period":"172800s"},"deposit_params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800s"},"tally_params":{"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000"},"params":{"min_deposit":[{"denom":"stake","amount":"10000000"}],"max_deposit_period":"172800s","voting_period":"172800s","quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto_threshold":"0.334000000000000000","min_initial_deposit_ratio":"0.000000000000000000","proposal_cancel_ratio":"0.500000000000000000","proposal_cancel_dest":""}}`,
},
{
"text output",
@@ -40,6 +40,8 @@ params:
- amount: "10000000"
denom: stake
min_initial_deposit_ratio: "0.000000000000000000"
proposal_cancel_dest: ""
proposal_cancel_ratio: "0.500000000000000000"
quorum: "0.334000000000000000"
threshold: "0.500000000000000000"
veto_threshold: "0.334000000000000000"
@@ -306,7 +308,7 @@ func (s *E2ETestSuite) TestCmdGetProposals() {
var proposals v1.QueryProposalsResponse
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposals), out.String())
s.Require().Len(proposals.Proposals, 3)
s.Require().Greater(len(proposals.Proposals), 0)
}
})
}
+138 -10
View File
@@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil"
"github.com/cosmos/cosmos-sdk/x/gov/types"
@@ -41,36 +42,51 @@ func (s *E2ETestSuite) SetupSuite() {
s.Require().NoError(s.network.WaitForNextBlock())
val := s.network.Validators[0]
clientCtx := val.ClientCtx
var resp sdk.TxResponse
// create a proposal with deposit
_, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
out, err := govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
"Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText,
fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String()))
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
// vote for proposal
_, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes")
out, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "1", "yes")
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
// create a proposal without deposit
_, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
out, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
"Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
// create a proposal3 with deposit
_, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
out, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
"Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText,
fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String()))
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
// create a proposal4 with deposit to check the cancel proposal cli tx
out, err = govclitestutil.MsgSubmitLegacyProposal(val.ClientCtx, val.Address.String(),
"Text Proposal 4", "Where is the title!?", v1beta1.ProposalTypeText,
fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, v1.DefaultMinDepositTokens).String()))
s.Require().NoError(err)
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
// vote for proposal3 as val
_, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05")
out, err = govclitestutil.MsgVote(val.ClientCtx, val.Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05")
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, 0))
}
func (s *E2ETestSuite) TearDownSuite() {
@@ -260,6 +276,118 @@ func (s *E2ETestSuite) TestNewCmdSubmitLegacyProposal() {
}
}
func (s *E2ETestSuite) TestNewCmdCancelProposal() {
val := s.network.Validators[0]
val2 := sdk.AccAddress("invalid_acc_addr")
testCases := []struct {
name string
args []string
expectErr bool
expectedCode uint32
}{
{
"without proposal id",
[]string{
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0,
},
{
"invalid proposal id",
[]string{
"asdasd",
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0,
},
{
"valid proposal-id but invalid proposer",
[]string{
"4",
fmt.Sprintf("--%s=%s", flags.FlagFrom, val2),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
true, 0,
},
{
"valid proposer",
[]string{
"4",
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
false, 0,
},
{
"proposal not exists after cancel",
[]string{
"4",
fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()),
},
false, 17,
},
}
for _, tc := range testCases {
var resp sdk.TxResponse
s.Run(tc.name, func() {
cmd := cli.NewCmdCancelProposal()
clientCtx := val.ClientCtx
var balRes banktypes.QueryAllBalancesResponse
var newBalance banktypes.QueryAllBalancesResponse
if !tc.expectErr && tc.expectedCode == 0 {
resp, err := clitestutil.QueryBalancesExec(clientCtx, val.Address)
s.Require().NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes)
s.Require().NoError(err)
}
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String())
s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, tc.expectedCode))
if !tc.expectErr && tc.expectedCode == 0 {
resp, err := clitestutil.QueryBalancesExec(clientCtx, val.Address)
s.Require().NoError(err)
err = val.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &newBalance)
s.Require().NoError(err)
remainingAmount := v1.DefaultMinDepositTokens.Mul(
v1.DefaultProposalCancelRatio.Mul(sdk.MustNewDecFromStr("100")).TruncateInt(),
).Quo(sdk.NewIntFromUint64(100))
// new balance = old balance + remaining amount from proposal deposit - txFee (cancel proposal)
txFee := sdk.NewInt(10)
s.Require().True(
newBalance.Balances.AmountOf(s.network.Config.BondDenom).Equal(
balRes.Balances.AmountOf(s.network.Config.BondDenom).Add(remainingAmount).Sub(txFee),
),
)
}
}
})
}
}
func (s *E2ETestSuite) TestNewCmdDeposit() {
val := s.network.Validators[0]
+2 -2
View File
@@ -22,7 +22,7 @@ import (
_ "github.com/cosmos/cosmos-sdk/x/consensus"
_ "github.com/cosmos/cosmos-sdk/x/distribution"
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
disttypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/gov"
"github.com/cosmos/cosmos-sdk/x/gov/keeper"
"github.com/cosmos/cosmos-sdk/x/gov/types"
@@ -106,7 +106,7 @@ func TestImportExportQueues(t *testing.T) {
genesisState[banktypes.ModuleName] = s1.cdc.MustMarshalJSON(bankGenState)
genesisState[types.ModuleName] = s1.cdc.MustMarshalJSON(govGenState)
genesisState[stakingtypes.ModuleName] = s1.cdc.MustMarshalJSON(stakingGenState)
genesisState[distributiontypes.ModuleName] = s1.cdc.MustMarshalJSON(distributionGenState)
genesisState[disttypes.ModuleName] = s1.cdc.MustMarshalJSON(distributionGenState)
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
assert.NilError(t, err)
+2
View File
@@ -10,6 +10,7 @@ import (
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
_ "github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/gov/types"
_ "github.com/cosmos/cosmos-sdk/x/mint"
)
@@ -23,6 +24,7 @@ func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
configurator.StakingModule(),
configurator.BankModule(),
configurator.GovModule(),
configurator.DistributionModule(),
configurator.ConsensusModule(),
),
&accountKeeper,