@@ -125,22 +125,28 @@ func (t *BatchTxPool) Add(
125125 }
126126
127127 t .txMux .Lock ()
128- defer t .txMux .Unlock ()
129128
130129 eoaActivity , found := t .eoaActivityCache .Get (from )
131130 nonce := tx .Nonce ()
132131
133132 // Skip transactions that have been already submitted,
134133 // as they are *likely* to fail.
135134 if found && slices .Contains (eoaActivity .txNonces , nonce ) {
135+ t .txMux .Unlock ()
136136 t .logger .Info ().
137137 Str ("evm_tx" , tx .Hash ().Hex ()).
138138 Str ("from" , from .Hex ()).
139139 Uint64 ("nonce" , nonce ).
140140 Msg ("tx with same nonce has been already submitted" )
141+
141142 return nil
142143 }
143144
145+ t .updateEOAActivityMetadata (from , nonce )
146+
147+ // Determine action while holding lock
148+ var shouldSubmitSingle bool
149+
144150 // Scenarios
145151 // 1. EOA activity not found:
146152 // => We send the transaction individually, without adding it
@@ -160,38 +166,47 @@ func (t *BatchTxPool) Add(
160166 // [X] is equal to the configured `TxBatchInterval` duration.
161167 if ! found {
162168 // Case 1. EOA activity not found:
163- err = t . submitSingleTransaction ( ctx , hexEncodedTx )
169+ shouldSubmitSingle = true
164170 } else if time .Since (eoaActivity .lastSubmission ) > t .config .TxBatchInterval {
171+ // Case 2. EOA activity found AND it was more than [X] seconds ago:
172+
165173 // If the EOA has pooled transactions, which are not yet processed,
166174 // due to congestion or anything, make sure to include the current
167175 // tx on that batch.
168- hasBatch := len (t .pooledTxs [from ]) > 0
169- if hasBatch {
170- userTx := pooledEvmTx {txPayload : hexEncodedTx , nonce : nonce }
171- t .pooledTxs [from ] = append (t .pooledTxs [from ], userTx )
172- }
173-
174- // If it wasn't batched, submit individually
175- if ! hasBatch {
176- // Case 2. EOA activity found AND it was more than [X] seconds ago:
177- err = t .submitSingleTransaction (ctx , hexEncodedTx )
178- }
176+ shouldSubmitSingle = (len (t .pooledTxs [from ]) == 0 )
179177 } else {
180178 // Case 3. EOA activity found AND it was less than [X] seconds ago:
179+ shouldSubmitSingle = false
180+ }
181+
182+ // Pool transaction in the batch
183+ if ! shouldSubmitSingle {
181184 userTx := pooledEvmTx {txPayload : hexEncodedTx , nonce : nonce }
182185 t .pooledTxs [from ] = append (t .pooledTxs [from ], userTx )
183186 }
184187
188+ // Release lock before network I/O operation
189+ t .txMux .Unlock ()
190+
191+ // Submit single transaction without holding lock
192+ if shouldSubmitSingle {
193+ err = t .submitSingleTransaction (ctx , hexEncodedTx )
194+ }
195+
185196 if err != nil {
197+ t .txMux .Lock ()
198+ // If there was an error during tx submission, remove the entry
199+ // from the cache, to not block future requests with same nonce.
200+ t .eoaActivityCache .Remove (from )
201+ t .txMux .Unlock ()
202+
186203 t .logger .Error ().Err (err ).Msgf (
187204 "failed to submit single Flow transaction for EOA: %s" ,
188205 from .Hex (),
189206 )
190207 return err
191208 }
192209
193- t .updateEOAActivityMetadata (from , nonce )
194-
195210 return nil
196211}
197212
0 commit comments