@@ -34,10 +34,10 @@ use crate::{config::PluginConfig, pool_position::PoolPosition, utils::read_or_ne
3434use super :: AccountGet ;
3535
3636/// Number of slots to wait before checking for a confirmed transaction.
37- static TRANSACTION_CONFIRMATION_PERIOD : u64 = 10 ;
37+ static TRANSACTION_CONFIRMATION_PERIOD : u64 = 24 ;
3838
3939/// Number of slots to wait before trying to execute a thread while not in the pool.
40- static THREAD_TIMEOUT_WINDOW : u64 = 8 ;
40+ static THREAD_TIMEOUT_WINDOW : u64 = 24 ;
4141
4242/// Number of times to retry a thread simulation.
4343static MAX_THREAD_SIMULATION_FAILURES : u32 = 5 ;
@@ -46,7 +46,7 @@ static MAX_THREAD_SIMULATION_FAILURES: u32 = 5;
4646static EXPONENTIAL_BACKOFF_CONSTANT : u32 = 2 ;
4747
4848/// The number of slots to wait since the last rotation attempt.
49- static ROTATION_CONFIRMATION_PERIOD : u64 = 9 ;
49+ static ROTATION_CONFIRMATION_PERIOD : u64 = 16 ;
5050
5151/// TxExecutor
5252pub struct TxExecutor {
@@ -66,7 +66,8 @@ pub struct ExecutableThreadMetadata {
6666
6767#[ derive( Debug ) ]
6868pub struct TransactionMetadata {
69- pub slot_sent : u64 ,
69+ pub due_slot : u64 ,
70+ pub sent_slot : u64 ,
7071 pub signature : Signature ,
7172}
7273
@@ -163,14 +164,16 @@ impl TxExecutor {
163164 ) -> PluginResult < ( ) > {
164165 // Get transaction signatures and corresponding threads to check.
165166 struct CheckableTransaction {
167+ due_slot : u64 ,
166168 thread_pubkey : Pubkey ,
167169 signature : Signature ,
168170 }
169171 let r_transaction_history = self . transaction_history . read ( ) . await ;
170172 let checkable_transactions = r_transaction_history
171173 . iter ( )
172- . filter ( |( _, metadata) | slot > metadata. slot_sent + TRANSACTION_CONFIRMATION_PERIOD )
174+ . filter ( |( _, metadata) | slot > metadata. sent_slot + TRANSACTION_CONFIRMATION_PERIOD )
173175 . map ( |( pubkey, metadata) | CheckableTransaction {
176+ due_slot : metadata. due_slot ,
174177 thread_pubkey : * pubkey,
175178 signature : metadata. signature ,
176179 } )
@@ -179,7 +182,7 @@ impl TxExecutor {
179182
180183 // Lookup transaction statuses and track which threads are successful / retriable.
181184 let mut failed_threads: HashSet < Pubkey > = HashSet :: new ( ) ;
182- let mut retriable_threads: HashSet < Pubkey > = HashSet :: new ( ) ;
185+ let mut retriable_threads: HashSet < ( Pubkey , u64 ) > = HashSet :: new ( ) ;
183186 let mut successful_threads: HashSet < Pubkey > = HashSet :: new ( ) ;
184187 for data in checkable_transactions {
185188 match client
@@ -196,7 +199,7 @@ impl TxExecutor {
196199 "Retrying thread: {:?} missing_signature: {:?}" ,
197200 data. thread_pubkey, data. signature
198201 ) ;
199- retriable_threads. insert ( data. thread_pubkey ) ;
202+ retriable_threads. insert ( ( data. thread_pubkey , data . due_slot ) ) ;
200203 }
201204 Some ( status) => match status {
202205 Err ( err) => {
@@ -223,12 +226,12 @@ impl TxExecutor {
223226 for pubkey in failed_threads {
224227 w_transaction_history. remove ( & pubkey) ;
225228 }
226- for pubkey in retriable_threads {
229+ for ( pubkey, due_slot ) in retriable_threads {
227230 w_transaction_history. remove ( & pubkey) ;
228231 w_executable_threads. insert (
229232 pubkey,
230233 ExecutableThreadMetadata {
231- due_slot : slot ,
234+ due_slot,
232235 simulation_failures : 0 ,
233236 } ,
234237 ) ;
@@ -251,7 +254,7 @@ impl TxExecutor {
251254 let rotation_history = r_rotation_history. as_ref ( ) . unwrap ( ) ;
252255 if slot
253256 > rotation_history
254- . slot_sent
257+ . sent_slot
255258 . checked_add ( ROTATION_CONFIRMATION_PERIOD )
256259 . unwrap ( )
257260 {
@@ -297,7 +300,8 @@ impl TxExecutor {
297300 self . clone ( ) . submit_tx ( & tx) . await ?;
298301 let mut w_rotation_history = self . rotation_history . write ( ) . await ;
299302 * w_rotation_history = Some ( TransactionMetadata {
300- slot_sent : slot,
303+ due_slot : slot,
304+ sent_slot : slot,
301305 signature : tx. signatures [ 0 ] ,
302306 } ) ;
303307 drop ( w_rotation_history) ;
@@ -364,7 +368,7 @@ impl TxExecutor {
364368 ) )
365369 } )
366370 . collect ( ) ;
367- let mut executed_threads: HashMap < Pubkey , Signature > = HashMap :: new ( ) ;
371+ let mut executed_threads: HashMap < Pubkey , ( Signature , u64 ) > = HashMap :: new ( ) ;
368372
369373 // Serialize to wire transactions.
370374 let wire_txs = futures:: future:: join_all ( tasks)
@@ -374,8 +378,8 @@ impl TxExecutor {
374378 Err ( _err) => None ,
375379 Ok ( res) => match res {
376380 None => None ,
377- Some ( ( pubkey, tx) ) => {
378- executed_threads. insert ( * pubkey, tx. signatures [ 0 ] ) ;
381+ Some ( ( pubkey, tx, due_slot ) ) => {
382+ executed_threads. insert ( * pubkey, ( tx. signatures [ 0 ] , * due_slot ) ) ;
379383 Some ( tx)
380384 }
381385 } ,
@@ -399,12 +403,13 @@ impl TxExecutor {
399403 Ok ( ( ) ) => {
400404 let mut w_executable_threads = self . executable_threads . write ( ) . await ;
401405 let mut w_transaction_history = self . transaction_history . write ( ) . await ;
402- for ( pubkey, signature) in executed_threads {
406+ for ( pubkey, ( signature, due_slot ) ) in executed_threads {
403407 w_executable_threads. remove ( & pubkey) ;
404408 w_transaction_history. insert (
405409 pubkey,
406410 TransactionMetadata {
407- slot_sent : observed_slot,
411+ due_slot,
412+ sent_slot : observed_slot,
408413 signature,
409414 } ,
410415 ) ;
@@ -423,7 +428,7 @@ impl TxExecutor {
423428 observed_slot : u64 ,
424429 due_slot : u64 ,
425430 thread_pubkey : Pubkey ,
426- ) -> Option < ( Pubkey , Transaction ) > {
431+ ) -> Option < ( Pubkey , Transaction , u64 ) > {
427432 let thread = match client. clone ( ) . get :: < VersionedThread > ( & thread_pubkey) . await {
428433 Err ( _err) => {
429434 self . increment_simulation_failure ( thread_pubkey) . await ;
@@ -432,6 +437,13 @@ impl TxExecutor {
432437 Ok ( thread) => thread,
433438 } ;
434439
440+ // Exit early if the thread has been executed after it became due.
441+ if let Some ( exec_context) = thread. exec_context ( ) {
442+ if exec_context. last_exec_at . gt ( & due_slot) {
443+ return None ;
444+ }
445+ }
446+
435447 if let Ok ( tx) = crate :: builders:: build_thread_exec_tx (
436448 client. clone ( ) ,
437449 & self . keypair ,
@@ -449,7 +461,7 @@ impl TxExecutor {
449461 . await
450462 . is_ok ( )
451463 {
452- Some ( ( thread_pubkey, tx) )
464+ Some ( ( thread_pubkey, tx, due_slot ) )
453465 } else {
454466 None
455467 }
@@ -478,7 +490,7 @@ impl TxExecutor {
478490 ) -> PluginResult < ( ) > {
479491 let r_transaction_history = self . transaction_history . read ( ) . await ;
480492 if let Some ( metadata) = r_transaction_history. get ( & thread_pubkey) {
481- if metadata. signature . eq ( & tx. signatures [ 0 ] ) && metadata. slot_sent . le ( & slot) {
493+ if metadata. signature . eq ( & tx. signatures [ 0 ] ) && metadata. sent_slot . le ( & slot) {
482494 return Err ( GeyserPluginError :: Custom ( format ! ( "Transaction signature is a duplicate of a previously submitted transaction" ) . into ( ) ) ) ;
483495 }
484496 }
0 commit comments