Auto merge of #2143 - str4d:1997-viewing-keys, r=str4d
Implement incoming viewing keys Closes #1997.
This commit is contained in:
@@ -2667,7 +2667,7 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
|
||||
}
|
||||
}
|
||||
|
||||
ZCNoteDecryption decryptor(k.viewing_key());
|
||||
ZCNoteDecryption decryptor(k.receiving_key());
|
||||
|
||||
NotePlaintext npt = NotePlaintext::decrypt(
|
||||
decryptor,
|
||||
@@ -2902,6 +2902,7 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
|
||||
"Output: {\n"
|
||||
" \"zcaddress\": zcaddr,\n"
|
||||
" \"zcsecretkey\": zcsecretkey,\n"
|
||||
" \"zcviewingkey\": zcviewingkey,\n"
|
||||
"}\n"
|
||||
);
|
||||
}
|
||||
@@ -2910,18 +2911,14 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
|
||||
auto addr = k.address();
|
||||
auto viewing_key = k.viewing_key();
|
||||
|
||||
CDataStream viewing(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
viewing << viewing_key;
|
||||
|
||||
CZCPaymentAddress pubaddr(addr);
|
||||
CZCSpendingKey spendingkey(k);
|
||||
std::string viewing_hex = HexStr(viewing.begin(), viewing.end());
|
||||
CZCViewingKey viewingkey(viewing_key);
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("zcaddress", pubaddr.ToString()));
|
||||
result.push_back(Pair("zcsecretkey", spendingkey.ToString()));
|
||||
result.push_back(Pair("zcviewingkey", viewing_hex));
|
||||
result.push_back(Pair("zcviewingkey", viewingkey.ToString()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2960,9 +2957,10 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
||||
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"z_listaddresses\n"
|
||||
"z_listaddresses ( includeWatchonly )\n"
|
||||
"\nReturns the list of zaddr belonging to the wallet.\n"
|
||||
"\nArguments:\n"
|
||||
"1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
|
||||
"\nResult:\n"
|
||||
"[ (json array of string)\n"
|
||||
" \"zaddr\" (string) a zaddr belonging to the wallet\n"
|
||||
@@ -2975,16 +2973,23 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
bool fIncludeWatchonly = false;
|
||||
if (params.size() > 0) {
|
||||
fIncludeWatchonly = params[0].get_bool();
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::set<libzcash::PaymentAddress> addresses;
|
||||
pwalletMain->GetPaymentAddresses(addresses);
|
||||
for (auto addr : addresses ) {
|
||||
ret.push_back(CZCPaymentAddress(addr).ToString());
|
||||
if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
|
||||
ret.push_back(CZCPaymentAddress(addr).ToString());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
|
||||
set<CBitcoinAddress> setAddress;
|
||||
vector<COutput> vecOutputs;
|
||||
CAmount balance = 0;
|
||||
@@ -3006,6 +3011,10 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ignoreUnspendable && !out.fSpendable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setAddress.size()) {
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
@@ -3023,11 +3032,11 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1) {
|
||||
return balance;
|
||||
}
|
||||
|
||||
CAmount getBalanceZaddr(std::string address, int minDepth = 1) {
|
||||
CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) {
|
||||
CAmount balance = 0;
|
||||
std::vector<CNotePlaintextEntry> entries;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
pwalletMain->GetFilteredNotes(entries, address, minDepth);
|
||||
pwalletMain->GetFilteredNotes(entries, address, minDepth, true, ignoreUnspendable);
|
||||
for (auto & entry : entries) {
|
||||
balance += CAmount(entry.plaintext.value);
|
||||
}
|
||||
@@ -3079,14 +3088,14 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
|
||||
}
|
||||
|
||||
if (!pwalletMain->HaveSpendingKey(zaddr)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
|
||||
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
|
||||
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);
|
||||
std::vector<CNotePlaintextEntry> entries;
|
||||
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false);
|
||||
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
|
||||
for (CNotePlaintextEntry & entry : entries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
||||
@@ -3108,6 +3117,8 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
||||
throw runtime_error(
|
||||
"z_getbalance \"address\" ( minconf )\n"
|
||||
"\nReturns the balance of a taddr or zaddr belonging to the node’s wallet.\n"
|
||||
"\nCAUTION: If address is a watch-only zaddr, the returned balance may be larger than the actual balance,"
|
||||
"\nbecause spends cannot be detected with incoming viewing keys.\n"
|
||||
"\nArguments:\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"
|
||||
@@ -3145,16 +3156,16 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
||||
} catch (const std::runtime_error&) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
|
||||
}
|
||||
if (!pwalletMain->HaveSpendingKey(zaddr)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
|
||||
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
|
||||
}
|
||||
}
|
||||
|
||||
CAmount nBalance = 0;
|
||||
if (fromTaddr) {
|
||||
nBalance = getBalanceTaddr(fromaddress, nMinDepth);
|
||||
nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
|
||||
} else {
|
||||
nBalance = getBalanceZaddr(fromaddress, nMinDepth);
|
||||
nBalance = getBalanceZaddr(fromaddress, nMinDepth, false);
|
||||
}
|
||||
|
||||
return ValueFromAmount(nBalance);
|
||||
@@ -3166,12 +3177,15 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (fHelp || params.size() > 1)
|
||||
if (fHelp || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"z_gettotalbalance ( minconf )\n"
|
||||
"z_gettotalbalance ( minconf includeWatchonly )\n"
|
||||
"\nReturn the total value of funds stored in the node’s wallet.\n"
|
||||
"\nCAUTION: If the wallet contains watch-only zaddrs, the returned private balance may be larger than the actual balance,"
|
||||
"\nbecause spends cannot be detected with incoming viewing keys.\n"
|
||||
"\nArguments:\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"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n"
|
||||
@@ -3190,19 +3204,24 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
int nMinDepth = 1;
|
||||
if (params.size() == 1) {
|
||||
if (params.size() > 0) {
|
||||
nMinDepth = params[0].get_int();
|
||||
}
|
||||
if (nMinDepth < 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
|
||||
}
|
||||
|
||||
bool fIncludeWatchonly = false;
|
||||
if (params.size() > 1) {
|
||||
fIncludeWatchonly = params[1].get_bool();
|
||||
}
|
||||
|
||||
// getbalance and "getbalance * 1 true" should return the same number
|
||||
// but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
|
||||
// pwalletMain->GetBalance() does not accept min depth parameter
|
||||
// so we use our own method to get balance of utxos.
|
||||
CAmount nBalance = getBalanceTaddr("", nMinDepth);
|
||||
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth);
|
||||
CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
|
||||
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly);
|
||||
CAmount nTotalBalance = nBalance + nPrivateBalance;
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("transparent", FormatMoney(nBalance)));
|
||||
|
||||
Reference in New Issue
Block a user