diff --git a/src/qt/forms/notifymnemonic.ui b/src/qt/forms/notifymnemonic.ui index 7a47de8f6f..837e02e9b0 100644 --- a/src/qt/forms/notifymnemonic.ui +++ b/src/qt/forms/notifymnemonic.ui @@ -108,11 +108,21 @@ + + + + + + + + true + + - Please write down these recovery seed phrase and keep them in a secure location. + Please write down these recovery seed phrase and wallet birth date and keep them in a secure location. Specifying the wallet's birth date when restoring your wallet speeds up and optimizes the scanning of your wallet. true diff --git a/src/qt/forms/recover.ui b/src/qt/forms/recover.ui index f8a3db384b..51c7cae951 100644 --- a/src/qt/forms/recover.ui +++ b/src/qt/forms/recover.ui @@ -41,6 +41,7 @@ You can also choose to further encrypt your recovery seed phrase with an additio You will need to save this passphrase as well with the recovery seed phrase. Failing to save the passphrase will lead to your funds being irrecoverable. If you have an existing recovery seed phrase, please select "Recover existing wallet". If you have secured your recovery seed phrase with an additional passphrase, enter it too. +Also you can choose wallet birth date for more faster and optimised wallet scan. @@ -134,20 +135,51 @@ If you have an existing recovery seed phrase, please select "Recover existing wa - + - - - Input recovery seed phrase here: - - - true - - + + + + + Input recovery seed phrase here: + + + true + + + + + + + - - + + + + + Choose the wallet creation date: + + + true + + + + + + + true + + + dd-MM-yyyy + + + + + + + + @@ -234,12 +266,6 @@ If you have an existing recovery seed phrase, please select "Recover existing wa - - - - - color:red; - diff --git a/src/qt/notifymnemonic.cpp b/src/qt/notifymnemonic.cpp index 4b722f68fd..2a852cfdcd 100644 --- a/src/qt/notifymnemonic.cpp +++ b/src/qt/notifymnemonic.cpp @@ -13,6 +13,7 @@ #include #include #include +#include NotifyMnemonic::NotifyMnemonic(QWidget *parent) : QWizard(parent), @@ -36,6 +37,10 @@ void NotifyMnemonic::cancelEvent() } } +QString getCurrentDate() { + return QDate::currentDate().toString("dd-MM-yyyy"); +} + void NotifyMnemonic::notify() { #ifdef ENABLE_WALLET @@ -44,6 +49,7 @@ void NotifyMnemonic::notify() NotifyMnemonic notify; notify.setWindowIcon(QIcon(":icons/firo")); notify.show(); + notify.ui->walletBirthDate->setText("Wallet creation date: " + getCurrentDate()); notify.ui->mnemonic->setText(mnemonic.c_str()); notify.restart(); while(true) diff --git a/src/qt/recover.cpp b/src/qt/recover.cpp index ba0611bebf..6be76c8089 100644 --- a/src/qt/recover.cpp +++ b/src/qt/recover.cpp @@ -31,6 +31,9 @@ Recover::Recover(QWidget *parent) : connect(this, &Recover::stopThread, thread, &QThread::quit); thread->start(); + + ui->dateInput->setDisplayFormat("dd-MM-yyyy"); + ui->dateInput->setMinimumDate(QDate(2019, 12, 11)); } Recover::~Recover() @@ -47,6 +50,8 @@ void Recover::setCreateNew() ui->textLabel2->setEnabled(false); ui->mnemonicWords->setEnabled(false); ui->mnemonicWords->clear(); + ui->dateInput->setEnabled(false); + ui->dateInput->clear(); ui->use24->setChecked(true); ui->usePassphrase->setChecked(false); ui->textLabel3->setEnabled(false); @@ -58,12 +63,18 @@ void Recover::setCreateNew() void Recover::on_createNew_clicked() { setCreateNew(); + ui->dateInput->setDisplayFormat("dd-MM-yyyy"); + ui->dateInput->setDate(QDate(2019, 12, 11)); } void Recover::on_recoverExisting_clicked() { ui->textLabel2->setEnabled(true); ui->mnemonicWords->setEnabled(true); + ui->dateInput->setEnabled(true); + ui->dateInput->setEnabled(true); + ui->dateInput->setDisplayFormat("dd-MM-yyyy"); + ui->dateInput->setDate(ui->dateInput->minimumDate()); } void Recover::on_usePassphrase_clicked() @@ -106,6 +117,10 @@ bool Recover::askRecover(bool& newWallet) if(recover.ui->recoverExisting->isChecked()) { newWallet = false; std::string mnemonic = recover.ui->mnemonicWords->text().toStdString(); + QDate date = recover.ui->dateInput->date(); + QDate newDate = date.addDays(-1); + recover.ui->dateInput->setDate(newDate); + SoftSetArg("-wcdate", recover.ui->dateInput->text().toStdString()); const char* str = mnemonic.c_str(); bool space = true; int n = 0; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f787c8dd5d..4273885fac 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2365,6 +2365,30 @@ void CWalletTx::GetAmounts(std::list& listReceived, } +static std::time_t parseDate(const std::string& dateStr) { + std::tm tm = {}; + std::istringstream ss(dateStr); + ss >> std::get_time(&tm, "%d-%m-%Y"); + if (ss.fail()) { + throw std::invalid_argument("Invalid date format: " + dateStr); + } + return std::mktime(&tm); +} + +CBlockIndex* CWallet::GetBlockByDate(CBlockIndex* pindexStart, const std::string& dateStr) { + std::time_t targetTimestamp = parseDate(dateStr); + + CBlockIndex* pindex = pindexStart; + + while (pindex) { + if (pindex->GetBlockTime() > targetTimestamp) { + return chainActive[pindex->nHeight - 200]; + } + pindex = chainActive.Next(pindex); + } + return chainActive[chainActive.Tip()->nHeight]; +} + /** * Scan the block chain (starting in pindexStart) for transactions * from or to us. If fUpdate is true, found transactions that already @@ -2383,18 +2407,34 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex *pindexStart, bool f CBlockIndex* pindex = pindexStart; { LOCK2(cs_main, cs_wallet); - - // no need to read and scan block, if block was created before - // our wallet birthday (as adjusted for block time variability) - // if you are recovering wallet with mnemonics start rescan from block when mnemonics implemented in Firo - if (fRecoverMnemonic) { - pindex = chainActive[chainParams.GetConsensus().nMnemonicBlock]; - if (pindex == NULL) - pindex = chainActive.Tip(); - } else - while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200))) - pindex = chainActive.Next(pindex); - + // No need to read and scan block if block was created before our wallet birthday (as adjusted for block time variability). + // If you are recovering wallet with mnemonics, start rescan from the block when mnemonics were implemented in Firo. + // If the user provides a date, start scanning from the block that corresponds to that date. + // If no date is provided, start scanning from the mnemonic start block. + + std::string wcdate = GetArg("-wcdate", ""); + CBlockIndex* mnemonicStartBlock = chainActive[chainParams.GetConsensus().nMnemonicBlock]; + if (mnemonicStartBlock == NULL) + mnemonicStartBlock = chainActive.Tip(); + + if (!wcdate.empty()) { + pindex = GetBlockByDate(mnemonicStartBlock, wcdate); + if (pindex->nHeight < chainParams.GetConsensus().nMnemonicBlock) { + pindex = mnemonicStartBlock; + } + } else { + bool fRescan = GetBoolArg("-rescan", false); + if (fRescan || fRecoverMnemonic) { + if (mnemonicContainer.IsNull()) + pindex = chainActive.Genesis(); + else + pindex = mnemonicStartBlock; + } + else + while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200))) + pindex = chainActive.Next(pindex); + } + LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height(), pindex->nHeight); ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup double dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex); double dProgressTip = GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()); @@ -7285,7 +7325,6 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } uiInterface.InitMessage(_("Rescanning...")); - LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); nStart = GetTimeMillis(); walletInstance->ScanForWalletTransactions(pindexRescan, true, fRecoverMnemonic); LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ab6e98fd7d..f9397f5150 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -929,6 +929,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override; bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fRecoverMnemonic = false); + CBlockIndex* GetBlockByDate(CBlockIndex* pindexStart, const std::string& dateStr); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; std::vector ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);