@@ -26,7 +26,15 @@ use starknet_api::test_utils::invoke::internal_invoke_tx;
2626use starknet_api:: test_utils:: valid_resource_bounds_for_testing;
2727use starknet_api:: transaction:: fields:: TransactionSignature ;
2828use starknet_api:: transaction:: TransactionHash ;
29- use starknet_api:: { contract_address, declare_tx_args, felt, invoke_tx_args, nonce, tx_hash} ;
29+ use starknet_api:: {
30+ contract_address,
31+ declare_tx_args,
32+ felt,
33+ invoke_tx_args,
34+ nonce,
35+ proof_facts,
36+ tx_hash,
37+ } ;
3038
3139use super :: DelayedQueues ;
3240use crate :: communication:: MempoolCommunicationWrapper ;
@@ -45,6 +53,7 @@ use crate::test_utils::{
4553 commit_block,
4654 declare_add_tx_input,
4755 get_txs_and_assert_expected,
56+ proof_tx_add_tx_input,
4857 validate_tx,
4958 validate_tx_expect_error,
5059 MempoolMetrics ,
@@ -150,7 +159,10 @@ impl MempoolTestContentBuilder {
150159 fn build_full_mempool ( self ) -> Mempool {
151160 Mempool {
152161 config : self . config . clone ( ) ,
153- delayed_queues : DelayedQueues :: new ( self . config . static_config . declare_delay ) ,
162+ delayed_queues : DelayedQueues :: new (
163+ self . config . static_config . declare_delay ,
164+ self . config . static_config . proof_tx_delay ,
165+ ) ,
154166 tx_pool : self . content . tx_pool . unwrap_or_default ( ) . into_values ( ) . collect ( ) ,
155167 tx_queue : Box :: new ( FeeTransactionQueue :: new (
156168 self . content . priority_txs . unwrap_or_default ( ) ,
@@ -1220,9 +1232,10 @@ fn metrics_correctness() {
12201232 // invoke_6 | 5 | Pending queue
12211233 // declare_1 | 6 | Priority queue
12221234 // declare_2 | 7 | Delayed declare
1223- // invoke_7 | 8 | Evicted
1224- // invoke_8 | 9 | Pending queue
1225- // invoke_9 | 10 | Committed
1235+ // proof_1 | 8 | Delayed invoke with proof
1236+ // invoke_7 | 9 | Evicted
1237+ // invoke_8 | 10 | Pending queue
1238+ // invoke_9 | 11 | Committed
12261239
12271240 let invoke_1 = add_tx_input ! ( tx_hash: 1 , address: "0x0" , tx_nonce: 0 , account_nonce: 0 ) ;
12281241 let invoke_2 = add_tx_input ! ( tx_hash: 2 , address: "0x1" , tx_nonce: 0 , account_nonce: 0 ) ;
@@ -1237,8 +1250,14 @@ fn metrics_correctness() {
12371250 let declare_2 = declare_add_tx_input (
12381251 declare_tx_args ! ( resource_bounds: valid_resource_bounds_for_testing( ) , sender_address: contract_address!( "0x6" ) , tx_hash: tx_hash!( 7 ) ) ,
12391252 ) ;
1240- let invoke_7 = add_tx_input ! ( tx_hash: 8 , address: "0x7" , tx_nonce: 1 , account_nonce: 0 ) ;
1241- let invoke_8 = add_tx_input ! ( tx_hash: 9 , address: "0x8" , tx_nonce: 0 , account_nonce: 0 ) ;
1253+ let proof_1 = proof_tx_add_tx_input ( invoke_tx_args ! (
1254+ resource_bounds: valid_resource_bounds_for_testing( ) ,
1255+ sender_address: contract_address!( "0x7" ) ,
1256+ tx_hash: tx_hash!( 8 ) ,
1257+ proof_facts: proof_facts![ felt!( "0x1" ) ]
1258+ ) ) ;
1259+ let invoke_7 = add_tx_input ! ( tx_hash: 9 , address: "0x8" , tx_nonce: 1 , account_nonce: 0 ) ;
1260+ let invoke_8 = add_tx_input ! ( tx_hash: 10 , address: "0x9" , tx_nonce: 0 , account_nonce: 0 ) ;
12421261
12431262 // Add invoke_1 and advance the clock so that it will be expired.
12441263 add_tx ( & mut mempool, & invoke_1) ;
@@ -1266,6 +1285,7 @@ fn metrics_correctness() {
12661285 // another declare tx, that would be delayed.
12671286 fake_clock. advance ( mempool. config . static_config . declare_delay + Duration :: from_secs ( 1 ) ) ;
12681287 add_tx ( & mut mempool, & declare_2) ;
1288+ add_tx ( & mut mempool, & proof_1) ;
12691289
12701290 // Request 1 transaction from the mempool, so that we have a staged transaction. (The staged
12711291 // tx should be invoke_5, since it is in the priority queue and has the highest tip.)
@@ -1280,19 +1300,19 @@ fn metrics_correctness() {
12801300 add_tx ( & mut mempool, & invoke_8) ;
12811301
12821302 // Add a long-delayed transaction to test time spent until committed.
1283- let invoke_9 = add_tx_input ! ( tx_hash: 10 , address: "0x9 " , tx_nonce: 0 , account_nonce: 0 ) ;
1303+ let invoke_9 = add_tx_input ! ( tx_hash: 11 , address: "0xa " , tx_nonce: 0 , account_nonce: 0 ) ;
12841304 mempool. config . static_config . capacity_in_bytes =
12851305 mempool. size_in_bytes ( ) + invoke_9. tx . total_bytes ( ) ;
12861306 add_tx ( & mut mempool, & invoke_9) ;
12871307 fake_clock. advance ( Duration :: from_secs ( 20 ) ) ;
1288- commit_block ( & mut mempool, [ ( "0x9 " , 1 ) , ( "0x3" , 1 ) ] , [ ] ) ;
1308+ commit_block ( & mut mempool, [ ( "0xa " , 1 ) , ( "0x3" , 1 ) ] , [ ] ) ;
12891309
12901310 let mut metrics = MempoolMetrics :: from_recorder ( & recorder) ;
12911311 metrics. transaction_time_spent_until_batched . histogram = Default :: default ( ) ;
12921312 metrics. transaction_time_spent_until_committed . histogram = Default :: default ( ) ;
12931313 expect ! [ [ r#"
12941314 MempoolMetrics {
1295- txs_received_invoke: 8 ,
1315+ txs_received_invoke: 9 ,
12961316 txs_received_declare: 2,
12971317 txs_received_deploy_account: 0,
12981318 txs_committed: 3,
@@ -1304,7 +1324,8 @@ fn metrics_correctness() {
13041324 pending_queue_size: 1,
13051325 get_txs_size: 1,
13061326 delayed_declares_size: 1,
1307- total_size_in_bytes: 1600,
1327+ delayed_proof_txs_size: 1,
1328+ total_size_in_bytes: 2056,
13081329 transaction_time_spent_until_batched: HistogramValue {
13091330 sum: 2.0,
13101331 count: 1,
@@ -1354,80 +1375,97 @@ fn expired_staged_txs_are_not_deleted() {
13541375 expected_mempool_content. assert_eq ( & mempool. content ( ) ) ;
13551376}
13561377
1378+ // Helpers for parameterized delayed tx tests.
1379+
1380+ fn make_delayed_declare ( addr : & str , hash : u64 ) -> AddTransactionArgs {
1381+ declare_add_tx_input ( declare_tx_args ! (
1382+ resource_bounds: valid_resource_bounds_for_testing( ) ,
1383+ sender_address: contract_address!( addr) ,
1384+ tx_hash: tx_hash!( hash)
1385+ ) )
1386+ }
1387+
1388+ fn make_delayed_proof_tx ( addr : & str , hash : u64 ) -> AddTransactionArgs {
1389+ proof_tx_add_tx_input ( invoke_tx_args ! (
1390+ resource_bounds: valid_resource_bounds_for_testing( ) ,
1391+ sender_address: contract_address!( addr) ,
1392+ tx_hash: tx_hash!( hash) ,
1393+ proof_facts: proof_facts![ felt!( "0x1" ) ]
1394+ ) )
1395+ }
1396+
1397+ fn declare_delay_config ( delay_secs : u64 ) -> MempoolStaticConfig {
1398+ MempoolStaticConfig { declare_delay : Duration :: from_secs ( delay_secs) , ..Default :: default ( ) }
1399+ }
1400+
1401+ fn proof_tx_delay_config ( delay_secs : u64 ) -> MempoolStaticConfig {
1402+ MempoolStaticConfig { proof_tx_delay : Duration :: from_secs ( delay_secs) , ..Default :: default ( ) }
1403+ }
1404+
13571405#[ rstest]
1358- fn delay_declare_txs ( ) {
1359- // Create a mempool with a fake clock.
1406+ #[ case:: declare( make_delayed_declare, declare_delay_config( 5 ) ) ]
1407+ #[ case:: proof_tx( make_delayed_proof_tx, proof_tx_delay_config( 5 ) ) ]
1408+ fn delay_txs (
1409+ #[ case] make_delayed_tx : fn ( & str , u64 ) -> AddTransactionArgs ,
1410+ #[ case] static_config : MempoolStaticConfig ,
1411+ ) {
13601412 let fake_clock = Arc :: new ( FakeClock :: default ( ) ) ;
1361- let declare_delay = Duration :: from_secs ( 5 ) ;
1362- let mut mempool = Mempool :: new (
1363- MempoolConfig {
1364- static_config : MempoolStaticConfig { declare_delay, ..Default :: default ( ) } ,
1365- ..Default :: default ( )
1366- } ,
1367- fake_clock. clone ( ) ,
1368- ) ;
1369- let first_declare = declare_add_tx_input (
1370- declare_tx_args ! ( resource_bounds: valid_resource_bounds_for_testing( ) , sender_address: contract_address!( "0x0" ) , tx_hash: tx_hash!( 0 ) ) ,
1371- ) ;
1372- add_tx ( & mut mempool, & first_declare) ;
1413+ let delay = Duration :: from_secs ( 5 ) ;
1414+ let mut mempool =
1415+ Mempool :: new ( MempoolConfig { static_config, ..Default :: default ( ) } , fake_clock. clone ( ) ) ;
1416+ let first_delayed = make_delayed_tx ( "0x0" , 0 ) ;
1417+ add_tx ( & mut mempool, & first_delayed) ;
13731418
13741419 fake_clock. advance ( Duration :: from_secs ( 1 ) ) ;
1375- let second_declare = declare_add_tx_input (
1376- declare_tx_args ! ( resource_bounds: valid_resource_bounds_for_testing( ) , sender_address: contract_address!( "0x1" ) , tx_hash: tx_hash!( 1 ) ) ,
1377- ) ;
1378- add_tx ( & mut mempool, & second_declare) ;
1420+ let second_delayed = make_delayed_tx ( "0x1" , 1 ) ;
1421+ add_tx ( & mut mempool, & second_delayed) ;
13791422
13801423 assert_eq ! ( mempool. get_txs( 2 ) . unwrap( ) , vec![ ] ) ;
13811424
1382- // Complete the first declare 's delay.
1383- fake_clock. advance ( declare_delay - Duration :: from_secs ( 1 ) ) ;
1425+ // Complete the first delayed tx 's delay.
1426+ fake_clock. advance ( delay - Duration :: from_secs ( 1 ) ) ;
13841427 // Add another transaction to trigger draining of ready delayed txs.
13851428 let another_tx_1 =
13861429 add_tx_input ! ( tx_hash: 123 , address: "0x123" , tx_nonce: 123 , account_nonce: 0 , tip: 123 ) ;
13871430 add_tx ( & mut mempool, & another_tx_1) ;
13881431
1389- // Assert only the first declare is in the mempool.
1390- assert_eq ! ( mempool. get_txs( 2 ) . unwrap( ) , vec![ first_declare. tx] ) ;
1432+ assert_eq ! ( mempool. get_txs( 2 ) . unwrap( ) , vec![ first_delayed. tx] ) ;
13911433
1392- // Complete the second declare 's delay.
1434+ // Complete the second delayed tx 's delay.
13931435 fake_clock. advance ( Duration :: from_secs ( 1 ) ) ;
13941436 // Add another transaction to trigger draining of ready delayed txs.
13951437 let another_tx_2 =
13961438 add_tx_input ! ( tx_hash: 2 , address: "0x1" , tx_nonce: 5 , account_nonce: 0 , tip: 100 ) ;
13971439 add_tx ( & mut mempool, & another_tx_2) ;
13981440
1399- // Assert the second declare was also added to the mempool.
1400- assert_eq ! ( mempool. get_txs( 2 ) . unwrap( ) , vec![ second_declare. tx] ) ;
1441+ assert_eq ! ( mempool. get_txs( 2 ) . unwrap( ) , vec![ second_delayed. tx] ) ;
14011442}
14021443
14031444#[ rstest]
1404- fn no_delay_declare_front_run ( ) {
1405- // Create a mempool with a fake clock.
1445+ #[ case:: declare(
1446+ make_delayed_declare,
1447+ MempoolStaticConfig { declare_delay: Duration :: from_secs( 5 ) , enable_fee_escalation: true , fee_escalation_percentage: 0 , ..Default :: default ( ) } ,
1448+ ) ]
1449+ #[ case:: proof_tx(
1450+ make_delayed_proof_tx,
1451+ MempoolStaticConfig { proof_tx_delay: Duration :: from_secs( 5 ) , enable_fee_escalation: true , fee_escalation_percentage: 0 , ..Default :: default ( ) } ,
1452+ ) ]
1453+ fn no_delay_front_run (
1454+ #[ case] make_delayed_tx : fn ( & str , u64 ) -> AddTransactionArgs ,
1455+ #[ case] static_config : MempoolStaticConfig ,
1456+ ) {
14061457 let fake_clock = Arc :: new ( FakeClock :: default ( ) ) ;
1407- let mut mempool = Mempool :: new (
1408- MempoolConfig {
1409- static_config : MempoolStaticConfig {
1410- declare_delay : Duration :: from_secs ( 5 ) ,
1411- // Always accept fee escalation to test only the delayed declare duplicate nonce.
1412- enable_fee_escalation : true ,
1413- fee_escalation_percentage : 0 ,
1414- ..Default :: default ( )
1415- } ,
1416- ..Default :: default ( )
1417- } ,
1418- fake_clock. clone ( ) ,
1419- ) ;
1420- let declare = declare_add_tx_input (
1421- declare_tx_args ! ( resource_bounds: valid_resource_bounds_for_testing( ) , sender_address: contract_address!( "0x0" ) , tx_hash: tx_hash!( 0 ) ) ,
1422- ) ;
1423- add_tx ( & mut mempool, & declare) ;
1458+ let mut mempool =
1459+ Mempool :: new ( MempoolConfig { static_config, ..Default :: default ( ) } , fake_clock. clone ( ) ) ;
1460+ let delayed_tx = make_delayed_tx ( "0x0" , 0 ) ;
1461+ add_tx ( & mut mempool, & delayed_tx) ;
14241462
14251463 let expected_error = MempoolError :: DuplicateNonce {
1426- address : declare . tx . contract_address ( ) ,
1427- nonce : declare . tx . nonce ( ) ,
1464+ address : delayed_tx . tx . contract_address ( ) ,
1465+ nonce : delayed_tx . tx . nonce ( ) ,
14281466 } ;
1429- add_tx_expect_error ( & mut mempool, & declare , expected_error. clone ( ) ) ;
1430- validate_tx_expect_error ( & mut mempool, & ValidationArgs :: from ( & declare ) , expected_error) ;
1467+ add_tx_expect_error ( & mut mempool, & delayed_tx , expected_error. clone ( ) ) ;
1468+ validate_tx_expect_error ( & mut mempool, & ValidationArgs :: from ( & delayed_tx ) , expected_error) ;
14311469}
14321470
14331471#[ rstest]
@@ -1658,61 +1696,72 @@ fn account_remains_evictable_after_tx_expiry() {
16581696 assert ! ( mempool. accounts_with_gap( ) . contains( & tx_nonce_2. tx. contract_address( ) ) ) ;
16591697}
16601698
1661- #[ test]
1662- fn delayed_declare_does_not_create_gap ( ) {
1699+ #[ rstest]
1700+ #[ case:: declare( make_delayed_declare, declare_delay_config( 10 ) ) ]
1701+ #[ case:: proof_tx( make_delayed_proof_tx, proof_tx_delay_config( 10 ) ) ]
1702+ fn delayed_tx_does_not_create_gap (
1703+ #[ case] make_delayed_tx : fn ( & str , u64 ) -> AddTransactionArgs ,
1704+ #[ case] static_config : MempoolStaticConfig ,
1705+ ) {
16631706 let fake_clock = Arc :: new ( FakeClock :: default ( ) ) ;
16641707 let mut mempool = Mempool :: new (
16651708 MempoolConfig {
16661709 dynamic_config : MempoolDynamicConfig { transaction_ttl : Duration :: from_secs ( 1000 ) } ,
1667- static_config : MempoolStaticConfig {
1668- declare_delay : Duration :: from_secs ( 10 ) ,
1669- ..Default :: default ( )
1670- } ,
1710+ static_config,
16711711 } ,
16721712 fake_clock. clone ( ) ,
16731713 ) ;
16741714
1675- let declare_tx = declare_add_tx_input ( declare_tx_args ! (
1676- tx_hash: tx_hash!( 1 ) ,
1677- sender_address: contract_address!( "0x0" ) ,
1678- nonce: nonce!( 0 )
1679- ) ) ;
1715+ let delayed_tx = make_delayed_tx ( "0x0" , 1 ) ;
16801716 let next_tx = add_tx_input ! ( tx_hash: 2 , address: "0x0" , tx_nonce: 1 , account_nonce: 0 ) ;
1681- for input in [ & declare_tx , & next_tx] {
1717+ for input in [ & delayed_tx , & next_tx] {
16821718 add_tx ( & mut mempool, input) ;
16831719 }
16841720
1685- assert ! ( !mempool. accounts_with_gap( ) . contains( & declare_tx. tx. contract_address( ) ) ) ;
1721+ assert ! ( !mempool. accounts_with_gap( ) . contains( & delayed_tx. tx. contract_address( ) ) ) ;
1722+ }
1723+
1724+ #[ rstest]
1725+ #[ case:: declare( make_delayed_declare, declare_delay_config( 100 ) ) ]
1726+ #[ case:: proof_tx( make_delayed_proof_tx, proof_tx_delay_config( 100 ) ) ]
1727+ fn delayed_tx_closes_a_gap (
1728+ #[ case] make_delayed_tx : fn ( & str , u64 ) -> AddTransactionArgs ,
1729+ #[ case] static_config : MempoolStaticConfig ,
1730+ ) {
1731+ let mut mempool = Mempool :: new (
1732+ MempoolConfig { static_config, ..Default :: default ( ) } ,
1733+ Arc :: new ( FakeClock :: default ( ) ) ,
1734+ ) ;
1735+
1736+ let gap_creating_tx = add_tx_input ! ( tx_hash: 1 , address: "0x0" , tx_nonce: 1 , account_nonce: 0 ) ;
1737+ add_tx ( & mut mempool, & gap_creating_tx) ;
1738+ assert ! ( mempool. accounts_with_gap( ) . contains( & gap_creating_tx. tx. contract_address( ) ) ) ;
1739+
1740+ let gap_closing_tx = make_delayed_tx ( "0x0" , 2 ) ;
1741+ add_tx ( & mut mempool, & gap_closing_tx) ;
1742+ assert ! ( !mempool. accounts_with_gap( ) . contains( & gap_closing_tx. tx. contract_address( ) ) ) ;
16861743}
16871744
16881745#[ rstest]
1689- fn declare_tx_closes_a_gap ( ) {
1746+ fn invoke_without_proof_not_delayed ( ) {
1747+ let fake_clock = Arc :: new ( FakeClock :: default ( ) ) ;
16901748 let mut mempool = Mempool :: new (
16911749 MempoolConfig {
16921750 static_config : MempoolStaticConfig {
1693- declare_delay : Duration :: from_secs ( 100 ) ,
1751+ proof_tx_delay : Duration :: from_secs ( 100 ) ,
16941752 ..Default :: default ( )
16951753 } ,
16961754 ..Default :: default ( )
16971755 } ,
1698- Arc :: new ( FakeClock :: default ( ) ) ,
1756+ fake_clock . clone ( ) ,
16991757 ) ;
17001758
1701- let gap_creating_tx = add_tx_input ! ( tx_hash : 1 , address : "0x0" , tx_nonce : 1 , account_nonce : 0 ) ;
1702- add_tx ( & mut mempool , & gap_creating_tx ) ;
1703- assert ! ( mempool. accounts_with_gap ( ) . contains ( & gap_creating_tx . tx . contract_address ( ) ) ) ;
1759+ // Invoke without proof_facts — should NOT be delayed.
1760+ let invoke_tx_input = add_tx_input ! ( tx_hash : 1 , address : "0x0" , tx_nonce : 0 , account_nonce : 0 ) ;
1761+ add_tx ( & mut mempool, & invoke_tx_input ) ;
17041762
1705- let delayed_declare_tx_closes_a_gap = declare_add_tx_input ( declare_tx_args ! (
1706- tx_hash: tx_hash!( 2 ) ,
1707- sender_address: contract_address!( "0x0" ) ,
1708- nonce: nonce!( 0 )
1709- ) ) ;
1710- add_tx ( & mut mempool, & delayed_declare_tx_closes_a_gap) ;
1711- assert ! (
1712- !mempool
1713- . accounts_with_gap( )
1714- . contains( & delayed_declare_tx_closes_a_gap. tx. contract_address( ) )
1715- ) ;
1763+ // Should be immediately available.
1764+ assert_eq ! ( mempool. get_txs( 1 ) . unwrap( ) , vec![ invoke_tx_input. tx] ) ;
17161765}
17171766
17181767#[ rstest]
0 commit comments