Skip to content

Commit 2c45fb2

Browse files
authored
fix(batcher): adjust MAX_DELAY to one hour (#1405)
1 parent ba24eba commit 2c45fb2

File tree

5 files changed

+50
-18
lines changed

5 files changed

+50
-18
lines changed

batcher/aligned-batcher/src/eth/utils.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
},
1010
};
1111
use aligned_sdk::core::constants::{
12-
DEFAULT_BACKOFF_FACTOR, DEFAULT_MAX_RETRIES, DEFAULT_MIN_RETRY_DELAY,
12+
DEFAULT_BACKOFF_FACTOR, DEFAULT_MAX_RETRIES, DEFAULT_MAX_RETRY_DELAY, DEFAULT_MIN_RETRY_DELAY,
1313
GAS_PRICE_INCREMENT_PERCENTAGE_PER_ITERATION, OVERRIDE_GAS_PRICE_PERCENTAGE_MULTIPLIER,
1414
PERCENTAGE_DIVIDER,
1515
};
@@ -61,6 +61,9 @@ pub fn calculate_bumped_gas_price(
6161
bumped_current_gas_price.max(bumped_previous_gas_price)
6262
}
6363

64+
/// Gets the current nonce from Ethereum.
65+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
66+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
6467
pub async fn get_current_nonce(
6568
eth_http_provider: &Provider<Http>,
6669
eth_http_provider_fallback: &Provider<Http>,
@@ -71,6 +74,7 @@ pub async fn get_current_nonce(
7174
DEFAULT_MIN_RETRY_DELAY,
7275
DEFAULT_BACKOFF_FACTOR,
7376
DEFAULT_MAX_RETRIES,
77+
DEFAULT_MAX_RETRY_DELAY,
7478
)
7579
.await
7680
.map_err(|e| {
@@ -79,7 +83,9 @@ pub async fn get_current_nonce(
7983
})
8084
}
8185

82-
/// Gets the current gas price from Ethereum using exponential backoff.
86+
/// Gets the current gas price from Ethereum.
87+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
88+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
8389
pub async fn get_gas_price(
8490
eth_http_provider: &Provider<Http>,
8591
eth_http_provider_fallback: &Provider<Http>,
@@ -89,6 +95,7 @@ pub async fn get_gas_price(
8995
DEFAULT_MIN_RETRY_DELAY,
9096
DEFAULT_BACKOFF_FACTOR,
9197
DEFAULT_MAX_RETRIES,
98+
DEFAULT_MAX_RETRY_DELAY,
9299
)
93100
.await
94101
.map_err(|e| {

batcher/aligned-batcher/src/lib.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use std::sync::Arc;
2222
use aligned_sdk::core::constants::{
2323
ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF, AGGREGATOR_GAS_COST, CANCEL_TRANSACTION_MAX_RETRIES,
2424
CONSTANT_GAS_COST, DEFAULT_AGGREGATOR_FEE_PERCENTAGE_MULTIPLIER, DEFAULT_BACKOFF_FACTOR,
25-
DEFAULT_MAX_FEE_PER_PROOF, DEFAULT_MAX_RETRIES, DEFAULT_MIN_RETRY_DELAY,
26-
GAS_PRICE_PERCENTAGE_MULTIPLIER, MIN_FEE_PER_PROOF, PERCENTAGE_DIVIDER,
27-
RESPOND_TO_TASK_FEE_LIMIT_PERCENTAGE_MULTIPLIER,
25+
DEFAULT_MAX_FEE_PER_PROOF, DEFAULT_MAX_RETRIES, DEFAULT_MAX_RETRY_DELAY,
26+
DEFAULT_MIN_RETRY_DELAY, GAS_PRICE_PERCENTAGE_MULTIPLIER, MIN_FEE_PER_PROOF,
27+
PERCENTAGE_DIVIDER, RESPOND_TO_TASK_FEE_LIMIT_PERCENTAGE_MULTIPLIER,
2828
};
2929
use aligned_sdk::core::types::{
3030
ClientMessage, GetNonceResponseMessage, NoncedVerificationData, ProofInvalidReason,
@@ -271,6 +271,9 @@ impl Batcher {
271271
Ok(())
272272
}
273273

274+
/// Listen for Ethereum new blocks.
275+
/// Retries on recoverable errors using exponential backoff
276+
/// with the maximum number of retries and a `MAX_DELAY` of 1 hour.
274277
pub async fn listen_new_blocks(self: Arc<Self>) -> Result<(), BatcherError> {
275278
retry_function(
276279
|| {
@@ -280,6 +283,7 @@ impl Batcher {
280283
DEFAULT_MIN_RETRY_DELAY,
281284
DEFAULT_BACKOFF_FACTOR,
282285
LISTEN_NEW_BLOCKS_MAX_TIMES,
286+
DEFAULT_MAX_RETRY_DELAY,
283287
)
284288
.await
285289
.map_err(|e| e.inner())
@@ -903,7 +907,9 @@ impl Batcher {
903907
}
904908
}
905909

906-
/// Gets the user nonce from Ethereum using exponential backoff.
910+
/// Gets the user nonce from Ethereum.
911+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
912+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
907913
async fn get_user_nonce_from_ethereum(
908914
&self,
909915
addr: Address,
@@ -919,6 +925,7 @@ impl Batcher {
919925
DEFAULT_MIN_RETRY_DELAY,
920926
DEFAULT_BACKOFF_FACTOR,
921927
DEFAULT_MAX_RETRIES,
928+
DEFAULT_MAX_RETRY_DELAY,
922929
)
923930
.await
924931
}
@@ -1358,6 +1365,10 @@ impl Batcher {
13581365
}
13591366
}
13601367

1368+
/// Sends a `create_new_task` transaction to Ethereum and waits for a maximum of 3 blocks for the receipt.
1369+
/// Retries up to `DEFAULT_MAX_RETRIES` times using exponential backoff on recoverable errors while trying to send the transaction:
1370+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
1371+
/// `ReceiptNotFoundError` is treated as non-recoverable, and the transaction will be canceled using `cancel_create_new_task_tx` in that case.
13611372
async fn create_new_task(
13621373
&self,
13631374
batch_merkle_root: [u8; 32],
@@ -1380,6 +1391,7 @@ impl Batcher {
13801391
DEFAULT_MIN_RETRY_DELAY,
13811392
DEFAULT_BACKOFF_FACTOR,
13821393
DEFAULT_MAX_RETRIES,
1394+
DEFAULT_MAX_RETRY_DELAY,
13831395
)
13841396
.await;
13851397
match result {
@@ -1403,11 +1415,10 @@ impl Batcher {
14031415
}
14041416

14051417
/// Sends a transaction to Ethereum with the same nonce as the previous one to override it.
1406-
/// In case of a recoverable error, it will retry with an exponential backoff up to CANCEL_TRANSACTION_MAX_RETRIES times.
1407-
/// A tx not included in 3 blocks will be considered an error, and will trigger a bump of the fee, with the rules on ```calculate_bumped_gas_price```
1408-
/// This will do 5 bumps every 3 blocks, and then the exponential backoff will dominate, doing bumps at 8,13,24,45,89 and so on.
1409-
/// Errors on ```get_gas_price``` calls inside this function are considered transient,
1410-
/// so they won't stop the retries.
1418+
/// Retries on recoverable errors with exponential backoff.
1419+
/// Bumps the fee if not included in 3 blocks, using `calculate_bumped_gas_price`.
1420+
/// In the first 5 attemps, bumps the fee every 3 blocks. Then exponential backoff takes over.
1421+
/// After 2 hours (attempt 13), retries occur hourly for 1 day (33 retries).
14111422
pub async fn cancel_create_new_task_tx(&self, old_tx_gas_price: U256) {
14121423
info!("Cancelling createNewTask transaction...");
14131424
let iteration = Arc::new(Mutex::new(0));
@@ -1445,6 +1456,7 @@ impl Batcher {
14451456
DEFAULT_MIN_RETRY_DELAY,
14461457
DEFAULT_BACKOFF_FACTOR,
14471458
CANCEL_TRANSACTION_MAX_RETRIES,
1459+
DEFAULT_MAX_RETRY_DELAY,
14481460
)
14491461
.await
14501462
{
@@ -1537,7 +1549,9 @@ impl Batcher {
15371549
Ok(())
15381550
}
15391551

1540-
/// Gets the balance of user with address `addr` from Ethereum using exponential backoff.
1552+
/// Gets the balance of user with address `addr` from Ethereum.
1553+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
1554+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs)
15411555
/// Returns `None` if the balance couldn't be returned
15421556
/// FIXME: This should return a `Result` instead.
15431557
async fn get_user_balance(&self, addr: &Address) -> Option<U256> {
@@ -1552,12 +1566,15 @@ impl Batcher {
15521566
DEFAULT_MIN_RETRY_DELAY,
15531567
DEFAULT_BACKOFF_FACTOR,
15541568
DEFAULT_MAX_RETRIES,
1569+
DEFAULT_MAX_RETRY_DELAY,
15551570
)
15561571
.await
15571572
.ok()
15581573
}
15591574

1560-
/// Checks if the user's balance is unlocked for a given address using exponential backoff.
1575+
/// Checks if the user's balance is unlocked for a given address.
1576+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
1577+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
15611578
/// Returns `false` if an error occurs during the retries.
15621579
async fn user_balance_is_unlocked(&self, addr: &Address) -> bool {
15631580
let Ok(unlocked) = retry_function(
@@ -1571,6 +1588,7 @@ impl Batcher {
15711588
DEFAULT_MIN_RETRY_DELAY,
15721589
DEFAULT_BACKOFF_FACTOR,
15731590
DEFAULT_MAX_RETRIES,
1591+
DEFAULT_MAX_RETRY_DELAY,
15741592
)
15751593
.await
15761594
else {
@@ -1580,7 +1598,9 @@ impl Batcher {
15801598
unlocked
15811599
}
15821600

1583-
/// Uploads the batch to s3 using exponential backoff.
1601+
/// Uploads the batch to s3.
1602+
/// Retries on recoverable errors using exponential backoff up to `DEFAULT_MAX_RETRIES` times:
1603+
/// (0,5 secs - 1 secs - 2 secs - 4 secs - 8 secs).
15841604
async fn upload_batch_to_s3(
15851605
&self,
15861606
batch_bytes: &[u8],
@@ -1598,6 +1618,7 @@ impl Batcher {
15981618
DEFAULT_MIN_RETRY_DELAY,
15991619
DEFAULT_BACKOFF_FACTOR,
16001620
DEFAULT_MAX_RETRIES,
1621+
DEFAULT_MAX_RETRY_DELAY,
16011622
)
16021623
.await
16031624
.map_err(|e| BatcherError::BatchUploadError(e.to_string()))

batcher/aligned-batcher/src/retry/batcher_retryables.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ pub async fn create_new_task_retryable(
170170
})?
171171
.map_err(|e| {
172172
warn!("Error while waiting for batch inclusion: {e}");
173-
RetryError::Transient(BatcherError::TransactionSendError(e.to_string()))
173+
RetryError::Permanent(BatcherError::ReceiptNotFoundError)
174174
})?
175175
.ok_or(RetryError::Permanent(BatcherError::ReceiptNotFoundError))
176176
}

batcher/aligned-batcher/src/retry/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ impl<E> RetryError<E> {
3030

3131
impl<E: std::fmt::Display> std::error::Error for RetryError<E> where E: std::fmt::Debug {}
3232

33-
// Supports retries only on async functions. See: https://docs.rs/backon/latest/backon/#retry-an-async-function
33+
/// Supports retries only on async functions. See: https://docs.rs/backon/latest/backon/#retry-an-async-function
34+
/// Runs with `jitter: false`.
3435
pub async fn retry_function<FutureFn, Fut, T, E>(
3536
function: FutureFn,
3637
min_delay: u64,
3738
factor: f32,
3839
max_times: usize,
40+
max_delay: u64,
3941
) -> Result<T, RetryError<E>>
4042
where
4143
Fut: Future<Output = Result<T, RetryError<E>>>,
@@ -44,7 +46,8 @@ where
4446
let backoff = ExponentialBuilder::default()
4547
.with_min_delay(Duration::from_millis(min_delay))
4648
.with_max_times(max_times)
47-
.with_factor(factor);
49+
.with_factor(factor)
50+
.with_max_delay(Duration::from_secs(max_delay));
4851

4952
function
5053
.retry(backoff)

batcher/aligned-sdk/src/core/constants.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// Batcher ///
22
pub const GAS_PRICE_INCREMENT_PERCENTAGE_PER_ITERATION: usize = 5;
3-
pub const CANCEL_TRANSACTION_MAX_RETRIES: usize = 20;
3+
pub const CANCEL_TRANSACTION_MAX_RETRIES: usize = 33; // ~ 1 day
44
pub const AGGREGATOR_GAS_COST: u128 = 400_000;
55
pub const BATCHER_SUBMISSION_BASE_GAS_COST: u128 = 125_000;
66
pub const ADDITIONAL_SUBMISSION_GAS_COST_PER_PROOF: u128 = 13_000;
@@ -31,3 +31,4 @@ pub const MAX_FEE_DEFAULT_PROOF_NUMBER: usize = 10;
3131
pub const DEFAULT_MIN_RETRY_DELAY: u64 = 500; // milliseconds
3232
pub const DEFAULT_MAX_RETRIES: usize = 5;
3333
pub const DEFAULT_BACKOFF_FACTOR: f32 = 2.0;
34+
pub const DEFAULT_MAX_RETRY_DELAY: u64 = 3600; // seconds

0 commit comments

Comments
 (0)