Add Sapling support to z_getbalance and z_gettotalbalance

Closes #3214

Co-authored-by: Sean Bowe <ewillbefull@gmail.com>
This commit is contained in:
Jack Grigg 2018-08-01 01:35:22 +01:00
parent 94e99acda6
commit 053cb3497d
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829
3 changed files with 49 additions and 11 deletions

View File

@ -3257,7 +3257,9 @@ CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspen
for (auto & entry : sproutEntries) { for (auto & entry : sproutEntries) {
balance += CAmount(entry.plaintext.value()); balance += CAmount(entry.plaintext.value());
} }
// TODO: Sapling for (auto & entry : saplingEntries) {
balance += CAmount(entry.note.value());
}
return balance; return balance;
} }
@ -3344,8 +3346,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
throw runtime_error( throw runtime_error(
"z_getbalance \"address\" ( minconf )\n" "z_getbalance \"address\" ( minconf )\n"
"\nReturns the balance of a taddr or zaddr belonging to the nodes wallet.\n" "\nReturns the balance of a taddr or zaddr belonging to the nodes wallet.\n"
"\nCAUTION: If address is a watch-only zaddr, the returned balance may be larger than the actual balance," "\nCAUTION: If address is a watch-only Sprout address, the returned balance may be larger"
"\nbecause spends cannot be detected with incoming viewing keys.\n" "\nthan the actual balance, because spends cannot be detected with incoming viewing keys.\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"address\" (string) The selected address. It may be a transparent or private address.\n" "1. \"address\" (string) The selected address. It may be a transparent or private address.\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
@ -3380,11 +3382,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
if (!IsValidPaymentAddress(res)) { if (!IsValidPaymentAddress(res)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr."); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
} }
// TODO: Add Sapling support. For now, ensure we can freely convert. if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), res)) {
assert(boost::get<libzcash::SproutPaymentAddress>(&res) != nullptr); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, spending key or viewing key not found.");
auto zaddr = boost::get<libzcash::SproutPaymentAddress>(res);
if (!(pwalletMain->HaveSproutSpendingKey(zaddr) || pwalletMain->HaveSproutViewingKey(zaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
} }
} }
@ -3408,15 +3407,15 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
throw runtime_error( throw runtime_error(
"z_gettotalbalance ( minconf includeWatchonly )\n" "z_gettotalbalance ( minconf includeWatchonly )\n"
"\nReturn the total value of funds stored in the nodes wallet.\n" "\nReturn the total value of funds stored in the nodes wallet.\n"
"\nCAUTION: If the wallet contains watch-only zaddrs, the returned private balance may be larger than the actual balance," "\nCAUTION: If the wallet contains watch-only Sprout addresses, the returned private balance may"
"\nbecause spends cannot be detected with incoming viewing keys.\n" "\nbe larger than the actual balance, because spends cannot be detected with incoming viewing keys.\n"
"\nArguments:\n" "\nArguments:\n"
"1. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n" "1. minconf (numeric, optional, default=1) Only include private and transparent transactions confirmed at least this many times.\n"
"2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n" "2. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress' and 'z_importviewingkey')\n"
"\nResult:\n" "\nResult:\n"
"{\n" "{\n"
" \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n" " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n"
" \"private\": xxxxx, (numeric) the total balance of private funds\n" " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n"
" \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n" " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n"
"}\n" "}\n"
"\nExamples:\n" "\nExamples:\n"

View File

@ -4350,3 +4350,26 @@ void CWallet::GetUnspentFilteredNotes(
} }
} }
//
// Shielded key and address generalizations
//
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const
{
return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr);
}
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
{
libzcash::SaplingIncomingViewingKey ivk;
// If we have a SaplingSpendingKey or SaplingExpandedSpendingKey in the
// wallet, then we will also have the corresponding SaplingFullViewingKey.
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
m_wallet->HaveSaplingFullViewingKey(ivk);
}
bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& no) const
{
return false;
}

View File

@ -1303,4 +1303,20 @@ public:
} }
}; };
//
// Shielded key and address generalizations
//
class PaymentAddressBelongsToWallet : public boost::static_visitor<bool>
{
private:
CWallet *m_wallet;
public:
PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {}
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
bool operator()(const libzcash::InvalidEncoding& no) const;
};
#endif // BITCOIN_WALLET_WALLET_H #endif // BITCOIN_WALLET_WALLET_H