Skip to content

Commit de934f5

Browse files
devin-ai-integration[bot]Jayant Krishnamurthy
and
Jayant Krishnamurthy
authored
feat: Delayed block processing for Fortuna (#2307)
* feat: add delayed block processing and bump minor version Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * fix: add clippy allow attribute for too many arguments Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * fix: remove trailing whitespace in config.sample.yaml Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * refactor: move block delays to EthereumConfig and support multiple delays Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> * fix: pass only block delays param and subtract delays Co-Authored-By: Jayant Krishnamurthy <jayant@dourolabs.xyz> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Jayant Krishnamurthy <jayant@dourolabs.xyz>
1 parent 326f234 commit de934f5

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

apps/fortuna/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/fortuna/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fortuna"
3-
version = "7.3.0"
3+
version = "7.4.0"
44
edition = "2021"
55

66
[dependencies]

apps/fortuna/config.sample.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ chains:
3939
target_profit_pct: 20
4040
max_profit_pct: 100
4141

42+
# A list of block delays for processing blocks multiple times. Each number represents
43+
# how many blocks to wait before processing. For example, [5, 10, 20] means process
44+
# blocks after 5 blocks, then again after 10 blocks, and finally after 20 blocks.
45+
block_delays: [5, 10, 20]
46+
4247
# Historical commitments -- delete this block for local development purposes
4348
commitments:
4449
# prettier-ignore

apps/fortuna/src/config.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ pub struct EthereumConfig {
177177
/// Maximum number of hashes to record in a request.
178178
/// This should be set according to the maximum gas limit the provider supports for callbacks.
179179
pub max_num_hashes: Option<u32>,
180+
181+
/// A list of delays (in blocks) that indicates how many blocks should be delayed
182+
/// before we process a block. For retry logic, we can process blocks multiple times
183+
/// at each specified delay. For example: [5, 10, 20].
184+
#[serde(default = "default_block_delays")]
185+
pub block_delays: Vec<u64>,
186+
}
187+
188+
fn default_block_delays() -> Vec<u64> {
189+
vec![5]
180190
}
181191

182192
fn default_priority_fee_multiplier_pct() -> u64 {

apps/fortuna/src/keeper.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl KeeperMetrics {
250250
}
251251
}
252252

253-
#[derive(Debug)]
253+
#[derive(Debug, Clone)]
254254
pub struct BlockRange {
255255
pub from: BlockNumber,
256256
pub to: BlockNumber,
@@ -346,7 +346,8 @@ pub async fn run_keeper_threads(
346346
)
347347
.in_current_span(),
348348
);
349-
// Spawn a thread that listens for block ranges on the `rx` channel and processes the events for those blocks.
349+
350+
// Spawn a thread for block processing with configured delays
350351
spawn(
351352
process_new_blocks(
352353
chain_state.clone(),
@@ -356,6 +357,7 @@ pub async fn run_keeper_threads(
356357
chain_eth_config.escalation_policy.clone(),
357358
metrics.clone(),
358359
fulfilled_requests_cache.clone(),
360+
chain_eth_config.block_delays.clone(),
359361
)
360362
.in_current_span(),
361363
);
@@ -965,8 +967,10 @@ pub async fn watch_blocks(
965967
}
966968
}
967969

968-
/// It waits on rx channel to receive block ranges and then calls process_block_range to process them.
970+
/// It waits on rx channel to receive block ranges and then calls process_block_range to process them
971+
/// for each configured block delay.
969972
#[tracing::instrument(skip_all)]
973+
#[allow(clippy::too_many_arguments)]
970974
pub async fn process_new_blocks(
971975
chain_state: BlockchainState,
972976
mut rx: mpsc::Receiver<BlockRange>,
@@ -975,12 +979,14 @@ pub async fn process_new_blocks(
975979
escalation_policy: EscalationPolicyConfig,
976980
metrics: Arc<KeeperMetrics>,
977981
fulfilled_requests_cache: Arc<RwLock<HashSet<u64>>>,
982+
block_delays: Vec<u64>,
978983
) {
979984
tracing::info!("Waiting for new block ranges to process");
980985
loop {
981986
if let Some(block_range) = rx.recv().await {
987+
// Process blocks immediately first
982988
process_block_range(
983-
block_range,
989+
block_range.clone(),
984990
Arc::clone(&contract),
985991
gas_limit,
986992
escalation_policy.clone(),
@@ -990,6 +996,25 @@ pub async fn process_new_blocks(
990996
)
991997
.in_current_span()
992998
.await;
999+
1000+
// Then process with each configured delay
1001+
for delay in &block_delays {
1002+
let adjusted_range = BlockRange {
1003+
from: block_range.from.saturating_sub(*delay),
1004+
to: block_range.to.saturating_sub(*delay),
1005+
};
1006+
process_block_range(
1007+
adjusted_range,
1008+
Arc::clone(&contract),
1009+
gas_limit,
1010+
escalation_policy.clone(),
1011+
chain_state.clone(),
1012+
metrics.clone(),
1013+
fulfilled_requests_cache.clone(),
1014+
)
1015+
.in_current_span()
1016+
.await;
1017+
}
9931018
}
9941019
}
9951020
}

0 commit comments

Comments
 (0)