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;
|
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);
|
LOCK(cs_wallet);
|
||||||
|
|
||||||
@ -914,7 +914,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmatio
|
|||||||
wtx.nTimeReceived = chain().getAdjustedTime();
|
wtx.nTimeReceived = chain().getAdjustedTime();
|
||||||
wtx.nOrderPos = IncOrderPosNext(&batch);
|
wtx.nOrderPos = IncOrderPosNext(&batch);
|
||||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
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);
|
AddToSpends(hash, &batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,7 +1031,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
|
|||||||
return true;
|
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;
|
const CTransaction& tx = *ptx;
|
||||||
{
|
{
|
||||||
@ -1069,7 +1069,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
|
|||||||
|
|
||||||
// Block disconnection override an abandoned tx as unconfirmed
|
// Block disconnection override an abandoned tx as unconfirmed
|
||||||
// which means user may have to call abandontransaction again
|
// 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;
|
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
|
return; // Not one of ours
|
||||||
|
|
||||||
// If a transaction changes 'conflicted' state, that changes the balance
|
// If a transaction changes 'conflicted' state, that changes the balance
|
||||||
@ -1643,7 +1643,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
|
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
|
// scan succeeded, record block as most recent successfully scanned
|
||||||
result.last_scanned_block = block_hash;
|
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://bitcointalk.org/?topic=54527, or
|
||||||
* https://github.com/bitcoin/bitcoin/pull/1393.
|
* 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;
|
unsigned int nTimeSmart = wtx.nTimeReceived;
|
||||||
if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
|
if (!wtx.isUnconfirmed() && !wtx.isAbandoned()) {
|
||||||
int64_t blocktime;
|
int64_t blocktime;
|
||||||
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime))) {
|
int64_t block_max_time;
|
||||||
int64_t latestNow = wtx.nTimeReceived;
|
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().time(blocktime).maxTime(block_max_time))) {
|
||||||
int64_t latestEntry = 0;
|
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
|
// Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
|
||||||
int64_t latestTolerated = latestNow + 300;
|
int64_t latestTolerated = latestNow + 300;
|
||||||
const TxItems& txOrdered = wtxOrdered;
|
const TxItems& txOrdered = wtxOrdered;
|
||||||
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
|
for (auto it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
|
||||||
CWalletTx* const pwtx = it->second;
|
CWalletTx* const pwtx = it->second;
|
||||||
if (pwtx == &wtx) {
|
if (pwtx == &wtx) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int64_t nSmartTime;
|
int64_t nSmartTime;
|
||||||
nSmartTime = pwtx->nTimeSmart;
|
nSmartTime = pwtx->nTimeSmart;
|
||||||
if (!nSmartTime) {
|
if (!nSmartTime) {
|
||||||
nSmartTime = pwtx->nTimeReceived;
|
nSmartTime = pwtx->nTimeReceived;
|
||||||
}
|
}
|
||||||
if (nSmartTime <= latestTolerated) {
|
if (nSmartTime <= latestTolerated) {
|
||||||
latestEntry = nSmartTime;
|
latestEntry = nSmartTime;
|
||||||
if (nSmartTime > latestNow) {
|
if (nSmartTime > latestNow) {
|
||||||
latestNow = nSmartTime;
|
latestNow = nSmartTime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
|
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WalletLogPrintf("%s: found %s in block %s not in index\n", __func__, wtx.GetHash().ToString(), wtx.m_confirm.hashBlock.ToString());
|
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
|
* Abandoned state should probably be more carefully tracked via different
|
||||||
* posInBlock signals or by checking mempool presence when necessary.
|
* 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. */
|
/** 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);
|
void MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx);
|
||||||
@ -284,7 +284,7 @@ private:
|
|||||||
|
|
||||||
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
|
/* 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. */
|
* 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. */
|
/** WalletFlags set on this wallet. */
|
||||||
std::atomic<uint64_t> m_wallet_flags{0};
|
std::atomic<uint64_t> m_wallet_flags{0};
|
||||||
@ -484,7 +484,7 @@ public:
|
|||||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||||
|
|
||||||
void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
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
|
* 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
|
//! @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)>;
|
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);
|
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 transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
|
||||||
void blockConnected(const CBlock& block, int height) override;
|
void blockConnected(const CBlock& block, int height) override;
|
||||||
|
Loading…
Reference in New Issue
Block a user