Skip to content

Commit 7661f62

Browse files
authored
fix(group)!: Fix group min execution period (cosmos#13876)
* fix: don't check MinExecutionPeriod in `Allow` * Check MinExecutionPeriod on doExecuteMsgs * Fix TestExec * Fix TestExec * test exec pruned * Fix submitproposal * Add changelog * typo * revert some changes * add minExecutionPeriod * Add docs and specs
1 parent 3423442 commit 7661f62

File tree

7 files changed

+178
-84
lines changed

7 files changed

+178
-84
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
114114
* (x/gov) [#12771](https://github.com/cosmos/cosmos-sdk/pull/12771) Initial deposit requirement for proposals at submission time.
115115
* (x/staking) [#12967](https://github.com/cosmos/cosmos-sdk/pull/12967) `unbond` now creates only one unbonding delegation entry when multiple unbondings exist at a single height (e.g. through multiple messages in a transaction).
116116
* (x/auth/vesting) [#13502](https://github.com/cosmos/cosmos-sdk/pull/13502) Add Amino Msg registration for `MsgCreatePeriodicVestingAccount`.
117+
* (x/group) [#13876](https://github.com/cosmos/cosmos-sdk/pull/13876) Fix group MinExecutionPeriod that is checked on execution now, instead of voting period end.
117118

118119
### API Breaking Changes
119120

@@ -168,6 +169,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
168169
* [#13794](https://github.com/cosmos/cosmos-sdk/pull/13794) Most methods on `types/module.AppModule` have been moved to
169170
extension interfaces. `module.Manager.Modules` is now of type `map[string]interface{}` to support in parallel the new
170171
`cosmossdk.io/core/appmodule.AppModule` API.
172+
* (x/group) [#13876](https://github.com/cosmos/cosmos-sdk/pull/13876) Add `GetMinExecutionPeriod` method on DecisionPolicy interface.
171173

172174
### CLI Breaking Changes
173175

x/group/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ A threshold decision policy defines a threshold of yes votes (based on a tally
109109
of voter weights) that must be achieved in order for a proposal to pass. For
110110
this decision policy, abstain and veto are simply treated as no's.
111111

112+
This decision policy also has a VotingPeriod window and a MinExecutionPeriod
113+
window. The former defines the duration after proposal submission where members
114+
are allowed to vote, after which tallying is performed. The latter specifies
115+
the minimum duration after proposal submission where the proposal can be
116+
executed. If set to 0, then the proposal is allowed to be executed immediately
117+
on submission (using the `TRY_EXEC` option). Obviously, MinExecutionPeriod
118+
cannot be greater than VotingPeriod+MaxExecutionPeriod (where MaxExecution is
119+
the app-defined duration that specifies the window after voting ended where a
120+
proposal can be executed).
121+
112122
#### Percentage decision policy
113123

114124
A percentage decision policy is similar to a threshold decision policy, except
@@ -117,6 +127,9 @@ It's more suited for groups where the group members' weights can be updated, as
117127
the percentage threshold stays the same, and doesn't depend on how those member
118128
weights get updated.
119129

130+
Same as the Threshold decision policy, the percentage decision policy has the
131+
two VotingPeriod and MinExecutionPeriod parameters.
132+
120133
### Proposal
121134

122135
Any member(s) of a group can submit a proposal for a group policy account to decide upon.

x/group/keeper/keeper_test.go

Lines changed: 136 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import (
3333
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
3434
)
3535

36+
const minExecutionPeriod = 5 * time.Second
37+
3638
type TestSuite struct {
3739
suite.Suite
3840

@@ -98,7 +100,7 @@ func (s *TestSuite) SetupTest() {
98100
policy := group.NewThresholdDecisionPolicy(
99101
"2",
100102
time.Second,
101-
0,
103+
minExecutionPeriod, // Must wait 5 seconds before executing proposal
102104
)
103105
policyReq := &group.MsgCreateGroupPolicy{
104106
Admin: s.addrs[0].String(),
@@ -1551,36 +1553,48 @@ func (s *TestSuite) TestGroupPoliciesByAdminOrGroup() {
15511553
func (s *TestSuite) TestSubmitProposal() {
15521554
addrs := s.addrs
15531555
addr1 := addrs[0]
1554-
addr2 := addrs[1]
1556+
addr2 := addrs[1] // Has weight 2
15551557
addr4 := addrs[3]
1556-
addr5 := addrs[4]
1558+
addr5 := addrs[4] // Has weight 1
15571559

15581560
myGroupID := s.groupID
15591561
accountAddr := s.groupPolicyAddr
15601562

1561-
msgSend := &banktypes.MsgSend{
1562-
FromAddress: s.groupPolicyAddr.String(),
1563-
ToAddress: addr2.String(),
1564-
Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)},
1565-
}
1566-
1563+
// Create a new group policy to test TRY_EXEC
15671564
policyReq := &group.MsgCreateGroupPolicy{
15681565
Admin: addr1.String(),
15691566
GroupId: myGroupID,
15701567
}
1571-
policy := group.NewThresholdDecisionPolicy(
1572-
"100",
1568+
noMinExecPeriodPolicy := group.NewThresholdDecisionPolicy(
1569+
"2",
15731570
time.Second,
1574-
0,
1571+
0, // no MinExecutionPeriod to test TRY_EXEC
15751572
)
1576-
err := policyReq.SetDecisionPolicy(policy)
1573+
err := policyReq.SetDecisionPolicy(noMinExecPeriodPolicy)
15771574
s.Require().NoError(err)
1575+
s.setNextAccount()
1576+
res, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq)
1577+
s.Require().NoError(err)
1578+
noMinExecPeriodPolicyAddr := sdk.MustAccAddressFromBech32(res.Address)
15781579

1580+
// Create a new group policy with super high threshold
1581+
bigThresholdPolicy := group.NewThresholdDecisionPolicy(
1582+
"100",
1583+
time.Second,
1584+
minExecutionPeriod,
1585+
)
15791586
s.setNextAccount()
1587+
err = policyReq.SetDecisionPolicy(bigThresholdPolicy)
1588+
s.Require().NoError(err)
15801589
bigThresholdRes, err := s.groupKeeper.CreateGroupPolicy(s.ctx, policyReq)
15811590
s.Require().NoError(err)
15821591
bigThresholdAddr := bigThresholdRes.Address
15831592

1593+
msgSend := &banktypes.MsgSend{
1594+
FromAddress: noMinExecPeriodPolicyAddr.String(),
1595+
ToAddress: addr2.String(),
1596+
Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)},
1597+
}
15841598
defaultProposal := group.Proposal{
15851599
GroupPolicyAddress: accountAddr.String(),
15861600
Status: group.PROPOSAL_STATUS_SUBMITTED,
@@ -1699,13 +1713,13 @@ func (s *TestSuite) TestSubmitProposal() {
16991713
}
17001714
},
17011715
req: &group.MsgSubmitProposal{
1702-
GroupPolicyAddress: accountAddr.String(),
1716+
GroupPolicyAddress: noMinExecPeriodPolicyAddr.String(),
17031717
Proposers: []string{addr2.String()},
17041718
Exec: group.Exec_EXEC_TRY,
17051719
},
17061720
msgs: []sdk.Msg{msgSend},
17071721
expProposal: group.Proposal{
1708-
GroupPolicyAddress: accountAddr.String(),
1722+
GroupPolicyAddress: noMinExecPeriodPolicyAddr.String(),
17091723
Status: group.PROPOSAL_STATUS_ACCEPTED,
17101724
FinalTallyResult: group.TallyResult{
17111725
YesCount: "2",
@@ -1716,24 +1730,24 @@ func (s *TestSuite) TestSubmitProposal() {
17161730
ExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
17171731
},
17181732
postRun: func(sdkCtx sdk.Context) {
1719-
s.bankKeeper.EXPECT().GetAllBalances(sdkCtx, accountAddr).Return(sdk.NewCoins(sdk.NewInt64Coin("test", 9900)))
1733+
s.bankKeeper.EXPECT().GetAllBalances(sdkCtx, noMinExecPeriodPolicyAddr).Return(sdk.NewCoins(sdk.NewInt64Coin("test", 9900)))
17201734
s.bankKeeper.EXPECT().GetAllBalances(sdkCtx, addr2).Return(sdk.NewCoins(sdk.NewInt64Coin("test", 100)))
17211735

1722-
fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, accountAddr)
1736+
fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, noMinExecPeriodPolicyAddr)
17231737
s.Require().Contains(fromBalances, sdk.NewInt64Coin("test", 9900))
17241738
toBalances := s.bankKeeper.GetAllBalances(sdkCtx, addr2)
17251739
s.Require().Contains(toBalances, sdk.NewInt64Coin("test", 100))
17261740
},
17271741
},
17281742
"with try exec, not enough yes votes for proposal to pass": {
17291743
req: &group.MsgSubmitProposal{
1730-
GroupPolicyAddress: accountAddr.String(),
1744+
GroupPolicyAddress: noMinExecPeriodPolicyAddr.String(),
17311745
Proposers: []string{addr5.String()},
17321746
Exec: group.Exec_EXEC_TRY,
17331747
},
17341748
msgs: []sdk.Msg{msgSend},
17351749
expProposal: group.Proposal{
1736-
GroupPolicyAddress: accountAddr.String(),
1750+
GroupPolicyAddress: noMinExecPeriodPolicyAddr.String(),
17371751
Status: group.PROPOSAL_STATUS_SUBMITTED,
17381752
FinalTallyResult: group.TallyResult{
17391753
YesCount: "0", // Since tally doesn't pass Allow(), we consider the proposal not final
@@ -2399,6 +2413,7 @@ func (s *TestSuite) TestExecProposal() {
23992413
msgs := []sdk.Msg{msgSend1}
24002414
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
24012415
},
2416+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
24022417
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
24032418
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
24042419
expBalance: true,
@@ -2412,6 +2427,7 @@ func (s *TestSuite) TestExecProposal() {
24122427

24132428
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
24142429
},
2430+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
24152431
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
24162432
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
24172433
expBalance: true,
@@ -2423,6 +2439,7 @@ func (s *TestSuite) TestExecProposal() {
24232439
msgs := []sdk.Msg{msgSend1}
24242440
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_NO)
24252441
},
2442+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
24262443
expProposalStatus: group.PROPOSAL_STATUS_REJECTED,
24272444
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN,
24282445
},
@@ -2439,34 +2456,59 @@ func (s *TestSuite) TestExecProposal() {
24392456
},
24402457
expErr: true,
24412458
},
2442-
"Decision policy also applied on timeout": {
2459+
"Decision policy also applied on exactly voting period end": {
24432460
setupProposal: func(ctx context.Context) uint64 {
24442461
msgs := []sdk.Msg{msgSend1}
24452462
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_NO)
24462463
},
2447-
srcBlockTime: s.blockTime.Add(time.Second),
2464+
srcBlockTime: s.blockTime.Add(time.Second), // Voting period is 1s
24482465
expProposalStatus: group.PROPOSAL_STATUS_REJECTED,
24492466
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN,
24502467
},
2451-
"Decision policy also applied after timeout": {
2468+
"Decision policy also applied after voting period end": {
24522469
setupProposal: func(ctx context.Context) uint64 {
24532470
msgs := []sdk.Msg{msgSend1}
24542471
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_NO)
24552472
},
2456-
srcBlockTime: s.blockTime.Add(time.Second).Add(time.Millisecond),
2473+
srcBlockTime: s.blockTime.Add(time.Second).Add(time.Millisecond), // Voting period is 1s
24572474
expProposalStatus: group.PROPOSAL_STATUS_REJECTED,
24582475
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_NOT_RUN,
24592476
},
2477+
"exec proposal before MinExecutionPeriod should fail": {
2478+
setupProposal: func(ctx context.Context) uint64 {
2479+
msgs := []sdk.Msg{msgSend1}
2480+
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
2481+
},
2482+
srcBlockTime: s.blockTime.Add(4 * time.Second), // min execution date is 5s later after s.blockTime
2483+
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
2484+
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE, // Because MinExecutionPeriod has not passed
2485+
},
2486+
"exec proposal at exactly MinExecutionPeriod should pass": {
2487+
setupProposal: func(ctx context.Context) uint64 {
2488+
msgs := []sdk.Msg{msgSend1}
2489+
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend1).Return(nil, nil)
2490+
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
2491+
},
2492+
srcBlockTime: s.blockTime.Add(5 * time.Second), // min execution date is 5s later after s.blockTime
2493+
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
2494+
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
2495+
},
24602496
"prevent double execution when successful": {
24612497
setupProposal: func(ctx context.Context) uint64 {
24622498
myProposalID := submitProposalAndVote(ctx, s, []sdk.Msg{msgSend1}, proposers, group.VOTE_OPTION_YES)
24632499
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend1).Return(nil, nil)
24642500

2501+
// Wait after min execution period end before Exec
2502+
sdkCtx := sdk.UnwrapSDKContext(ctx)
2503+
sdkCtx = sdkCtx.WithBlockTime(sdkCtx.BlockTime().Add(minExecutionPeriod)) // MinExecutionPeriod is 5s
2504+
ctx = sdk.WrapSDKContext(sdkCtx)
2505+
24652506
_, err := s.groupKeeper.Exec(ctx, &group.MsgExec{Executor: addr1.String(), ProposalId: myProposalID})
24662507
s.Require().NoError(err)
24672508
return myProposalID
24682509
},
2469-
expErr: true, // since proposal is pruned after a successful MsgExec
2510+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
2511+
expErr: true, // since proposal is pruned after a successful MsgExec
24702512
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
24712513
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
24722514
expBalance: true,
@@ -2481,6 +2523,7 @@ func (s *TestSuite) TestExecProposal() {
24812523

24822524
return submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
24832525
},
2526+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
24842527
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
24852528
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_FAILURE,
24862529
},
@@ -2489,6 +2532,11 @@ func (s *TestSuite) TestExecProposal() {
24892532
msgs := []sdk.Msg{msgSend2}
24902533
myProposalID := submitProposalAndVote(ctx, s, msgs, proposers, group.VOTE_OPTION_YES)
24912534

2535+
// Wait after min execution period end before Exec
2536+
sdkCtx := sdk.UnwrapSDKContext(ctx)
2537+
sdkCtx = sdkCtx.WithBlockTime(sdkCtx.BlockTime().Add(minExecutionPeriod)) // MinExecutionPeriod is 5s
2538+
ctx = sdk.WrapSDKContext(sdkCtx)
2539+
24922540
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend2).Return(nil, fmt.Errorf("error"))
24932541
_, err := s.groupKeeper.Exec(ctx, &group.MsgExec{Executor: addr1.String(), ProposalId: myProposalID})
24942542
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend2).Return(nil, nil)
@@ -2498,6 +2546,7 @@ func (s *TestSuite) TestExecProposal() {
24982546

24992547
return myProposalID
25002548
},
2549+
srcBlockTime: s.blockTime.Add(minExecutionPeriod), // After min execution period end
25012550
expProposalStatus: group.PROPOSAL_STATUS_ACCEPTED,
25022551
expExecutorResult: group.PROPOSAL_EXECUTOR_RESULT_SUCCESS,
25032552
},
@@ -2689,6 +2738,11 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() {
26892738

26902739
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend2).Return(nil, fmt.Errorf("error"))
26912740

2741+
// Wait for min execution period end
2742+
sdkCtx := sdk.UnwrapSDKContext(ctx)
2743+
sdkCtx = sdkCtx.WithBlockTime(sdkCtx.BlockTime().Add(minExecutionPeriod))
2744+
ctx = sdk.WrapSDKContext(sdkCtx)
2745+
26922746
_, err := s.groupKeeper.Exec(ctx, &group.MsgExec{Executor: addr1.String(), ProposalId: myProposalID})
26932747
s.bankKeeper.EXPECT().Send(gomock.Any(), msgSend2).Return(nil, nil)
26942748

@@ -2710,6 +2764,8 @@ func (s *TestSuite) TestExecPrunedProposalsAndVotes() {
27102764
sdkCtx = sdkCtx.WithBlockTime(spec.srcBlockTime)
27112765
}
27122766

2767+
// Wait for min execution period end
2768+
sdkCtx = sdkCtx.WithBlockTime(sdkCtx.BlockTime().Add(minExecutionPeriod))
27132769
ctx = sdk.WrapSDKContext(sdkCtx)
27142770
_, err := s.groupKeeper.Exec(ctx, &group.MsgExec{Executor: addr1.String(), ProposalId: proposalID})
27152771
if spec.expErr {
@@ -3173,3 +3229,59 @@ func (s *TestSuite) createGroupAndGroupPolicy(
31733229

31743230
return policyAddr, groupID
31753231
}
3232+
3233+
func (s *TestSuite) TestTallyProposalsAtVPEnd() {
3234+
addrs := s.addrs
3235+
addr1 := addrs[0]
3236+
addr2 := addrs[1]
3237+
votingPeriod := time.Duration(4 * time.Minute)
3238+
minExecutionPeriod := votingPeriod + group.DefaultConfig().MaxExecutionPeriod
3239+
3240+
groupMsg := &group.MsgCreateGroupWithPolicy{
3241+
Admin: addr1.String(),
3242+
Members: []group.MemberRequest{
3243+
{Address: addr1.String(), Weight: "1"},
3244+
{Address: addr2.String(), Weight: "1"},
3245+
},
3246+
}
3247+
policy := group.NewThresholdDecisionPolicy(
3248+
"1",
3249+
votingPeriod,
3250+
minExecutionPeriod,
3251+
)
3252+
s.Require().NoError(groupMsg.SetDecisionPolicy(policy))
3253+
3254+
s.setNextAccount()
3255+
groupRes, err := s.groupKeeper.CreateGroupWithPolicy(s.ctx, groupMsg)
3256+
s.Require().NoError(err)
3257+
accountAddr := groupRes.GetGroupPolicyAddress()
3258+
groupPolicy, err := sdk.AccAddressFromBech32(accountAddr)
3259+
s.Require().NoError(err)
3260+
s.Require().NotNil(groupPolicy)
3261+
3262+
proposalRes, err := s.groupKeeper.SubmitProposal(s.ctx, &group.MsgSubmitProposal{
3263+
GroupPolicyAddress: accountAddr,
3264+
Proposers: []string{addr1.String()},
3265+
Messages: nil,
3266+
})
3267+
s.Require().NoError(err)
3268+
3269+
_, err = s.groupKeeper.Vote(s.ctx, &group.MsgVote{
3270+
ProposalId: proposalRes.ProposalId,
3271+
Voter: addr1.String(),
3272+
Option: group.VOTE_OPTION_YES,
3273+
})
3274+
s.Require().NoError(err)
3275+
3276+
// move forward in time
3277+
ctx := s.sdkCtx.WithBlockTime(s.sdkCtx.BlockTime().Add(votingPeriod + 1))
3278+
3279+
result, err := s.groupKeeper.TallyResult(ctx, &group.QueryTallyResultRequest{
3280+
ProposalId: proposalRes.ProposalId,
3281+
})
3282+
s.Require().Equal("1", result.Tally.YesCount)
3283+
s.Require().NoError(err)
3284+
3285+
s.Require().NoError(s.groupKeeper.TallyProposalsAtVPEnd(ctx))
3286+
s.NotPanics(func() { module.EndBlocker(ctx, s.groupKeeper) })
3287+
}

x/group/keeper/msg_server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,7 @@ func (k Keeper) doTallyAndUpdate(ctx sdk.Context, p *group.Proposal, electorate
685685
return err
686686
}
687687

688-
sinceSubmission := ctx.BlockTime().Sub(p.SubmitTime) // duration passed since proposal submission.
689-
result, err := policy.Allow(tallyResult, electorate.TotalWeight, sinceSubmission)
688+
result, err := policy.Allow(tallyResult, electorate.TotalWeight)
690689
if err != nil {
691690
return sdkerrors.Wrap(err, "policy allow")
692691
}
@@ -752,7 +751,8 @@ func (k Keeper) Exec(goCtx context.Context, req *group.MsgExec) (*group.MsgExecR
752751
return nil, err
753752
}
754753

755-
if results, err := k.doExecuteMsgs(cacheCtx, k.router, proposal, addr); err != nil {
754+
decisionPolicy := policyInfo.DecisionPolicy.GetCachedValue().(group.DecisionPolicy)
755+
if results, err := k.doExecuteMsgs(cacheCtx, k.router, proposal, addr, decisionPolicy); err != nil {
756756
proposal.ExecutorResult = group.PROPOSAL_EXECUTOR_RESULT_FAILURE
757757
logs = fmt.Sprintf("proposal execution failed on proposal %d, because of error %s", id, err.Error())
758758
k.Logger(ctx).Info("proposal execution failed", "cause", err, "proposalID", id)

x/group/keeper/proposal_executor.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ import (
1212

1313
// doExecuteMsgs routes the messages to the registered handlers. Messages are limited to those that require no authZ or
1414
// by the account of group policy only. Otherwise this gives access to other peoples accounts as the sdk middlewares are bypassed
15-
func (s Keeper) doExecuteMsgs(ctx sdk.Context, router *baseapp.MsgServiceRouter, proposal group.Proposal, groupPolicyAcc sdk.AccAddress) ([]sdk.Result, error) {
15+
func (s Keeper) doExecuteMsgs(ctx sdk.Context, router *baseapp.MsgServiceRouter, proposal group.Proposal, groupPolicyAcc sdk.AccAddress, decisionPolicy group.DecisionPolicy) ([]sdk.Result, error) {
16+
// Ensure it's not too early to execute the messages.
17+
minExecutionDate := proposal.SubmitTime.Add(decisionPolicy.GetMinExecutionPeriod())
18+
if ctx.BlockTime().Before(minExecutionDate) {
19+
return nil, errors.ErrInvalid.Wrapf("must wait until %s to execute proposal %d", minExecutionDate, proposal.Id)
20+
}
21+
1622
// Ensure it's not too late to execute the messages.
1723
// After https://github.com/cosmos/cosmos-sdk/issues/11245, proposals should
1824
// be pruned automatically, so this function should not even be called, as

0 commit comments

Comments
 (0)