def test(self): q = TransactionQueue() # (startgas, gasprice) pairs params = [ (100000, 81), (50000, 74), (40000, 65), (60000, 39), (30000, 50), (30000, 50), (30000, 80), ] # (maxgas, expected_startgas, expected_gasprice) triplets operations = [ (999999, 100000, 81), (999999, 30000, 80), (30000, 30000, 50), (29000, None, None), (30000, 30000, 50), (30000, None, None), (999999, 50000, 74), ] # Add transactions to queue for param in params: q.add_transaction(make_test_tx(s=param[0], g=param[1])) # Attempt pops from queue for (max_gas, expected_s, expected_g) in operations: tx = q.pop_transaction(req_nonce_getter=lambda _: 0, max_gas=max_gas) if tx: assert (tx.startgas, tx.gasprice) == (expected_s, expected_g) else: assert expected_s is expected_g is None
def test_multiple_future_tx(self): q = TransactionQueue() nonce_getter_maker = lambda i: (lambda _: i) # Future tx with increasing gas price for i in range(1, 6): q.add_transaction(make_test_tx(nonce=1, g=i)) # Expect nonce to be 0 res = q.pop_transaction(nonce_getter_maker(0)) self.assertIsNone(res) # Internal state: total tx size == 5 self.assertEqual(len(q), 5) # Add first valid tx q.add_transaction(make_test_tx(nonce=0)) res = q.pop_transaction(nonce_getter_maker(0)) self.assertIsNotNone(res) # Now verify next tx res = q.pop_transaction(nonce_getter_maker(1)) self.assertEqual(res.nonce, 1) self.assertEqual(res.gasprice, 5) # Verify internal state, still have remaining txs with nonce == 1 self.assertEqual(len(q), 4) # Stale tx will be cleaned up in the future res = q.pop_transaction(nonce_getter_maker(2)) self.assertIsNone(res) self.assertEqual(len(q), 0)
def test_diff(self): key = b"00000000000000000000000000000000" tx1 = make_test_tx(data=b"foo", nonce=1, key=key) tx2 = make_test_tx(data=b"bar") tx3 = make_test_tx(data=b"baz") tx4 = make_test_tx(data=b"foobar") tx5 = make_test_tx(data=b"foobaz", nonce=1, key=key) q1 = TransactionQueue() for tx in [tx1, tx2, tx3, tx4]: q1.add_transaction(tx) q2 = q1.diff([tx2]) assert len(q2) == 3 assert tx1 in [item.tx for item in q2.txs] assert tx3 in [item.tx for item in q2.txs] assert tx4 in [item.tx for item in q2.txs] q3 = q2.diff([tx4]) assert len(q3) == 2 assert tx1 in [item.tx for item in q3.txs] assert tx3 in [item.tx for item in q3.txs] q3.add_transaction(tx5) assert len(q3) == 3 assert tx1 in [item.tx for item in q3.txs] assert tx5 in [item.tx for item in q3.txs] q4 = q3.diff([tx5]) assert len(q4) == 1 assert tx3 in [item.tx for item in q3.txs]
def test_future_tx_higher_nonce(self): q = TransactionQueue() nonce_getter_maker = lambda i: (lambda _: i) # Expect nonce to be 0 q.add_transaction(make_test_tx(nonce=1)) res = q.pop_transaction(nonce_getter_maker(0)) self.assertIsNone(res) # Now add a current tx q.add_transaction(make_test_tx(nonce=0)) res = q.pop_transaction(nonce_getter_maker(0)) self.assertIsNotNone(res) # Now try fetching the future tx with updated nonce state res = q.pop_transaction(nonce_getter_maker(1)) self.assertIsNotNone(res)
def test_ordering_for_same_prio(self): q = TransactionQueue() count = 10 # Add <count> transactions to the queue, all with the same # startgas/gasprice but with sequential nonces. for i in range(count): q.add_transaction(make_test_tx(nonce=i)) expected_nonce_order = [i for i in range(count)] nonces = [] for i in range(count): tx = q.pop_transaction(req_nonce_getter=lambda _: i) nonces.append(tx.nonce) # Since they have the same gasprice they should have the same priority and # thus be popped in the order they were inserted. assert nonces == expected_nonce_order
def test_diff(self): tx1 = make_test_tx(data=b"foo") tx2 = make_test_tx(data=b"bar") tx3 = make_test_tx(data=b"baz") tx4 = make_test_tx(data=b"foobar") q1 = TransactionQueue() for tx in [tx1, tx2, tx3, tx4]: q1.add_transaction(tx) q2 = q1.diff([tx2]) assert len(q2) == 3 assert tx1 in [item.tx for item in q2.txs] assert tx3 in [item.tx for item in q2.txs] assert tx4 in [item.tx for item in q2.txs] q3 = q2.diff([tx4]) assert len(q3) == 2 assert tx1 in [item.tx for item in q3.txs] assert tx3 in [item.tx for item in q3.txs]
def test_discard_underpriced_tx(self): q = TransactionQueue(limit=6) # (startgas, gasprice) pairs params = [ (100000, 81), (50000, 74), (40000, 65), (60000, 39), (30000, 50), (30000, 80), ] # Add transactions to queue for param in params: q.add_transaction(make_test_tx(s=param[0], g=param[1])) prices = self._gasprices(q) self.assertListEqual(prices, [81, 80, 74, 65, 50, 39]) # Add a lower priced tx is a no-op q.add_transaction(make_test_tx(s=100000, g=38)) self.assertListEqual(self._gasprices(q), prices) # Add a higher priced tx, should be placed inside the queue q.add_transaction(make_test_tx(s=100000, g=70)) self.assertListEqual(self._gasprices(q), [81, 80, 74, 70, 65, 50])