@@ -3,17 +3,20 @@ use crate::{
33 signer:: LocalOrAws ,
44 tasks:: block:: InProgressBlock ,
55} ;
6- use alloy:: consensus:: { constants:: GWEI_TO_WEI , SimpleCoder } ;
7- use alloy:: eips:: BlockNumberOrTag ;
8- use alloy:: network:: { TransactionBuilder , TransactionBuilder4844 } ;
9- use alloy:: providers:: { Provider as _, WalletProvider } ;
10- use alloy:: rpc:: types:: eth:: TransactionRequest ;
11- use alloy:: signers:: Signer ;
12- use alloy:: sol_types:: SolCall ;
13- use alloy:: transports:: TransportError ;
6+ use alloy:: {
7+ consensus:: { constants:: GWEI_TO_WEI , SimpleCoder } ,
8+ eips:: BlockNumberOrTag ,
9+ network:: { TransactionBuilder , TransactionBuilder4844 } ,
10+ providers:: SendableTx ,
11+ providers:: { Provider as _, WalletProvider } ,
12+ rpc:: types:: eth:: TransactionRequest ,
13+ signers:: Signer ,
14+ sol_types:: SolCall ,
15+ transports:: TransportError ,
16+ } ;
1417use alloy_primitives:: { FixedBytes , U256 } ;
1518use alloy_sol_types:: SolError ;
16- use eyre:: eyre;
19+ use eyre:: { bail , eyre} ;
1720use oauth2:: {
1821 basic:: BasicClient , basic:: BasicTokenType , reqwest:: http_client, AuthUrl , ClientId ,
1922 ClientSecret , EmptyExtraTokenFields , StandardTokenResponse , TokenResponse , TokenUrl ,
@@ -25,6 +28,20 @@ use zenith_types::{
2528 Zenith :: { self , IncorrectHostBlock } ,
2629} ;
2730
31+ macro_rules! spawn_provider_send {
32+ ( $provider: expr, $tx: expr) => {
33+ {
34+ let p = $provider. clone( ) ;
35+ let t = $tx. clone( ) ;
36+ tokio:: spawn( async move {
37+ p. send_tx_envelope( t) . await . inspect_err( |e| {
38+ tracing:: warn!( %e, "error in transaction broadcast" )
39+ } )
40+ } )
41+ }
42+ } ;
43+ }
44+
2845/// OAuth Audience Claim Name, required param by IdP for client credential grant
2946const OAUTH_AUDIENCE_CLAIM : & str = "audience" ;
3047
@@ -186,21 +203,41 @@ impl SubmitTask {
186203 return Ok ( ControlFlow :: Skip ) ;
187204 }
188205
206+ self . send_transaction ( resp, tx) . await
207+ }
208+
209+ async fn send_transaction (
210+ & self ,
211+ resp : & SignResponse ,
212+ tx : TransactionRequest ,
213+ ) -> Result < ControlFlow , eyre:: Error > {
189214 tracing:: debug!(
190215 host_block_number = %resp. req. host_block_number,
191216 gas_limit = %resp. req. gas_limit,
192217 "sending transaction to network"
193218 ) ;
194219
195- let _ = match self . provider . send_transaction ( tx) . await {
196- Ok ( result) => result,
197- Err ( e) => {
198- error ! ( error = %e, "error sending transaction" ) ;
199- return Ok ( ControlFlow :: Skip ) ;
200- }
220+ let SendableTx :: Envelope ( tx) = self . provider . fill ( tx) . await ? else {
221+ bail ! ( "failed to fill transaction" )
201222 } ;
202223
224+ // Send the tx via the primary provider
225+ let fut = spawn_provider_send ! ( & self . provider, & tx) ;
226+
227+ // Spawn send_tx futures for all additional broadcast providers
228+ for provider in self . config . connect_additional_broadcast ( ) . await ? {
229+ spawn_provider_send ! ( & provider, & tx) ;
230+ }
231+
232+ // question mark unwraps join error, which would be an internal panic
233+ // then if let checks for rpc error
234+ if let Err ( e) = fut. await ? {
235+ tracing:: error!( error = %e, "Primary tx broadcast failed. Skipping transaction." ) ;
236+ return Ok ( ControlFlow :: Skip ) ;
237+ }
238+
203239 tracing:: info!(
240+ tx_hash = %tx. tx_hash( ) ,
204241 ru_chain_id = %resp. req. ru_chain_id,
205242 gas_limit = %resp. req. gas_limit,
206243 "dispatched to network"
0 commit comments