wallet: Reset reused transactions cache

If a destination is reused we mark the cache of the other transactions going to that destination dirty so they are not accidentally reported as trusted when the cache is hit.
This commit is contained in:
Fabian Jahr
2019-12-31 19:55:18 +01:00
parent 6196e93001
commit 6fc554f591
3 changed files with 63 additions and 5 deletions

View File

@@ -708,7 +708,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
return success;
}
void CWallet::SetUsedDestinationState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used)
void CWallet::SetUsedDestinationState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations)
{
AssertLockHeld(cs_wallet);
const CWalletTx* srctx = GetWalletTx(hash);
@@ -718,7 +718,9 @@ void CWallet::SetUsedDestinationState(WalletBatch& batch, const uint256& hash, u
if (ExtractDestination(srctx->tx->vout[n].scriptPubKey, dst)) {
if (IsMine(dst)) {
if (used && !GetDestData(dst, "used", nullptr)) {
AddDestData(batch, dst, "used", "p"); // p for "present", opposite of absent (null)
if (AddDestData(batch, dst, "used", "p")) { // p for "present", opposite of absent (null)
tx_destinations.insert(dst);
}
} else if (!used && GetDestData(dst, "used", nullptr)) {
EraseDestData(batch, dst, "used");
}
@@ -765,10 +767,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
// Mark used destinations
std::set<CTxDestination> tx_destinations;
for (const CTxIn& txin : wtxIn.tx->vin) {
const COutPoint& op = txin.prevout;
SetUsedDestinationState(batch, op.hash, op.n, true);
SetUsedDestinationState(batch, op.hash, op.n, true, tx_destinations);
}
MarkDestinationsDirty(tx_destinations);
}
// Inserts only if not already there, returns tx inserted or tx found
@@ -3162,6 +3168,21 @@ int64_t CWallet::GetOldestKeyPoolTime()
return oldestKey;
}
void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations) {
for (auto& entry : mapWallet) {
CWalletTx& wtx = entry.second;
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
CTxDestination dst;
if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, dst) && destinations.count(dst)) {
wtx.MarkDirty();
break;
}
}
}
}
std::map<CTxDestination, CAmount> CWallet::GetAddressBalances(interfaces::Chain::Lock& locked_chain)
{
std::map<CTxDestination, CAmount> balances;