auto *fromDateEdit = new QDateEdit(QDate::currentDate().addDays(-defaultDays));
fromDateEdit->setCalendarPopup(true);
fromDateEdit->setDisplayFormat("yyyy-MM-dd");
- fromDateEdit->setCalendarPopup(true);
- fromDateEdit->setDisplayFormat("yyyy-MM-dd");
fromDateEdit->setToolTip(tr("Calculated from 'End date' and day span."));
-
- toDateEdit->setCalendarPopup(true);
- toDateEdit->setDisplayFormat("yyyy-MM-dd");
-
auto *infoLabel = new QLabel;
infoLabel->setWordWrap(true);
infoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; }");
} else {
// Calculate depth
quint64 blocksLeft = (target > height) ? (target - height) : 0;
- // Estimate download size in MB: assuming 500 MB for full history,
- // and we are blocksLeft behind out of (target-1) total blocks (since block 0 is genesis)
- double approximateSizeMB = 0.0;
+ // Estimate download size
+ QString sizeText;
if (target > 1) {
quint64 estimatedBytes = Utils::estimateSyncDataSize(blocksLeft);
sizeText = Utils::formatBytes(estimatedBytes);
}
QString statusMsg = Utils::formatSyncStatus(height, target, daemonSync);
- // Shows "# blocks remaining (approx. X MB)" to sync
- // Shows "Wallet sync: # blocks remaining (approx. X MB)"
- this->setStatusText(QString("%1 (approx. %2)").arg(statusMsg).arg(sizeText));
+ // Show size estimate only if available
+ if (!sizeText.isEmpty()) {
+ this->setStatusText(QString("%1 (approx. %2)").arg(statusMsg).arg(sizeText));
+ } else {
+ this->setStatusText(statusMsg);
+ }
}
m_statusLabelStatus->setToolTip(QString("Wallet Height: %1 | Network Tip: %2").arg(height).arg(target));
}
// Stop Tor manager threads
torManager()->stop();
- // Wait for all threads in the global thread pool
- QThreadPool::globalInstance()->waitForDone();
+ // Wait for all threads in the global thread pool with timeout to prevent indefinite blocking
+ if (!QThreadPool::globalInstance()->waitForDone(15000)) {
+ qCritical() << "WindowManager: Thread pool tasks did not complete within 30s timeout. "
+ << "Forcing exit to prevent use-after-free.";
+ std::_Exit(1); // Fast exit without cleanup - threads may still hold resources
+ }
for (const auto &window: m_windows) {
window->close();
cryptonote::network_type nettype = m_wallet2->nettype();
QString filename = Utils::getRestoreHeightFilename(static_cast<NetworkType::Type>(nettype));
- auto lookup = RestoreHeightLookup::fromFile(filename, static_cast<NetworkType::Type>(nettype));
+ std::unique_ptr<RestoreHeightLookup> lookup(RestoreHeightLookup::fromFile(filename, static_cast<NetworkType::Type>(nettype)));
uint64_t startHeight = lookup->dateToHeight(start.startOfDay().toSecsSinceEpoch());
uint64_t endHeight = lookup->dateToHeight(end.startOfDay().toSecsSinceEpoch());
- delete lookup;
if (startHeight >= endHeight)
return;
if (!storedHeight.isEmpty()) {
originalHeight = storedHeight.toULongLong();
} else {
- // Fallback (dangerous if skipped, but better than 0)
+ // Fallback: if skipToTip() was used, this may be the current tip, missing all transactions
originalHeight = m_wallet2->get_refresh_from_block_height();
->>>>>>> 43ee0e4e (Implement Skip Sync and Data Saving features)
+ qWarning() << "fullSync: No stored creation height found (feather.creation_height). "
+ << "Falling back to current refresh height:" << originalHeight
+ << ". This may miss transactions if skipToTip() was previously used.";
}
m_wallet2->set_refresh_from_block_height(originalHeight);
m_wallet2->scan_tx(txids);
qInfo() << "Successfully imported transaction:" << txid;
this->updateBalance();
+ this->history()->refresh();
return true;
} catch (const std::exception &e) {
qWarning() << "Failed to import transaction: " << txid << ", error: " << e.what();
QTimer *m_storeTimer = nullptr;
std::set<std::string> m_selectedInputs;
- uint64_t m_stopHeight = 0;
- bool m_rangeSyncActive = false;
+ std::atomic<quint64> m_stopHeight{0};
+ std::atomic<bool> m_rangeSyncActive{false};
};
#endif // FEATHER_WALLET_H
if (tooltip) {
*tooltip = QString("Wallet Height: %1 | Network Tip: %2").arg(walletHeight).arg(daemonHeight);
}
+ quint64 blocksBehind = (daemonHeight > startHeight) ? (daemonHeight - startHeight) : 0;
if (blocksBehind == 0) {
return "[PAUSED] Sync paused";
}