Use `libzcash::RawAddress` in `CWallet::GetFilteredNotes`
`getBalanceZaddr` is modified to take an optional `RawAddress` instead of a string. This limits it to showing the balance of a single protocol address, which is fine: `z_getbalance` is the only user of this function, and we are deprecating that RPC method (replacing it with RPC methods that can show more detailed information for UAs). `CWallet::GetNullifiersForAddresses` and `CWallet::IsNote*Change` now use `RawAddress` because they are generally fed the same addresses as `GetFilteredNotes`, and in the context of specific notes we need to work with protocol addresses.
This commit is contained in:
parent
6f1a54cd16
commit
22ffee8da6
|
@ -2343,7 +2343,7 @@ UniValue settxfee(const UniValue& params, bool fHelp)
|
|||
return true;
|
||||
}
|
||||
|
||||
CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true);
|
||||
CAmount getBalanceZaddr(std::optional<libzcash::RawAddress> address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true);
|
||||
|
||||
UniValue getwalletinfo(const UniValue& params, bool fHelp)
|
||||
{
|
||||
|
@ -2381,8 +2381,8 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
|
|||
obj.pushKV("balance", ValueFromAmount(pwalletMain->GetBalance()));
|
||||
obj.pushKV("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance()));
|
||||
obj.pushKV("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance()));
|
||||
obj.pushKV("shielded_balance", FormatMoney(getBalanceZaddr("", 1, INT_MAX)));
|
||||
obj.pushKV("shielded_unconfirmed_balance", FormatMoney(getBalanceZaddr("", 0, 0)));
|
||||
obj.pushKV("shielded_balance", FormatMoney(getBalanceZaddr(std::nullopt, 1, INT_MAX)));
|
||||
obj.pushKV("shielded_unconfirmed_balance", FormatMoney(getBalanceZaddr(std::nullopt, 0, 0)));
|
||||
obj.pushKV("txcount", (int)pwalletMain->mapWallet.size());
|
||||
obj.pushKV("keypoololdest", pwalletMain->GetOldestKeyPoolTime());
|
||||
obj.pushKV("keypoolsize", (int)pwalletMain->GetKeyPoolSize());
|
||||
|
@ -2601,7 +2601,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum number of confirmations must be greater or equal to the minimum number of confirmations");
|
||||
}
|
||||
|
||||
std::set<libzcash::PaymentAddress> zaddrs = {};
|
||||
std::set<libzcash::RawAddress> zaddrs = {};
|
||||
|
||||
bool fIncludeWatchonly = false;
|
||||
if (params.size() > 2) {
|
||||
|
@ -2634,7 +2634,11 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
if (!fIncludeWatchonly && !hasSpendingKey) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
|
||||
}
|
||||
zaddrs.insert(zaddr);
|
||||
// We want to return unspent notes corresponding to any receiver within a
|
||||
// Unified Address.
|
||||
for (const auto ra : std::visit(GetRawAddresses(), zaddr)) {
|
||||
zaddrs.insert(ra);
|
||||
}
|
||||
|
||||
if (setAddress.count(address)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ") + address);
|
||||
|
@ -2661,7 +2665,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
std::vector<SproutNoteEntry> sproutEntries;
|
||||
std::vector<SaplingNoteEntry> saplingEntries;
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false);
|
||||
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
|
||||
auto nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
|
||||
|
||||
for (auto & entry : sproutEntries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
@ -2688,6 +2692,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
obj.pushKV("confirmations", entry.confirmations);
|
||||
bool hasSaplingSpendingKey = HaveSpendingKeyForPaymentAddress(pwalletMain)(entry.address);
|
||||
obj.pushKV("spendable", hasSaplingSpendingKey);
|
||||
// TODO: If we found this entry via a UA, show that instead.
|
||||
obj.pushKV("address", keyIO.EncodePaymentAddress(entry.address));
|
||||
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); // note.value() is equivalent to plaintext.value()
|
||||
obj.pushKV("memo", HexStr(entry.memo));
|
||||
|
@ -3394,16 +3399,15 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign
|
|||
return balance;
|
||||
}
|
||||
|
||||
CAmount getBalanceZaddr(std::string address, int minDepth, int maxDepth, bool ignoreUnspendable) {
|
||||
CAmount getBalanceZaddr(std::optional<libzcash::RawAddress> address, int minDepth, int maxDepth, bool ignoreUnspendable) {
|
||||
CAmount balance = 0;
|
||||
std::vector<SproutNoteEntry> sproutEntries;
|
||||
std::vector<SaplingNoteEntry> saplingEntries;
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
std::set<PaymentAddress> filterAddresses;
|
||||
if (address.length() > 0) {
|
||||
KeyIO keyIO(Params());
|
||||
filterAddresses.insert(keyIO.DecodePaymentAddress(address));
|
||||
std::set<libzcash::RawAddress> filterAddresses;
|
||||
if (address) {
|
||||
filterAddresses.insert(address.value());
|
||||
}
|
||||
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, maxDepth, true, ignoreUnspendable);
|
||||
|
@ -3495,10 +3499,10 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
|||
std::vector<SaplingNoteEntry> saplingEntries;
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false);
|
||||
|
||||
std::set<std::pair<PaymentAddress, uint256>> nullifierSet;
|
||||
std::set<std::pair<libzcash::RawAddress, uint256>> nullifierSet;
|
||||
auto hasSpendingKey = std::visit(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
|
||||
if (hasSpendingKey) {
|
||||
nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr});
|
||||
nullifierSet = pwalletMain->GetNullifiersForAddresses(std::visit(GetRawAddresses(), zaddr));
|
||||
}
|
||||
|
||||
if (std::get_if<libzcash::SproutPaymentAddress>(&zaddr) != nullptr) {
|
||||
|
@ -3588,13 +3592,13 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
|||
auto fromaddress = params[0].get_str();
|
||||
bool fromTaddr = false;
|
||||
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
|
||||
auto pa = keyIO.DecodePaymentAddress(fromaddress);
|
||||
fromTaddr = IsValidDestination(taddr);
|
||||
if (!fromTaddr) {
|
||||
auto res = keyIO.DecodePaymentAddress(fromaddress);
|
||||
if (!IsValidPaymentAddress(res)) {
|
||||
if (!IsValidPaymentAddress(pa)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
|
||||
}
|
||||
if (!std::visit(PaymentAddressBelongsToWallet(pwalletMain), res)) {
|
||||
if (!std::visit(PaymentAddressBelongsToWallet(pwalletMain), pa)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, spending key or viewing key not found.");
|
||||
}
|
||||
}
|
||||
|
@ -3603,7 +3607,9 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
|||
if (fromTaddr) {
|
||||
nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
|
||||
} else {
|
||||
nBalance = getBalanceZaddr(fromaddress, nMinDepth, INT_MAX, false);
|
||||
// TODO: Return an error if a UA is provided (once we support UAs).
|
||||
auto zaddr = std::visit(RecipientForPaymentAddress(), pa).value();
|
||||
nBalance = getBalanceZaddr(zaddr, nMinDepth, INT_MAX, false);
|
||||
}
|
||||
|
||||
// inZat
|
||||
|
@ -3665,7 +3671,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
|
|||
// pwalletMain->GetBalance() does not accept min depth parameter
|
||||
// so we use our own method to get balance of utxos.
|
||||
CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
|
||||
CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, INT_MAX, !fIncludeWatchonly);
|
||||
CAmount nPrivateBalance = getBalanceZaddr(std::nullopt, nMinDepth, INT_MAX, !fIncludeWatchonly);
|
||||
CAmount nTotalBalance = nBalance + nPrivateBalance;
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("transparent", FormatMoney(nBalance));
|
||||
|
@ -4384,7 +4390,7 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) {
|
|||
{
|
||||
std::vector<SproutNoteEntry> sproutEntries;
|
||||
std::vector<SaplingNoteEntry> saplingEntries;
|
||||
std::set<PaymentAddress> noFilter;
|
||||
std::set<libzcash::RawAddress> noFilter;
|
||||
// Here we are looking for any and all Sprout notes for which we have the spending key, including those
|
||||
// which are locked and/or only exist in the mempool, as they should be included in the unmigrated amount.
|
||||
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, noFilter, 0, INT_MAX, true, true, false);
|
||||
|
@ -4747,7 +4753,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
bool useAnySprout = false;
|
||||
bool useAnySapling = false;
|
||||
std::set<CTxDestination> taddrs = {};
|
||||
std::set<libzcash::PaymentAddress> zaddrs = {};
|
||||
std::set<libzcash::RawAddress> zaddrs = {};
|
||||
|
||||
UniValue addresses = params[0].get_array();
|
||||
if (addresses.size()==0)
|
||||
|
@ -4782,10 +4788,14 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
} else {
|
||||
auto zaddr = keyIO.DecodePaymentAddress(address);
|
||||
if (IsValidPaymentAddress(zaddr)) {
|
||||
zaddrs.insert(zaddr);
|
||||
if (std::get_if<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
|
||||
// We want to merge notes corresponding to any receiver within a
|
||||
// Unified Address.
|
||||
for (const auto ra : std::visit(GetRawAddresses(), zaddr)) {
|
||||
zaddrs.insert(ra);
|
||||
if (std::get_if<libzcash::SaplingPaymentAddress>(&ra) != nullptr) {
|
||||
isFromNonSprout = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
|
||||
}
|
||||
|
|
|
@ -684,10 +684,10 @@ void CWallet::SetBestChain(const CBlockLocator& loc)
|
|||
SetBestChainINTERNAL(walletdb, loc);
|
||||
}
|
||||
|
||||
std::set<std::pair<libzcash::PaymentAddress, uint256>> CWallet::GetNullifiersForAddresses(
|
||||
const std::set<libzcash::PaymentAddress> & addresses)
|
||||
std::set<std::pair<libzcash::RawAddress, uint256>> CWallet::GetNullifiersForAddresses(
|
||||
const std::set<libzcash::RawAddress> & addresses)
|
||||
{
|
||||
std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet;
|
||||
std::set<std::pair<libzcash::RawAddress, uint256>> nullifierSet;
|
||||
// Sapling ivk -> list of addrs map
|
||||
// (There may be more than one diversified address for a given ivk.)
|
||||
std::map<libzcash::SaplingIncomingViewingKey, std::vector<libzcash::SaplingPaymentAddress>> ivkMap;
|
||||
|
@ -725,8 +725,8 @@ std::set<std::pair<libzcash::PaymentAddress, uint256>> CWallet::GetNullifiersFor
|
|||
}
|
||||
|
||||
bool CWallet::IsNoteSproutChange(
|
||||
const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
|
||||
const PaymentAddress & address,
|
||||
const std::set<std::pair<libzcash::RawAddress, uint256>> & nullifierSet,
|
||||
const libzcash::RawAddress & address,
|
||||
const JSOutPoint & jsop)
|
||||
{
|
||||
// A Note is marked as "change" if the address that received it
|
||||
|
@ -748,8 +748,8 @@ bool CWallet::IsNoteSproutChange(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CWallet::IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
|
||||
const libzcash::PaymentAddress & address,
|
||||
bool CWallet::IsNoteSaplingChange(const std::set<std::pair<libzcash::RawAddress, uint256>> & nullifierSet,
|
||||
const libzcash::RawAddress & address,
|
||||
const SaplingOutPoint & op)
|
||||
{
|
||||
// A Note is marked as "change" if the address that received it
|
||||
|
@ -5034,11 +5034,14 @@ void CWallet::GetFilteredNotes(
|
|||
bool ignoreSpent,
|
||||
bool requireSpendingKey)
|
||||
{
|
||||
std::set<PaymentAddress> filterAddresses;
|
||||
std::set<libzcash::RawAddress> filterAddresses;
|
||||
|
||||
KeyIO keyIO(Params());
|
||||
if (address.length() > 0) {
|
||||
filterAddresses.insert(keyIO.DecodePaymentAddress(address));
|
||||
auto addr = keyIO.DecodePaymentAddress(address);
|
||||
for (const auto ra : std::visit(GetRawAddresses(), addr)) {
|
||||
filterAddresses.insert(ra);
|
||||
}
|
||||
}
|
||||
|
||||
GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey);
|
||||
|
@ -5052,7 +5055,7 @@ void CWallet::GetFilteredNotes(
|
|||
void CWallet::GetFilteredNotes(
|
||||
std::vector<SproutNoteEntry>& sproutEntries,
|
||||
std::vector<SaplingNoteEntry>& saplingEntries,
|
||||
std::set<PaymentAddress>& filterAddresses,
|
||||
std::set<libzcash::RawAddress>& filterAddresses,
|
||||
int minDepth,
|
||||
int maxDepth,
|
||||
bool ignoreSpent,
|
||||
|
|
|
@ -1273,9 +1273,9 @@ public:
|
|||
void AddPendingSaplingMigrationTx(const CTransaction& tx);
|
||||
/** Saves witness caches and best block locator to disk. */
|
||||
void SetBestChain(const CBlockLocator& loc);
|
||||
std::set<std::pair<libzcash::PaymentAddress, uint256>> GetNullifiersForAddresses(const std::set<libzcash::PaymentAddress> & addresses);
|
||||
bool IsNoteSproutChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const libzcash::PaymentAddress & address, const JSOutPoint & entry);
|
||||
bool IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const libzcash::PaymentAddress & address, const SaplingOutPoint & entry);
|
||||
std::set<std::pair<libzcash::RawAddress, uint256>> GetNullifiersForAddresses(const std::set<libzcash::RawAddress> & addresses);
|
||||
bool IsNoteSproutChange(const std::set<std::pair<libzcash::RawAddress, uint256>> & nullifierSet, const libzcash::RawAddress & address, const JSOutPoint & entry);
|
||||
bool IsNoteSaplingChange(const std::set<std::pair<libzcash::RawAddress, uint256>> & nullifierSet, const libzcash::RawAddress & address, const SaplingOutPoint & entry);
|
||||
|
||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
||||
|
@ -1392,7 +1392,7 @@ public:
|
|||
if a spending key is required, and if they are locked */
|
||||
void GetFilteredNotes(std::vector<SproutNoteEntry>& sproutEntries,
|
||||
std::vector<SaplingNoteEntry>& saplingEntries,
|
||||
std::set<libzcash::PaymentAddress>& filterAddresses,
|
||||
std::set<libzcash::RawAddress>& filterAddresses,
|
||||
int minDepth=1,
|
||||
int maxDepth=INT_MAX,
|
||||
bool ignoreSpent=true,
|
||||
|
|
Loading…
Reference in New Issue