Skip to content

Commit 07b44f1

Browse files
author
BitcoinTsunami
committed
wallet: fix ComputeTimeSmart algorithm to use blocktime during old block rescanning
1 parent 09cb5ec commit 07b44f1

File tree

2 files changed

+41
-36
lines changed

2 files changed

+41
-36
lines changed

src/wallet/wallet.cpp

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
884884
return false;
885885
}
886886

887-
CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose)
887+
CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose, bool rescanning_old_block)
888888
{
889889
LOCK(cs_wallet);
890890

@@ -914,7 +914,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmatio
914914
wtx.nTimeReceived = chain().getAdjustedTime();
915915
wtx.nOrderPos = IncOrderPosNext(&batch);
916916
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
917-
wtx.nTimeSmart = ComputeTimeSmart(wtx);
917+
wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
918918
AddToSpends(hash, &batch);
919919
}
920920

@@ -1031,7 +1031,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
10311031
return true;
10321032
}
10331033

1034-
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate)
1034+
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate, bool rescanning_old_block)
10351035
{
10361036
const CTransaction& tx = *ptx;
10371037
{
@@ -1069,7 +1069,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
10691069

10701070
// Block disconnection override an abandoned tx as unconfirmed
10711071
// which means user may have to call abandontransaction again
1072-
return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false);
1072+
return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false, rescanning_old_block);
10731073
}
10741074
}
10751075
return false;
@@ -1198,9 +1198,9 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
11981198
}
11991199
}
12001200

1201-
void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx)
1201+
void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx, bool rescanning_old_block)
12021202
{
1203-
if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
1203+
if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx, rescanning_old_block))
12041204
return; // Not one of ours
12051205

12061206
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1643,7 +1643,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
16431643
break;
16441644
}
16451645
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
1646-
SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
1646+
SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate, /* rescanning_old_block */ true);
16471647
}
16481648
// scan succeeded, record block as most recent successfully scanned
16491649
result.last_scanned_block = block_hash;
@@ -2398,38 +2398,43 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
23982398
* https://bitcointalk.org/?topic=54527, or
23992399
* https://github.com/bitcoin/bitcoin/pull/1393.
24002400
*/
2401-
unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
2401+
unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
24022402
{
24032403
unsigned int nTimeSmart = wtx.nTimeReceived;
24042404
if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
24052405
int64_t blocktime;
2406-
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
2407-
int64_t latestNow = wtx.nTimeReceived;
2408-
int64_t latestEntry = 0;
2409-
2410-
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2411-
int64_t latestTolerated = latestNow + 300;
2412-
const TxItems& txOrdered = wtxOrdered;
2413-
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2414-
CWalletTx* const pwtx = it->second;
2415-
if (pwtx == &wtx) {
2416-
continue;
2417-
}
2418-
int64_t nSmartTime;
2419-
nSmartTime = pwtx->nTimeSmart;
2420-
if (!nSmartTime) {
2421-
nSmartTime = pwtx->nTimeReceived;
2422-
}
2423-
if (nSmartTime <= latestTolerated) {
2424-
latestEntry = nSmartTime;
2425-
if (nSmartTime > latestNow) {
2426-
latestNow = nSmartTime;
2406+
int64_t block_max_time;
2407+
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime).maxTime(block_max_time))) {
2408+
if (rescanning_old_block) {
2409+
nTimeSmart = block_max_time;
2410+
} else {
2411+
int64_t latestNow = wtx.nTimeReceived;
2412+
int64_t latestEntry = 0;
2413+
2414+
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
2415+
int64_t latestTolerated = latestNow + 300;
2416+
const TxItems& txOrdered = wtxOrdered;
2417+
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
2418+
CWalletTx* const pwtx = it->second;
2419+
if (pwtx == &wtx) {
2420+
continue;
2421+
}
2422+
int64_t nSmartTime;
2423+
nSmartTime = pwtx->nTimeSmart;
2424+
if (!nSmartTime) {
2425+
nSmartTime = pwtx->nTimeReceived;
2426+
}
2427+
if (nSmartTime <= latestTolerated) {
2428+
latestEntry = nSmartTime;
2429+
if (nSmartTime > latestNow) {
2430+
latestNow = nSmartTime;
2431+
}
2432+
break;
24272433
}
2428-
break;
24292434
}
2430-
}
24312435

2432-
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2436+
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
2437+
}
24332438
} else {
24342439
WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
24352440
}

src/wallet/wallet.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
272272
* Abandoned state should probably be more carefully tracked via different
273273
* posInBlock signals or by checking mempool presence when necessary.
274274
*/
275-
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
275+
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
276276

277277
/** Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
278278
void MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx);
@@ -284,7 +284,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
284284

285285
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
286286
* Should be called with non-zero block_hash and posInBlock if this is for a transaction that is included in a block. */
287-
void SyncTransaction(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
287+
void SyncTransaction(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool update_tx = true, bool rescanning_old_block = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
288288

289289
/** WalletFlags set on this wallet. */
290290
std::atomic<uint64_t> m_wallet_flags{0};
@@ -484,7 +484,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
484484
bool EncryptWallet(const SecureString& strWalletPassphrase);
485485

486486
void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
487-
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
487+
unsigned int ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const;
488488

489489
/**
490490
* Increment the next transaction order id
@@ -503,7 +503,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
503503
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
504504
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
505505

506-
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true);
506+
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false);
507507
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
508508
void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
509509
void blockConnected(const CBlock& block, int height) override;

0 commit comments

Comments
 (0)