Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 545 Lines • ▼ Show 20 Lines | static UniValue listaddressgroupings(const Config &config, | ||||
for (const std::set<CTxDestination> &grouping : | for (const std::set<CTxDestination> &grouping : | ||||
pwallet->GetAddressGroupings()) { | pwallet->GetAddressGroupings()) { | ||||
UniValue jsonGrouping(UniValue::VARR); | UniValue jsonGrouping(UniValue::VARR); | ||||
for (const CTxDestination &address : grouping) { | for (const CTxDestination &address : grouping) { | ||||
UniValue addressInfo(UniValue::VARR); | UniValue addressInfo(UniValue::VARR); | ||||
addressInfo.push_back(EncodeDestination(address, config)); | addressInfo.push_back(EncodeDestination(address, config)); | ||||
addressInfo.push_back(ValueFromAmount(balances[address])); | addressInfo.push_back(ValueFromAmount(balances[address])); | ||||
if (pwallet->mapAddressBook.find(address) != | const auto *address_book_entry = | ||||
pwallet->mapAddressBook.end()) { | pwallet->FindAddressBookEntry(address); | ||||
addressInfo.push_back( | if (address_book_entry) { | ||||
pwallet->mapAddressBook.find(address)->second.name); | addressInfo.push_back(address_book_entry->name); | ||||
} | } | ||||
jsonGrouping.push_back(addressInfo); | jsonGrouping.push_back(addressInfo); | ||||
} | } | ||||
jsonGroupings.push_back(jsonGrouping); | jsonGroupings.push_back(jsonGrouping); | ||||
} | } | ||||
return jsonGroupings; | return jsonGroupings; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 685 Lines • ▼ Show 20 Lines | for (const std::pair<const TxId, CWalletTx> &pairWtx : pwallet->mapWallet) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Reply | // Reply | ||||
UniValue ret(UniValue::VARR); | UniValue ret(UniValue::VARR); | ||||
std::map<std::string, tallyitem> label_tally; | std::map<std::string, tallyitem> label_tally; | ||||
// Create mapAddressBook iterator | // Create m_address_book iterator | ||||
// If we aren't filtering, go from begin() to end() | // If we aren't filtering, go from begin() to end() | ||||
auto start = pwallet->mapAddressBook.begin(); | auto start = pwallet->m_address_book.begin(); | ||||
auto end = pwallet->mapAddressBook.end(); | auto end = pwallet->m_address_book.end(); | ||||
// If we are filtering, find() the applicable entry | // If we are filtering, find() the applicable entry | ||||
if (has_filtered_address) { | if (has_filtered_address) { | ||||
start = pwallet->mapAddressBook.find(filtered_address); | start = pwallet->m_address_book.find(filtered_address); | ||||
if (start != end) { | if (start != end) { | ||||
end = std::next(start); | end = std::next(start); | ||||
} | } | ||||
} | } | ||||
for (auto item_it = start; item_it != end; ++item_it) { | for (auto item_it = start; item_it != end; ++item_it) { | ||||
if (item_it->second.IsChange()) { | |||||
continue; | |||||
} | |||||
const CTxDestination &address = item_it->first; | const CTxDestination &address = item_it->first; | ||||
const std::string &label = item_it->second.name; | const std::string &label = item_it->second.name; | ||||
std::map<CTxDestination, tallyitem>::iterator it = | std::map<CTxDestination, tallyitem>::iterator it = | ||||
mapTally.find(address); | mapTally.find(address); | ||||
if (it == mapTally.end() && !fIncludeEmpty) { | if (it == mapTally.end() && !fIncludeEmpty) { | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | if (!filter_label) { | ||||
UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
if (involvesWatchonly || | if (involvesWatchonly || | ||||
(pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) { | (pwallet->IsMine(s.destination) & ISMINE_WATCH_ONLY)) { | ||||
entry.pushKV("involvesWatchonly", true); | entry.pushKV("involvesWatchonly", true); | ||||
} | } | ||||
MaybePushAddress(entry, s.destination); | MaybePushAddress(entry, s.destination); | ||||
entry.pushKV("category", "send"); | entry.pushKV("category", "send"); | ||||
entry.pushKV("amount", ValueFromAmount(-s.amount)); | entry.pushKV("amount", ValueFromAmount(-s.amount)); | ||||
if (pwallet->mapAddressBook.count(s.destination)) { | const auto *address_book_entry = | ||||
entry.pushKV("label", | pwallet->FindAddressBookEntry(s.destination); | ||||
pwallet->mapAddressBook[s.destination].name); | if (address_book_entry) { | ||||
entry.pushKV("label", address_book_entry->name); | |||||
} | } | ||||
entry.pushKV("vout", s.vout); | entry.pushKV("vout", s.vout); | ||||
entry.pushKV("fee", ValueFromAmount(-1 * nFee)); | entry.pushKV("fee", ValueFromAmount(-1 * nFee)); | ||||
if (fLong) { | if (fLong) { | ||||
WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry); | WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry); | ||||
} | } | ||||
entry.pushKV("abandoned", wtx.isAbandoned()); | entry.pushKV("abandoned", wtx.isAbandoned()); | ||||
ret.push_back(entry); | ret.push_back(entry); | ||||
} | } | ||||
} | } | ||||
// Received | // Received | ||||
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { | if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { | ||||
for (const COutputEntry &r : listReceived) { | for (const COutputEntry &r : listReceived) { | ||||
std::string label; | std::string label; | ||||
if (pwallet->mapAddressBook.count(r.destination)) { | const auto *address_book_entry = | ||||
label = pwallet->mapAddressBook[r.destination].name; | pwallet->FindAddressBookEntry(r.destination); | ||||
if (address_book_entry) { | |||||
label = address_book_entry->name; | |||||
} | } | ||||
if (filter_label && label != *filter_label) { | if (filter_label && label != *filter_label) { | ||||
continue; | continue; | ||||
} | } | ||||
UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
if (involvesWatchonly || | if (involvesWatchonly || | ||||
(pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) { | (pwallet->IsMine(r.destination) & ISMINE_WATCH_ONLY)) { | ||||
entry.pushKV("involvesWatchonly", true); | entry.pushKV("involvesWatchonly", true); | ||||
} | } | ||||
MaybePushAddress(entry, r.destination); | MaybePushAddress(entry, r.destination); | ||||
if (wtx.IsCoinBase()) { | if (wtx.IsCoinBase()) { | ||||
if (wtx.GetDepthInMainChain() < 1) { | if (wtx.GetDepthInMainChain() < 1) { | ||||
entry.pushKV("category", "orphan"); | entry.pushKV("category", "orphan"); | ||||
} else if (wtx.IsImmatureCoinBase()) { | } else if (wtx.IsImmatureCoinBase()) { | ||||
entry.pushKV("category", "immature"); | entry.pushKV("category", "immature"); | ||||
} else { | } else { | ||||
entry.pushKV("category", "generate"); | entry.pushKV("category", "generate"); | ||||
} | } | ||||
} else { | } else { | ||||
entry.pushKV("category", "receive"); | entry.pushKV("category", "receive"); | ||||
} | } | ||||
entry.pushKV("amount", ValueFromAmount(r.amount)); | entry.pushKV("amount", ValueFromAmount(r.amount)); | ||||
if (pwallet->mapAddressBook.count(r.destination)) { | if (address_book_entry) { | ||||
entry.pushKV("label", label); | entry.pushKV("label", label); | ||||
} | } | ||||
entry.pushKV("vout", r.vout); | entry.pushKV("vout", r.vout); | ||||
if (fLong) { | if (fLong) { | ||||
WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry); | WalletTxToJSON(pwallet->chain(), locked_chain, wtx, entry); | ||||
} | } | ||||
ret.push_back(entry); | ret.push_back(entry); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,974 Lines • ▼ Show 20 Lines | for (const COutput &out : vecOutputs) { | ||||
UniValue entry(UniValue::VOBJ); | UniValue entry(UniValue::VOBJ); | ||||
entry.pushKV("txid", out.tx->GetId().GetHex()); | entry.pushKV("txid", out.tx->GetId().GetHex()); | ||||
entry.pushKV("vout", out.i); | entry.pushKV("vout", out.i); | ||||
if (fValidAddress) { | if (fValidAddress) { | ||||
entry.pushKV("address", EncodeDestination(address, config)); | entry.pushKV("address", EncodeDestination(address, config)); | ||||
auto i = pwallet->mapAddressBook.find(address); | const auto *address_book_entry = | ||||
if (i != pwallet->mapAddressBook.end()) { | pwallet->FindAddressBookEntry(address); | ||||
entry.pushKV("label", i->second.name); | if (address_book_entry) { | ||||
entry.pushKV("label", address_book_entry->name); | |||||
} | } | ||||
const SigningProvider *provider = | const SigningProvider *provider = | ||||
pwallet->GetSigningProvider(scriptPubKey); | pwallet->GetSigningProvider(scriptPubKey); | ||||
if (provider) { | if (provider) { | ||||
if (scriptPubKey.IsPayToScriptHash()) { | if (scriptPubKey.IsPayToScriptHash()) { | ||||
const CScriptID &hash = | const CScriptID &hash = | ||||
CScriptID(boost::get<ScriptHash>(address)); | CScriptID(boost::get<ScriptHash>(address)); | ||||
▲ Show 20 Lines • Show All 741 Lines • ▼ Show 20 Lines | UniValue getaddressinfo(const Config &config, const JSONRPCRequest &request) { | ||||
ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); | ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)); | ||||
UniValue detail = DescribeWalletAddress(pwallet, dest); | UniValue detail = DescribeWalletAddress(pwallet, dest); | ||||
ret.pushKVs(detail); | ret.pushKVs(detail); | ||||
// Return label field if existing. Currently only one label can be | // Return label field if existing. Currently only one label can be | ||||
// associated with an address, so the label should be equivalent to the | // associated with an address, so the label should be equivalent to the | ||||
// value of the name key/value pair in the labels array below. | // value of the name key/value pair in the labels array below. | ||||
if (pwallet->mapAddressBook.count(dest)) { | const auto *address_book_entry = pwallet->FindAddressBookEntry(dest); | ||||
ret.pushKV("label", pwallet->mapAddressBook[dest].name); | if (address_book_entry) { | ||||
ret.pushKV("label", address_book_entry->name); | |||||
} | } | ||||
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); | ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); | ||||
ScriptPubKeyMan *spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey); | ScriptPubKeyMan *spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey); | ||||
if (spk_man) { | if (spk_man) { | ||||
if (const CKeyMetadata *meta = spk_man->GetMetadata(dest)) { | if (const CKeyMetadata *meta = spk_man->GetMetadata(dest)) { | ||||
ret.pushKV("timestamp", meta->nCreateTime); | ret.pushKV("timestamp", meta->nCreateTime); | ||||
Show All 11 Lines | UniValue getaddressinfo(const Config &config, const JSONRPCRequest &request) { | ||||
// equivalent to the `label` field above. Currently only one label can be | // equivalent to the `label` field above. Currently only one label can be | ||||
// associated with an address, but we return an array so the API remains | // associated with an address, but we return an array so the API remains | ||||
// stable if we allow multiple labels to be associated with an address in | // stable if we allow multiple labels to be associated with an address in | ||||
// the future. | // the future. | ||||
// | // | ||||
// DEPRECATED: The previous behavior of returning an array containing a JSON | // DEPRECATED: The previous behavior of returning an array containing a JSON | ||||
// object of `name` and `purpose` key/value pairs has been deprecated. | // object of `name` and `purpose` key/value pairs has been deprecated. | ||||
UniValue labels(UniValue::VARR); | UniValue labels(UniValue::VARR); | ||||
std::map<CTxDestination, CAddressBookData>::iterator mi = | if (address_book_entry) { | ||||
pwallet->mapAddressBook.find(dest); | |||||
if (mi != pwallet->mapAddressBook.end()) { | |||||
if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) { | if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) { | ||||
labels.push_back(AddressBookDataToJSON(mi->second, true)); | labels.push_back(AddressBookDataToJSON(*address_book_entry, true)); | ||||
} else { | } else { | ||||
labels.push_back(mi->second.name); | labels.push_back(address_book_entry->name); | ||||
} | } | ||||
} | } | ||||
ret.pushKV("labels", std::move(labels)); | ret.pushKV("labels", std::move(labels)); | ||||
return ret; | return ret; | ||||
} | } | ||||
UniValue getaddressesbylabel(const Config &config, | UniValue getaddressesbylabel(const Config &config, | ||||
Show All 26 Lines | UniValue getaddressesbylabel(const Config &config, | ||||
LOCK(pwallet->cs_wallet); | LOCK(pwallet->cs_wallet); | ||||
std::string label = LabelFromValue(request.params[0]); | std::string label = LabelFromValue(request.params[0]); | ||||
// Find all addresses that have the given label | // Find all addresses that have the given label | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
std::set<std::string> addresses; | std::set<std::string> addresses; | ||||
for (const std::pair<const CTxDestination, CAddressBookData> &item : | for (const std::pair<const CTxDestination, CAddressBookData> &item : | ||||
pwallet->mapAddressBook) { | pwallet->m_address_book) { | ||||
if (item.second.IsChange()) { | |||||
continue; | |||||
} | |||||
if (item.second.name == label) { | if (item.second.name == label) { | ||||
std::string address = EncodeDestination(item.first, config); | std::string address = EncodeDestination(item.first, config); | ||||
// CWallet::mapAddressBook is not expected to contain duplicate | // CWallet::m_address_book is not expected to contain duplicate | ||||
// address strings, but build a separate set as a precaution just in | // address strings, but build a separate set as a precaution just in | ||||
// case it does. | // case it does. | ||||
bool unique = addresses.emplace(address).second; | bool unique = addresses.emplace(address).second; | ||||
CHECK_NONFATAL(unique); | CHECK_NONFATAL(unique); | ||||
// UniValue::pushKV checks if the key exists in O(N) | // UniValue::pushKV checks if the key exists in O(N) | ||||
// and since duplicate addresses are unexpected (checked with | // and since duplicate addresses are unexpected (checked with | ||||
// std::set in O(log(N))), UniValue::__pushKV is used instead, | // std::set in O(log(N))), UniValue::__pushKV is used instead, | ||||
// which currently is O(1). | // which currently is O(1). | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | UniValue listlabels(const Config &config, const JSONRPCRequest &request) { | ||||
std::string purpose; | std::string purpose; | ||||
if (!request.params[0].isNull()) { | if (!request.params[0].isNull()) { | ||||
purpose = request.params[0].get_str(); | purpose = request.params[0].get_str(); | ||||
} | } | ||||
// Add to a set to sort by label name, then insert into Univalue array | // Add to a set to sort by label name, then insert into Univalue array | ||||
std::set<std::string> label_set; | std::set<std::string> label_set; | ||||
for (const std::pair<const CTxDestination, CAddressBookData> &entry : | for (const std::pair<const CTxDestination, CAddressBookData> &entry : | ||||
pwallet->mapAddressBook) { | pwallet->m_address_book) { | ||||
if (entry.second.IsChange()) { | |||||
continue; | |||||
} | |||||
if (purpose.empty() || entry.second.purpose == purpose) { | if (purpose.empty() || entry.second.purpose == purpose) { | ||||
label_set.insert(entry.second.name); | label_set.insert(entry.second.name); | ||||
} | } | ||||
} | } | ||||
UniValue ret(UniValue::VARR); | UniValue ret(UniValue::VARR); | ||||
for (const std::string &name : label_set) { | for (const std::string &name : label_set) { | ||||
ret.push_back(name); | ret.push_back(name); | ||||
▲ Show 20 Lines • Show All 430 Lines • Show Last 20 Lines |