github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/sequencer/worker_test.go (about) 1 package sequencer 2 3 import ( 4 "context" 5 "fmt" 6 "math/big" 7 "testing" 8 9 "github.com/0xPolygon/supernets2-node/state" 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 var ( 15 workerCfg = WorkerCfg{ 16 ResourceCostMultiplier: 1000, 17 } 18 ) 19 20 type workerAddTxTestCase struct { 21 name string 22 from common.Address 23 txHash common.Hash 24 nonce uint64 25 // isClaim bool 26 benefit int64 27 cost *big.Int 28 counters state.ZKCounters 29 usedBytes uint64 30 expectedEfficiencyList []common.Hash 31 } 32 33 type workerAddrQueueInfo struct { 34 from common.Address 35 nonce *big.Int 36 balance *big.Int 37 } 38 39 func processWorkerAddTxTestCases(t *testing.T, worker *Worker, testCases []workerAddTxTestCase) { 40 totalWeight := float64(worker.batchResourceWeights.WeightArithmetics + 41 worker.batchResourceWeights.WeightBatchBytesSize + worker.batchResourceWeights.WeightBinaries + 42 worker.batchResourceWeights.WeightCumulativeGasUsed + worker.batchResourceWeights.WeightKeccakHashes + 43 worker.batchResourceWeights.WeightMemAligns + worker.batchResourceWeights.WeightPoseidonHashes + 44 worker.batchResourceWeights.WeightPoseidonPaddings + worker.batchResourceWeights.WeightSteps) 45 46 for _, testCase := range testCases { 47 t.Run(testCase.name, func(t *testing.T) { 48 tx := TxTracker{} 49 50 tx.weightMultipliers = calculateWeightMultipliers(worker.batchResourceWeights, totalWeight) 51 tx.constraints = worker.batchConstraints 52 tx.resourceCostMultiplier = worker.cfg.ResourceCostMultiplier 53 tx.Hash = testCase.txHash 54 tx.HashStr = testCase.txHash.String() 55 tx.From = testCase.from 56 tx.FromStr = testCase.from.String() 57 tx.Nonce = testCase.nonce 58 tx.Benefit = new(big.Int).SetInt64(testCase.benefit) 59 tx.Cost = testCase.cost 60 tx.BatchResources.Bytes = testCase.usedBytes 61 tx.updateZKCounters(testCase.counters, worker.batchConstraints, worker.batchResourceWeights) 62 t.Logf("%s=%s", testCase.name, fmt.Sprintf("%.2f", tx.Efficiency)) 63 64 err, _ := worker.AddTxTracker(ctx, &tx) 65 if err != nil { 66 return 67 } 68 69 el := worker.efficiencyList 70 if el.len() != len(testCase.expectedEfficiencyList) { 71 t.Fatalf("Error efficiencylist.len(%d) != expectedEfficiencyList.len(%d)", el.len(), len(testCase.expectedEfficiencyList)) 72 } 73 for i := 0; i < el.len(); i++ { 74 if el.getByIndex(i).HashStr != string(testCase.expectedEfficiencyList[i].String()) { 75 t.Fatalf("Error efficiencylist(%d). Expected=%s, Actual=%s", i, testCase.expectedEfficiencyList[i].String(), el.getByIndex(i).HashStr) 76 } 77 } 78 }) 79 } 80 } 81 82 func TestWorkerAddTx(t *testing.T) { 83 var nilErr error 84 85 // Init ZKEVM resourceCostWeight values 86 rcWeigth := batchResourceWeights{} 87 rcWeigth.WeightCumulativeGasUsed = 1 88 rcWeigth.WeightArithmetics = 1 89 rcWeigth.WeightBinaries = 1 90 rcWeigth.WeightKeccakHashes = 1 91 rcWeigth.WeightMemAligns = 1 92 rcWeigth.WeightPoseidonHashes = 1 93 rcWeigth.WeightPoseidonPaddings = 1 94 rcWeigth.WeightSteps = 1 95 rcWeigth.WeightBatchBytesSize = 2 96 97 // Init ZKEVM resourceCostMax values 98 rcMax := batchConstraints{} 99 rcMax.MaxCumulativeGasUsed = 10 100 rcMax.MaxArithmetics = 10 101 rcMax.MaxBinaries = 10 102 rcMax.MaxKeccakHashes = 10 103 rcMax.MaxMemAligns = 10 104 rcMax.MaxPoseidonHashes = 10 105 rcMax.MaxPoseidonPaddings = 10 106 rcMax.MaxSteps = 10 107 rcMax.MaxBatchBytesSize = 10 108 109 stateMock := NewStateMock(t) 110 worker := initWorker(stateMock, rcMax, rcWeigth) 111 112 ctx := context.Background() 113 114 stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr) 115 116 addrQueueInfo := []workerAddrQueueInfo{ 117 {from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 118 {from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 119 {from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 120 {from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 121 } 122 123 for _, aq := range addrQueueInfo { 124 stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr) 125 stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr) 126 } 127 128 addTxsTC := []workerAddTxTestCase{ 129 { 130 name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1, 131 benefit: 1000, cost: new(big.Int).SetInt64(5), 132 counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, 133 usedBytes: 1, 134 expectedEfficiencyList: []common.Hash{ 135 {1}, 136 }, 137 }, 138 { 139 name: "Adding from:0x02, tx:0x02/ef:20", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, 140 benefit: 2000, cost: new(big.Int).SetInt64(5), 141 counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, 142 usedBytes: 1, 143 expectedEfficiencyList: []common.Hash{ 144 {2}, {1}, 145 }, 146 }, 147 { 148 name: "Readding from:0x02, tx:0x02/ef:4", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, 149 benefit: 2000, cost: new(big.Int).SetInt64(5), 150 counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, 151 usedBytes: 5, 152 expectedEfficiencyList: []common.Hash{ 153 {1}, {2}, 154 }, 155 }, 156 { 157 name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1, 158 benefit: 5000, cost: new(big.Int).SetInt64(5), 159 counters: state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2}, 160 usedBytes: 2, 161 expectedEfficiencyList: []common.Hash{ 162 {3}, {1}, {2}, 163 }, 164 }, 165 } 166 167 processWorkerAddTxTestCases(t, worker, addTxsTC) 168 169 // Change counters fpr tx:0x03/ef:9.61 170 counters := state.ZKCounters{CumulativeGasUsed: 6, UsedKeccakHashes: 6, UsedPoseidonHashes: 6, UsedPoseidonPaddings: 6, UsedMemAligns: 6, UsedArithmetics: 6, UsedBinaries: 6, UsedSteps: 6} 171 worker.UpdateTx(common.Hash{3}, common.Address{3}, counters) 172 173 addTxsTC = []workerAddTxTestCase{ 174 { 175 name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1, 176 benefit: 10000, cost: new(big.Int).SetInt64(5), 177 counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, 178 usedBytes: 1, 179 expectedEfficiencyList: []common.Hash{ 180 {4}, {1}, {3}, {2}, 181 }, 182 }, 183 } 184 185 processWorkerAddTxTestCases(t, worker, addTxsTC) 186 } 187 188 func TestWorkerGetBestTx(t *testing.T) { 189 var nilErr error 190 191 // Init ZKEVM resourceCostWeight values 192 rcWeight := batchResourceWeights{} 193 rcWeight.WeightCumulativeGasUsed = 1 194 rcWeight.WeightArithmetics = 1 195 rcWeight.WeightBinaries = 1 196 rcWeight.WeightKeccakHashes = 1 197 rcWeight.WeightMemAligns = 1 198 rcWeight.WeightPoseidonHashes = 1 199 rcWeight.WeightPoseidonPaddings = 1 200 rcWeight.WeightSteps = 1 201 rcWeight.WeightBatchBytesSize = 2 202 203 // Init ZKEVM resourceCostMax values 204 rcMax := batchConstraints{} 205 rcMax.MaxCumulativeGasUsed = 10 206 rcMax.MaxArithmetics = 10 207 rcMax.MaxBinaries = 10 208 rcMax.MaxKeccakHashes = 10 209 rcMax.MaxMemAligns = 10 210 rcMax.MaxPoseidonHashes = 10 211 rcMax.MaxPoseidonPaddings = 10 212 rcMax.MaxSteps = 10 213 rcMax.MaxBatchBytesSize = 10 214 215 rc := state.BatchResources{ 216 ZKCounters: state.ZKCounters{CumulativeGasUsed: 10, UsedKeccakHashes: 10, UsedPoseidonHashes: 10, UsedPoseidonPaddings: 10, UsedMemAligns: 10, UsedArithmetics: 10, UsedBinaries: 10, UsedSteps: 10}, 217 Bytes: 10, 218 } 219 220 stateMock := NewStateMock(t) 221 worker := initWorker(stateMock, rcMax, rcWeight) 222 223 ctx := context.Background() 224 225 stateMock.On("GetLastStateRoot", ctx, nil).Return(common.Hash{0}, nilErr) 226 227 addrQueueInfo := []workerAddrQueueInfo{ 228 {from: common.Address{1}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 229 {from: common.Address{2}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 230 {from: common.Address{3}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 231 {from: common.Address{4}, nonce: new(big.Int).SetInt64(1), balance: new(big.Int).SetInt64(10)}, 232 } 233 234 for _, aq := range addrQueueInfo { 235 stateMock.On("GetNonceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.nonce, nilErr) 236 stateMock.On("GetBalanceByStateRoot", ctx, aq.from, common.Hash{0}).Return(aq.balance, nilErr) 237 } 238 239 addTxsTC := []workerAddTxTestCase{ 240 { 241 name: "Adding from:0x01, tx:0x01/ef:10", from: common.Address{1}, txHash: common.Hash{1}, nonce: 1, 242 benefit: 1000, cost: new(big.Int).SetInt64(5), 243 counters: state.ZKCounters{CumulativeGasUsed: 1, UsedKeccakHashes: 1, UsedPoseidonHashes: 1, UsedPoseidonPaddings: 1, UsedMemAligns: 1, UsedArithmetics: 1, UsedBinaries: 1, UsedSteps: 1}, 244 usedBytes: 1, 245 expectedEfficiencyList: []common.Hash{ 246 {1}, 247 }, 248 }, 249 { 250 name: "Adding from:0x02, tx:0x02/ef:12", from: common.Address{2}, txHash: common.Hash{2}, nonce: 1, 251 benefit: 6000, cost: new(big.Int).SetInt64(5), 252 counters: state.ZKCounters{CumulativeGasUsed: 5, UsedKeccakHashes: 5, UsedPoseidonHashes: 5, UsedPoseidonPaddings: 5, UsedMemAligns: 5, UsedArithmetics: 5, UsedBinaries: 5, UsedSteps: 5}, 253 usedBytes: 5, 254 expectedEfficiencyList: []common.Hash{ 255 {2}, {1}, 256 }, 257 }, 258 { 259 name: "Readding from:0x03, tx:0x03/ef:25", from: common.Address{3}, txHash: common.Hash{3}, nonce: 1, 260 benefit: 5000, cost: new(big.Int).SetInt64(5), 261 counters: state.ZKCounters{CumulativeGasUsed: 2, UsedKeccakHashes: 2, UsedPoseidonHashes: 2, UsedPoseidonPaddings: 2, UsedMemAligns: 2, UsedArithmetics: 2, UsedBinaries: 2, UsedSteps: 2}, 262 usedBytes: 2, 263 expectedEfficiencyList: []common.Hash{ 264 {3}, {2}, {1}, 265 }, 266 }, 267 { 268 name: "Adding from:0x04, tx:0x04/ef:100", from: common.Address{4}, txHash: common.Hash{4}, nonce: 1, 269 benefit: 40000, cost: new(big.Int).SetInt64(5), 270 counters: state.ZKCounters{CumulativeGasUsed: 4, UsedKeccakHashes: 4, UsedPoseidonHashes: 4, UsedPoseidonPaddings: 4, UsedMemAligns: 4, UsedArithmetics: 4, UsedBinaries: 4, UsedSteps: 4}, 271 usedBytes: 4, 272 expectedEfficiencyList: []common.Hash{ 273 {4}, {3}, {2}, {1}, 274 }, 275 }, 276 } 277 278 processWorkerAddTxTestCases(t, worker, addTxsTC) 279 280 expectedGetBestTx := []common.Hash{{4}, {3}, {1}} 281 ct := 0 282 283 for { 284 tx := worker.GetBestFittingTx(rc) 285 if tx != nil { 286 if ct >= len(expectedGetBestTx) { 287 t.Fatalf("Error getting more best tx than expected. Expected=%d, Actual=%d", len(expectedGetBestTx), ct+1) 288 } 289 if tx.HashStr != string(expectedGetBestTx[ct].String()) { 290 t.Fatalf("Error GetBestFittingTx(%d). Expected=%s, Actual=%s", ct, expectedGetBestTx[ct].String(), tx.HashStr) 291 } 292 err := rc.Sub(tx.BatchResources) 293 assert.NoError(t, err) 294 295 touch := make(map[common.Address]*state.InfoReadWrite) 296 var newNonce uint64 = tx.Nonce + 1 297 touch[tx.From] = &state.InfoReadWrite{Address: tx.From, Nonce: &newNonce, Balance: new(big.Int).SetInt64(10)} 298 worker.UpdateAfterSingleSuccessfulTxExecution(tx.From, touch) 299 ct++ 300 } else { 301 if ct < len(expectedGetBestTx) { 302 t.Fatalf("Error expecting more best tx. Expected=%d, Actual=%d", len(expectedGetBestTx), ct) 303 } 304 break 305 } 306 } 307 } 308 309 func initWorker(stateMock *StateMock, rcMax batchConstraints, rcWeigth batchResourceWeights) *Worker { 310 worker := NewWorker(workerCfg, stateMock, rcMax, rcWeigth) 311 return worker 312 }