Only include the change field if we have a spending key

This commit is contained in:
Eirik Ogilvie-Wigley 2018-08-01 14:16:04 -06:00
parent 8df048b1de
commit 7929851626
2 changed files with 24 additions and 6 deletions

View File

@ -60,5 +60,18 @@ class WalletChangeIndicatorTest (BitcoinTestFramework):
assert_equal(Decimal('0.6'), sortedunspent[1]['amount']) assert_equal(Decimal('0.6'), sortedunspent[1]['amount'])
assert_false(sortedunspent[1]['change'], "Unspent note valued at 0.6 should not be change") assert_false(sortedunspent[1]['change'], "Unspent note valued at 0.6 should not be change")
# Give node 0 a viewing key
viewing_key = self.nodes[1].z_exportviewingkey(zaddr1)
self.nodes[0].z_importviewingkey(viewing_key)
received_node0 = self.nodes[0].z_listreceivedbyaddress(zaddr1, 0)
assert_equal(2, len(received_node0))
unspent_node0 = self.nodes[0].z_listunspent(1, 9999999, True)
assert_equal(2, len(unspent_node0))
# node 0 only has a viewing key so does not see the change field
assert_false('change' in received_node0[0])
assert_false('change' in received_node0[1])
assert_false('change' in unspent_node0[0])
assert_false('change' in unspent_node0[1])
if __name__ == '__main__': if __name__ == '__main__':
WalletChangeIndicatorTest().main() WalletChangeIndicatorTest().main()

View File

@ -2565,12 +2565,15 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
obj.push_back(Pair("jsindex", (int)entry.jsop.js )); obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
obj.push_back(Pair("jsoutindex", (int)entry.jsop.n)); obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
obj.push_back(Pair("confirmations", entry.nHeight)); obj.push_back(Pair("confirmations", entry.nHeight));
obj.push_back(Pair("spendable", pwalletMain->HaveSproutSpendingKey(boost::get<libzcash::SproutPaymentAddress>(entry.address)))); bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(boost::get<libzcash::SproutPaymentAddress>(entry.address));
obj.push_back(Pair("spendable", hasSproutSpendingKey));
obj.push_back(Pair("address", EncodePaymentAddress(entry.address))); obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value())))); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
obj.push_back(Pair("memo", HexStr(data))); obj.push_back(Pair("memo", HexStr(data)));
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop))); if (hasSproutSpendingKey) {
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
}
results.push_back(obj); results.push_back(obj);
} }
} }
@ -3296,15 +3299,15 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
assert(boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr); assert(boost::get<libzcash::SproutPaymentAddress>(&zaddr) != nullptr);
auto sproutzaddr = boost::get<libzcash::SproutPaymentAddress>(zaddr); auto sproutzaddr = boost::get<libzcash::SproutPaymentAddress>(zaddr);
if (!(pwalletMain->HaveSproutSpendingKey(sproutzaddr) || pwalletMain->HaveSproutViewingKey(sproutzaddr))) { bool hasSproutSpendingKey = pwalletMain->HaveSproutSpendingKey(sproutzaddr);
if (!(hasSproutSpendingKey || pwalletMain->HaveSproutViewingKey(sproutzaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
} }
UniValue result(UniValue::VARR); UniValue result(UniValue::VARR);
std::vector<CSproutNotePlaintextEntry> entries; std::vector<CSproutNotePlaintextEntry> entries;
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false); pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr}); auto nullifierSet = hasSproutSpendingKey ? pwalletMain->GetNullifiersForAddresses({zaddr}) : std::set<std::pair<PaymentAddress, uint256>>();
for (CSproutNotePlaintextEntry & entry : entries) { for (CSproutNotePlaintextEntry & entry : entries) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("txid", entry.jsop.hash.ToString())); obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
@ -3314,7 +3317,9 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
// (txid, jsindex, jsoutindex) is needed to globally identify a note // (txid, jsindex, jsoutindex) is needed to globally identify a note
obj.push_back(Pair("jsindex", entry.jsop.js)); obj.push_back(Pair("jsindex", entry.jsop.js));
obj.push_back(Pair("jsoutindex", entry.jsop.n)); obj.push_back(Pair("jsoutindex", entry.jsop.n));
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop))); if (hasSproutSpendingKey) {
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
}
result.push_back(obj); result.push_back(obj);
} }
return result; return result;