@@ -119,31 +119,10 @@ where
119
119
120
120
let base_fee = block_builder. header ( ) . base_fee ;
121
121
let comparator: Box < MineOrderComparator > = match mine_ordering {
122
- MineOrdering :: Fifo => Box :: new ( |lhs, rhs| lhs. order_id ( ) . cmp ( & rhs. order_id ( ) ) ) ,
123
- MineOrdering :: Priority => Box :: new ( move |lhs, rhs| {
124
- let effective_miner_fee = |transaction : & ExecutableTransaction | {
125
- let max_fee_per_gas = transaction. gas_price ( ) ;
126
- let max_priority_fee_per_gas = transaction
127
- . max_priority_fee_per_gas ( )
128
- . unwrap_or ( max_fee_per_gas) ;
129
-
130
- base_fee. map_or ( max_fee_per_gas, |base_fee| {
131
- max_priority_fee_per_gas. min ( max_fee_per_gas - base_fee)
132
- } )
133
- } ;
134
-
135
- // Invert lhs and rhs to get decreasing order by effective miner fee
136
- let ordering =
137
- effective_miner_fee ( rhs. pending ( ) ) . cmp ( & effective_miner_fee ( lhs. pending ( ) ) ) ;
138
-
139
- // If two txs have the same effective miner fee we want to sort them
140
- // in increasing order by orderId
141
- if ordering == Ordering :: Equal {
142
- lhs. order_id ( ) . cmp ( & rhs. order_id ( ) )
143
- } else {
144
- ordering
145
- }
146
- } ) ,
122
+ MineOrdering :: Fifo => Box :: new ( first_in_first_out_comparator) ,
123
+ MineOrdering :: Priority => {
124
+ Box :: new ( move |lhs, rhs| priority_comparator ( lhs, rhs, base_fee) )
125
+ }
147
126
} ;
148
127
149
128
mem_pool. iter ( comparator)
@@ -199,3 +178,277 @@ where
199
178
transaction_traces : traces,
200
179
} )
201
180
}
181
+
182
+ fn effective_miner_fee ( transaction : & ExecutableTransaction , base_fee : Option < U256 > ) -> U256 {
183
+ let max_fee_per_gas = transaction. gas_price ( ) ;
184
+ let max_priority_fee_per_gas = transaction
185
+ . max_priority_fee_per_gas ( )
186
+ . unwrap_or ( max_fee_per_gas) ;
187
+
188
+ base_fee. map_or ( max_fee_per_gas, |base_fee| {
189
+ max_priority_fee_per_gas. min ( max_fee_per_gas - base_fee)
190
+ } )
191
+ }
192
+
193
+ fn first_in_first_out_comparator ( lhs : & OrderedTransaction , rhs : & OrderedTransaction ) -> Ordering {
194
+ lhs. order_id ( ) . cmp ( & rhs. order_id ( ) )
195
+ }
196
+
197
+ fn priority_comparator (
198
+ lhs : & OrderedTransaction ,
199
+ rhs : & OrderedTransaction ,
200
+ base_fee : Option < U256 > ,
201
+ ) -> Ordering {
202
+ let effective_miner_fee =
203
+ move |transaction : & ExecutableTransaction | effective_miner_fee ( transaction, base_fee) ;
204
+
205
+ // Invert lhs and rhs to get decreasing order by effective miner fee
206
+ let ordering = effective_miner_fee ( rhs. pending ( ) ) . cmp ( & effective_miner_fee ( lhs. pending ( ) ) ) ;
207
+
208
+ // If two txs have the same effective miner fee we want to sort them
209
+ // in increasing order by orderId
210
+ if ordering == Ordering :: Equal {
211
+ lhs. order_id ( ) . cmp ( & rhs. order_id ( ) )
212
+ } else {
213
+ ordering
214
+ }
215
+ }
216
+
217
+ #[ cfg( test) ]
218
+ mod tests {
219
+ use edr_eth:: { AccountInfo , Address } ;
220
+
221
+ use super :: * ;
222
+ use crate :: test_utils:: {
223
+ dummy_eip1559_transaction, dummy_eip155_transaction_with_price, MemPoolTestFixture ,
224
+ } ;
225
+
226
+ #[ test]
227
+ fn fifo_ordering ( ) -> anyhow:: Result < ( ) > {
228
+ let sender1 = Address :: random ( ) ;
229
+ let sender2 = Address :: random ( ) ;
230
+ let sender3 = Address :: random ( ) ;
231
+
232
+ let account_with_balance = AccountInfo {
233
+ balance : U256 :: from ( 100_000_000u64 ) ,
234
+ ..AccountInfo :: default ( )
235
+ } ;
236
+ let mut fixture = MemPoolTestFixture :: with_accounts ( & [
237
+ ( sender1, account_with_balance. clone ( ) ) ,
238
+ ( sender2, account_with_balance. clone ( ) ) ,
239
+ ( sender3, account_with_balance) ,
240
+ ] ) ;
241
+
242
+ let base_fee = Some ( U256 :: from ( 15 ) ) ;
243
+
244
+ let transaction1 = dummy_eip155_transaction_with_price ( sender1, 0 , U256 :: from ( 111 ) ) ?;
245
+ assert_eq ! ( effective_miner_fee( & transaction1, base_fee) , U256 :: from( 96 ) ) ;
246
+ fixture. add_transaction ( transaction1. clone ( ) ) ?;
247
+
248
+ let transaction2 = dummy_eip1559_transaction ( sender2, 0 , U256 :: from ( 120 ) , U256 :: from ( 100 ) ) ?;
249
+ assert_eq ! (
250
+ effective_miner_fee( & transaction2, base_fee) ,
251
+ U256 :: from( 100 )
252
+ ) ;
253
+ fixture. add_transaction ( transaction2. clone ( ) ) ?;
254
+
255
+ let transaction3 = dummy_eip1559_transaction ( sender3, 0 , U256 :: from ( 140 ) , U256 :: from ( 110 ) ) ?;
256
+ assert_eq ! (
257
+ effective_miner_fee( & transaction3, base_fee) ,
258
+ U256 :: from( 110 )
259
+ ) ;
260
+ fixture. add_transaction ( transaction3. clone ( ) ) ?;
261
+
262
+ let mut ordered_transactions = fixture. mem_pool . iter ( first_in_first_out_comparator) ;
263
+
264
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction1) ) ;
265
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction2) ) ;
266
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction3) ) ;
267
+
268
+ Ok ( ( ) )
269
+ }
270
+
271
+ #[ test]
272
+ fn priority_ordering_gas_price_without_base_fee ( ) -> anyhow:: Result < ( ) > {
273
+ let sender1 = Address :: random ( ) ;
274
+ let sender2 = Address :: random ( ) ;
275
+ let sender3 = Address :: random ( ) ;
276
+ let sender4 = Address :: random ( ) ;
277
+
278
+ let account_with_balance = AccountInfo {
279
+ balance : U256 :: from ( 100_000_000u64 ) ,
280
+ ..AccountInfo :: default ( )
281
+ } ;
282
+ let mut fixture = MemPoolTestFixture :: with_accounts ( & [
283
+ ( sender1, account_with_balance. clone ( ) ) ,
284
+ ( sender2, account_with_balance. clone ( ) ) ,
285
+ ( sender3, account_with_balance. clone ( ) ) ,
286
+ ( sender4, account_with_balance) ,
287
+ ] ) ;
288
+
289
+ let transaction1 = dummy_eip155_transaction_with_price ( sender1, 0 , U256 :: from ( 123 ) ) ?;
290
+ fixture. add_transaction ( transaction1. clone ( ) ) ?;
291
+
292
+ let transaction2 = dummy_eip155_transaction_with_price ( sender2, 0 , U256 :: from ( 1_000 ) ) ?;
293
+ fixture. add_transaction ( transaction2. clone ( ) ) ?;
294
+
295
+ // This has the same gasPrice than tx2, but arrived later, so it's placed later
296
+ // in the queue
297
+ let transaction3 = dummy_eip155_transaction_with_price ( sender3, 0 , U256 :: from ( 1_000 ) ) ?;
298
+ fixture. add_transaction ( transaction3. clone ( ) ) ?;
299
+
300
+ let transaction4 = dummy_eip155_transaction_with_price ( sender4, 0 , U256 :: from ( 2_000 ) ) ?;
301
+ fixture. add_transaction ( transaction4. clone ( ) ) ?;
302
+
303
+ let mut ordered_transactions = fixture
304
+ . mem_pool
305
+ . iter ( |lhs, rhs| priority_comparator ( lhs, rhs, None ) ) ;
306
+
307
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction4) ) ;
308
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction2) ) ;
309
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction3) ) ;
310
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction1) ) ;
311
+
312
+ Ok ( ( ) )
313
+ }
314
+
315
+ #[ test]
316
+ fn priority_ordering_gas_price_with_base_fee ( ) -> anyhow:: Result < ( ) > {
317
+ let sender1 = Address :: random ( ) ;
318
+ let sender2 = Address :: random ( ) ;
319
+ let sender3 = Address :: random ( ) ;
320
+ let sender4 = Address :: random ( ) ;
321
+ let sender5 = Address :: random ( ) ;
322
+
323
+ let account_with_balance = AccountInfo {
324
+ balance : U256 :: from ( 100_000_000u64 ) ,
325
+ ..AccountInfo :: default ( )
326
+ } ;
327
+ let mut fixture = MemPoolTestFixture :: with_accounts ( & [
328
+ ( sender1, account_with_balance. clone ( ) ) ,
329
+ ( sender2, account_with_balance. clone ( ) ) ,
330
+ ( sender3, account_with_balance. clone ( ) ) ,
331
+ ( sender4, account_with_balance. clone ( ) ) ,
332
+ ( sender5, account_with_balance) ,
333
+ ] ) ;
334
+
335
+ let base_fee = Some ( U256 :: from ( 15 ) ) ;
336
+
337
+ let transaction1 = dummy_eip155_transaction_with_price ( sender1, 0 , U256 :: from ( 111 ) ) ?;
338
+ assert_eq ! ( effective_miner_fee( & transaction1, base_fee) , U256 :: from( 96 ) ) ;
339
+ fixture. add_transaction ( transaction1. clone ( ) ) ?;
340
+
341
+ let transaction2 = dummy_eip1559_transaction ( sender2, 0 , U256 :: from ( 120 ) , U256 :: from ( 100 ) ) ?;
342
+ assert_eq ! (
343
+ effective_miner_fee( & transaction2, base_fee) ,
344
+ U256 :: from( 100 )
345
+ ) ;
346
+ fixture. add_transaction ( transaction2. clone ( ) ) ?;
347
+
348
+ let transaction3 = dummy_eip1559_transaction ( sender3, 0 , U256 :: from ( 140 ) , U256 :: from ( 110 ) ) ?;
349
+ assert_eq ! (
350
+ effective_miner_fee( & transaction3, base_fee) ,
351
+ U256 :: from( 110 )
352
+ ) ;
353
+ fixture. add_transaction ( transaction3. clone ( ) ) ?;
354
+
355
+ let transaction4 = dummy_eip1559_transaction ( sender4, 0 , U256 :: from ( 140 ) , U256 :: from ( 130 ) ) ?;
356
+ assert_eq ! (
357
+ effective_miner_fee( & transaction4, base_fee) ,
358
+ U256 :: from( 125 )
359
+ ) ;
360
+ fixture. add_transaction ( transaction4. clone ( ) ) ?;
361
+
362
+ let transaction5 = dummy_eip155_transaction_with_price ( sender5, 0 , U256 :: from ( 170 ) ) ?;
363
+ assert_eq ! (
364
+ effective_miner_fee( & transaction5, base_fee) ,
365
+ U256 :: from( 155 )
366
+ ) ;
367
+ fixture. add_transaction ( transaction5. clone ( ) ) ?;
368
+
369
+ let mut ordered_transactions = fixture
370
+ . mem_pool
371
+ . iter ( |lhs, rhs| priority_comparator ( lhs, rhs, base_fee) ) ;
372
+
373
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction5) ) ;
374
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction4) ) ;
375
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction3) ) ;
376
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction2) ) ;
377
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction1) ) ;
378
+
379
+ Ok ( ( ) )
380
+ }
381
+
382
+ #[ test]
383
+ fn ordering_remove_caller ( ) -> anyhow:: Result < ( ) > {
384
+ let sender1 = Address :: random ( ) ;
385
+ let sender2 = Address :: random ( ) ;
386
+ let sender3 = Address :: random ( ) ;
387
+ let sender4 = Address :: random ( ) ;
388
+
389
+ let account_with_balance = AccountInfo {
390
+ balance : U256 :: from ( 100_000_000u64 ) ,
391
+ ..AccountInfo :: default ( )
392
+ } ;
393
+ let mut fixture = MemPoolTestFixture :: with_accounts ( & [
394
+ ( sender1, account_with_balance. clone ( ) ) ,
395
+ ( sender2, account_with_balance. clone ( ) ) ,
396
+ ( sender3, account_with_balance. clone ( ) ) ,
397
+ ( sender4, account_with_balance) ,
398
+ ] ) ;
399
+
400
+ // Insert 9 transactions sequentially (no for loop)
401
+ let transaction1 = dummy_eip155_transaction_with_price ( sender1, 0 , U256 :: from ( 100 ) ) ?;
402
+ fixture. add_transaction ( transaction1. clone ( ) ) ?;
403
+
404
+ let transaction2 = dummy_eip155_transaction_with_price ( sender1, 1 , U256 :: from ( 99 ) ) ?;
405
+ fixture. add_transaction ( transaction2. clone ( ) ) ?;
406
+
407
+ let transaction3 = dummy_eip155_transaction_with_price ( sender2, 0 , U256 :: from ( 98 ) ) ?;
408
+ fixture. add_transaction ( transaction3. clone ( ) ) ?;
409
+
410
+ let transaction4 = dummy_eip155_transaction_with_price ( sender2, 1 , U256 :: from ( 97 ) ) ?;
411
+ fixture. add_transaction ( transaction4. clone ( ) ) ?;
412
+
413
+ let transaction5 = dummy_eip155_transaction_with_price ( sender3, 0 , U256 :: from ( 96 ) ) ?;
414
+ fixture. add_transaction ( transaction5. clone ( ) ) ?;
415
+
416
+ let transaction6 = dummy_eip155_transaction_with_price ( sender3, 1 , U256 :: from ( 95 ) ) ?;
417
+ fixture. add_transaction ( transaction6. clone ( ) ) ?;
418
+
419
+ let transaction7 = dummy_eip155_transaction_with_price ( sender3, 2 , U256 :: from ( 94 ) ) ?;
420
+ fixture. add_transaction ( transaction7. clone ( ) ) ?;
421
+
422
+ let transaction8 = dummy_eip155_transaction_with_price ( sender3, 3 , U256 :: from ( 93 ) ) ?;
423
+ fixture. add_transaction ( transaction8. clone ( ) ) ?;
424
+
425
+ let transaction9 = dummy_eip155_transaction_with_price ( sender4, 0 , U256 :: from ( 92 ) ) ?;
426
+ fixture. add_transaction ( transaction9. clone ( ) ) ?;
427
+
428
+ let transaction10 = dummy_eip155_transaction_with_price ( sender4, 1 , U256 :: from ( 91 ) ) ?;
429
+ fixture. add_transaction ( transaction10. clone ( ) ) ?;
430
+
431
+ let mut ordered_transactions = fixture
432
+ . mem_pool
433
+ . iter ( |lhs, rhs| priority_comparator ( lhs, rhs, None ) ) ;
434
+
435
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction1) ) ;
436
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction2) ) ;
437
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction3) ) ;
438
+
439
+ // Remove all transactions for sender 2
440
+ ordered_transactions. remove_caller ( & sender2) ;
441
+
442
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction5) ) ;
443
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction6) ) ;
444
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction7) ) ;
445
+
446
+ // Remove all transactions for sender 3
447
+ ordered_transactions. remove_caller ( & sender3) ;
448
+
449
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction9) ) ;
450
+ assert_eq ! ( ordered_transactions. next( ) , Some ( transaction10) ) ;
451
+
452
+ Ok ( ( ) )
453
+ }
454
+ }
0 commit comments