Skip to content

Commit 3f0f394

Browse files
committed
Merge #13060: [wallet] [rpc] Remove getlabeladdress RPC
67e0e04 [wallet] [docs] Update release notes for removing `getlabeladdress` (John Newbery) 8160817 [wallet] [rpc] Remove getlabeladdress RPC (John Newbery) Pull request description: labels are associated with addresses (rather than addresses being associated with labels, as was the case with accounts). The getlabeladdress does not make sense in this model, so remove it. getaccountaddress is still supported for one release as the accounts API is deprecated. Tree-SHA512: 7f45d0456248ebcc4e54dd34e2578a09a8ea8e4fceda75238ccea9d731dc99a3f3c0519b18a9739de17d2e6e59c9c2259ba67c9ae2e3cb2a40ddb14b9193fe29
2 parents 26c93ed + 67e0e04 commit 3f0f394

File tree

5 files changed

+86
-79
lines changed

5 files changed

+86
-79
lines changed

doc/release-notes-pr12892.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Here are the changes to RPC methods:
1818
| Deprecated Method | New Method | Notes |
1919
| :---------------------- | :-------------------- | :-----------|
2020
| `getaccount` | `getaddressinfo` | `getaddressinfo` returns a json object with address information instead of just the name of the account as a string. |
21-
| `getaccountaddress` | `getlabeladdress` | `getlabeladdress` throws an error by default if the label does not already exist, but provides a `force` option for compatibility with existing applications. |
21+
| `getaccountaddress` | n/a | There is no replacement for `getaccountaddress` since labels do not have an associated receive address. |
2222
| `getaddressesbyaccount` | `getaddressesbylabel` | `getaddressesbylabel` returns a json object with the addresses as keys, instead of a list of strings. |
2323
| `getreceivedbyaccount` | `getreceivedbylabel` | _no change in behavior_ |
2424
| `listaccounts` | `listlabels` | `listlabels` does not return a balance or accept `minconf` and `watchonly` arguments. |

src/rpc/client.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
5252
{ "listreceivedbylabel", 0, "minconf" },
5353
{ "listreceivedbylabel", 1, "include_empty" },
5454
{ "listreceivedbylabel", 2, "include_watchonly" },
55-
{ "getlabeladdress", 1, "force" },
5655
{ "getbalance", 1, "minconf" },
5756
{ "getbalance", 2, "include_watchonly" },
5857
{ "getblockhash", 0, "height" },

src/wallet/rpcwallet.cpp

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& la
198198
return dest;
199199
}
200200

201-
static UniValue getlabeladdress(const JSONRPCRequest& request)
201+
static UniValue getaccountaddress(const JSONRPCRequest& request)
202202
{
203203
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
204204
CWallet* const pwallet = wallet.get();
@@ -207,53 +207,36 @@ static UniValue getlabeladdress(const JSONRPCRequest& request)
207207
return NullUniValue;
208208
}
209209

210-
if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "getaccountaddress") {
210+
if (!IsDeprecatedRPCEnabled("accounts")) {
211211
if (request.fHelp) {
212212
throw std::runtime_error("getaccountaddress (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)");
213213
}
214214
throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaccountaddress is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts.");
215215
}
216216

217-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
217+
if (request.fHelp || request.params.size() != 1)
218218
throw std::runtime_error(
219-
"getlabeladdress \"label\" ( force ) \n"
220-
"\nReturns the default receiving address for this label. This will reset to a fresh address once there's a transaction that spends to it.\n"
219+
"getaccountaddress \"account\"\n"
220+
"\n\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
221221
"\nArguments:\n"
222-
"1. \"label\" (string, required) The label for the address. It can also be set to the empty string \"\" to represent the default label.\n"
223-
"2. \"force\" (bool, optional) Whether the label should be created if it does not yet exist. If False, the RPC will return an error if called with a label that doesn't exist.\n"
224-
" Defaults to false (unless the getaccountaddress method alias is being called, in which case defaults to true for backwards compatibility).\n"
222+
"1. \"account\" (string, required) The account for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
225223
"\nResult:\n"
226-
"\"address\" (string) The current receiving address for the label.\n"
224+
"\"address\" (string) The account bitcoin address\n"
227225
"\nExamples:\n"
228-
+ HelpExampleCli("getlabeladdress", "")
229-
+ HelpExampleCli("getlabeladdress", "\"\"")
230-
+ HelpExampleCli("getlabeladdress", "\"mylabel\"")
231-
+ HelpExampleRpc("getlabeladdress", "\"mylabel\"")
226+
+ HelpExampleCli("getaccountaddress", "")
227+
+ HelpExampleCli("getaccountaddress", "\"\"")
228+
+ HelpExampleCli("getaccountaddress", "\"myaccount\"")
229+
+ HelpExampleRpc("getaccountaddress", "\"myaccount\"")
232230
);
233231

234232
LOCK2(cs_main, pwallet->cs_wallet);
235233

236-
// Parse the label first so we don't generate a key if there's an error
237-
std::string label = LabelFromValue(request.params[0]);
238-
bool force = request.strMethod == "getaccountaddress";
239-
if (!request.params[1].isNull()) {
240-
force = request.params[1].get_bool();
241-
}
242-
243-
bool label_found = false;
244-
for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
245-
if (item.second.name == label) {
246-
label_found = true;
247-
break;
248-
}
249-
}
250-
if (!force && !label_found) {
251-
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
252-
}
234+
// Parse the account first so we don't generate a key if there's an error
235+
std::string account = LabelFromValue(request.params[0]);
253236

254237
UniValue ret(UniValue::VSTR);
255238

256-
ret = EncodeDestination(GetLabelDestination(pwallet, label));
239+
ret = EncodeDestination(GetLabelDestination(pwallet, account));
257240
return ret;
258241
}
259242

@@ -343,23 +326,33 @@ static UniValue setlabel(const JSONRPCRequest& request)
343326
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
344327
}
345328

329+
std::string old_label = pwallet->mapAddressBook[dest].name;
346330
std::string label = LabelFromValue(request.params[1]);
347331

348332
if (IsMine(*pwallet, dest)) {
349-
// Detect when changing the label of an address that is the receiving address of another label:
350-
// If so, delete the account record for it. Labels, unlike addresses, can be deleted,
351-
// and if we wouldn't do this, the record would stick around forever.
352-
if (pwallet->mapAddressBook.count(dest)) {
353-
std::string old_label = pwallet->mapAddressBook[dest].name;
354-
if (old_label != label && dest == GetLabelDestination(pwallet, old_label)) {
355-
pwallet->DeleteLabel(old_label);
356-
}
357-
}
358333
pwallet->SetAddressBook(dest, label, "receive");
334+
if (request.strMethod == "setaccount" && old_label != label && dest == GetLabelDestination(pwallet, old_label)) {
335+
// for setaccount, call GetLabelDestination so a new receive address is created for the old account
336+
GetLabelDestination(pwallet, old_label, true);
337+
}
359338
} else {
360339
pwallet->SetAddressBook(dest, label, "send");
361340
}
362341

342+
// Detect when there are no addresses using this label.
343+
// If so, delete the account record for it. Labels, unlike addresses, can be deleted,
344+
// and if we wouldn't do this, the record would stick around forever.
345+
bool found_address = false;
346+
for (const std::pair<CTxDestination, CAddressBookData>& item : pwallet->mapAddressBook) {
347+
if (item.second.name == label) {
348+
found_address = true;
349+
break;
350+
}
351+
}
352+
if (!found_address) {
353+
pwallet->DeleteLabel(old_label);
354+
}
355+
363356
return NullUniValue;
364357
}
365358

@@ -4404,7 +4397,7 @@ static const CRPCCommand commands[] =
44044397
{ "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
44054398

44064399
/** Account functions (deprecated) */
4407-
{ "wallet", "getaccountaddress", &getlabeladdress, {"account"} },
4400+
{ "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
44084401
{ "wallet", "getaccount", &getaccount, {"address"} },
44094402
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
44104403
{ "wallet", "getreceivedbyaccount", &getreceivedbylabel, {"account","minconf"} },
@@ -4414,7 +4407,6 @@ static const CRPCCommand commands[] =
44144407
{ "wallet", "move", &movecmd, {"fromaccount","toaccount","amount","minconf","comment"} },
44154408

44164409
/** Label functions (to replace non-balance account functions) */
4417-
{ "wallet", "getlabeladdress", &getlabeladdress, {"label","force"} },
44184410
{ "wallet", "getaddressesbylabel", &getaddressesbylabel, {"label"} },
44194411
{ "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
44204412
{ "wallet", "listlabels", &listlabels, {"purpose"} },

test/functional/rpc_deprecated.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def run_test(self):
4040
#
4141
# The following 'label' RPC methods are usable both with and without the
4242
# -deprecatedrpc=accounts switch enabled.
43-
# - getlabeladdress
4443
# - getaddressesbylabel
4544
# - getreceivedbylabel
4645
# - listlabels
@@ -69,10 +68,6 @@ def run_test(self):
6968
assert_raises_rpc_error(-32, "getaccountaddress is deprecated", self.nodes[0].getaccountaddress, "label0")
7069
self.nodes[1].getaccountaddress("label1")
7170

72-
self.log.info("- getlabeladdress")
73-
self.nodes[0].getlabeladdress("label0")
74-
self.nodes[1].getlabeladdress("label1")
75-
7671
self.log.info("- getaddressesbyaccount")
7772
assert_raises_rpc_error(-32, "getaddressesbyaccount is deprecated", self.nodes[0].getaddressesbyaccount, "label0")
7873
self.nodes[1].getaddressesbyaccount("label1")

test/functional/wallet_labels.py

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""Test label RPCs.
66
77
RPCs tested are:
8-
- getlabeladdress
8+
- getaccountaddress
99
- getaddressesbyaccount/getaddressesbylabel
1010
- listaddressgroupings
1111
- setlabel
@@ -92,17 +92,24 @@ def _run_subtest(self, accounts_api, node):
9292
# recognize the label/address associations.
9393
labels = [Label(name, accounts_api) for name in ("a", "b", "c", "d", "e")]
9494
for label in labels:
95-
label.add_receive_address(node.getlabeladdress(label=label.name, force=True))
95+
if accounts_api:
96+
address = node.getaccountaddress(label.name)
97+
else:
98+
address = node.getnewaddress(label.name)
99+
label.add_receive_address(address)
96100
label.verify(node)
97101

98102
# Check all labels are returned by listlabels.
99103
assert_equal(node.listlabels(), [label.name for label in labels])
100104

101105
# Send a transaction to each label, and make sure this forces
102-
# getlabeladdress to generate a new receiving address.
106+
# getaccountaddress to generate a new receiving address.
103107
for label in labels:
104-
node.sendtoaddress(label.receive_address, amount_to_send)
105-
label.add_receive_address(node.getlabeladdress(label.name))
108+
if accounts_api:
109+
node.sendtoaddress(label.receive_address, amount_to_send)
110+
label.add_receive_address(node.getaccountaddress(label.name))
111+
else:
112+
node.sendtoaddress(label.addresses[0], amount_to_send)
106113
label.verify(node)
107114

108115
# Check the amounts received.
@@ -115,10 +122,17 @@ def _run_subtest(self, accounts_api, node):
115122
# Check that sendfrom label reduces listaccounts balances.
116123
for i, label in enumerate(labels):
117124
to_label = labels[(i + 1) % len(labels)]
118-
node.sendfrom(label.name, to_label.receive_address, amount_to_send)
125+
if accounts_api:
126+
node.sendfrom(label.name, to_label.receive_address, amount_to_send)
127+
else:
128+
node.sendfrom(label.name, to_label.addresses[0], amount_to_send)
119129
node.generate(1)
120130
for label in labels:
121-
label.add_receive_address(node.getlabeladdress(label.name))
131+
if accounts_api:
132+
address = node.getaccountaddress(label.name)
133+
else:
134+
address = node.getnewaddress(label.name)
135+
label.add_receive_address(address)
122136
label.verify(node)
123137
assert_equal(node.getreceivedbylabel(label.name), 2)
124138
if accounts_api:
@@ -134,12 +148,12 @@ def _run_subtest(self, accounts_api, node):
134148

135149
# Check that setlabel can assign a label to a new unused address.
136150
for label in labels:
137-
address = node.getlabeladdress(label="", force=True)
151+
address = node.getnewaddress()
138152
node.setlabel(address, label.name)
139153
label.add_address(address)
140154
label.verify(node)
141155
if accounts_api:
142-
assert(address not in node.getaddressesbyaccount(""))
156+
assert address not in node.getaddressesbyaccount("")
143157
else:
144158
assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "")
145159

@@ -160,19 +174,20 @@ def _run_subtest(self, accounts_api, node):
160174

161175
# Check that setlabel can change the label of an address from a
162176
# different label.
163-
change_label(node, labels[0].addresses[0], labels[0], labels[1])
164-
165-
# Check that setlabel can change the label of an address which
166-
# is the receiving address of a different label.
167-
change_label(node, labels[0].receive_address, labels[0], labels[1])
177+
change_label(node, labels[0].addresses[0], labels[0], labels[1], accounts_api)
168178

169179
# Check that setlabel can set the label of an address already
170180
# in the label. This is a no-op.
171-
change_label(node, labels[2].addresses[0], labels[2], labels[2])
181+
change_label(node, labels[2].addresses[0], labels[2], labels[2], accounts_api)
182+
183+
if accounts_api:
184+
# Check that setaccount can change the label of an address which
185+
# is the receiving address of a different label.
186+
change_label(node, labels[0].receive_address, labels[0], labels[1], accounts_api)
172187

173-
# Check that setlabel can set the label of an address which is
174-
# already the receiving address of the label. This is a no-op.
175-
change_label(node, labels[2].receive_address, labels[2], labels[2])
188+
# Check that setaccount can set the label of an address which is
189+
# already the receiving address of the label. This is a no-op.
190+
change_label(node, labels[2].receive_address, labels[2], labels[2], accounts_api)
176191

177192
class Label:
178193
def __init__(self, name, accounts_api):
@@ -192,12 +207,14 @@ def add_address(self, address):
192207

193208
def add_receive_address(self, address):
194209
self.add_address(address)
195-
self.receive_address = address
210+
if self.accounts_api:
211+
self.receive_address = address
196212

197213
def verify(self, node):
198214
if self.receive_address is not None:
199215
assert self.receive_address in self.addresses
200-
assert_equal(node.getlabeladdress(self.name), self.receive_address)
216+
if self.accounts_api:
217+
assert_equal(node.getaccountaddress(self.name), self.receive_address)
201218

202219
for address in self.addresses:
203220
assert_equal(
@@ -216,22 +233,26 @@ def verify(self, node):
216233
assert_equal(set(node.getaddressesbyaccount(self.name)), set(self.addresses))
217234

218235

219-
def change_label(node, address, old_label, new_label):
236+
def change_label(node, address, old_label, new_label, accounts_api):
220237
assert_equal(address in old_label.addresses, True)
221-
node.setlabel(address, new_label.name)
238+
if accounts_api:
239+
node.setaccount(address, new_label.name)
240+
else:
241+
node.setlabel(address, new_label.name)
222242

223243
old_label.addresses.remove(address)
224244
new_label.add_address(address)
225245

226-
# Calling setlabel on an address which was previously the receiving
227-
# address of a different label should reset the receiving address of
228-
# the old label, causing getlabeladdress to return a brand new
246+
# Calling setaccount on an address which was previously the receiving
247+
# address of a different account should reset the receiving address of
248+
# the old account, causing getaccountaddress to return a brand new
229249
# address.
230-
if old_label.name != new_label.name and address == old_label.receive_address:
231-
new_address = node.getlabeladdress(old_label.name)
232-
assert_equal(new_address not in old_label.addresses, True)
233-
assert_equal(new_address not in new_label.addresses, True)
234-
old_label.add_receive_address(new_address)
250+
if accounts_api:
251+
if old_label.name != new_label.name and address == old_label.receive_address:
252+
new_address = node.getaccountaddress(old_label.name)
253+
assert_equal(new_address not in old_label.addresses, True)
254+
assert_equal(new_address not in new_label.addresses, True)
255+
old_label.add_receive_address(new_address)
235256

236257
old_label.verify(node)
237258
new_label.verify(node)

0 commit comments

Comments
 (0)