diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -171,7 +171,7 @@ return false; } if (name) { - *name = it->second.name; + *name = it->second.GetLabel(); } if (is_mine) { *is_mine = m_wallet->IsMine(dest); @@ -189,7 +189,8 @@ continue; } result.emplace_back(item.first, m_wallet->IsMine(item.first), - item.second.name, item.second.purpose); + item.second.GetLabel(), + item.second.purpose); } return result; } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -67,7 +67,7 @@ strAddr += ","; } strAddr += EncodeDestination(dest, config); - strLabel = EncodeDumpString(address_book_entry->name); + strLabel = EncodeDumpString(address_book_entry->GetLabel()); fLabelFound = true; } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -554,7 +554,7 @@ const auto *address_book_entry = pwallet->FindAddressBookEntry(address); if (address_book_entry) { - addressInfo.push_back(address_book_entry->name); + addressInfo.push_back(address_book_entry->GetLabel()); } jsonGrouping.push_back(addressInfo); } @@ -1273,7 +1273,7 @@ continue; } const CTxDestination &address = item_it->first; - const std::string &label = item_it->second.name; + const std::string &label = item_it->second.GetLabel(); std::map::iterator it = mapTally.find(address); if (it == mapTally.end() && !fIncludeEmpty) { @@ -1500,7 +1500,7 @@ const auto *address_book_entry = pwallet->FindAddressBookEntry(s.destination); if (address_book_entry) { - entry.pushKV("label", address_book_entry->name); + entry.pushKV("label", address_book_entry->GetLabel()); } entry.pushKV("vout", s.vout); entry.pushKV("fee", ValueFromAmount(-1 * nFee)); @@ -1519,7 +1519,7 @@ const auto *address_book_entry = pwallet->FindAddressBookEntry(r.destination); if (address_book_entry) { - label = address_book_entry->name; + label = address_book_entry->GetLabel(); } if (filter_label && label != *filter_label) { continue; @@ -3536,7 +3536,7 @@ const auto *address_book_entry = pwallet->FindAddressBookEntry(address); if (address_book_entry) { - entry.pushKV("label", address_book_entry->name); + entry.pushKV("label", address_book_entry->GetLabel()); } const SigningProvider *provider = @@ -4143,7 +4143,7 @@ const bool verbose) { UniValue ret(UniValue::VOBJ); if (verbose) { - ret.pushKV("name", data.name); + ret.pushKV("name", data.GetLabel()); } ret.pushKV("purpose", data.purpose); return ret; @@ -4296,7 +4296,7 @@ // value of the name key/value pair in the labels array below. const auto *address_book_entry = pwallet->FindAddressBookEntry(dest); if (address_book_entry) { - ret.pushKV("label", address_book_entry->name); + ret.pushKV("label", address_book_entry->GetLabel()); } ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); @@ -4328,7 +4328,7 @@ if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) { labels.push_back(AddressBookDataToJSON(*address_book_entry, true)); } else { - labels.push_back(address_book_entry->name); + labels.push_back(address_book_entry->GetLabel()); } } ret.pushKV("labels", std::move(labels)); @@ -4375,7 +4375,7 @@ if (item.second.IsChange()) { continue; } - if (item.second.name == label) { + if (item.second.GetLabel() == label) { std::string address = EncodeDestination(item.first, config); // CWallet::m_address_book is not expected to contain duplicate // address strings, but build a separate set as a precaution just in @@ -4443,7 +4443,7 @@ continue; } if (purpose.empty() || entry.second.purpose == purpose) { - label_set.insert(entry.second.name); + label_set.insert(entry.second.GetLabel()); } } diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp --- a/src/wallet/test/walletdb_tests.cpp +++ b/src/wallet/test/walletdb_tests.cpp @@ -42,8 +42,8 @@ auto w = LoadWallet(batch); LOCK(w->cs_wallet); BOOST_CHECK_EQUAL(1, w->m_address_book.count(dst1)); - BOOST_CHECK_EQUAL("name1", w->m_address_book[dst1].name); - BOOST_CHECK_EQUAL("name2", w->m_address_book[dst2].name); + BOOST_CHECK_EQUAL("name1", w->m_address_book[dst1].GetLabel()); + BOOST_CHECK_EQUAL("name2", w->m_address_book[dst2].GetLabel()); } batch.EraseName(dst1); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -195,15 +195,15 @@ std::string m_label; public: - const std::string &name; std::string purpose; - CAddressBookData() : name(m_label), purpose("unknown") {} + CAddressBookData() : purpose("unknown") {} typedef std::map StringMap; StringMap destdata; bool IsChange() const { return m_change; } + const std::string &GetLabel() const { return m_label; } void SetLabel(const std::string &label) { m_change = false; m_label = label; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3462,7 +3462,12 @@ // NOTE: This isn't a problem for sending addresses because they never have // any DestData yet! When adding new DestData, it should be considered here // whether to retain or delete it (or move it?). - assert(!IsMine(address)); + if (IsMine(address)) { + WalletLogPrintf("%s called with IsMine address, NOT SUPPORTED. Please " + "report this bug! %s\n", + __func__, PACKAGE_BUGREPORT); + return false; + } { LOCK(cs_wallet); @@ -3731,7 +3736,7 @@ continue; } const CTxDestination &address = item.first; - const std::string &strName = item.second.name; + const std::string &strName = item.second.GetLabel(); if (strName == label) { result.insert(address); } diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py --- a/test/functional/wallet_avoidreuse.py +++ b/test/functional/wallet_avoidreuse.py @@ -93,6 +93,7 @@ self.nodes[0].generate(110) self.sync_all() + self.test_change_remains_change(self.nodes[1]) reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) self.test_fund_send_fund_senddirty() reset_balance(self.nodes[1], self.nodes[0].getnewaddress()) @@ -158,6 +159,31 @@ # Unload temp wallet self.nodes[1].unloadwallet(tempwallet) + def test_change_remains_change(self, node): + self.log.info( + "Test that change doesn't turn into non-change when spent") + + reset_balance(node, node.getnewaddress()) + addr = node.getnewaddress() + txid = node.sendtoaddress(addr, 1) + out = node.listunspent(minconf=0, query_options={'minimumAmount': 2}) + assert_equal(len(out), 1) + assert_equal(out[0]['txid'], txid) + changeaddr = out[0]['address'] + + # Make sure it's starting out as change as expected + assert node.getaddressinfo(changeaddr)['ischange'] + for logical_tx in node.listtransactions(): + assert logical_tx.get('address') != changeaddr + + # Spend it + reset_balance(node, node.getnewaddress()) + + # It should still be change + assert node.getaddressinfo(changeaddr)['ischange'] + for logical_tx in node.listtransactions(): + assert logical_tx.get('address') != changeaddr + def test_fund_send_fund_senddirty(self): ''' Test the same as test_fund_send_fund_send, except send the 10 BCH with