mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
wallet: fix ComputeTimeSmart algorithm to use blocktime during old block rescanning
This commit is contained in:
parent
09cb5ec6c8
commit
07b44f16e7
@ -884,7 +884,7 @@ bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
|
||||
return false;
|
||||
}
|
||||
|
||||
CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose)
|
||||
CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose, bool rescanning_old_block)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
||||
@ -914,7 +914,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmatio
|
||||
wtx.nTimeReceived = chain().getAdjustedTime();
|
||||
wtx.nOrderPos = IncOrderPosNext(&batch);
|
||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
||||
wtx.nTimeSmart = ComputeTimeSmart(wtx);
|
||||
wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
|
||||
AddToSpends(hash, &batch);
|
||||
}
|
||||
|
||||
@ -1031,7 +1031,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate)
|
||||
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool fUpdate, bool rescanning_old_block)
|
||||
{
|
||||
const CTransaction& tx = *ptx;
|
||||
{
|
||||
@ -1069,7 +1069,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
|
||||
|
||||
// Block disconnection override an abandoned tx as unconfirmed
|
||||
// which means user may have to call abandontransaction again
|
||||
return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false);
|
||||
return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false, rescanning_old_block);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1198,9 +1198,9 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx)
|
||||
void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, bool update_tx, bool rescanning_old_block)
|
||||
{
|
||||
if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx))
|
||||
if (!AddToWalletIfInvolvingMe(ptx, confirm, update_tx, rescanning_old_block))
|
||||
return; // Not one of ours
|
||||
|
||||
// If a transaction changes 'conflicted' state, that changes the balance
|
||||
@ -1643,7 +1643,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
|
||||
break;
|
||||
}
|
||||
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
|
||||
SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate);
|
||||
SyncTransaction(block.vtx[posInBlock], {CWalletTx::Status::CONFIRMED, block_height, block_hash, (int)posInBlock}, fUpdate, /* rescanning_old_block */ true);
|
||||
}
|
||||
// scan succeeded, record block as most recent successfully scanned
|
||||
result.last_scanned_block = block_hash;
|
||||
@ -2398,38 +2398,43 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
|
||||
* https://bitcointalk.org/?topic=54527, or
|
||||
* https://github.com/bitcoin/bitcoin/pull/1393.
|
||||
*/
|
||||
unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const
|
||||
unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const
|
||||
{
|
||||
unsigned int nTimeSmart = wtx.nTimeReceived;
|
||||
if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
|
||||
int64_t blocktime;
|
||||
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
|
||||
int64_t latestNow = wtx.nTimeReceived;
|
||||
int64_t latestEntry = 0;
|
||||
int64_t block_max_time;
|
||||
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime).maxTime(block_max_time))) {
|
||||
if (rescanning_old_block) {
|
||||
nTimeSmart = block_max_time;
|
||||
} else {
|
||||
int64_t latestNow = wtx.nTimeReceived;
|
||||
int64_t latestEntry = 0;
|
||||
|
||||
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
|
||||
int64_t latestTolerated = latestNow + 300;
|
||||
const TxItems& txOrdered = wtxOrdered;
|
||||
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
|
||||
CWalletTx* const pwtx = it->second;
|
||||
if (pwtx == &wtx) {
|
||||
continue;
|
||||
}
|
||||
int64_t nSmartTime;
|
||||
nSmartTime = pwtx->nTimeSmart;
|
||||
if (!nSmartTime) {
|
||||
nSmartTime = pwtx->nTimeReceived;
|
||||
}
|
||||
if (nSmartTime <= latestTolerated) {
|
||||
latestEntry = nSmartTime;
|
||||
if (nSmartTime > latestNow) {
|
||||
latestNow = nSmartTime;
|
||||
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
|
||||
int64_t latestTolerated = latestNow + 300;
|
||||
const TxItems& txOrdered = wtxOrdered;
|
||||
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
|
||||
CWalletTx* const pwtx = it->second;
|
||||
if (pwtx == &wtx) {
|
||||
continue;
|
||||
}
|
||||
int64_t nSmartTime;
|
||||
nSmartTime = pwtx->nTimeSmart;
|
||||
if (!nSmartTime) {
|
||||
nSmartTime = pwtx->nTimeReceived;
|
||||
}
|
||||
if (nSmartTime <= latestTolerated) {
|
||||
latestEntry = nSmartTime;
|
||||
if (nSmartTime > latestNow) {
|
||||
latestNow = nSmartTime;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
|
||||
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
|
||||
}
|
||||
} else {
|
||||
WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ private:
|
||||
* Abandoned state should probably be more carefully tracked via different
|
||||
* posInBlock signals or by checking mempool presence when necessary.
|
||||
*/
|
||||
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool fUpdate, bool rescanning_old_block) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/** Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
|
||||
void MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx);
|
||||
@ -284,7 +284,7 @@ private:
|
||||
|
||||
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
|
||||
* Should be called with non-zero block_hash and posInBlock if this is for a transaction that is included in a block. */
|
||||
void SyncTransaction(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void SyncTransaction(const CTransactionRef& tx, CWalletTx::Confirmation confirm, bool update_tx = true, bool rescanning_old_block = false) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/** WalletFlags set on this wallet. */
|
||||
std::atomic<uint64_t> m_wallet_flags{0};
|
||||
@ -484,7 +484,7 @@ public:
|
||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||
|
||||
void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
|
||||
unsigned int ComputeTimeSmart(const CWalletTx& wtx, bool rescanning_old_block) const;
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
@ -503,7 +503,7 @@ public:
|
||||
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
|
||||
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
|
||||
|
||||
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true);
|
||||
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false);
|
||||
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
|
||||
void blockConnected(const CBlock& block, int height) override;
|
||||
|
Loading…
Reference in New Issue
Block a user