@@ -159,17 +159,85 @@ impl EthereumNode for Instance {
159159 let connection_string = self . connection_string ( ) ;
160160 let wallet = self . wallet . clone ( ) ;
161161
162- tracing:: debug!( "Submitting transaction: {transaction:#?}" ) ;
163-
164162 execute_transaction ( Box :: pin ( async move {
165- Ok ( ProviderBuilder :: new ( )
163+ let outer_span = tracing:: debug_span!( "Submitting transaction" , ?transaction, ) ;
164+ let _outer_guard = outer_span. enter ( ) ;
165+
166+ let provider = ProviderBuilder :: new ( )
166167 . wallet ( wallet)
167168 . connect ( & connection_string)
168- . await ?
169- . send_transaction ( transaction)
170- . await ?
171- . get_receipt ( )
172- . await ?)
169+ . await ?;
170+
171+ let pending_transaction = provider. send_transaction ( transaction) . await ?;
172+ let transaction_hash = pending_transaction. tx_hash ( ) ;
173+
174+ let span = tracing:: info_span!( "Awaiting transaction receipt" , ?transaction_hash) ;
175+ let _guard = span. enter ( ) ;
176+
177+ // The following is a fix for the "transaction indexing is in progress" error that we
178+ // used to get. You can find more information on this in the following GH issue in geth
179+ // https://github.com/ethereum/go-ethereum/issues/28877. To summarize what's going on,
180+ // before we can get the receipt of the transaction it needs to have been indexed by the
181+ // node's indexer. Just because the transaction has been confirmed it doesn't mean that
182+ // it has been indexed. When we call alloy's `get_receipt` it checks if the transaction
183+ // was confirmed. If it has been, then it will call `eth_getTransactionReceipt` method
184+ // which _might_ return the above error if the tx has not yet been indexed yet. So, we
185+ // need to implement a retry mechanism for the receipt to keep retrying to get it until
186+ // it eventually works, but we only do that if the error we get back is the "transaction
187+ // indexing is in progress" error or if the receipt is None.
188+ //
189+ // At the moment we do not allow for the 60 seconds to be modified and we take it as
190+ // being an implementation detail that's invisible to anything outside of this module.
191+ //
192+ // We allow a total of 60 retries for getting the receipt with one second between each
193+ // retry and the next which means that we allow for a total of 60 seconds of waiting
194+ // before we consider that we're unable to get the transaction receipt.
195+ let mut retries = 0 ;
196+ loop {
197+ match provider. get_transaction_receipt ( * transaction_hash) . await {
198+ Ok ( Some ( receipt) ) => {
199+ tracing:: info!( "Obtained the transaction receipt" ) ;
200+ break Ok ( receipt) ;
201+ }
202+ Ok ( None ) => {
203+ if retries == 60 {
204+ tracing:: error!(
205+ "Polled for transaction receipt for 60 seconds but failed to get it"
206+ ) ;
207+ break Err ( anyhow:: anyhow!( "Failed to get the transaction receipt" ) ) ;
208+ } else {
209+ tracing:: trace!(
210+ retries,
211+ "Sleeping for 1 second and trying to get the receipt again"
212+ ) ;
213+ retries += 1 ;
214+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
215+ continue ;
216+ }
217+ }
218+ Err ( error) => {
219+ let error_string = error. to_string ( ) ;
220+ if error_string. contains ( "transaction indexing is in progress" ) {
221+ if retries == 60 {
222+ tracing:: error!(
223+ "Polled for transaction receipt for 60 seconds but failed to get it"
224+ ) ;
225+ break Err ( error. into ( ) ) ;
226+ } else {
227+ tracing:: trace!(
228+ retries,
229+ "Sleeping for 1 second and trying to get the receipt again"
230+ ) ;
231+ retries += 1 ;
232+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
233+ continue ;
234+ }
235+ } else {
236+ break Err ( error. into ( ) ) ;
237+ }
238+ }
239+ }
240+ }
173241 } ) )
174242 }
175243
@@ -270,6 +338,7 @@ impl Node for Instance {
270338
271339impl Drop for Instance {
272340 fn drop ( & mut self ) {
341+ tracing:: info!( id = self . id, "Dropping node" ) ;
273342 if let Some ( child) = self . handle . as_mut ( ) {
274343 let _ = child. kill ( ) ;
275344 }
0 commit comments