code.vegaprotocol.io/vega@v0.79.0/core/processor/gastimator_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 processor_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/processor" 23 "code.vegaprotocol.io/vega/core/txn" 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/libs/num" 26 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 27 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestUpdateMaxGas(t *testing.T) { 32 eet := &ExecEngineTest{marketCounters: map[string]*types.MarketCounters{}} 33 gastimator := processor.NewGastimator(eet) 34 gastimator.OnMaxGasUpdate(context.Background(), num.NewUint(1234)) 35 require.Equal(t, uint64(1234), gastimator.GetMaxGas()) 36 } 37 38 func TestSubmitOrder(t *testing.T) { 39 tx := &testTx{ 40 command: txn.SubmitOrderCommand, 41 unmarshaller: unmarshalSubmitOrder(&commandspb.OrderSubmission{MarketId: "1"}), 42 } 43 testSubmitOrAmendOrder(t, tx) 44 } 45 46 func TestAmendOrder(t *testing.T) { 47 tx := &testTx{ 48 command: txn.AmendOrderCommand, 49 unmarshaller: unmarshalAmendtOrder(&commandspb.OrderAmendment{MarketId: "1"}), 50 } 51 testSubmitOrAmendOrder(t, tx) 52 } 53 54 func testSubmitOrAmendOrder(t *testing.T, tx *testTx) { 55 t.Helper() 56 marketCounters := map[string]*types.MarketCounters{} 57 eet := &ExecEngineTest{marketCounters: marketCounters} 58 gastimator := processor.NewGastimator(eet) 59 gastimator.OnMaxGasUpdate(context.Background(), num.NewUint(1234)) 60 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(1)) 61 gastimator.OnMinBlockCapacityUpdate(context.Background(), num.NewUint(1)) 62 63 // there's nothing yet for the market so expect default counters 64 count, err := gastimator.CalcGasWantedForTx(tx) 65 require.NoError(t, err) 66 require.Equal(t, uint64(1), count) 67 68 // change the default gas to see we get the new default 69 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(10)) 70 count, err = gastimator.CalcGasWantedForTx(tx) 71 require.NoError(t, err) 72 require.Equal(t, uint64(10), count) 73 74 // set some counters 75 marketCounters["1"] = &types.MarketCounters{ 76 PeggedOrderCounter: 1, 77 PositionCount: 2, 78 OrderbookLevelCount: 10, 79 } 80 gastimator.OnBlockEnd() 81 82 // gasOrder = network.transaction.defaultgas + peg cost factor x pegs 83 // + position factor x positions 84 // + level factor x levels 85 // gasOrder = min(maxGas-1,gasOrder) 86 // gasOrder = min(1233, 10 + 50 * 1 + 2 + 10 * 0.1) = 563 87 count, err = gastimator.CalcGasWantedForTx(tx) 88 require.NoError(t, err) 89 require.Equal(t, uint64(63), count) 90 91 // update counters such that now the max gas is lower than gas wanted for the order 92 marketCounters["1"] = &types.MarketCounters{ 93 PeggedOrderCounter: 8, 94 PositionCount: 2, 95 OrderbookLevelCount: 100, 96 } 97 98 // gasOrder = min(1233, 10 + 50 * 8 + 2 + 100 * 0.1) = 422 99 count, err = gastimator.CalcGasWantedForTx(tx) 100 require.NoError(t, err) 101 require.Equal(t, uint64(422), count) 102 } 103 104 func TestCancelOrder(t *testing.T) { 105 tx := &testTx{ 106 command: txn.CancelOrderCommand, 107 unmarshaller: unmarshalCancelOrder(&commandspb.OrderCancellation{MarketId: "1", OrderId: "1"}), 108 } 109 110 marketCounters := map[string]*types.MarketCounters{} 111 eet := &ExecEngineTest{marketCounters: marketCounters} 112 gastimator := processor.NewGastimator(eet) 113 gastimator.OnMaxGasUpdate(context.Background(), num.NewUint(1234)) 114 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(1)) 115 gastimator.OnMinBlockCapacityUpdate(context.Background(), num.NewUint(1)) 116 117 // there's nothing yet for the market so expect default counters 118 count, err := gastimator.CalcGasWantedForTx(tx) 119 require.NoError(t, err) 120 require.Equal(t, uint64(1), count) 121 122 // change the default gas to see we get the new default 123 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(10)) 124 count, err = gastimator.CalcGasWantedForTx(tx) 125 require.NoError(t, err) 126 require.Equal(t, uint64(10), count) 127 128 // set some counters 129 marketCounters["1"] = &types.MarketCounters{ 130 PeggedOrderCounter: 1, 131 PositionCount: 2, 132 OrderbookLevelCount: 10, 133 } 134 gastimator.OnBlockEnd() 135 136 // gasCancel = network.transaction.defaultgas + peg cost factor x pegs 137 // + level factor x levels 138 // gasCancel = min(maxGas-1,gasCancel) 139 // gasOrder = min(1233, 10 + 50 * 1 + 10 * 0.1) = 561 140 count, err = gastimator.CalcGasWantedForTx(tx) 141 require.NoError(t, err) 142 require.Equal(t, uint64(61), count) 143 144 // update counters such that now the max gas is lower than gasCancel 145 marketCounters["1"] = &types.MarketCounters{ 146 PeggedOrderCounter: 8, 147 PositionCount: 2, 148 OrderbookLevelCount: 100, 149 } 150 151 // gasOrder = min(1233, 10 + 50 * 8 + 100 * 0.1) = 420 152 count, err = gastimator.CalcGasWantedForTx(tx) 153 require.NoError(t, err) 154 require.Equal(t, uint64(420), count) 155 } 156 157 func TestBatch(t *testing.T) { 158 tx := &testTx{ 159 command: txn.BatchMarketInstructions, 160 unmarshaller: unmarshalBatch(&commandspb.BatchMarketInstructions{ 161 Submissions: []*commandspb.OrderSubmission{{MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}}, 162 Cancellations: []*commandspb.OrderCancellation{{MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}}, 163 Amendments: []*commandspb.OrderAmendment{{MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}, {MarketId: "1"}}, 164 }, 165 ), 166 } 167 168 marketCounters := map[string]*types.MarketCounters{} 169 eet := &ExecEngineTest{marketCounters: marketCounters} 170 gastimator := processor.NewGastimator(eet) 171 gastimator.OnMaxGasUpdate(context.Background(), num.NewUint(10000)) 172 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(1)) 173 gastimator.OnMinBlockCapacityUpdate(context.Background(), num.NewUint(1)) 174 175 // there's nothing yet for any market so expect defaultgas * 3 + 4 * defaultgas = 7 * defaultgas 176 count, err := gastimator.CalcGasWantedForTx(tx) 177 require.NoError(t, err) 178 require.Equal(t, uint64(7), count) 179 180 // change the default gas to see we get the new default 181 // defaultGas + 0.5 * 2 * defaultGas + 182 // defaultGas + 2 * defaultGas + 183 // defaultGas + 1.5 * defaultGas = 75 184 gastimator.OnDefaultGasUpdate(context.Background(), num.NewUint(10)) 185 count, err = gastimator.CalcGasWantedForTx(tx) 186 require.NoError(t, err) 187 require.Equal(t, uint64(75), count) 188 189 // set some counters 190 marketCounters["1"] = &types.MarketCounters{ 191 PeggedOrderCounter: 1, 192 PositionCount: 2, 193 OrderbookLevelCount: 10, 194 } 195 196 gastimator.OnBlockEnd() 197 198 // we have 3 submissions, 5 cancellations and 4 amendments 199 count, err = gastimator.CalcGasWantedForTx(tx) 200 require.NoError(t, err) 201 require.Equal(t, uint64(466), count) 202 203 // update counters such that now the max gas is lower than gasCancel 204 marketCounters["1"] = &types.MarketCounters{ 205 PeggedOrderCounter: 8, 206 PositionCount: 2, 207 OrderbookLevelCount: 100, 208 } 209 210 count, err = gastimator.CalcGasWantedForTx(tx) 211 require.NoError(t, err) 212 require.Equal(t, uint64(3159), count) 213 } 214 215 func TestGetPriority(t *testing.T) { 216 command := []txn.Command{ 217 txn.SubmitOrderCommand, 218 txn.CancelOrderCommand, 219 txn.AmendOrderCommand, 220 txn.WithdrawCommand, 221 txn.ProposeCommand, 222 txn.BatchProposeCommand, 223 txn.VoteCommand, 224 txn.AnnounceNodeCommand, 225 txn.NodeVoteCommand, 226 txn.NodeSignatureCommand, 227 txn.LiquidityProvisionCommand, 228 txn.CancelLiquidityProvisionCommand, 229 txn.AmendLiquidityProvisionCommand, 230 txn.ChainEventCommand, 231 txn.SubmitOracleDataCommand, 232 txn.DelegateCommand, 233 txn.UndelegateCommand, 234 txn.RotateKeySubmissionCommand, 235 txn.StateVariableProposalCommand, 236 txn.TransferFundsCommand, 237 txn.CancelTransferFundsCommand, 238 txn.ValidatorHeartbeatCommand, 239 txn.RotateEthereumKeySubmissionCommand, 240 txn.ProtocolUpgradeCommand, 241 txn.IssueSignatures, 242 txn.BatchMarketInstructions, 243 } 244 marketCounters := map[string]*types.MarketCounters{} 245 eet := &ExecEngineTest{marketCounters: marketCounters} 246 gastimator := processor.NewGastimator(eet) 247 for _, c := range command { 248 expected := uint64(1) 249 if c.IsValidatorCommand() { 250 expected = uint64(10000) 251 } else if c == txn.ProposeCommand || c == txn.VoteCommand || c == txn.BatchProposeCommand { 252 expected = uint64(100) 253 } 254 require.Equal(t, expected, gastimator.GetPriority(&testTx{command: c}), c) 255 } 256 } 257 258 type ExecEngineTest struct { 259 marketCounters map[string]*types.MarketCounters 260 } 261 262 func (eet *ExecEngineTest) GetMarketCounters() map[string]*types.MarketCounters { 263 return eet.marketCounters 264 } 265 266 func unmarshalBatch(batch *commandspb.BatchMarketInstructions) func(interface{}) error { 267 return func(i interface{}) error { 268 underlyingCmd, _ := i.(*commandspb.BatchMarketInstructions) 269 *underlyingCmd = *batch 270 return nil 271 } 272 } 273 274 func unmarshalSubmitOrder(order *commandspb.OrderSubmission) func(interface{}) error { 275 return func(i interface{}) error { 276 underlyingCmd, _ := i.(*commandspb.OrderSubmission) 277 *underlyingCmd = *order 278 return nil 279 } 280 } 281 282 func unmarshalAmendtOrder(order *commandspb.OrderAmendment) func(interface{}) error { 283 return func(i interface{}) error { 284 underlyingCmd, _ := i.(*commandspb.OrderAmendment) 285 *underlyingCmd = *order 286 return nil 287 } 288 } 289 290 func unmarshalCancelOrder(order *commandspb.OrderCancellation) func(interface{}) error { 291 return func(i interface{}) error { 292 underlyingCmd, _ := i.(*commandspb.OrderCancellation) 293 *underlyingCmd = *order 294 return nil 295 } 296 } 297 298 type testTx struct { 299 command txn.Command 300 unmarshaller func(interface{}) error 301 } 302 303 func (tx *testTx) GetLength() int { return 0 } 304 func (tx *testTx) Unmarshal(i interface{}) error { return tx.unmarshaller(i) } 305 func (tx *testTx) GetPoWTID() string { return "" } 306 func (tx *testTx) GetVersion() uint32 { return 2 } 307 func (tx *testTx) GetPoWNonce() uint64 { return 0 } 308 func (tx *testTx) GetNonce() uint64 { return 0 } 309 func (tx *testTx) Signature() []byte { return []byte{} } 310 func (tx *testTx) Payload() []byte { return nil } 311 func (tx *testTx) PubKey() []byte { return []byte{} } 312 func (tx *testTx) PubKeyHex() string { return "" } 313 func (tx *testTx) Party() string { return "" } 314 func (tx *testTx) Hash() []byte { return []byte{} } 315 func (tx *testTx) Command() txn.Command { return tx.command } 316 func (tx *testTx) BlockHeight() uint64 { return 0 } 317 func (tx *testTx) GetCmd() interface{} { return nil }