@@ -12,18 +12,28 @@ use alloy::signers::Signer;
12
12
use alloy:: sol_types:: SolCall ;
13
13
use alloy:: transports:: TransportError ;
14
14
use alloy_primitives:: { FixedBytes , U256 } ;
15
- use eyre:: { bail, eyre} ;
15
+ use alloy_sol_types:: SolError ;
16
+ use eyre:: eyre;
16
17
use oauth2:: {
17
18
basic:: BasicClient , basic:: BasicTokenType , reqwest:: http_client, AuthUrl , ClientId ,
18
19
ClientSecret , EmptyExtraTokenFields , StandardTokenResponse , TokenResponse , TokenUrl ,
19
20
} ;
20
21
use tokio:: { sync:: mpsc, task:: JoinHandle } ;
21
22
use tracing:: { debug, error, instrument, trace} ;
22
- use zenith_types:: { SignRequest , SignResponse , Zenith } ;
23
+ use zenith_types:: {
24
+ SignRequest , SignResponse ,
25
+ Zenith :: { self , IncorrectHostBlock } ,
26
+ } ;
23
27
24
28
/// OAuth Audience Claim Name, required param by IdP for client credential grant
25
29
const OAUTH_AUDIENCE_CLAIM : & str = "audience" ;
26
30
31
+ pub enum ControlFlow {
32
+ Retry ,
33
+ Skip ,
34
+ Done ,
35
+ }
36
+
27
37
/// Submits sidecars in ethereum txns to mainnet ethereum
28
38
pub struct SubmitTask {
29
39
/// Ethereum Provider
@@ -128,7 +138,7 @@ impl SubmitTask {
128
138
& self ,
129
139
resp : & SignResponse ,
130
140
in_progress : & InProgressBlock ,
131
- ) -> eyre:: Result < ( ) > {
141
+ ) -> eyre:: Result < ControlFlow > {
132
142
let v: u8 = resp. sig . v ( ) . y_parity_byte ( ) + 27 ;
133
143
let r: FixedBytes < 32 > = resp. sig . r ( ) . into ( ) ;
134
144
let s: FixedBytes < 32 > = resp. sig . s ( ) . into ( ) ;
@@ -157,7 +167,11 @@ impl SubmitTask {
157
167
"error in transaction submission"
158
168
) ;
159
169
160
- bail ! ( "simulation failed, bailing transaction submission" )
170
+ if e. as_revert_data ( ) == Some ( IncorrectHostBlock :: SELECTOR . into ( ) ) {
171
+ return Ok ( ControlFlow :: Retry ) ;
172
+ }
173
+
174
+ return Ok ( ControlFlow :: Skip ) ;
161
175
}
162
176
163
177
tracing:: debug!(
@@ -166,7 +180,13 @@ impl SubmitTask {
166
180
"sending transaction to network"
167
181
) ;
168
182
169
- let result = self . provider . send_transaction ( tx) . await ?;
183
+ let result = match self . provider . send_transaction ( tx) . await {
184
+ Ok ( result) => result,
185
+ Err ( e) => {
186
+ error ! ( error = %e, "error sending transaction" ) ;
187
+ return Ok ( ControlFlow :: Skip ) ;
188
+ }
189
+ } ;
170
190
171
191
let tx_hash = result. tx_hash ( ) ;
172
192
@@ -177,13 +197,19 @@ impl SubmitTask {
177
197
"dispatched to network"
178
198
) ;
179
199
180
- Ok ( ( ) )
200
+ Ok ( ControlFlow :: Done )
181
201
}
182
202
183
203
#[ instrument( skip_all, err) ]
184
- async fn handle_inbound ( & self , in_progress : & InProgressBlock ) -> eyre:: Result < ( ) > {
204
+ async fn handle_inbound ( & self , in_progress : & InProgressBlock ) -> eyre:: Result < ControlFlow > {
185
205
tracing:: info!( txns = in_progress. len( ) , "handling inbound block" ) ;
186
- let sig_request = self . construct_sig_request ( in_progress) . await ?;
206
+ let sig_request = match self . construct_sig_request ( in_progress) . await {
207
+ Ok ( sig_request) => sig_request,
208
+ Err ( e) => {
209
+ tracing:: error!( error = %e, "error constructing signature request" ) ;
210
+ return Ok ( ControlFlow :: Skip ) ;
211
+ }
212
+ } ;
187
213
188
214
tracing:: debug!(
189
215
host_block_number = %sig_request. host_block_number,
@@ -201,7 +227,13 @@ impl SubmitTask {
201
227
) ;
202
228
SignResponse { req : sig_request, sig }
203
229
} else {
204
- let resp: SignResponse = self . sup_quincey ( & sig_request) . await ?;
230
+ let resp: SignResponse = match self . sup_quincey ( & sig_request) . await {
231
+ Ok ( resp) => resp,
232
+ Err ( e) => {
233
+ tracing:: error!( error = %e, "error acquiring signature from quincey" ) ;
234
+ return Ok ( ControlFlow :: Retry ) ;
235
+ }
236
+ } ;
205
237
tracing:: debug!(
206
238
sig = hex:: encode( resp. sig. as_bytes( ) ) ,
207
239
"acquired signature from quincey"
@@ -218,8 +250,33 @@ impl SubmitTask {
218
250
let handle = tokio:: spawn ( async move {
219
251
loop {
220
252
if let Some ( in_progress) = inbound. recv ( ) . await {
221
- if let Err ( e) = self . handle_inbound ( & in_progress) . await {
222
- error ! ( %e, "error in block submission. Dropping block." ) ;
253
+ let mut retries = 0 ;
254
+ loop {
255
+ match self . handle_inbound ( & in_progress) . await {
256
+ Ok ( ControlFlow :: Retry ) => {
257
+ retries += 1 ;
258
+ if retries > 3 {
259
+ tracing:: error!(
260
+ "error handling inbound block: too many retries"
261
+ ) ;
262
+ break ;
263
+ }
264
+ tracing:: error!( "error handling inbound block: retrying" ) ;
265
+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 2 ) ) . await ;
266
+ }
267
+ Ok ( ControlFlow :: Skip ) => {
268
+ tracing:: info!( "skipping block" ) ;
269
+ break ;
270
+ }
271
+ Ok ( ControlFlow :: Done ) => {
272
+ tracing:: info!( "block landed successfully" ) ;
273
+ break ;
274
+ }
275
+ Err ( e) => {
276
+ tracing:: error!( error = %e, "error handling inbound block" ) ;
277
+ break ;
278
+ }
279
+ }
223
280
}
224
281
} else {
225
282
tracing:: debug!( "upstream task gone" ) ;
0 commit comments