Skip to content

Commit c2475f4

Browse files
committed
fix double solve problem
1 parent fc3f06f commit c2475f4

File tree

1 file changed

+95
-59
lines changed

1 file changed

+95
-59
lines changed

src/main.rs

Lines changed: 95 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,84 @@ impl<'a> DataDir<'a> {
390390
}
391391
}
392392

393+
fn next_wallet_deriv_index_for_challenge(
394+
base_dir: &Option<String>,
395+
challenge_id: &str,
396+
data_dir_for_path: &DataDir
397+
) -> Result<u32, String> {
398+
399+
// Always start from 0 for the check
400+
const START_INDEX: u32 = 0;
401+
402+
Ok(if let Some(data_base_dir) = base_dir {
403+
404+
let temp_data_dir_mnemonic = match data_dir_for_path {
405+
DataDir::Mnemonic(wallet) => DataDir::Mnemonic(DataDirMnemonic {
406+
mnemonic: wallet.mnemonic,
407+
account: wallet.account,
408+
deriv_index: 0,
409+
}),
410+
_ => return Err("next_wallet_deriv_index_for_challenge called with non-Mnemonic DataDir".to_string()),
411+
};
412+
413+
let mut account_dir = temp_data_dir_mnemonic.receipt_dir(data_base_dir, challenge_id)?;
414+
account_dir.pop();
415+
416+
// --- GATHER AND PARSE INDICES ---
417+
let mut parsed_indices: Vec<u32> = std::fs::read_dir(&account_dir)
418+
.map_err(|e| format!("Could not read the mnemonic's account dir: {}", e))?
419+
.filter_map(|entry| entry.ok().map(|e| e.path()))
420+
.filter(|path| {
421+
// Check if the directory path points to a valid index directory
422+
path.file_stem().and_then(OsStr::to_str).and_then(|s| s.parse::<u32>().ok()).is_some()
423+
})
424+
.filter(|path| {
425+
// Check if the receipt file exists inside this index directory
426+
let mut receipt_path = path.clone();
427+
receipt_path.push(FILE_NAME_RECEIPT);
428+
429+
match std::fs::exists(&receipt_path) {
430+
Err(e) => {
431+
eprintln!("Could not check for receipt at {:?}: {}", path, e);
432+
true // Treat error as receipt existing to avoid retrying a potentially problematic index
433+
},
434+
Ok(exists) => exists,
435+
}
436+
})
437+
.filter_map(|path| path.file_stem()
438+
.and_then(OsStr::to_str)
439+
.and_then(|s| s.parse::<u32>().ok()))
440+
.collect();
441+
442+
parsed_indices.sort();
443+
444+
if parsed_indices.is_empty() {
445+
eprintln!("no highest index: using {}", START_INDEX);
446+
START_INDEX
447+
} else {
448+
// --- CHECK FOR GAPS ---
449+
let mut expected_index = START_INDEX;
450+
for &index in parsed_indices.iter() {
451+
if index > expected_index {
452+
// Gap found: an index is missing a receipt. Return the missing index.
453+
eprintln!("Gap found in receipts. Highest continuous index is {}. Retrying missing index {}.", expected_index.wrapping_sub(1), expected_index);
454+
return Ok(expected_index);
455+
}
456+
// Move to the next expected index
457+
expected_index = index.wrapping_add(1);
458+
}
459+
460+
// --- NO GAPS FOUND ---
461+
// The next index to mine is the one that was *expected* after the last saved index.
462+
expected_index
463+
}
464+
} else {
465+
// If no data_dir is provided, always start at 0.
466+
START_INDEX
467+
})
468+
}
469+
470+
393471
/// Runs the main application logic based on CLI flags.
394472
fn run_app(cli: Cli) -> Result<(), String> {
395473
// 1. Check for --api-url
@@ -510,8 +588,8 @@ fn run_app(cli: Cli) -> Result<(), String> {
510588
Ok(Some(params)) => params,
511589
Ok(None) => continue, // Continue polling after sleep/wait
512590
Err(e) => {
513-
eprintln!("⚠️ Critical API Error during challenge check: {}. Retrying in 5 minutes...", e);
514-
thread::sleep(Duration::from_secs(5 * 60));
591+
eprintln!("⚠️ Critical API Error during challenge check: {}. Retrying in 1 minute...", e);
592+
thread::sleep(Duration::from_secs(60));
515593
continue;
516594
}
517595
};
@@ -595,8 +673,8 @@ fn run_app(cli: Cli) -> Result<(), String> {
595673
if let Some(ref mnemonic_phrase) = mnemonic {
596674

597675
let reg_message = tc_response.message.clone();
598-
// Start at derivation index 0 or CLI flag passed in if resuming
599-
let mut wallet_deriv_index: u32 = cli.mnemonic_starting_index;
676+
// ⭐ REMOVED cli.mnemonic_starting_index, now initialized to 0 implicitly via gap check
677+
let mut wallet_deriv_index: u32 = 0;
600678
let mut first_run = true;
601679
let mut max_registered_index = None;
602680
let mut backoff_challenge = Backoff::new(5, 300, 2.0);
@@ -613,6 +691,7 @@ fn run_app(cli: Cli) -> Result<(), String> {
613691

614692
// Outer Polling loop (robustly checks for challenge changes)
615693
loop {
694+
// DataDir is constructed with the current index, used for the current wallet and for path generation in the gap check.
616695
let data_dir = DataDir::Mnemonic(DataDirMnemonic {
617696
mnemonic: mnemonic_phrase,
618697
account: cli.mnemonic_account,
@@ -627,66 +706,20 @@ fn run_app(cli: Cli) -> Result<(), String> {
627706
// which is exactly the point of increasing the wallet derivation path index.
628707
current_challenge_id.clear();
629708

630-
fn next_wallet_deriv_index_for_challenge(base_dir: &Option<String>, data_dir: &DataDir, challenge_id: &str) -> Result<u32, String> {
631-
let initial_deriv_index = match data_dir {
632-
DataDir::Mnemonic(wallet) => wallet.deriv_index,
633-
// Handle other DataDir variants if necessary, or panic/return an error
634-
// for cases where deriv_index is not applicable/available.
635-
// For this specific logic, we assume it's only called with DataDir::Mnemonic.
636-
_ => return Err("next_wallet_deriv_index_for_challenge called with non-Mnemonic DataDir".to_string()),
637-
};
638-
Ok(if let Some(data_base_dir) = base_dir {
639-
let mut account_dir = data_dir.receipt_dir(data_base_dir, challenge_id)?;
640-
account_dir.pop();
641-
642-
let mut indices: Vec<String> = std::fs::read_dir(&account_dir)
643-
.map_err(|e| format!("Could not read the mnemonic's account dir: {}", e))?
644-
.filter_map(|entry| entry.ok().map(|e| e.path()))
645-
.filter(|path| {
646-
let mut receipt_path = path.clone();
647-
receipt_path.push(FILE_NAME_RECEIPT);
648-
649-
match std::fs::exists(&receipt_path) {
650-
Err(e) => {
651-
eprintln!("Could not check for receipt: {}", e);
652-
true // better to skip an index than to solve the challenge twice
653-
},
654-
Ok(exists) => exists,
655-
}
656-
})
657-
.filter_map(|path| path.file_stem()
658-
.and_then(OsStr::to_str)
659-
.map(ToOwned::to_owned))
660-
.collect();
661-
662-
indices.sort();
663-
664-
if let Some(highest_index_string) = indices.pop() {
665-
let highest_index = highest_index_string.parse::<u32>()
666-
.map_err(|e| format!("Wallet derivation index directory name is not a positive integer: {}", e))?;
667-
if initial_deriv_index > highest_index {
668-
eprintln!("Using initial deriv_index {} which is higher than highest existing index {}", initial_deriv_index, highest_index);
669-
initial_deriv_index
670-
} else {
671-
highest_index + 1
672-
}
673-
} else {
674-
eprintln!("no highest index: using {}", initial_deriv_index);
675-
initial_deriv_index
676-
}
677-
} else {
678-
0
679-
})
680-
}
681-
682709
// Get challenge parameters (fixed or dynamic)
683710
let challenge_params = match get_challenge_params(&client, &api_url, cli_challenge_ref, &mut current_challenge_id) {
684711
Ok(Some(params)) => {
685712
backoff_challenge.reset();
686713

687-
// Reset index only if we saw a new challenge
714+
// ⭐ Index reset logic simplified: Always check for the next index from 0 on a new challenge
688715
if first_run || (cli_challenge_ref.is_none() && params.challenge_id != old_challenge_id) {
689-
wallet_deriv_index = next_wallet_deriv_index_for_challenge(&cli.data_dir, &data_dir, &params.challenge_id)?;
716+
717+
// ⭐ Simplified call: default_start_index is always 0, as per request
718+
wallet_deriv_index = next_wallet_deriv_index_for_challenge(
719+
&cli.data_dir,
720+
&params.challenge_id,
721+
&data_dir
722+
)?;
690723
}
691724

692725
// Update last seen only on success
@@ -778,10 +811,13 @@ fn run_app(cli: Cli) -> Result<(), String> {
778811
if let Some(ref base_dir) = cli.data_dir {
779812
data_dir.save_receipt(base_dir, &challenge_params.challenge_id, &receipt, &donation)?;
780813
}
814+
// Index must be incremented after a successful submit
815+
wallet_deriv_index = wallet_deriv_index.wrapping_add(1);
816+
println!("\n✅ Solution submitted. Incrementing index to {}.", wallet_deriv_index);
781817
},
782818
MiningResult::AlreadySolved => {
783819
wallet_deriv_index = wallet_deriv_index.wrapping_add(1);
784-
println!("\nCycle complete. Incrementing index to {}.", wallet_deriv_index);
820+
println!("\nChallenge already solved. Incrementing index to {}.", wallet_deriv_index);
785821
// The outer loop restarts, calling get_challenge_params again.
786822
}
787823
MiningResult::MiningFailed => {

0 commit comments

Comments
 (0)