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}