code.vegaprotocol.io/vega@v0.79.0/core/governance/engine_new_net_param_test.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package governance_test 17 18 import ( 19 "context" 20 "testing" 21 "time" 22 23 "code.vegaprotocol.io/vega/core/netparams" 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/libs/num" 26 vgrand "code.vegaprotocol.io/vega/libs/rand" 27 28 "github.com/golang/mock/gomock" 29 "github.com/stretchr/testify/require" 30 ) 31 32 // TestProposalForNetParamInvalidOnProposal verifies that an invalid value with respect to current values (i.e. crossing with the other current value) fails at submission time. 33 func TestProposalForNetParamInvalidOnProposal(t *testing.T) { 34 now := time.Now() 35 36 eng := getTestEngine(t, now) 37 38 party := eng.newValidParty("a-valid-party", 1) 39 40 // propose a min time that is greater than the max time, this should be invalid upon proposal and should be immediately rejected 41 p1 := eng.newProposalForNetParam(party.Id, netparams.MarketAuctionMinimumDuration, "169h", now.Add(48*time.Hour)) 42 43 // setup 44 eng.broker.EXPECT().Send(gomock.Any()).Times(1) 45 46 _, err := eng.submitProposal(t, p1) 47 48 // then 49 require.Equal(t, "unable to validate market.auction.minimumDuration: expect <= 24h0m0s got 169h0m0s, expect < 168h0m0s (market.auction.maximumDuration) got 169h0m0s", err.Error()) 50 } 51 52 // TestProposalForNetParamCrossingOnUpdate submits two crossing proposals with the same enactment time. In this case the proposals pass the initial validation but also 53 // pass the enactment validation and only fail at the last step of updating the param. The proposal will be marked as faild and only one of the values will go through. 54 func TestProposalForNetParamCrossingOnUpdate(t *testing.T) { 55 eng := getTestEngine(t, time.Now()) 56 57 party1 := eng.newValidParty("a-valid-party", 1) 58 party2 := eng.newValidParty("another-valid-party", 1) 59 60 now := eng.tsvc.GetTimeNow() 61 date1 := now.Add(5 * 24 * time.Hour) 62 63 // lower the max first, this should go through 64 p1 := eng.newProposalForNetParam(party1.Id, netparams.MarketAuctionMaximumDuration, "10h", date1) 65 66 // setup 67 eng.broker.EXPECT().Send(gomock.Any()).AnyTimes() 68 eng.broker.EXPECT().SendBatch(gomock.Any()).AnyTimes() 69 70 _, err := eng.submitProposal(t, p1) 71 require.NoError(t, err) 72 73 // now increase the min above the max, this should be valid at the time of proposal 74 p2 := eng.newProposalForNetParam(party2.Id, netparams.MarketAuctionMinimumDuration, "11h", date1) 75 76 _, err = eng.submitProposal(t, p2) 77 require.NoError(t, err) 78 79 // now get them enacted in order, the expected result is that the one enacted first gets through and the latter gets rejected 80 // i.e. min = 5s, max = 10h 81 82 eng.accounts.EXPECT().GetStakingAssetTotalSupply().Times(2).Return(num.NewUint(9)) 83 eng.ensureTokenBalanceForParty(t, party1.Id, 1) 84 eng.ensureTokenBalanceForParty(t, party2.Id, 1) 85 86 // vote for first proposal 87 voter1 := vgrand.RandomStr(5) 88 eng.ensureTokenBalanceForParty(t, voter1, 7) 89 err = eng.addYesVote(t, voter1, p1.ID) 90 require.NoError(t, err) 91 92 // vote for second proposal 93 voter2 := vgrand.RandomStr(5) 94 eng.ensureTokenBalanceForParty(t, voter2, 7) 95 err = eng.addYesVote(t, voter2, p2.ID) 96 require.NoError(t, err) 97 98 // given 99 afterEnactment := time.Unix(p1.Terms.EnactmentTimestamp, 0).Add(time.Second) 100 101 // time to enact, expect both of them to be enacted because at the time of check none has updated yet 102 enacted, _ := eng.OnTick(context.Background(), afterEnactment) 103 require.Equal(t, 2, len(enacted)) 104 105 // update enacted - first is expected to pass 106 err = eng.netp.Update(context.Background(), enacted[0].UpdateNetworkParameter().Key, enacted[0].UpdateNetworkParameter().Value) 107 require.NoError(t, err) 108 109 // second expected to fail the validation as the first has already been updated 110 err = eng.netp.Update(context.Background(), enacted[1].UpdateNetworkParameter().Key, enacted[1].UpdateNetworkParameter().Value) 111 require.Equal(t, "unable to update market.auction.minimumDuration: expect < 10h0m0s (market.auction.maximumDuration) got 11h0m0s", err.Error()) 112 113 max, err := eng.netp.Get(netparams.MarketAuctionMaximumDuration) 114 require.Equal(t, "10h", max) 115 require.NoError(t, err) 116 117 min, err := eng.netp.Get(netparams.MarketAuctionMinimumDuration) 118 require.Equal(t, "30m0s", min) 119 require.NoError(t, err) 120 } 121 122 // TestProposalForNetParamCrossingAtEnactment submits two crossing proposals such that one goes in before the other. In this case the first proposal passes and will get updated while 123 // the second proposal will fail pre-enactment. 124 func TestProposalForNetParamCrossingAtEnactment(t *testing.T) { 125 eng := getTestEngine(t, time.Now()) 126 127 party1 := eng.newValidParty("a-valid-party", 1) 128 party2 := eng.newValidParty("another-valid-party", 1) 129 130 now := eng.tsvc.GetTimeNow() 131 132 date1 := now.Add(5 * 24 * time.Hour) 133 date2 := date1.Add(time.Hour) 134 135 // lower the max first, this should go through 136 p1 := eng.newProposalForNetParam(party1.Id, netparams.MarketAuctionMaximumDuration, "10h", date1) 137 138 // setup 139 eng.broker.EXPECT().Send(gomock.Any()).AnyTimes() 140 eng.broker.EXPECT().SendBatch(gomock.Any()).AnyTimes() 141 142 _, err := eng.submitProposal(t, p1) 143 require.NoError(t, err) 144 145 // now increase the min above the max, this should be valid at the time of proposal 146 p2 := eng.newProposalForNetParam(party2.Id, netparams.MarketAuctionMinimumDuration, "11h", date2) 147 148 _, err = eng.submitProposal(t, p2) 149 require.NoError(t, err) 150 151 // now get them enacted in order, the expected result is that the one enacted first gets through and the latter gets rejected 152 // i.e. min = 5s, max = 10h 153 154 eng.accounts.EXPECT().GetStakingAssetTotalSupply().Times(2).Return(num.NewUint(9)) 155 eng.ensureTokenBalanceForParty(t, party1.Id, 1) 156 eng.ensureTokenBalanceForParty(t, party2.Id, 1) 157 158 // vote for first proposal 159 voter1 := vgrand.RandomStr(5) 160 eng.ensureTokenBalanceForParty(t, voter1, 7) 161 err = eng.addYesVote(t, voter1, p1.ID) 162 require.NoError(t, err) 163 164 // vote for second proposal 165 voter2 := vgrand.RandomStr(5) 166 eng.ensureTokenBalanceForParty(t, voter2, 7) 167 err = eng.addYesVote(t, voter2, p2.ID) 168 require.NoError(t, err) 169 170 // move time to after the enactment time of the first proposal 171 afterEnactment1 := time.Unix(p1.Terms.EnactmentTimestamp, 0).Add(time.Second) 172 173 // time to enact, expect both of them to be enacted because at the time of check none has updated yet 174 enacted, _ := eng.OnTick(context.Background(), afterEnactment1) 175 require.Equal(t, 1, len(enacted)) 176 177 // update enacted - first is expected to pass 178 err = eng.netp.Update(context.Background(), enacted[0].UpdateNetworkParameter().Key, enacted[0].UpdateNetworkParameter().Value) 179 require.NoError(t, err) 180 181 // move time to after the enactment time of the second proposal 182 afterEnactment2 := time.Unix(p2.Terms.EnactmentTimestamp, 0).Add(time.Second) 183 184 // time to enact, expect both of them to be enacted because at the time of check none has updated yet 185 enacted, _ = eng.OnTick(context.Background(), afterEnactment2) 186 require.Equal(t, 0, len(enacted)) 187 188 max, err := eng.netp.Get(netparams.MarketAuctionMaximumDuration) 189 require.Equal(t, "10h", max) 190 require.NoError(t, err) 191 192 min, err := eng.netp.Get(netparams.MarketAuctionMinimumDuration) 193 require.Equal(t, "30m0s", min) 194 require.NoError(t, err) 195 196 eng.OnTick(context.Background(), afterEnactment1.Add(1*time.Second)) 197 } 198 199 func (e *tstEngine) newProposalForNetParam(partyID, key, value string, now time.Time) types.Proposal { 200 id := e.newProposalID() 201 return types.Proposal{ 202 ID: id, 203 Reference: "ref-" + id, 204 Party: partyID, 205 State: types.ProposalStateOpen, 206 Terms: &types.ProposalTerms{ 207 ClosingTimestamp: now.Add(48 * time.Hour).Unix(), 208 EnactmentTimestamp: now.Add(2 * 48 * time.Hour).Unix(), 209 ValidationTimestamp: now.Add(1 * time.Hour).Unix(), 210 Change: newNetParamTerms(key, value), 211 }, 212 Rationale: &types.ProposalRationale{ 213 Description: "some description", 214 }, 215 } 216 }