Auto merge of #3156 - Eirik0:2935-change-indicator, r=bitcartel
Add change indicator This adds to the json returned when calling z_listreceivedbyaddress and z_listuspent an additional field entitiled 'change' which will be either true or false depending on whether or not the note was change from another transaction.
This commit is contained in:
@@ -2469,6 +2469,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
||||
" \"address\" : \"address\", (string) the shielded address\n"
|
||||
" \"amount\": xxxxx, (numeric) the amount of value in the note\n"
|
||||
" \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
|
||||
" \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
"]\n"
|
||||
@@ -2553,9 +2554,10 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
||||
if (zaddrs.size() > 0) {
|
||||
std::vector<CUnspentSproutNotePlaintextEntry> entries;
|
||||
pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly);
|
||||
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs);
|
||||
for (CUnspentSproutNotePlaintextEntry & entry : entries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
||||
obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
|
||||
obj.push_back(Pair("jsindex", (int)entry.jsop.js ));
|
||||
obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
|
||||
obj.push_back(Pair("confirmations", entry.nHeight));
|
||||
@@ -2564,6 +2566,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
||||
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
|
||||
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
|
||||
obj.push_back(Pair("memo", HexStr(data)));
|
||||
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
|
||||
results.push_back(obj);
|
||||
}
|
||||
}
|
||||
@@ -3226,9 +3229,10 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"txid\": xxxxx, (string) the transaction id\n"
|
||||
" \"amount\": xxxxx, (numeric) the amount of value in the note\n"
|
||||
" \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
|
||||
" \"txid\": xxxxx, (string) the transaction id\n"
|
||||
" \"amount\": xxxxx, (numeric) the amount of value in the note\n"
|
||||
" \"memo\": xxxxx, (string) hexademical string representation of memo field\n"
|
||||
" \"change\": true|false, (boolean) true if the address that received the note is also one of the sending addresses\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("z_listreceivedbyaddress", "\"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
|
||||
@@ -3264,21 +3268,22 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
|
||||
UniValue result(UniValue::VARR);
|
||||
std::vector<CSproutNotePlaintextEntry> entries;
|
||||
pwalletMain->GetFilteredNotes(entries, fromaddress, nMinDepth, false, false);
|
||||
std::set<std::pair<PaymentAddress, uint256>> nullifierSet = pwalletMain->GetNullifiersForAddresses({zaddr});
|
||||
for (CSproutNotePlaintextEntry & entry : entries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.push_back(Pair("txid",entry.jsop.hash.ToString()));
|
||||
obj.push_back(Pair("txid", entry.jsop.hash.ToString()));
|
||||
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
|
||||
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
|
||||
obj.push_back(Pair("memo", HexStr(data)));
|
||||
// (txid, jsindex, jsoutindex) is needed to globally identify a note
|
||||
obj.push_back(Pair("jsindex", entry.jsop.js));
|
||||
obj.push_back(Pair("jsoutindex", entry.jsop.n));
|
||||
obj.push_back(Pair("change", pwalletMain->IsNoteChange(nullifierSet, entry.address, entry.jsop)));
|
||||
result.push_back(obj);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
UniValue z_getbalance(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (!EnsureWalletIsAvailable(fHelp))
|
||||
|
||||
@@ -465,6 +465,40 @@ 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::PaymentAddress, uint256>> nullifierSet;
|
||||
for (const auto & txPair : mapWallet) {
|
||||
for (const auto & noteDataPair : txPair.second.mapNoteData) {
|
||||
if (noteDataPair.second.nullifier && addresses.count(noteDataPair.second.address)) {
|
||||
nullifierSet.insert(std::make_pair(noteDataPair.second.address, noteDataPair.second.nullifier.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullifierSet;
|
||||
}
|
||||
|
||||
bool CWallet::IsNoteChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const PaymentAddress & address, const JSOutPoint & jsop)
|
||||
{
|
||||
// A Note is marked as "change" if the address that received it
|
||||
// also spent Notes in the same transaction. This will catch,
|
||||
// for instance:
|
||||
// - Change created by spending fractions of Notes (because
|
||||
// z_sendmany sends change to the originating z-address).
|
||||
// - "Chaining Notes" used to connect JoinSplits together.
|
||||
// - Notes created by consolidation transactions (e.g. using
|
||||
// z_mergetoaddress).
|
||||
// - Notes sent from one address to itself.
|
||||
for (const JSDescription & jsd : mapWallet[jsop.hash].vjoinsplit) {
|
||||
for (const uint256 & nullifier : jsd.nullifiers) {
|
||||
if (nullifierSet.count(std::make_pair(address, nullifier))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
|
||||
{
|
||||
LOCK(cs_wallet); // nWalletVersion
|
||||
|
||||
@@ -1074,6 +1074,8 @@ public:
|
||||
void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, ZCIncrementalMerkleTree tree, bool added);
|
||||
/** 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 IsNoteChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const libzcash::PaymentAddress & address, const JSOutPoint & entry);
|
||||
|
||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
||||
|
||||
Reference in New Issue
Block a user