Skip to content

Commit 60aba1f

Browse files
committed
rpc: simplify getaddressinfo labels, deprecate previous behavior
- change the value returned in the RPC getaddressinfo `labels` field to an array of label name strings - deprecate the previous behavior of returning a JSON hash structure containing label `name` and address `purpose` key/value pairs - update the relevant tests
1 parent 7851f14 commit 60aba1f

File tree

7 files changed

+40
-70
lines changed

7 files changed

+40
-70
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3744,18 +3744,20 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
37443744
" getaddressinfo output fields for the embedded address, excluding metadata (timestamp, hdkeypath,\n"
37453745
" hdseedid) and relation to the wallet (ismine, iswatchonly).\n"
37463746
" \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed.\n"
3747-
" \"label\" : \"label\" (string) The label associated with the address. Defaults to \"\". Equivalent to the name field in the labels array.\n"
3747+
" \"label\" : \"label\" (string) The label associated with the address. Defaults to \"\". Equivalent to the label name in the labels array below.\n"
37483748
" \"timestamp\" : timestamp, (number, optional) The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + ".\n"
37493749
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath, if the key is HD and available.\n"
37503750
" \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed.\n"
37513751
" \"hdmasterfingerprint\" : \"<hash160>\" (string, optional) The fingerprint of the master key.\n"
3752-
" \"labels\" (object) An array of labels associated with the address. Currently limited to one label but returned\n"
3752+
" \"labels\" (json object) An array of labels associated with the address. Currently limited to one label but returned\n"
37533753
" as an array to keep the API stable if multiple labels are enabled in the future.\n"
37543754
" [\n"
3755+
" \"label name\" (string) The label name. Defaults to \"\". Equivalent to the label field above.\n\n"
3756+
" DEPRECATED, will be removed in 0.21. To re-enable, launch bitcoind with `-deprecatedrpc=labelspurpose`:\n"
37553757
" { (json object of label data)\n"
3756-
" \"name\": \"label name\" (string) The label name. Defaults to \"\". Equivalent to the label field above.\n"
3757-
" \"purpose\": \"purpose\" (string) The purpose of the associated address (send or receive).\n"
3758-
" },...\n"
3758+
" \"name\" : \"label name\" (string) The label name. Defaults to \"\". Equivalent to the label field above.\n"
3759+
" \"purpose\" : \"purpose\" (string) The purpose of the associated address (send or receive).\n"
3760+
" }\n"
37593761
" ]\n"
37603762
"}\n"
37613763
},
@@ -3769,7 +3771,6 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
37693771

37703772
UniValue ret(UniValue::VOBJ);
37713773
CTxDestination dest = DecodeDestination(request.params[0].get_str());
3772-
37733774
// Make sure the destination is valid
37743775
if (!IsValidDestination(dest)) {
37753776
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
@@ -3800,7 +3801,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
38003801

38013802
// Return label field if existing. Currently only one label can be
38023803
// associated with an address, so the label should be equivalent to the
3803-
// value of the name key/value pair in the labels hash array below.
3804+
// value of the name key/value pair in the labels array below.
38043805
if (pwallet->mapAddressBook.count(dest)) {
38053806
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
38063807
}
@@ -3819,15 +3820,22 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
38193820
}
38203821
}
38213822

3822-
// Return a labels array containing a hash of key/value pairs for the label
3823-
// name and address purpose. The name value is equivalent to the label field
3824-
// above. Currently only one label can be associated with an address, but we
3825-
// return an array so the API remains stable if we allow multiple labels to
3826-
// be associated with an address in the future.
3823+
// Return a `labels` array containing the label associated with the address,
3824+
// equivalent to the `label` field above. Currently only one label can be
3825+
// associated with an address, but we return an array so the API remains
3826+
// stable if we allow multiple labels to be associated with an address in
3827+
// the future.
3828+
//
3829+
// DEPRECATED: The previous behavior of returning an array containing a JSON
3830+
// object of `name` and `purpose` key/value pairs has been deprecated.
38273831
UniValue labels(UniValue::VARR);
38283832
std::map<CTxDestination, CAddressBookData>::iterator mi = pwallet->mapAddressBook.find(dest);
38293833
if (mi != pwallet->mapAddressBook.end()) {
3830-
labels.push_back(AddressBookDataToJSON(mi->second, true));
3834+
if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) {
3835+
labels.push_back(AddressBookDataToJSON(mi->second, true));
3836+
} else {
3837+
labels.push_back(mi->second.name);
3838+
}
38313839
}
38323840
ret.pushKV("labels", std::move(labels));
38333841

test/functional/test_framework/wallet_util.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ def get_multisig(node):
8888
p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(),
8989
p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code))
9090

91-
def labels_value(name="", purpose="receive"):
92-
"""Generate a getaddressinfo labels array from a name and purpose.
93-
Often used as the value of a labels kwarg for calling test_address below."""
94-
return [{"name": name, "purpose": purpose}]
95-
9691
def test_address(node, address, **kwargs):
9792
"""Get address info for `address` and test whether the returned values are as expected."""
9893
addr_info = node.getaddressinfo(address)

test/functional/wallet_basic.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
connect_nodes,
1616
wait_until,
1717
)
18-
from test_framework.wallet_util import (
19-
labels_value,
20-
test_address,
21-
)
18+
from test_framework.wallet_util import test_address
2219

2320

2421
class WalletTest(BitcoinTestFramework):
@@ -395,7 +392,7 @@ def run_test(self):
395392
for label in [u'рыба', u'𝅘𝅥𝅯']:
396393
addr = self.nodes[0].getnewaddress()
397394
self.nodes[0].setlabel(addr, label)
398-
test_address(self.nodes[0], addr, label=label, labels=labels_value(name=label))
395+
test_address(self.nodes[0], addr, label=label, labels=[label])
399396
assert label in self.nodes[0].listlabels()
400397
self.nodes[0].rpc.ensure_ascii = True # restore to default
401398

test/functional/wallet_import_with_label.py

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
"""
1212

1313
from test_framework.test_framework import BitcoinTestFramework
14-
from test_framework.wallet_util import (
15-
labels_value,
16-
test_address,
17-
)
14+
from test_framework.wallet_util import test_address
1815

1916

2017
class ImportWithLabel(BitcoinTestFramework):
@@ -40,19 +37,15 @@ def run_test(self):
4037
iswatchonly=True,
4138
ismine=False,
4239
label=label,
43-
labels=labels_value(name=label))
40+
labels=[label])
4441

4542
self.log.info(
4643
"Import the watch-only address's private key without a "
4744
"label and the address should keep its label."
4845
)
4946
priv_key = self.nodes[0].dumpprivkey(address)
5047
self.nodes[1].importprivkey(priv_key)
51-
52-
test_address(self.nodes[1],
53-
address,
54-
label=label,
55-
labels=labels_value(name=label))
48+
test_address(self.nodes[1], address, label=label, labels=[label])
5649

5750
self.log.info(
5851
"Test importaddress without label and importprivkey with label."
@@ -65,7 +58,7 @@ def run_test(self):
6558
iswatchonly=True,
6659
ismine=False,
6760
label="",
68-
labels=labels_value())
61+
labels=[""])
6962

7063
self.log.info(
7164
"Import the watch-only address's private key with a "
@@ -75,10 +68,7 @@ def run_test(self):
7568
label2 = "Test Label 2"
7669
self.nodes[1].importprivkey(priv_key2, label2)
7770

78-
test_address(self.nodes[1],
79-
address2,
80-
label=label2,
81-
labels=labels_value(name=label2))
71+
test_address(self.nodes[1], address2, label=label2, labels=[label2])
8272

8373
self.log.info("Test importaddress with label and importprivkey with label.")
8474
self.log.info("Import a watch-only address with a label.")
@@ -90,7 +80,7 @@ def run_test(self):
9080
iswatchonly=True,
9181
ismine=False,
9282
label=label3_addr,
93-
labels=labels_value(name=label3_addr))
83+
labels=[label3_addr])
9484

9585
self.log.info(
9686
"Import the watch-only address's private key with a "
@@ -100,10 +90,7 @@ def run_test(self):
10090
label3_priv = "Test Label 3 for importprivkey"
10191
self.nodes[1].importprivkey(priv_key3, label3_priv)
10292

103-
test_address(self.nodes[1],
104-
address3,
105-
label=label3_priv,
106-
labels=labels_value(name=label3_priv))
93+
test_address(self.nodes[1], address3, label=label3_priv, labels=[label3_priv])
10794

10895
self.log.info(
10996
"Test importprivkey won't label new dests with the same "
@@ -118,7 +105,7 @@ def run_test(self):
118105
iswatchonly=True,
119106
ismine=False,
120107
label=label4_addr,
121-
labels=labels_value(name=label4_addr),
108+
labels=[label4_addr],
122109
embedded=None)
123110

124111
self.log.info(
@@ -131,15 +118,9 @@ def run_test(self):
131118
self.nodes[1].importprivkey(priv_key4)
132119
embedded_addr = self.nodes[1].getaddressinfo(address4)['embedded']['address']
133120

134-
test_address(self.nodes[1],
135-
embedded_addr,
136-
label="",
137-
labels=labels_value())
121+
test_address(self.nodes[1], embedded_addr, label="", labels=[""])
138122

139-
test_address(self.nodes[1],
140-
address4,
141-
label=label4_addr,
142-
labels=labels_value(name=label4_addr))
123+
test_address(self.nodes[1], address4, label=label4_addr, labels=[label4_addr])
143124

144125
self.stop_nodes()
145126

test/functional/wallet_importmulti.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
from test_framework.wallet_util import (
3030
get_key,
3131
get_multisig,
32-
labels_value,
3332
test_address,
3433
)
3534

@@ -571,7 +570,7 @@ def run_test(self):
571570
solvable=True,
572571
ismine=True,
573572
label=p2sh_p2wpkh_label,
574-
labels=labels_value(name=p2sh_p2wpkh_label))
573+
labels=[p2sh_p2wpkh_label])
575574

576575
# Test ranged descriptor fails if range is not specified
577576
xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg"
@@ -643,7 +642,7 @@ def run_test(self):
643642
solvable=True,
644643
ismine=False,
645644
label=p2pkh_label,
646-
labels=labels_value(name=p2pkh_label))
645+
labels=[p2pkh_label])
647646

648647
# Test import fails if both desc and scriptPubKey are provided
649648
key = get_key(self.nodes[0])

test/functional/wallet_labels.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@
1313

1414
from test_framework.test_framework import BitcoinTestFramework
1515
from test_framework.util import assert_equal, assert_raises_rpc_error
16-
from test_framework.wallet_util import (
17-
labels_value,
18-
test_address,
19-
)
16+
from test_framework.wallet_util import test_address
17+
2018

2119
class WalletLabelsTest(BitcoinTestFramework):
2220
def set_test_params(self):
@@ -157,12 +155,7 @@ def verify(self, node):
157155
if self.receive_address is not None:
158156
assert self.receive_address in self.addresses
159157
for address in self.addresses:
160-
test_address(
161-
node,
162-
address,
163-
label=self.name,
164-
labels=labels_value(name=self.name, purpose=self.purpose[address])
165-
)
158+
test_address(node, address, label=self.name, labels=[self.name])
166159
assert self.name in node.listlabels()
167160
assert_equal(
168161
node.getaddressesbylabel(self.name),

test/functional/wallet_listreceivedby.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
assert_equal,
1212
assert_raises_rpc_error,
1313
)
14-
from test_framework.wallet_util import (
15-
labels_value,
16-
test_address,
17-
)
14+
from test_framework.wallet_util import test_address
1815

1916

2017
class ReceivedByTest(BitcoinTestFramework):
@@ -131,7 +128,7 @@ def run_test(self):
131128
# set pre-state
132129
label = ''
133130
address = self.nodes[1].getnewaddress()
134-
test_address(self.nodes[1], address, label=label, labels=labels_value(name=label))
131+
test_address(self.nodes[1], address, label=label, labels=[label])
135132
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
136133
balance_by_label = self.nodes[1].getreceivedbylabel(label)
137134

0 commit comments

Comments
 (0)