Skip to content

Commit 2ea0715

Browse files
authored
Merge pull request #365 from abdulla-ashurov/issue-344-repropose-upgrade-with-same-name
Issue 344 - Re-propose upgrade with same name
2 parents ecaa4b9 + b59987b commit 2ea0715

File tree

5 files changed

+264
-12
lines changed

5 files changed

+264
-12
lines changed

docs/transactions.md

+2
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,8 @@ dcld tx dclupgrade propose-upgrade --name=<string> --upgrade-height=<int64> --fr
16391639
dcld tx dclupgrade propose-upgrade --name=<string> --upgrade-height=<int64> --upgrade-info=<string> --from=<account>
16401640
```
16411641

1642+
> **_Note:_** If the current upgrade proposal is out of date(when the current network height is greater than the proposed upgrade height), we can resubmit the upgrade proposal with the same name.
1643+
16421644
#### APPROVE_UPGRADE
16431645

16441646
**Status: Implemented**

integration_tests/cli/upgrade-demo.sh

+83
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,87 @@ check_response "$approved_dclupgrade_query" "Not Found"
222222

223223
test_divider
224224

225+
# APPROVE UPGRADE'S PLAN HEIGHT LESS THAN BLOCK HEIGHT AND RE-PROPOSE UPGRADE PLAN HEIGHT BIGGER THAN BLOCK HEIGHT
226+
###########################################################################################################################################
227+
get_height current_height
228+
echo "Current height is $current_height"
229+
plan_height=$(expr $current_height + 2)
230+
echo "$plan_height"
231+
random_string upgrade_name
232+
random_string upgrade_info
233+
234+
echo "propose upgrade's plan height bigger than block height"
235+
propose=$(dcld tx dclupgrade propose-upgrade --name=$upgrade_name --upgrade-height=$plan_height --upgrade-info=$upgrade_info --from jack --yes)
236+
echo "propose upgrade response: $propose"
237+
check_response "$propose" "\"code\": 0"
238+
239+
proposed_dclupgrade_query=$(dcld query dclupgrade proposed-upgrade --name=$upgrade_name)
240+
echo "dclupgrade proposed upgrade query: $proposed_dclupgrade_query"
241+
check_response_and_report "$proposed_dclupgrade_query" "\"name\": \"$upgrade_name\""
242+
check_response_and_report "$proposed_dclupgrade_query" "\"height\": \"$plan_height\""
243+
check_response_and_report "$proposed_dclupgrade_query" "\"info\": \"$upgrade_info\""
244+
245+
wait_for_height $(expr $plan_height + 5) 300 outage-safe
246+
get_height current_height
247+
echo "Current height is $current_height"
248+
249+
echo "approve upgrade's plan height less than block height"
250+
approve=$(dcld tx dclupgrade approve-upgrade --name=$upgrade_name --from alice --yes)
251+
echo "approve upgrade response: $approve"
252+
check_response_and_report "$approve" "upgrade cannot be scheduled in the past" raw
253+
254+
get_height current_height
255+
echo "Current height is $current_height"
256+
plan_height=$(expr $current_height + 3)
257+
258+
echo "re-propose upgrade's plan height bigger than block height"
259+
propose=$(dcld tx dclupgrade propose-upgrade --name=$upgrade_name --upgrade-height=$plan_height --upgrade-info=$upgrade_info --from jack --yes)
260+
echo "propose upgrade response: $propose"
261+
check_response "$propose" "\"code\": 0"
262+
263+
proposed_dclupgrade_query=$(dcld query dclupgrade proposed-upgrade --name=$upgrade_name)
264+
echo "dclupgrade proposed upgrade query: $proposed_dclupgrade_query"
265+
check_response_and_report "$proposed_dclupgrade_query" "\"name\": \"$upgrade_name\""
266+
check_response_and_report "$proposed_dclupgrade_query" "\"height\": \"$plan_height\""
267+
check_response_and_report "$proposed_dclupgrade_query" "\"info\": \"$upgrade_info\""
268+
###########################################################################################################################################
269+
270+
test_divider
271+
272+
# APPROVE UPGRADE'S PLAN HEIGHT LESS THAN BLOCK HEIGHT AND RE-PROPOSE UPGRADE PLAN HEIGHT LESS THAN BLOCK HEIGHT
273+
###########################################################################################################################################
274+
get_height current_height
275+
echo "Current height is $current_height"
276+
plan_height=$(expr $current_height + 3)
277+
random_string upgrade_name
278+
random_string upgrade_info
279+
280+
echo "propose upgrade's plan height bigger than block height"
281+
propose=$(dcld tx dclupgrade propose-upgrade --name=$upgrade_name --upgrade-height=$plan_height --upgrade-info=$upgrade_info --from jack --yes)
282+
echo "propose upgrade response: $propose"
283+
check_response "$propose" "\"code\": 0"
284+
285+
proposed_dclupgrade_query=$(dcld query dclupgrade proposed-upgrade --name=$upgrade_name)
286+
echo "dclupgrade proposed upgrade query: $proposed_dclupgrade_query"
287+
check_response_and_report "$proposed_dclupgrade_query" "\"name\": \"$upgrade_name\""
288+
check_response_and_report "$proposed_dclupgrade_query" "\"height\": \"$plan_height\""
289+
check_response_and_report "$proposed_dclupgrade_query" "\"info\": \"$upgrade_info\""
290+
291+
wait_for_height $(expr $plan_height + 5) 300 outage-safe
292+
get_height current_height
293+
echo "Current height is $current_height"
294+
295+
echo "approve upgrade's plan height less than block height"
296+
approve=$(dcld tx dclupgrade approve-upgrade --name=$upgrade_name --from alice --yes)
297+
echo "approve upgrade response: $approve"
298+
check_response_and_report "$approve" "upgrade cannot be scheduled in the past" raw
299+
300+
echo "re-propose upgrade's plan height bigger than block height"
301+
propose=$(dcld tx dclupgrade propose-upgrade --name=$upgrade_name --upgrade-height=$plan_height --upgrade-info=$upgrade_info --from jack --yes)
302+
echo "propose upgrade response: $propose"
303+
check_response_and_report "$propose" "upgrade cannot be scheduled in the past" raw
304+
###########################################################################################################################################
305+
306+
test_divider
307+
225308
echo "PASSED"

x/dclupgrade/handler_test.go

+157
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,163 @@ func TestHandler_DoubleTimeRejectUpgrade(t *testing.T) {
843843
require.False(t, isFound)
844844
}
845845

846+
func TestHandler_DoubleTimeProposeUpgradePlanHeightBiggerThanBlockHeight(t *testing.T) {
847+
setup := Setup(t)
848+
849+
trusteeAccAddress1 := testdata.GenerateAccAddress()
850+
trusteeAccAddress2 := testdata.GenerateAccAddress()
851+
trusteeAccAddress3 := testdata.GenerateAccAddress()
852+
853+
setup.AddAccount(trusteeAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
854+
setup.AddAccount(trusteeAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
855+
setup.AddAccount(trusteeAccAddress3, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
856+
setup.DclauthKeeper.On("CountAccountsWithRole", mock.Anything, dclauthtypes.Trustee).Return(3)
857+
858+
// propose new upgrade with plan height > block height
859+
msgProposeUpgrade := NewMsgProposeUpgrade(trusteeAccAddress1)
860+
msgProposeUpgrade.Plan.Height = 3
861+
setup.Ctx = setup.Ctx.WithBlockHeight(1)
862+
863+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, msgProposeUpgrade.Plan).Return(nil).Once()
864+
_, err := setup.Handler(setup.Ctx, msgProposeUpgrade)
865+
require.NoError(t, err)
866+
867+
// second time propose upgrade same plan name with plan height > block height
868+
msgProposeUpgrade = NewMsgProposeUpgrade(trusteeAccAddress2)
869+
msgProposeUpgrade.Plan.Height = 5
870+
setup.Ctx = setup.Ctx.WithBlockHeight(2)
871+
872+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, msgProposeUpgrade.Plan).Return(nil).Once()
873+
_, err = setup.Handler(setup.Ctx, msgProposeUpgrade)
874+
require.Error(t, err)
875+
require.True(t, types.ErrProposedUpgradeAlreadyExists.Is(err))
876+
}
877+
878+
func TestHandler_ApproveUpgradePlanHeightLessThanBlockHeight_And_ReProposeUpgradePlanHeightBiggerThanBlockHeight(t *testing.T) {
879+
setup := Setup(t)
880+
881+
trusteeAccAddress1 := testdata.GenerateAccAddress()
882+
trusteeAccAddress2 := testdata.GenerateAccAddress()
883+
trusteeAccAddress3 := testdata.GenerateAccAddress()
884+
setup.AddAccount(trusteeAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
885+
setup.AddAccount(trusteeAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
886+
setup.AddAccount(trusteeAccAddress3, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
887+
setup.DclauthKeeper.On("CountAccountsWithRole", mock.Anything, dclauthtypes.Trustee).Return(3)
888+
889+
// propose new upgrade
890+
proposeUpgrade := NewMsgProposeUpgrade(trusteeAccAddress1)
891+
proposeUpgrade.Plan.Height = 2
892+
setup.Ctx = setup.Ctx.WithBlockHeight(1)
893+
894+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(nil).Once()
895+
_, err := setup.Handler(setup.Ctx, proposeUpgrade)
896+
require.NoError(t, err)
897+
898+
// check first proposed upgrade for being created
899+
proposedUpgrade, isFound := setup.Keeper.GetProposedUpgrade(setup.Ctx, proposeUpgrade.Plan.Name)
900+
require.True(t, isFound)
901+
902+
require.Equal(t, proposeUpgrade.Plan, proposedUpgrade.Plan)
903+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Creator)
904+
905+
require.Equal(t, 1, len(proposedUpgrade.Approvals))
906+
907+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Approvals[0].Address)
908+
require.Equal(t, proposeUpgrade.Time, proposedUpgrade.Approvals[0].Time)
909+
require.Equal(t, proposeUpgrade.Info, proposedUpgrade.Approvals[0].Info)
910+
911+
// create approve message from trustee2
912+
msgApproveUpgrade := NewMsgApproveUpgrade(trusteeAccAddress2)
913+
914+
// approve new upgrade with plan height < block height
915+
setup.Ctx = setup.Ctx.WithBlockHeight(3)
916+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(sdkerrors.ErrInvalidRequest).Once()
917+
_, err = setup.Handler(setup.Ctx, msgApproveUpgrade)
918+
require.Error(t, err, sdkerrors.ErrInvalidRequest)
919+
920+
// check upgrade for not being added to ApprovedUpgrade store
921+
_, isFound = setup.Keeper.GetApprovedUpgrade(setup.Ctx, proposeUpgrade.Plan.Name)
922+
require.False(t, isFound)
923+
924+
// second time propose upgrade with same name with propose height > current height
925+
proposeUpgrade = NewMsgProposeUpgrade(trusteeAccAddress3)
926+
proposeUpgrade.Plan.Height = 5
927+
928+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(nil).Once()
929+
_, err = setup.Handler(setup.Ctx, proposeUpgrade)
930+
require.NoError(t, err)
931+
932+
// check second proposed upgrade for being created
933+
proposedUpgrade, isFound = setup.Keeper.GetProposedUpgrade(setup.Ctx, proposeUpgrade.Plan.Name)
934+
require.True(t, isFound)
935+
936+
require.Equal(t, proposeUpgrade.Plan, proposedUpgrade.Plan)
937+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Creator)
938+
939+
require.Equal(t, 1, len(proposedUpgrade.Approvals))
940+
941+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Approvals[0].Address)
942+
require.Equal(t, proposeUpgrade.Time, proposedUpgrade.Approvals[0].Time)
943+
require.Equal(t, proposeUpgrade.Info, proposedUpgrade.Approvals[0].Info)
944+
}
945+
946+
func TestHandler_ApproveUpgradePlanHeightLessThanBlockHeight_And_ReProposeUpgradePlanHeightLessThanBlockHeight(t *testing.T) {
947+
setup := Setup(t)
948+
949+
trusteeAccAddress1 := testdata.GenerateAccAddress()
950+
trusteeAccAddress2 := testdata.GenerateAccAddress()
951+
trusteeAccAddress3 := testdata.GenerateAccAddress()
952+
setup.AddAccount(trusteeAccAddress1, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
953+
setup.AddAccount(trusteeAccAddress2, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
954+
setup.AddAccount(trusteeAccAddress3, []dclauthtypes.AccountRole{dclauthtypes.Trustee})
955+
setup.DclauthKeeper.On("CountAccountsWithRole", mock.Anything, dclauthtypes.Trustee).Return(3)
956+
957+
// propose new upgrade
958+
proposeUpgrade := NewMsgProposeUpgrade(trusteeAccAddress1)
959+
proposeUpgrade.Plan.Height = 2
960+
setup.Ctx = setup.Ctx.WithBlockHeight(1)
961+
962+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(nil).Once()
963+
_, err := setup.Handler(setup.Ctx, proposeUpgrade)
964+
require.NoError(t, err)
965+
966+
// check first proposed upgrade for being created
967+
proposedUpgrade, isFound := setup.Keeper.GetProposedUpgrade(setup.Ctx, proposeUpgrade.Plan.Name)
968+
require.True(t, isFound)
969+
970+
require.Equal(t, proposeUpgrade.Plan, proposedUpgrade.Plan)
971+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Creator)
972+
973+
require.Equal(t, 1, len(proposedUpgrade.Approvals))
974+
975+
require.Equal(t, proposeUpgrade.Creator, proposedUpgrade.Approvals[0].Address)
976+
require.Equal(t, proposeUpgrade.Time, proposedUpgrade.Approvals[0].Time)
977+
require.Equal(t, proposeUpgrade.Info, proposedUpgrade.Approvals[0].Info)
978+
979+
// create approve message from trustee2
980+
msgApproveUpgrade := NewMsgApproveUpgrade(trusteeAccAddress2)
981+
982+
// approve new upgrade with plan height < block height
983+
setup.Ctx = setup.Ctx.WithBlockHeight(3)
984+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(sdkerrors.ErrInvalidRequest).Once()
985+
_, err = setup.Handler(setup.Ctx, msgApproveUpgrade)
986+
require.Error(t, err, sdkerrors.ErrInvalidRequest)
987+
988+
// check upgrade for not being added to ApprovedUpgrade store
989+
_, isFound = setup.Keeper.GetApprovedUpgrade(setup.Ctx, proposeUpgrade.Plan.Name)
990+
require.False(t, isFound)
991+
992+
// second time propose upgrade with same name with propose height < current height
993+
proposeUpgrade = NewMsgProposeUpgrade(trusteeAccAddress3)
994+
proposeUpgrade.Plan.Height = 3
995+
setup.Ctx = setup.Ctx.WithBlockHeight(5)
996+
997+
setup.UpgradeKeeper.On("ScheduleUpgrade", mock.Anything, proposeUpgrade.Plan).Return(types.ErrProposedUpgradeAlreadyExists).Once()
998+
_, err = setup.Handler(setup.Ctx, proposeUpgrade)
999+
require.Error(t, err)
1000+
require.True(t, types.ErrProposedUpgradeAlreadyExists.Is(err))
1001+
}
1002+
8461003
func isContextWithCachedMultiStore(ctx sdk.Context) bool {
8471004
_, ok := ctx.MultiStore().(storetypes.CacheMultiStore)
8481005

x/dclupgrade/keeper/msg_server_approve_upgrade.go

+8
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ func (k msgServer) ApproveUpgrade(goCtx context.Context, msg *types.MsgApproveUp
6969
approvedUpgrage := types.ApprovedUpgrade(proposedUpgrade)
7070
k.SetApprovedUpgrade(ctx, approvedUpgrage)
7171
} else {
72+
// Execute scheduling upgrade in a new context branch (with branched store)
73+
// to validate msg.Plan before the proposal proceeds through the approval process.
74+
// State is not persisted.
75+
cacheCtx, _ := ctx.CacheContext()
76+
err = k.upgradeKeeper.ScheduleUpgrade(cacheCtx, proposedUpgrade.Plan)
77+
if err != nil {
78+
return nil, err
79+
}
7280
// update proposed upgrade
7381
k.SetProposedUpgrade(ctx, proposedUpgrade)
7482
}

x/dclupgrade/keeper/msg_server_propose_upgrade.go

+14-12
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@ func (k msgServer) ProposeUpgrade(goCtx context.Context, msg *types.MsgProposeUp
2424
)
2525
}
2626

27-
// check if proposed upgrade with the same name already exists
28-
_, isFound := k.GetProposedUpgrade(ctx, msg.Plan.Name)
29-
if isFound {
30-
return nil, types.NewErrProposedUpgradeAlreadyExists(msg.Plan.Name)
31-
}
32-
33-
// check if approved upgrade with the same name already exists
34-
_, isFound = k.GetApprovedUpgrade(ctx, msg.Plan.Name)
35-
if isFound {
36-
return nil, types.NewErrApprovedUpgradeAlreadyExists(msg.Plan.Name)
37-
}
38-
3927
// Execute scheduling upgrade in a new context branch (with branched store)
4028
// to validate msg.Plan before the proposal proceeds through the approval process.
4129
// State is not persisted.
@@ -45,6 +33,20 @@ func (k msgServer) ProposeUpgrade(goCtx context.Context, msg *types.MsgProposeUp
4533
return nil, err
4634
}
4735

36+
// check if proposed upgrade with the same name already exists and propose plan height
37+
existingProposedUpgrade, isFound := k.GetProposedUpgrade(ctx, msg.Plan.Name)
38+
if isFound && ctx.BlockHeight() > existingProposedUpgrade.Plan.Height {
39+
k.RemoveProposedUpgrade(ctx, msg.Plan.Name)
40+
} else if isFound {
41+
return nil, types.NewErrProposedUpgradeAlreadyExists(msg.Plan.Name)
42+
}
43+
44+
// check if approved upgrade with the same name already exists
45+
_, isFound = k.GetApprovedUpgrade(ctx, msg.Plan.Name)
46+
if isFound {
47+
return nil, types.NewErrApprovedUpgradeAlreadyExists(msg.Plan.Name)
48+
}
49+
4850
grant := types.Grant{
4951
Address: creatorAddr.String(),
5052
Time: msg.Time,

0 commit comments

Comments
 (0)