diff options
author | Fabian Jahr <fjahr@protonmail.com> | 2019-12-31 19:55:18 +0100 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2020-02-06 05:17:18 +0000 |
commit | f11872cbf46128e22e33c3138755c4aa32e80de7 (patch) | |
tree | 8f56238d58781f002188ee6ce9dc90981d9060c2 /src | |
parent | 178a8346871e17d621ac780a5c47be65508ce176 (diff) |
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.
Github-Pull: #17843
Rebased-From: 6fc554f591d8ea1681b8bb25aa12da8d4f023f66
Diffstat (limited to 'src')
-rw-r--r-- | src/wallet/wallet.cpp | 27 | ||||
-rw-r--r-- | src/wallet/wallet.h | 8 |
2 files changed, 31 insertions, 4 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4c3b633fe4..fdaafd5189 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1055,7 +1055,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash) return success; } -void CWallet::SetUsedDestinationState(const uint256& hash, unsigned int n, bool used) +void CWallet::SetUsedDestinationState(const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) { const CWalletTx* srctx = GetWalletTx(hash); if (!srctx) return; @@ -1065,7 +1065,9 @@ void CWallet::SetUsedDestinationState(const uint256& hash, unsigned int n, bool if (::IsMine(*this, dst)) { LOCK(cs_wallet); if (used && !GetDestData(dst, "used", nullptr)) { - AddDestData(dst, "used", "p"); // p for "present", opposite of absent (null) + if (AddDestData(dst, "used", "p")) { // p for "present", opposite of absent (null) + tx_destinations.insert(dst); + } } else if (!used && GetDestData(dst, "used", nullptr)) { EraseDestData(dst, "used"); } @@ -1110,10 +1112,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(op.hash, op.n, true); + SetUsedDestinationState(op.hash, op.n, true, tx_destinations); } + + MarkDestinationsDirty(tx_destinations); } // Inserts only if not already there, returns tx inserted or tx found @@ -3793,6 +3799,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; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ee4ac91588..f4f0156b41 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1006,7 +1006,7 @@ public: // Whether this or any known UTXO with the same single key has been spent. bool IsUsedDestination(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - void SetUsedDestinationState(const uint256& hash, unsigned int n, bool used); + void SetUsedDestinationState(const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations); std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const; @@ -1216,6 +1216,12 @@ public: std::set<CTxDestination> GetLabelAddresses(const std::string& label) const; + /** + * Marks all outputs in each one of the destinations dirty, so their cache is + * reset and does not return outdated information. + */ + void MarkDestinationsDirty(const std::set<CTxDestination>& destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error); bool GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error); |