diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9e7bba003..b2300c2b4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -977,7 +977,8 @@ void CWallet::MarkDirty() } /** - * Ensure that every note in the wallet has a cached nullifier. + * Ensure that every note in the wallet (for which we possess a spending key) + * has a cached nullifier. */ bool CWallet::UpdateNullifierNoteMap() { @@ -991,16 +992,17 @@ bool CWallet::UpdateNullifierNoteMap() for (std::pair& wtxItem : mapWallet) { for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) { if (!item.second.nullifier) { - auto i = item.first.js; - GetNoteDecryptor(item.second.address, dec); - auto hSig = wtxItem.second.vjoinsplit[i].h_sig( - *pzcashParams, wtxItem.second.joinSplitPubKey); - item.second.nullifier = GetNoteNullifier( - wtxItem.second.vjoinsplit[i], - item.second.address, - dec, - hSig, - item.first.n); + if (GetNoteDecryptor(item.second.address, dec)) { + auto i = item.first.js; + auto hSig = wtxItem.second.vjoinsplit[i].h_sig( + *pzcashParams, wtxItem.second.joinSplitPubKey); + item.second.nullifier = GetNoteNullifier( + wtxItem.second.vjoinsplit[i], + item.second.address, + dec, + hSig, + item.first.n); + } } } UpdateNullifierNoteMapWithTx(wtxItem.second); @@ -1262,7 +1264,9 @@ boost::optional CWallet::GetNoteNullifier(const JSDescription& jsdesc, hSig, (unsigned char) n); auto note = note_pt.note(address); - // SpendingKeys are only available if the wallet is unlocked + // SpendingKeys are only available if: + // - We have them (this isn't a viewing key) + // - The wallet is unlocked libzcash::SpendingKey key; if (GetSpendingKey(address, key)) { ret = note.nullifier(key); @@ -3639,7 +3643,7 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee) * Find notes in the wallet filtered by payment address, min depth and ability to spend. * These notes are decrypted and added to the output parameter vector, outEntries. */ -void CWallet::GetFilteredNotes(std::vector & outEntries, std::string address, int minDepth, bool ignoreSpent) +void CWallet::GetFilteredNotes(std::vector & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable) { bool fFilterAddress = false; libzcash::PaymentAddress filterPaymentAddress; @@ -3677,6 +3681,11 @@ void CWallet::GetFilteredNotes(std::vector & outEntries, st continue; } + // skip notes which cannot be spent + if (ignoreUnspendable && !HaveSpendingKey(pa)) { + continue; + } + int i = jsop.js; // Index into CTransaction.vjoinsplit int j = jsop.n; // Index into JSDescription.ciphertexts diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 878a23a5d..eaaf6bbdf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1121,7 +1121,11 @@ public: void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; } /* Find notes filtered by payment address, min depth, ability to spend */ - void GetFilteredNotes(std::vector & outEntries, std::string address, int minDepth=1, bool ignoreSpent=true); + void GetFilteredNotes(std::vector & outEntries, + std::string address, + int minDepth=1, + bool ignoreSpent=true, + bool ignoreUnspendable=true); };