aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp110
1 files changed, 68 insertions, 42 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 70349b2455..6885499be2 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -589,11 +589,16 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
return false;
}
-void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
+void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch)
{
mapTxSpends.insert(std::make_pair(outpoint, wtxid));
- setLockedCoins.erase(outpoint);
+ if (batch) {
+ UnlockCoin(outpoint, batch);
+ } else {
+ WalletBatch temp_batch(GetDatabase());
+ UnlockCoin(outpoint, &temp_batch);
+ }
std::pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint);
@@ -601,7 +606,7 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
}
-void CWallet::AddToSpends(const uint256& wtxid)
+void CWallet::AddToSpends(const uint256& wtxid, WalletBatch* batch)
{
auto it = mapWallet.find(wtxid);
assert(it != mapWallet.end());
@@ -610,7 +615,7 @@ void CWallet::AddToSpends(const uint256& wtxid)
return;
for (const CTxIn& txin : thisTx.tx->vin)
- AddToSpends(txin.prevout, wtxid);
+ AddToSpends(txin.prevout, wtxid, batch);
}
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
@@ -879,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);
@@ -909,8 +914,8 @@ 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);
- AddToSpends(hash);
+ wtx.nTimeSmart = ComputeTimeSmart(wtx, rescanning_old_block);
+ AddToSpends(hash, &batch);
}
if (!fInsertedNew)
@@ -1026,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;
{
@@ -1064,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;
@@ -1193,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
@@ -1638,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;
@@ -2260,22 +2265,36 @@ bool CWallet::DisplayAddress(const CTxDestination& dest)
return signer_spk_man->DisplayAddress(scriptPubKey, signer);
}
-void CWallet::LockCoin(const COutPoint& output)
+bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
{
AssertLockHeld(cs_wallet);
setLockedCoins.insert(output);
+ if (batch) {
+ return batch->WriteLockedUTXO(output);
+ }
+ return true;
}
-void CWallet::UnlockCoin(const COutPoint& output)
+bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
{
AssertLockHeld(cs_wallet);
- setLockedCoins.erase(output);
+ bool was_locked = setLockedCoins.erase(output);
+ if (batch && was_locked) {
+ return batch->EraseLockedUTXO(output);
+ }
+ return true;
}
-void CWallet::UnlockAllCoins()
+bool CWallet::UnlockAllCoins()
{
AssertLockHeld(cs_wallet);
+ bool success = true;
+ WalletBatch batch(GetDatabase());
+ for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
+ success &= batch.EraseLockedUTXO(*it);
+ }
setLockedCoins.clear();
+ return success;
}
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
@@ -2365,6 +2384,8 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t>& mapKeyBirth) const {
* - If sending a transaction, assign its timestamp to the current time.
* - If receiving a transaction outside a block, assign its timestamp to the
* current time.
+ * - If receiving a transaction during a rescanning process, assign all its
+ * (not already known) transactions' timestamps to the block time.
* - If receiving a block with a future timestamp, assign all its (not already
* known) transactions' timestamps to the current time.
* - If receiving a block with a past timestamp, before the most recent known
@@ -2379,38 +2400,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;
-
- // 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;
+ 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;
+ }
+ 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());
}
@@ -2716,7 +2742,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
_("The wallet will avoid paying less than the minimum relay fee."));
}
- walletInstance->m_confirm_target = args.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
+ walletInstance->m_confirm_target = args.GetIntArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
walletInstance->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
walletInstance->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);