Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wallet scan optimisation #1474

Merged
merged 10 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/qt/forms/notifymnemonic.ui
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,21 @@
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="walletBirthDate">
<property name="text">
<string></string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Please write down these recovery seed phrase and keep them in a secure location.</string>
<string>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.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
Expand Down
60 changes: 43 additions & 17 deletions src/qt/forms/recover.ui
Original file line number Diff line number Diff line change
Expand Up @@ -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.
</string>
</property>
<property name="wordWrap">
Expand Down Expand Up @@ -134,20 +135,51 @@ If you have an existing recovery seed phrase, please select "Recover existing wa
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout2">
<layout class="QVBoxLayout" name="verticalLayout2">
<item>
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Input recovery seed phrase here:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout2">
<item>
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Input recovery seed phrase here:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mnemonicWords"/>
</item>
</layout>
</item>
<item>
<widget class="QLineEdit" name="mnemonicWords"/>
</item>
<layout class="QHBoxLayout" name="horizontalLayoutDate">
<item>
<widget class="QLabel" name="textLabelDate">
<property name="text">
<string>Choose the wallet creation date:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="dateInput">
<property name="calendarPopup">
<bool>true</bool>
</property>
<property name="displayFormat">
<string>dd-MM-yyyy</string>
</property>
<property name="date">
</property>
</widget>
</item>
</layout>
</item>

</layout>
</item>
<item>
Expand Down Expand Up @@ -234,12 +266,6 @@ If you have an existing recovery seed phrase, please select "Recover existing wa
</item>
<item>
<widget class="QLabel" name="errorMessage">
<property name="text">
<string/>
</property>
<property name="styleSheet">
<string notr="true">color:red;</string>
</property>
<property name="text">
<string/>
</property>
Expand Down
6 changes: 6 additions & 0 deletions src/qt/notifymnemonic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <QSettings>
#include <QMessageBox>
#include <QAbstractButton>
#include <QDate>

NotifyMnemonic::NotifyMnemonic(QWidget *parent) :
QWizard(parent),
Expand All @@ -36,6 +37,10 @@ void NotifyMnemonic::cancelEvent()
}
}

QString getCurrentDate() {
return QDate::currentDate().toString("dd-MM-yyyy");
}

void NotifyMnemonic::notify()
{
#ifdef ENABLE_WALLET
Expand All @@ -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)
Expand Down
15 changes: 15 additions & 0 deletions src/qt/recover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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);
Expand All @@ -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()
Expand Down Expand Up @@ -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;
Expand Down
61 changes: 49 additions & 12 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2364,6 +2364,30 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& 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
Expand All @@ -2382,18 +2406,32 @@ 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 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];
levoncrypto marked this conversation as resolved.
Show resolved Hide resolved
if (!wcdate.empty()) {
pindex = GetBlockByDate(mnemonicStartBlock, wcdate);
if (pindex->nHeight < chainParams.GetConsensus().nMnemonicBlock) {
pindex = chainActive[chainParams.GetConsensus().nMnemonicBlock];
levoncrypto marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
bool fRescan = GetBoolArg("-rescan", false);
if (fRescan) {
levoncrypto marked this conversation as resolved.
Show resolved Hide resolved
if (nTimeFirstKey < mnemonicStartBlock->GetBlockTime())
pindex = chainActive.Genesis();
levoncrypto marked this conversation as resolved.
Show resolved Hide resolved
else
pindex = mnemonicStartBlock;
}
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 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);

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());
Expand Down Expand Up @@ -7284,7 +7322,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);
Expand Down
1 change: 1 addition & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint256> ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman);
Expand Down
Loading