|
13 | 13 | import static org.mockito.ArgumentMatchers.anyList; |
14 | 14 | import static org.mockito.Mockito.doAnswer; |
15 | 15 | import static org.mockito.Mockito.mock; |
| 16 | +import static org.mockito.Mockito.verify; |
16 | 17 | import static org.mockito.Mockito.when; |
17 | 18 |
|
| 19 | +import java.util.ArrayList; |
18 | 20 | import java.util.List; |
19 | 21 | import java.util.concurrent.CountDownLatch; |
20 | 22 | import java.util.concurrent.ExecutorService; |
21 | 23 | import java.util.concurrent.Executors; |
22 | 24 | import java.util.concurrent.Future; |
23 | 25 | import java.util.concurrent.TimeUnit; |
24 | 26 | import net.consensys.linea.rpc.methods.LineaSendForcedRawTransaction.ForcedTransactionResponse; |
| 27 | +import net.consensys.linea.sequencer.forced.ForcedTransaction; |
25 | 28 | import net.consensys.linea.sequencer.forced.ForcedTransactionPoolService; |
26 | 29 | import net.consensys.linea.sequencer.forced.LineaForcedTransactionPool; |
27 | 30 | import net.consensys.linea.utils.TestTransactionFactory; |
@@ -241,6 +244,40 @@ void execute_partialSuccessWhenMiddleTransactionFails() { |
241 | 244 | assertThat(pool.pendingCount()).isEqualTo(2); |
242 | 245 | } |
243 | 246 |
|
| 247 | + @Test |
| 248 | + void execute_sortsTransactionsByForcedTransactionNumberBeforeAddingToPool() { |
| 249 | + final List<ForcedTransaction> capturedTransactions = new ArrayList<>(); |
| 250 | + final ForcedTransactionPoolService mockPool = mock(ForcedTransactionPoolService.class); |
| 251 | + doAnswer( |
| 252 | + invocation -> { |
| 253 | + capturedTransactions.addAll(invocation.getArgument(0)); |
| 254 | + return null; |
| 255 | + }) |
| 256 | + .when(mockPool) |
| 257 | + .addForcedTransactions(anyList()); |
| 258 | + |
| 259 | + final LineaSendForcedRawTransaction methodWithMock = |
| 260 | + new LineaSendForcedRawTransaction().init(mockPool); |
| 261 | + |
| 262 | + final Transaction tx1 = txFactory.createTransaction(); |
| 263 | + final Transaction tx2 = txFactory.createTransaction(); |
| 264 | + final Transaction tx3 = txFactory.createTransaction(); |
| 265 | + |
| 266 | + // Submit transactions out of order: 9, 5, 7 |
| 267 | + methodWithMock.execute( |
| 268 | + request( |
| 269 | + new ForcedTxParam(9L, TestTransactionFactory.encodeTransaction(tx1), "0x1000"), |
| 270 | + new ForcedTxParam(5L, TestTransactionFactory.encodeTransaction(tx2), "0x2000"), |
| 271 | + new ForcedTxParam(7L, TestTransactionFactory.encodeTransaction(tx3), "0x3000"))); |
| 272 | + |
| 273 | + verify(mockPool).addForcedTransactions(anyList()); |
| 274 | + assertThat(capturedTransactions).hasSize(3); |
| 275 | + // Verify they are sorted by forcedTransactionNumber: 5, 7, 9 |
| 276 | + assertThat(capturedTransactions.get(0).forcedTransactionNumber()).isEqualTo(5L); |
| 277 | + assertThat(capturedTransactions.get(1).forcedTransactionNumber()).isEqualTo(7L); |
| 278 | + assertThat(capturedTransactions.get(2).forcedTransactionNumber()).isEqualTo(9L); |
| 279 | + } |
| 280 | + |
244 | 281 | @Test |
245 | 282 | void execute_rejectsConcurrentRequests() throws Exception { |
246 | 283 | // Use a mock pool that blocks to simulate slow processing |
|
0 commit comments