@@ -767,6 +767,13 @@ int App::runECMMarinTwistedEdwards()
767767 // (options.torsion16 ? string("16") : string("8"));
768768 bool built = false ;
769769
770+ // In-memory checkpoint of the last known good state for fast recovery on errors
771+ std::vector<char > last_good_state;
772+ bool have_last_good_state = false ;
773+ uint32_t last_good_iter = 0 ;
774+ uint32_t current_iter_for_invariant = 0 ;
775+ const size_t ctx_ckpt_size = eng->get_checkpoint_size ();
776+
770777 auto force_on_curve = [&](mpz_class& aE_ref,
771778 mpz_class& dE_ref,
772779 const mpz_class& X,
@@ -873,15 +880,24 @@ int App::runECMMarinTwistedEdwards()
873880 auto lhs = addm (mulm (aE, sqrm (Xv)), sqrm (Yv));
874881 auto rhs = addm (sqrm (Zv), mulm (dE, sqrm (Tv)));
875882 auto rel = subm (lhs, rhs);
876- if (rel != 0 ){std::cout << " [ECM] invariant FAIL (a="
877- << aE << " )\n " ;
878- return false ;
879- }
880- else {
881- std::cout << " [ECM] check invariant OK (a="
882- << aE << " )\n " ;
883- return true ;
884- }
883+ if (rel != 0 ){
884+ std::cout << " [ECM] invariant FAIL (a="
885+ << aE << " )\n " ;
886+ return false ;
887+ }
888+ else {
889+ std::cout << " [ECM] check invariant OK (a="
890+ << aE << " )\n " ;
891+ // Save an in-memory checkpoint of this good state
892+ if (ctx_ckpt_size > 0 ) {
893+ last_good_state.resize (ctx_ckpt_size);
894+ if (eng->get_checkpoint (last_good_state)) {
895+ have_last_good_state = true ;
896+ last_good_iter = current_iter_for_invariant;
897+ }
898+ }
899+ return true ;
900+ }
885901 };
886902
887903 torsion_last = torsion_used;
@@ -1328,7 +1344,20 @@ int App::runECMMarinTwistedEdwards()
13281344
13291345
13301346 bool resumed = (rr == 0 && start_i > 0 );
1331- if (!resumed) { saved_et = 0.0 ; nb_ck = 0 ; }
1347+ if (!resumed) {
1348+ saved_et = 0.0 ;
1349+ nb_ck = 0 ;
1350+ } else {
1351+ // Treat the resumed state as a valid last-good checkpoint
1352+ if (ctx_ckpt_size > 0 ) {
1353+ last_good_state.resize (ctx_ckpt_size);
1354+ if (eng->get_checkpoint (last_good_state)) {
1355+ have_last_good_state = true ;
1356+ last_good_iter = start_i;
1357+ current_iter_for_invariant = start_i;
1358+ }
1359+ }
1360+ }
13321361
13331362 auto t0 = high_resolution_clock::now ();
13341363 auto last_save = t0;
@@ -1395,6 +1424,10 @@ int App::runECMMarinTwistedEdwards()
13951424 }
13961425 }
13971426 bool errordone = false ;
1427+ bool fatal_error = false ;
1428+ if (resume_stage2){
1429+ start_i = total_steps;
1430+ }
13981431 for (uint32_t i = start_i; i < total_steps; ++i) {
13991432 if (core::algo::interrupted) {
14001433 double elapsed = duration<double >(high_resolution_clock::now () - t0).count () + saved_et;
@@ -1440,14 +1473,32 @@ int App::runECMMarinTwistedEdwards()
14401473 }
14411474 }
14421475 auto now = high_resolution_clock::now ();
1443- if (duration_cast<seconds>(now - last_check).count () >= options.ecm_check_interval ) {
1476+ if (duration_cast<seconds>(now - last_check).count () >= options.ecm_check_interval || i+ 1 == total_steps ) {
14441477
14451478 std::cout<<" \n [ECM] Error check ...." <<std::endl;
1479+ // remember which iteration this invariant corresponds to
1480+ current_iter_for_invariant = i + 1 ;
14461481 if (check_invariant ()){
14471482 std::cout<<" [ECM] Error check Done ! ...." <<std::endl;
14481483 }
14491484 else {
14501485 std::cout<<" [ECM] Error detected!!!!!!!! ...." <<std::endl;
1486+ if (have_last_good_state) {
1487+ std::cout << " [ECM] Restoring last known good state at iteration "
1488+ << last_good_iter << " and retrying from there." << std::endl;
1489+ if (eng->set_checkpoint (last_good_state)) {
1490+ // rewind loop to last_good_iter so it will be processed again
1491+ i = (last_good_iter > 0 ) ? (last_good_iter - 1 ) : 0 ;
1492+ last_check = now;
1493+ last_save = now;
1494+ continue ;
1495+ } else {
1496+ std::cout << " [ECM] Failed to restore last good state, aborting curve." << std::endl;
1497+ }
1498+ } else {
1499+ std::cout << " [ECM] No saved good state available, aborting curve." << std::endl;
1500+ }
1501+ fatal_error = true ;
14511502 break ;
14521503 }
14531504 /* std::cout<<"[ECM] Check if factored ...."<<std::endl;
@@ -1487,6 +1538,12 @@ int App::runECMMarinTwistedEdwards()
14871538 mpz_clear (zXpos); mpz_clear (zYpos); mpz_clear (zTpos);
14881539 mpz_clear (zXneg); mpz_clear (zYneg); mpz_clear (zTneg);
14891540
1541+ if (fatal_error) {
1542+ std::cout << " [ECM] Curve " << (c+1 ) << " aborted after unrecoverable error, skipping.\n " ;
1543+ delete eng;
1544+ continue ;
1545+ }
1546+
14901547 mpz_class Zacc = compute_X_with_dots (eng, (engine::Reg)5 , N);
14911548 mpz_class g = gcd_with_dots (Zacc, N);
14921549 if (g == N) {
@@ -1538,13 +1595,6 @@ int App::runECMMarinTwistedEdwards()
15381595 continue;
15391596 }*/
15401597 if (B2 > B1) {
1541- if (check_invariant ()){
1542- std::cout<<" [ECM] Error check Done and OK! ...." <<std::endl;
1543- }
1544- else {
1545- std::cout<<" [ECM] Error detected!!!!!!!! ...." <<std::endl;
1546- continue ;
1547- }
15481598 mpz_class M (1 );
15491599 for (uint64_t q : primesS2_v) mpz_mul_ui (M.get_mpz_t (), M.get_mpz_t (), q);
15501600 uint32_t stage2_bits = (uint32_t )mpz_sizeinbase (M.get_mpz_t (), 2 );
0 commit comments