Skip to content

Commit a62d3ba

Browse files
committed
keep mining if challenge API fails
1 parent ee636c9 commit a62d3ba

File tree

1 file changed

+54
-13
lines changed

1 file changed

+54
-13
lines changed

src/mining.rs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// src/mining.rs
22

33
use crate::api;
4-
use crate::data_types::{DataDir, DataDirMnemonic, MiningContext, MiningResult};
4+
use crate::data_types::{DataDir, DataDirMnemonic, MiningContext, MiningResult, ChallengeData}; // Added ChallengeData
55
use crate::cli::Cli;
66
use crate::cardano;
77
use crate::utils::{self, next_wallet_deriv_index_for_challenge, print_mining_setup, print_statistics, receipt_exists_for_index, run_single_mining_cycle};
@@ -35,14 +35,28 @@ pub fn run_persistent_key_mining(context: MiningContext, skey_hex: &String) -> R
3535
if context.donate_to_option.is_some() { println!("Donation Target: {}", context.donate_to_option.unwrap()); }
3636

3737
let mut current_challenge_id = String::new();
38+
let mut last_active_challenge_data: Option<ChallengeData> = None; // ADDED: Store last valid challenge data
3839
loop {
39-
let challenge_params = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
40-
Ok(Some(params)) => params,
40+
let challenge_params: ChallengeData = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
41+
Ok(Some(params)) => {
42+
last_active_challenge_data = Some(params.clone()); // Store on success
43+
params
44+
},
4145
Ok(None) => continue,
4246
Err(e) => {
43-
eprintln!("⚠️ Critical API Error during challenge check: {}. Retrying in 1 minute...", e);
44-
std::thread::sleep(std::time::Duration::from_secs(60));
45-
continue;
47+
// NEW LOGIC: If a challenge ID is set AND we detect a network failure, continue mining.
48+
if !current_challenge_id.is_empty() && e.contains("API request failed") {
49+
eprintln!("⚠️ Challenge API poll failed (Network Error): {}. Continuing mining with previous challenge parameters (ID: {})...", e, current_challenge_id);
50+
// Use the last stored parameters, which must exist if current_challenge_id is set.
51+
last_active_challenge_data.as_ref().cloned().ok_or_else(|| {
52+
format!("FATAL LOGIC ERROR: Challenge ID {} is set but no previous challenge data was stored.", current_challenge_id)
53+
})?
54+
} else {
55+
// Otherwise, it's a critical error (non-network failure or no challenge active), so wait and retry poll.
56+
eprintln!("⚠️ Critical API Error during challenge check: {}. Retrying in 1 minute...", e);
57+
std::thread::sleep(std::time::Duration::from_secs(60));
58+
continue;
59+
}
4660
}
4761
};
4862

@@ -106,6 +120,7 @@ pub fn run_mnemonic_sequential_mining(cli: &Cli, context: MiningContext, mnemoni
106120
let mut backoff_reg = crate::backoff::Backoff::new(5, 300, 2.0);
107121
let mut last_seen_challenge_id = String::new();
108122
let mut current_challenge_id = String::new();
123+
let mut last_active_challenge_data: Option<ChallengeData> = None; // ADDED: Store last valid challenge data
109124

110125
println!("\n==============================================");
111126
println!("⛏️ Shadow Harvester: MNEMONIC SEQUENTIAL MINING Mode ({})", if context.cli_challenge.is_some() { "FIXED CHALLENGE" } else { "DYNAMIC POLLING" });
@@ -118,9 +133,10 @@ pub fn run_mnemonic_sequential_mining(cli: &Cli, context: MiningContext, mnemoni
118133
let old_challenge_id = last_seen_challenge_id.clone();
119134
current_challenge_id.clear();
120135

121-
let challenge_params = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
136+
let challenge_params: ChallengeData = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
122137
Ok(Some(params)) => {
123138
backoff_challenge.reset();
139+
last_active_challenge_data = Some(params.clone()); // Store on success
124140
if first_run || (context.cli_challenge.is_none() && params.challenge_id != old_challenge_id) {
125141
// Create a dummy DataDir with index 0 to calculate the base path for scanning
126142
let temp_data_dir = DataDir::Mnemonic(DataDirMnemonic { mnemonic: &mnemonic_phrase, account: cli.mnemonic_account, deriv_index: 0 });
@@ -130,7 +146,20 @@ pub fn run_mnemonic_sequential_mining(cli: &Cli, context: MiningContext, mnemoni
130146
params
131147
},
132148
Ok(None) => { backoff_challenge.reset(); continue; },
133-
Err(e) => { eprintln!("⚠️ Critical API Error during challenge polling: {}. Retrying with exponential backoff...", e); backoff_challenge.sleep(); continue; }
149+
Err(e) => {
150+
// NEW LOGIC: If a challenge ID is set AND we detect a network failure, continue mining.
151+
if !current_challenge_id.is_empty() && e.contains("API request failed") {
152+
eprintln!("⚠️ Challenge API poll failed (Network Error): {}. Continuing mining with previous challenge parameters (ID: {})...", e, current_challenge_id);
153+
backoff_challenge.reset();
154+
last_active_challenge_data.as_ref().cloned().ok_or_else(|| {
155+
format!("FATAL LOGIC ERROR: Challenge ID {} is set but no previous challenge data was stored.", current_challenge_id)
156+
})?
157+
} else {
158+
eprintln!("⚠️ Critical API Error during challenge polling: {}. Retrying with exponential backoff...", e);
159+
backoff_challenge.sleep();
160+
continue;
161+
}
162+
}
134163
};
135164
first_run = false;
136165

@@ -213,15 +242,27 @@ pub fn run_ephemeral_key_mining(context: MiningContext) -> Result<(), String> {
213242
let mut final_hashes: u64;
214243
let mut final_elapsed: f64;
215244
let mut current_challenge_id = String::new();
245+
let mut last_active_challenge_data: Option<ChallengeData> = None; // ADDED: Store last valid challenge data
216246

217247
loop {
218-
let challenge_params = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
219-
Ok(Some(p)) => p,
248+
let challenge_params: ChallengeData = match utils::get_challenge_params(&context.client, &context.api_url, context.cli_challenge, &mut current_challenge_id) {
249+
Ok(Some(p)) => {
250+
last_active_challenge_data = Some(p.clone()); // Store on success
251+
p
252+
},
220253
Ok(None) => continue,
221254
Err(e) => {
222-
eprintln!("⚠️ Could not fetch active challenge (Ephemeral Key Mode): {}. Retrying in 5 minutes...", e);
223-
std::thread::sleep(std::time::Duration::from_secs(5 * 60));
224-
continue;
255+
// NEW LOGIC: If a challenge ID is set AND we detect a network failure, continue mining.
256+
if !current_challenge_id.is_empty() && e.contains("API request failed") {
257+
eprintln!("⚠️ Challenge API poll failed (Network Error): {}. Continuing mining with previous challenge parameters (ID: {})...", e, current_challenge_id);
258+
last_active_challenge_data.as_ref().cloned().ok_or_else(|| {
259+
format!("FATAL LOGIC ERROR: Challenge ID {} is set but no previous challenge data was stored.", current_challenge_id)
260+
})?
261+
} else {
262+
eprintln!("⚠️ Could not fetch active challenge (Ephemeral Key Mode): {}. Retrying in 5 minutes...", e);
263+
std::thread::sleep(std::time::Duration::from_secs(5 * 60));
264+
continue;
265+
}
225266
}
226267
};
227268

0 commit comments

Comments
 (0)