openzeppelin_relayer/constants/
status_check.rs

1//! Status check constants for circuit breaker configuration.
2//!
3//! This module defines network-specific constants for the transaction status check
4//! circuit breaker. These values determine when a transaction should be force-finalized
5//! after repeated status check failures.
6//!
7//! Two thresholds are used:
8//! - **Consecutive failures**: Quick trigger for complete RPC outage (~5 min window)
9//! - **Total failures**: Safety net for flaky RPC (~15 min window), since consecutive
10//!   counter resets on any success
11
12use crate::models::NetworkType;
13
14// =============================================================================
15// EVM Constants
16// =============================================================================
17
18/// Maximum consecutive status check failures before forcing finalization for EVM networks.
19///
20/// With worker backoff capped at 12s, 25 failures ≈ 5 minutes of monitoring.
21/// Quick trigger for complete RPC outage - if RPC is down for 5 min straight, act.
22pub const EVM_MAX_CONSECUTIVE_STATUS_FAILURES: u32 = 25;
23
24/// Maximum total status check failures before forcing finalization for EVM networks.
25///
26/// With worker backoff capped at 12s, 75 failures ≈ 15 minutes of monitoring.
27/// Safety net for flaky RPC that occasionally succeeds (resetting consecutive counter).
28/// Prevents transactions from being stuck indefinitely due to intermittent failures.
29pub const EVM_MAX_TOTAL_STATUS_FAILURES: u32 = 75;
30
31// =============================================================================
32// Stellar Constants
33// =============================================================================
34
35/// Maximum consecutive status check failures before forcing finalization for Stellar.
36///
37/// With worker backoff capped at 3s, 100 failures ≈ 5 minutes of monitoring.
38/// Quick trigger for complete RPC outage.
39pub const STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES: u32 = 100;
40
41/// Maximum total status check failures before forcing finalization for Stellar.
42///
43/// With worker backoff capped at 3s, 300 failures ≈ 15 minutes of monitoring.
44/// Safety net for flaky RPC.
45pub const STELLAR_MAX_TOTAL_STATUS_FAILURES: u32 = 300;
46
47// =============================================================================
48// Solana Constants
49// =============================================================================
50
51/// Maximum consecutive status check failures before forcing finalization for Solana.
52///
53/// With worker backoff capped at 8s, 38 failures ≈ 5 minutes of monitoring.
54/// Quick trigger for complete RPC outage.
55pub const SOLANA_MAX_CONSECUTIVE_STATUS_FAILURES: u32 = 38;
56
57/// Maximum total status check failures before forcing finalization for Solana.
58///
59/// With worker backoff capped at 8s, 115 failures ≈ 15 minutes of monitoring.
60/// Safety net for flaky RPC.
61pub const SOLANA_MAX_TOTAL_STATUS_FAILURES: u32 = 115;
62
63// =============================================================================
64// Helper Functions
65// =============================================================================
66
67/// Returns the maximum consecutive status check failures allowed for a given network type.
68///
69/// This function maps network types to their specific failure limits, allowing
70/// network handlers to apply appropriate circuit breaker thresholds.
71///
72/// # Arguments
73///
74/// * `network_type` - The blockchain network type
75///
76/// # Returns
77///
78/// The maximum number of consecutive failures before force-finalization.
79///
80/// # Example
81///
82/// ```ignore
83/// let max_failures = get_max_consecutive_status_failures(NetworkType::Stellar);
84/// assert_eq!(max_failures, STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES);
85/// ```
86pub fn get_max_consecutive_status_failures(network_type: NetworkType) -> u32 {
87    match network_type {
88        NetworkType::Evm => EVM_MAX_CONSECUTIVE_STATUS_FAILURES,
89        NetworkType::Stellar => STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES,
90        NetworkType::Solana => SOLANA_MAX_CONSECUTIVE_STATUS_FAILURES,
91    }
92}
93
94/// Returns the maximum total status check failures allowed for a given network type.
95///
96/// This is a safety net for flaky RPC connections that occasionally succeed
97/// (resetting the consecutive counter) but continue to fail overall.
98///
99/// # Arguments
100///
101/// * `network_type` - The blockchain network type
102///
103/// # Returns
104///
105/// The maximum number of total failures before force-finalization.
106pub fn get_max_total_status_failures(network_type: NetworkType) -> u32 {
107    match network_type {
108        NetworkType::Evm => EVM_MAX_TOTAL_STATUS_FAILURES,
109        NetworkType::Stellar => STELLAR_MAX_TOTAL_STATUS_FAILURES,
110        NetworkType::Solana => SOLANA_MAX_TOTAL_STATUS_FAILURES,
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    #[test]
119    fn test_evm_max_consecutive_failures() {
120        assert_eq!(
121            get_max_consecutive_status_failures(NetworkType::Evm),
122            EVM_MAX_CONSECUTIVE_STATUS_FAILURES
123        );
124    }
125
126    #[test]
127    fn test_evm_max_total_failures() {
128        assert_eq!(
129            get_max_total_status_failures(NetworkType::Evm),
130            EVM_MAX_TOTAL_STATUS_FAILURES
131        );
132    }
133
134    #[test]
135    fn test_stellar_max_consecutive_failures() {
136        assert_eq!(
137            get_max_consecutive_status_failures(NetworkType::Stellar),
138            STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES
139        );
140    }
141
142    #[test]
143    fn test_stellar_max_total_failures() {
144        assert_eq!(
145            get_max_total_status_failures(NetworkType::Stellar),
146            STELLAR_MAX_TOTAL_STATUS_FAILURES
147        );
148    }
149
150    #[test]
151    fn test_solana_max_consecutive_failures() {
152        assert_eq!(
153            get_max_consecutive_status_failures(NetworkType::Solana),
154            SOLANA_MAX_CONSECUTIVE_STATUS_FAILURES
155        );
156    }
157
158    #[test]
159    fn test_solana_max_total_failures() {
160        assert_eq!(
161            get_max_total_status_failures(NetworkType::Solana),
162            SOLANA_MAX_TOTAL_STATUS_FAILURES
163        );
164    }
165
166    #[test]
167    fn test_consecutive_provides_5_min_window() {
168        // Consecutive failures = quick trigger for complete RPC outage (~5 min)
169        // EVM: 25 failures × 12s backoff = 300s = 5 min
170        // Stellar: 100 failures × 3s backoff = 300s = 5 min
171        // Solana: 38 failures × 8s backoff = 304s ≈ 5 min
172        assert!(EVM_MAX_CONSECUTIVE_STATUS_FAILURES >= 25);
173        assert!(STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES >= 100);
174        assert!(SOLANA_MAX_CONSECUTIVE_STATUS_FAILURES >= 38);
175    }
176
177    #[test]
178    fn test_total_provides_15_min_window() {
179        // Total failures = safety net for flaky RPC (~15 min)
180        // EVM: 75 failures × 12s backoff = 900s = 15 min
181        // Stellar: 300 failures × 3s backoff = 900s = 15 min
182        // Solana: 115 failures × 8s backoff = 920s ≈ 15 min
183        assert!(EVM_MAX_TOTAL_STATUS_FAILURES >= 75);
184        assert!(STELLAR_MAX_TOTAL_STATUS_FAILURES >= 300);
185        assert!(SOLANA_MAX_TOTAL_STATUS_FAILURES >= 115);
186    }
187
188    #[test]
189    fn test_total_failures_greater_than_consecutive() {
190        // Total failures should always be greater than consecutive (safety net)
191        assert!(EVM_MAX_TOTAL_STATUS_FAILURES > EVM_MAX_CONSECUTIVE_STATUS_FAILURES);
192        assert!(STELLAR_MAX_TOTAL_STATUS_FAILURES > STELLAR_MAX_CONSECUTIVE_STATUS_FAILURES);
193        assert!(SOLANA_MAX_TOTAL_STATUS_FAILURES > SOLANA_MAX_CONSECUTIVE_STATUS_FAILURES);
194    }
195}