Update wallet logic to account for viewing keys

The wallet code previously assumed that an unlocked wallet would always
have a spending key associated with a note decryptor. Viewing keys break
this assumption.
This commit is contained in:
Jack Grigg 2017-03-08 16:31:59 +13:00
parent e85b33a52e
commit 9a2b8ae57f
No known key found for this signature in database
GPG Key ID: 665DBCD284F7DAFF
2 changed files with 27 additions and 14 deletions

View File

@ -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() bool CWallet::UpdateNullifierNoteMap()
{ {
@ -991,8 +992,8 @@ bool CWallet::UpdateNullifierNoteMap()
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) { for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) { for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) {
if (!item.second.nullifier) { if (!item.second.nullifier) {
if (GetNoteDecryptor(item.second.address, dec)) {
auto i = item.first.js; auto i = item.first.js;
GetNoteDecryptor(item.second.address, dec);
auto hSig = wtxItem.second.vjoinsplit[i].h_sig( auto hSig = wtxItem.second.vjoinsplit[i].h_sig(
*pzcashParams, wtxItem.second.joinSplitPubKey); *pzcashParams, wtxItem.second.joinSplitPubKey);
item.second.nullifier = GetNoteNullifier( item.second.nullifier = GetNoteNullifier(
@ -1003,6 +1004,7 @@ bool CWallet::UpdateNullifierNoteMap()
item.first.n); item.first.n);
} }
} }
}
UpdateNullifierNoteMapWithTx(wtxItem.second); UpdateNullifierNoteMapWithTx(wtxItem.second);
} }
} }
@ -1262,7 +1264,9 @@ boost::optional<uint256> CWallet::GetNoteNullifier(const JSDescription& jsdesc,
hSig, hSig,
(unsigned char) n); (unsigned char) n);
auto note = note_pt.note(address); 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; libzcash::SpendingKey key;
if (GetSpendingKey(address, key)) { if (GetSpendingKey(address, key)) {
ret = note.nullifier(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. * 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. * These notes are decrypted and added to the output parameter vector, outEntries.
*/ */
void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent) void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth, bool ignoreSpent, bool ignoreUnspendable)
{ {
bool fFilterAddress = false; bool fFilterAddress = false;
libzcash::PaymentAddress filterPaymentAddress; libzcash::PaymentAddress filterPaymentAddress;
@ -3677,6 +3681,11 @@ void CWallet::GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, st
continue; continue;
} }
// skip notes which cannot be spent
if (ignoreUnspendable && !HaveSpendingKey(pa)) {
continue;
}
int i = jsop.js; // Index into CTransaction.vjoinsplit int i = jsop.js; // Index into CTransaction.vjoinsplit
int j = jsop.n; // Index into JSDescription.ciphertexts int j = jsop.n; // Index into JSDescription.ciphertexts

View File

@ -1121,7 +1121,11 @@ public:
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; } void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
/* Find notes filtered by payment address, min depth, ability to spend */ /* Find notes filtered by payment address, min depth, ability to spend */
void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries, std::string address, int minDepth=1, bool ignoreSpent=true); void GetFilteredNotes(std::vector<CNotePlaintextEntry> & outEntries,
std::string address,
int minDepth=1,
bool ignoreSpent=true,
bool ignoreUnspendable=true);
}; };