Skip to content

Commit 1db8f03

Browse files
authored
Problem: expedited related gov params are not adjusted (#1087)
* Problem: expedited related gov params are not adjusted * fix test
1 parent 452e088 commit 1db8f03

File tree

7 files changed

+250
-6
lines changed

7 files changed

+250
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- [#1061](https://github.com/crypto-org-chain/chain-main/pull/1061) Integrate sdk 0.50.
99
- [#1068](https://github.com/crypto-org-chain/chain-main/pull/1068) Upgrade ibc-go to `v8.3.2` and remove icaauth module.
1010
- [#1084](https://github.com/crypto-org-chain/chain-main/pull/1084) Add MsgModuleQuerySafe in allowed messages for ica host param.
11+
- [#1087](https://github.com/crypto-org-chain/chain-main/pull/1087) Ensure expedited related gov params pass the basic validation.
1112

1213
*Dec 6, 2023*
1314

app/upgrades.go

+59
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import (
44
"context"
55
"fmt"
66
"slices"
7+
"time"
78

9+
sdkmath "cosmossdk.io/math"
810
storetypes "cosmossdk.io/store/types"
911
upgradetypes "cosmossdk.io/x/upgrade/types"
1012
"github.com/cosmos/cosmos-sdk/codec"
1113
sdk "github.com/cosmos/cosmos-sdk/types"
1214
"github.com/cosmos/cosmos-sdk/types/module"
15+
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
16+
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
1317
)
1418

1519
func (app *ChainApp) RegisterUpgradeHandlers(cdc codec.BinaryCodec) {
@@ -29,6 +33,9 @@ func (app *ChainApp) RegisterUpgradeHandlers(cdc codec.BinaryCodec) {
2933
params.AllowMessages = append(params.AllowMessages, msg)
3034
app.ICAHostKeeper.SetParams(sdkCtx, params)
3135
}
36+
if err := UpdateExpeditedParams(ctx, app.GovKeeper); err != nil {
37+
return m, err
38+
}
3239
}
3340
return m, nil
3441
})
@@ -45,3 +52,55 @@ func (app *ChainApp) RegisterUpgradeHandlers(cdc codec.BinaryCodec) {
4552
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
4653
}
4754
}
55+
56+
func UpdateExpeditedParams(ctx context.Context, gov govkeeper.Keeper) error {
57+
govParams, err := gov.Params.Get(ctx)
58+
if err != nil {
59+
return err
60+
}
61+
if len(govParams.MinDeposit) > 0 {
62+
minDeposit := govParams.MinDeposit[0]
63+
expeditedAmount := minDeposit.Amount.MulRaw(govv1.DefaultMinExpeditedDepositTokensRatio)
64+
govParams.ExpeditedMinDeposit = sdk.NewCoins(sdk.NewCoin(minDeposit.Denom, expeditedAmount))
65+
}
66+
threshold, err := sdkmath.LegacyNewDecFromStr(govParams.Threshold)
67+
if err != nil {
68+
return fmt.Errorf("invalid threshold string: %w", err)
69+
}
70+
expeditedThreshold, err := sdkmath.LegacyNewDecFromStr(govParams.ExpeditedThreshold)
71+
if err != nil {
72+
return fmt.Errorf("invalid expedited threshold string: %w", err)
73+
}
74+
if expeditedThreshold.LTE(threshold) {
75+
expeditedThreshold = threshold.Mul(DefaultThresholdRatio())
76+
}
77+
if expeditedThreshold.GT(sdkmath.LegacyOneDec()) {
78+
expeditedThreshold = sdkmath.LegacyOneDec()
79+
}
80+
govParams.ExpeditedThreshold = expeditedThreshold.String()
81+
if govParams.ExpeditedVotingPeriod != nil && govParams.VotingPeriod != nil && *govParams.ExpeditedVotingPeriod >= *govParams.VotingPeriod {
82+
votingPeriod := DurationToDec(*govParams.VotingPeriod)
83+
period := DecToDuration(DefaultPeriodRatio().Mul(votingPeriod))
84+
govParams.ExpeditedVotingPeriod = &period
85+
}
86+
if err := govParams.ValidateBasic(); err != nil {
87+
return err
88+
}
89+
return gov.Params.Set(ctx, govParams)
90+
}
91+
92+
func DefaultThresholdRatio() sdkmath.LegacyDec {
93+
return govv1.DefaultExpeditedThreshold.Quo(govv1.DefaultThreshold)
94+
}
95+
96+
func DefaultPeriodRatio() sdkmath.LegacyDec {
97+
return DurationToDec(govv1.DefaultExpeditedPeriod).Quo(DurationToDec(govv1.DefaultPeriod))
98+
}
99+
100+
func DurationToDec(d time.Duration) sdkmath.LegacyDec {
101+
return sdkmath.LegacyMustNewDecFromStr(fmt.Sprintf("%f", d.Seconds()))
102+
}
103+
104+
func DecToDuration(d sdkmath.LegacyDec) time.Duration {
105+
return time.Second * time.Duration(d.RoundInt64())
106+
}

app/upgrades_test.go

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package app_test
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"cosmossdk.io/math"
8+
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
9+
sdk "github.com/cosmos/cosmos-sdk/types"
10+
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
11+
"github.com/crypto-org-chain/chain-main/v4/app"
12+
"github.com/crypto-org-chain/chain-main/v4/testutil"
13+
"github.com/stretchr/testify/suite"
14+
)
15+
16+
type AppTestSuite struct {
17+
suite.Suite
18+
19+
ctx sdk.Context
20+
app *app.ChainApp
21+
govParams govv1.Params
22+
}
23+
24+
func TestAppTestSuite(t *testing.T) {
25+
suite.Run(t, new(AppTestSuite))
26+
}
27+
28+
func (suite *AppTestSuite) SetupTest() {
29+
checkTx := false
30+
suite.app = testutil.Setup(checkTx, nil)
31+
suite.ctx = suite.app.NewContext(checkTx).WithBlockHeader(tmproto.Header{Height: 1, ChainID: testutil.ChainID, Time: time.Now().UTC()})
32+
var err error
33+
suite.govParams, err = suite.app.GovKeeper.Params.Get(suite.ctx)
34+
suite.Require().NoError(err)
35+
suite.Require().Equal(govv1.DefaultParams(), suite.govParams)
36+
}
37+
38+
func (suite *AppTestSuite) TestUpdateExpeditedParams() {
39+
const baseDenom = "basecro"
40+
41+
testCases := []struct {
42+
name string
43+
malleate func()
44+
exp func(params govv1.Params)
45+
}{
46+
{
47+
name: "update ExpeditedMinDeposit with baseDenom",
48+
malleate: func() {
49+
suite.govParams.MinDeposit = sdk.NewCoins(sdk.NewCoin(baseDenom, math.NewInt(2000000000000)))
50+
},
51+
exp: func(params govv1.Params) {
52+
expected := sdk.NewCoins(sdk.NewCoin(suite.govParams.MinDeposit[0].Denom, suite.govParams.MinDeposit[0].Amount.MulRaw(govv1.DefaultMinExpeditedDepositTokensRatio)))
53+
suite.Require().Equal(expected[0], params.ExpeditedMinDeposit[0])
54+
},
55+
},
56+
{
57+
name: "update ExpeditedThreshold when DefaultExpeditedThreshold >= Threshold",
58+
malleate: func() {
59+
suite.govParams.Threshold = "0.99"
60+
},
61+
exp: func(params govv1.Params) {
62+
suite.Require().Equal(math.LegacyOneDec().String(), params.ExpeditedThreshold)
63+
},
64+
},
65+
{
66+
name: "update ExpeditedThreshold when DefaultExpeditedThreshold >= Threshold",
67+
malleate: func() {
68+
suite.govParams.Threshold = govv1.DefaultExpeditedThreshold.String()
69+
},
70+
exp: func(params govv1.Params) {
71+
expected := app.DefaultThresholdRatio().Mul(math.LegacyMustNewDecFromStr(suite.govParams.Threshold))
72+
suite.Require().Equal(expected.String(), params.ExpeditedThreshold)
73+
},
74+
},
75+
{
76+
name: "no update ExpeditedThreshold when DefaultExpeditedThreshold < Threshold",
77+
malleate: func() {
78+
suite.govParams.Threshold = govv1.DefaultExpeditedThreshold.Quo(math.LegacyMustNewDecFromStr("1.1")).String()
79+
},
80+
exp: func(params govv1.Params) {
81+
suite.Require().Equal(suite.govParams.ExpeditedThreshold, params.ExpeditedThreshold)
82+
},
83+
},
84+
{
85+
name: "update ExpeditedVotingPeriod when DefaultExpeditedPeriod >= VotingPeriod",
86+
malleate: func() {
87+
period := govv1.DefaultExpeditedPeriod
88+
suite.govParams.VotingPeriod = &period
89+
},
90+
exp: func(params govv1.Params) {
91+
votingPeriod := app.DurationToDec(*suite.govParams.VotingPeriod)
92+
expected := app.DecToDuration(app.DefaultPeriodRatio().Mul(votingPeriod))
93+
suite.Require().Equal(expected, *params.ExpeditedVotingPeriod)
94+
},
95+
},
96+
{
97+
name: "no update ExpeditedVotingPeriod when DefaultExpeditedPeriod < VotingPeriod",
98+
malleate: func() {
99+
period := govv1.DefaultExpeditedPeriod + 1
100+
suite.govParams.VotingPeriod = &period
101+
},
102+
exp: func(params govv1.Params) {
103+
suite.Require().Equal(*suite.govParams.ExpeditedVotingPeriod, *params.ExpeditedVotingPeriod)
104+
},
105+
},
106+
}
107+
108+
for _, tc := range testCases {
109+
suite.Run(tc.name, func() {
110+
suite.SetupTest()
111+
tc.malleate()
112+
suite.Require().NoError(suite.app.GovKeeper.Params.Set(suite.ctx, suite.govParams))
113+
suite.Require().NoError(app.UpdateExpeditedParams(suite.ctx, suite.app.GovKeeper))
114+
params, err := suite.app.GovKeeper.Params.Get(suite.ctx)
115+
suite.Require().NoError(err)
116+
tc.exp(params)
117+
})
118+
}
119+
}

integration_tests/cosmoscli.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,16 @@ def query_params(self, mod):
298298
"node": self.node_rpc,
299299
"output": "json",
300300
}
301-
return json.loads(
301+
res = json.loads(
302302
self.raw(
303303
"q",
304304
mod,
305305
"params",
306306
**kwargs,
307307
)
308308
)
309+
res = res.get("params") or res
310+
return res
309311

310312

311313
class ClusterCLI(cluster.ClusterCLI):

integration_tests/test_gov.py

+36-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
from .utils import (
88
approve_proposal,
9+
assert_gov_params,
10+
get_expedited_params,
911
get_proposal_id,
1012
module_address,
1113
wait_for_block,
@@ -222,6 +224,35 @@ def test_inherit_vote(cluster, tmp_path):
222224

223225
def test_host_enabled(cluster, tmp_path):
224226
cli = cluster.cosmos_cli()
227+
param0 = cli.query_params("gov")
228+
param1 = get_expedited_params(param0)
229+
# governance module account as signer
230+
authority = module_address("gov")
231+
proposal = tmp_path / "proposal.json"
232+
type = "/cosmos.gov.v1.MsgUpdateParams"
233+
deposit = "0.1cro"
234+
proposal_src = {
235+
"title": "title",
236+
"summary": "summary",
237+
"deposit": deposit,
238+
"messages": [
239+
{
240+
"@type": type,
241+
"authority": authority,
242+
"params": {
243+
**param0,
244+
**param1,
245+
},
246+
}
247+
],
248+
}
249+
proposal.write_text(json.dumps(proposal_src))
250+
rsp = cli.submit_gov_proposal(proposal, from_="community")
251+
assert rsp["code"] == 0, rsp["raw_log"]
252+
approve_proposal(cluster, rsp, msg=f",{type}")
253+
print("check params have been updated now")
254+
assert_gov_params(cli, param0)
255+
225256
p = cli.query_host_params()
226257
assert p["host_enabled"]
227258
p["host_enabled"] = False
@@ -236,7 +267,7 @@ def test_host_enabled(cluster, tmp_path):
236267
"params": p,
237268
}
238269
],
239-
"deposit": "10000000basecro",
270+
"deposit": deposit,
240271
"title": "title",
241272
"summary": "summary",
242273
}
@@ -255,9 +286,9 @@ def test_gov_voting(cluster, tmp_path):
255286
"""
256287
cli = cluster.cosmos_cli()
257288
p = cli.query_params("gov")
258-
assert p["params"]["voting_period"] == "10s"
289+
assert p["voting_period"] == "10s"
259290
updated = "3m36s"
260-
p["params"]["voting_period"] = updated
291+
p["voting_period"] = updated
261292
proposal = tmp_path / "proposal.json"
262293
authority = module_address("gov")
263294
type = "/cosmos.gov.v1.MsgUpdateParams"
@@ -266,7 +297,7 @@ def test_gov_voting(cluster, tmp_path):
266297
{
267298
"@type": type,
268299
"authority": authority,
269-
"params": p["params"],
300+
"params": p,
270301
}
271302
],
272303
"deposit": "10000000basecro",
@@ -278,4 +309,4 @@ def test_gov_voting(cluster, tmp_path):
278309
assert rsp["code"] == 0, rsp["raw_log"]
279310
approve_proposal(cluster, rsp, msg=f",{type}")
280311
p = cli.query_params("gov")
281-
assert p["params"]["voting_period"] == updated
312+
assert p["voting_period"] == updated

integration_tests/test_upgrade.py

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from .utils import (
1515
approve_proposal,
16+
assert_gov_params,
1617
cluster_fixture,
1718
wait_for_block,
1819
wait_for_block_time,
@@ -428,10 +429,12 @@ def assert_commission(adr, expected):
428429
upgrade(cluster, "v4.3.0", target_height)
429430

430431
target_height = cluster.block_height() + 15
432+
gov_param = cli.query_params("gov")
431433
upgrade(cluster, "v5.0", target_height, broadcast_mode="sync")
432434
cli = cluster.cosmos_cli()
433435
with pytest.raises(AssertionError):
434436
cli.query_params("icaauth")
437+
assert_gov_params(cli, gov_param)
435438

436439

437440
def test_cancel_upgrade(cluster):

integration_tests/utils.py

+29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import time
77
from datetime import timedelta
8+
from decimal import Decimal
89

910
import bech32
1011
from dateutil.parser import isoparse
@@ -587,3 +588,31 @@ def wait_for_fn(name, fn, *, timeout=240, interval=1):
587588
time.sleep(interval)
588589
else:
589590
raise TimeoutError(f"wait for {name} timeout")
591+
592+
593+
def get_expedited_params(param):
594+
min_deposit = param["min_deposit"][0]
595+
voting_period = param["voting_period"]
596+
tokens_ratio = 5
597+
threshold_ratio = 1.334
598+
period_ratio = 0.5
599+
expedited_threshold = float(param["threshold"]) * threshold_ratio
600+
expedited_threshold = Decimal(f"{expedited_threshold}")
601+
expedited_voting_period = int(int(voting_period[:-1]) * period_ratio)
602+
return {
603+
"expedited_min_deposit": [
604+
{
605+
"denom": min_deposit["denom"],
606+
"amount": str(int(min_deposit["amount"]) * tokens_ratio),
607+
}
608+
],
609+
"expedited_threshold": f"{expedited_threshold:.18f}",
610+
"expedited_voting_period": f"{expedited_voting_period}s",
611+
}
612+
613+
614+
def assert_gov_params(cli, old_param):
615+
param = cli.query_params("gov")
616+
expedited_param = get_expedited_params(old_param)
617+
for key, value in expedited_param.items():
618+
assert param[key] == value, param

0 commit comments

Comments
 (0)