From a28b907f8a1e398eb458088a415d002ddbeee491 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 16 Apr 2018 14:42:31 -0400 Subject: [wallet] [rpc] Remove duplicate entries in rpcwallet.cpp's CRPCCommand table Remove duplicate listreceivedby{account,label} methods. --- src/wallet/rpcwallet.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 6212ea7512..b81e6c1213 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3996,8 +3996,6 @@ static const CRPCCommand commands[] = { "wallet", "keypoolrefill", &keypoolrefill, {"newsize"} }, { "wallet", "listaddressgroupings", &listaddressgroupings, {} }, { "wallet", "listlockunspent", &listlockunspent, {} }, - { "wallet", "listreceivedbylabel", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} }, - { "wallet", "listreceivedbyaccount", &listreceivedbylabel, {"minconf","include_empty","include_watchonly"} }, { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly","address_filter"} }, { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} }, { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} }, -- cgit v1.2.3 From 4e671f0353beaa3759f2069569f05239c0be89cf Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 11 Apr 2018 14:24:34 -0400 Subject: [tests] Rename rpc_listtransactions.py to wallet_listtransactions.py listtransactions is a wallet RPC. The test name should indicate that this is a wallet test. --- test/functional/rpc_listtransactions.py | 202 ----------------------------- test/functional/test_runner.py | 2 +- test/functional/wallet_listtransactions.py | 202 +++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 203 deletions(-) delete mode 100755 test/functional/rpc_listtransactions.py create mode 100755 test/functional/wallet_listtransactions.py diff --git a/test/functional/rpc_listtransactions.py b/test/functional/rpc_listtransactions.py deleted file mode 100755 index 0dd7372e6b..0000000000 --- a/test/functional/rpc_listtransactions.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2014-2017 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test the listtransactions API.""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from test_framework.mininode import CTransaction, COIN -from io import BytesIO - -def txFromHex(hexstring): - tx = CTransaction() - f = BytesIO(hex_str_to_bytes(hexstring)) - tx.deserialize(f) - return tx - -class ListTransactionsTest(BitcoinTestFramework): - def set_test_params(self): - self.num_nodes = 2 - self.enable_mocktime() - - def run_test(self): - # Simple send, 0 to 1: - txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) - self.sync_all() - assert_array_result(self.nodes[0].listtransactions(), - {"txid":txid}, - {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0}) - assert_array_result(self.nodes[1].listtransactions(), - {"txid":txid}, - {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0}) - # mine a block, confirmations should change: - self.nodes[0].generate(1) - self.sync_all() - assert_array_result(self.nodes[0].listtransactions(), - {"txid":txid}, - {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1}) - assert_array_result(self.nodes[1].listtransactions(), - {"txid":txid}, - {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1}) - - # send-to-self: - txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) - assert_array_result(self.nodes[0].listtransactions(), - {"txid":txid, "category":"send"}, - {"amount":Decimal("-0.2")}) - assert_array_result(self.nodes[0].listtransactions(), - {"txid":txid, "category":"receive"}, - {"amount":Decimal("0.2")}) - - # sendmany from node1: twice to self, twice to node2: - send_to = { self.nodes[0].getnewaddress() : 0.11, - self.nodes[1].getnewaddress() : 0.22, - self.nodes[0].getaccountaddress("from1") : 0.33, - self.nodes[1].getaccountaddress("toself") : 0.44 } - txid = self.nodes[1].sendmany("", send_to) - self.sync_all() - assert_array_result(self.nodes[1].listtransactions(), - {"category":"send","amount":Decimal("-0.11")}, - {"txid":txid} ) - assert_array_result(self.nodes[0].listtransactions(), - {"category":"receive","amount":Decimal("0.11")}, - {"txid":txid} ) - assert_array_result(self.nodes[1].listtransactions(), - {"category":"send","amount":Decimal("-0.22")}, - {"txid":txid} ) - assert_array_result(self.nodes[1].listtransactions(), - {"category":"receive","amount":Decimal("0.22")}, - {"txid":txid} ) - assert_array_result(self.nodes[1].listtransactions(), - {"category":"send","amount":Decimal("-0.33")}, - {"txid":txid} ) - assert_array_result(self.nodes[0].listtransactions(), - {"category":"receive","amount":Decimal("0.33")}, - {"txid":txid, "account" : "from1"} ) - assert_array_result(self.nodes[1].listtransactions(), - {"category":"send","amount":Decimal("-0.44")}, - {"txid":txid, "account" : ""} ) - assert_array_result(self.nodes[1].listtransactions(), - {"category":"receive","amount":Decimal("0.44")}, - {"txid":txid, "account" : "toself"} ) - - pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey'] - multisig = self.nodes[1].createmultisig(1, [pubkey]) - self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True) - txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1) - self.nodes[1].generate(1) - self.sync_all() - assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0) - assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True), - {"category":"receive","amount":Decimal("0.1")}, - {"txid":txid, "account" : "watchonly"} ) - - self.run_rbf_opt_in_test() - - # Check that the opt-in-rbf flag works properly, for sent and received - # transactions. - def run_rbf_opt_in_test(self): - # Check whether a transaction signals opt-in RBF itself - def is_opt_in(node, txid): - rawtx = node.getrawtransaction(txid, 1) - for x in rawtx["vin"]: - if x["sequence"] < 0xfffffffe: - return True - return False - - # Find an unconfirmed output matching a certain txid - def get_unconfirmed_utxo_entry(node, txid_to_match): - utxo = node.listunspent(0, 0) - for i in utxo: - if i["txid"] == txid_to_match: - return i - return None - - # 1. Chain a few transactions that don't opt-in. - txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) - assert(not is_opt_in(self.nodes[0], txid_1)) - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) - sync_mempools(self.nodes) - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) - - # Tx2 will build off txid_1, still not opting in to RBF. - utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1) - assert_equal(utxo_to_use["safe"], True) - utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1) - utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1) - assert_equal(utxo_to_use["safe"], False) - - # Create tx2 using createrawtransaction - inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}] - outputs = {self.nodes[0].getnewaddress(): 0.999} - tx2 = self.nodes[1].createrawtransaction(inputs, outputs) - tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"] - txid_2 = self.nodes[1].sendrawtransaction(tx2_signed) - - # ...and check the result - assert(not is_opt_in(self.nodes[1], txid_2)) - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) - sync_mempools(self.nodes) - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) - - # Tx3 will opt-in to RBF - utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2) - inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}] - outputs = {self.nodes[1].getnewaddress(): 0.998} - tx3 = self.nodes[0].createrawtransaction(inputs, outputs) - tx3_modified = txFromHex(tx3) - tx3_modified.vin[0].nSequence = 0 - tx3 = bytes_to_hex_str(tx3_modified.serialize()) - tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex'] - txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) - - assert(is_opt_in(self.nodes[0], txid_3)) - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) - sync_mempools(self.nodes) - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) - - # Tx4 will chain off tx3. Doesn't signal itself, but depends on one - # that does. - utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3) - inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}] - outputs = {self.nodes[0].getnewaddress(): 0.997} - tx4 = self.nodes[1].createrawtransaction(inputs, outputs) - tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"] - txid_4 = self.nodes[1].sendrawtransaction(tx4_signed) - - assert(not is_opt_in(self.nodes[1], txid_4)) - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) - sync_mempools(self.nodes) - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) - - # Replace tx3, and check that tx4 becomes unknown - tx3_b = tx3_modified - tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee - tx3_b = bytes_to_hex_str(tx3_b.serialize()) - tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex'] - txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) - assert(is_opt_in(self.nodes[0], txid_3b)) - - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) - sync_mempools(self.nodes) - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) - - # Check gettransaction as well: - for n in self.nodes[0:2]: - assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no") - assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no") - assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes") - assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes") - assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown") - - # After mining a transaction, it's no longer BIP125-replaceable - self.nodes[0].generate(1) - assert(txid_3b not in self.nodes[0].getrawmempool()) - assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no") - assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown") - - -if __name__ == '__main__': - ListTransactionsTest().main() - diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 518c16b5f1..c93f7592e9 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -70,7 +70,7 @@ BASE_SCRIPTS = [ 'wallet_labels.py', 'p2p_segwit.py', 'wallet_dump.py', - 'rpc_listtransactions.py', + 'wallet_listtransactions.py', # vv Tests less than 60s vv 'p2p_sendheaders.py', 'wallet_zapwallettxes.py', diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py new file mode 100755 index 0000000000..0dd7372e6b --- /dev/null +++ b/test/functional/wallet_listtransactions.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test the listtransactions API.""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.mininode import CTransaction, COIN +from io import BytesIO + +def txFromHex(hexstring): + tx = CTransaction() + f = BytesIO(hex_str_to_bytes(hexstring)) + tx.deserialize(f) + return tx + +class ListTransactionsTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.enable_mocktime() + + def run_test(self): + # Simple send, 0 to 1: + txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) + self.sync_all() + assert_array_result(self.nodes[0].listtransactions(), + {"txid":txid}, + {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0}) + assert_array_result(self.nodes[1].listtransactions(), + {"txid":txid}, + {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0}) + # mine a block, confirmations should change: + self.nodes[0].generate(1) + self.sync_all() + assert_array_result(self.nodes[0].listtransactions(), + {"txid":txid}, + {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1}) + assert_array_result(self.nodes[1].listtransactions(), + {"txid":txid}, + {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1}) + + # send-to-self: + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2) + assert_array_result(self.nodes[0].listtransactions(), + {"txid":txid, "category":"send"}, + {"amount":Decimal("-0.2")}) + assert_array_result(self.nodes[0].listtransactions(), + {"txid":txid, "category":"receive"}, + {"amount":Decimal("0.2")}) + + # sendmany from node1: twice to self, twice to node2: + send_to = { self.nodes[0].getnewaddress() : 0.11, + self.nodes[1].getnewaddress() : 0.22, + self.nodes[0].getaccountaddress("from1") : 0.33, + self.nodes[1].getaccountaddress("toself") : 0.44 } + txid = self.nodes[1].sendmany("", send_to) + self.sync_all() + assert_array_result(self.nodes[1].listtransactions(), + {"category":"send","amount":Decimal("-0.11")}, + {"txid":txid} ) + assert_array_result(self.nodes[0].listtransactions(), + {"category":"receive","amount":Decimal("0.11")}, + {"txid":txid} ) + assert_array_result(self.nodes[1].listtransactions(), + {"category":"send","amount":Decimal("-0.22")}, + {"txid":txid} ) + assert_array_result(self.nodes[1].listtransactions(), + {"category":"receive","amount":Decimal("0.22")}, + {"txid":txid} ) + assert_array_result(self.nodes[1].listtransactions(), + {"category":"send","amount":Decimal("-0.33")}, + {"txid":txid} ) + assert_array_result(self.nodes[0].listtransactions(), + {"category":"receive","amount":Decimal("0.33")}, + {"txid":txid, "account" : "from1"} ) + assert_array_result(self.nodes[1].listtransactions(), + {"category":"send","amount":Decimal("-0.44")}, + {"txid":txid, "account" : ""} ) + assert_array_result(self.nodes[1].listtransactions(), + {"category":"receive","amount":Decimal("0.44")}, + {"txid":txid, "account" : "toself"} ) + + pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey'] + multisig = self.nodes[1].createmultisig(1, [pubkey]) + self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True) + txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1) + self.nodes[1].generate(1) + self.sync_all() + assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0) + assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True), + {"category":"receive","amount":Decimal("0.1")}, + {"txid":txid, "account" : "watchonly"} ) + + self.run_rbf_opt_in_test() + + # Check that the opt-in-rbf flag works properly, for sent and received + # transactions. + def run_rbf_opt_in_test(self): + # Check whether a transaction signals opt-in RBF itself + def is_opt_in(node, txid): + rawtx = node.getrawtransaction(txid, 1) + for x in rawtx["vin"]: + if x["sequence"] < 0xfffffffe: + return True + return False + + # Find an unconfirmed output matching a certain txid + def get_unconfirmed_utxo_entry(node, txid_to_match): + utxo = node.listunspent(0, 0) + for i in utxo: + if i["txid"] == txid_to_match: + return i + return None + + # 1. Chain a few transactions that don't opt-in. + txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1) + assert(not is_opt_in(self.nodes[0], txid_1)) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) + sync_mempools(self.nodes) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"}) + + # Tx2 will build off txid_1, still not opting in to RBF. + utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1) + assert_equal(utxo_to_use["safe"], True) + utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1) + utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1) + assert_equal(utxo_to_use["safe"], False) + + # Create tx2 using createrawtransaction + inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}] + outputs = {self.nodes[0].getnewaddress(): 0.999} + tx2 = self.nodes[1].createrawtransaction(inputs, outputs) + tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"] + txid_2 = self.nodes[1].sendrawtransaction(tx2_signed) + + # ...and check the result + assert(not is_opt_in(self.nodes[1], txid_2)) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) + sync_mempools(self.nodes) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"}) + + # Tx3 will opt-in to RBF + utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2) + inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}] + outputs = {self.nodes[1].getnewaddress(): 0.998} + tx3 = self.nodes[0].createrawtransaction(inputs, outputs) + tx3_modified = txFromHex(tx3) + tx3_modified.vin[0].nSequence = 0 + tx3 = bytes_to_hex_str(tx3_modified.serialize()) + tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex'] + txid_3 = self.nodes[0].sendrawtransaction(tx3_signed) + + assert(is_opt_in(self.nodes[0], txid_3)) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) + sync_mempools(self.nodes) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"}) + + # Tx4 will chain off tx3. Doesn't signal itself, but depends on one + # that does. + utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3) + inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}] + outputs = {self.nodes[0].getnewaddress(): 0.997} + tx4 = self.nodes[1].createrawtransaction(inputs, outputs) + tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"] + txid_4 = self.nodes[1].sendrawtransaction(tx4_signed) + + assert(not is_opt_in(self.nodes[1], txid_4)) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) + sync_mempools(self.nodes) + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"}) + + # Replace tx3, and check that tx4 becomes unknown + tx3_b = tx3_modified + tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee + tx3_b = bytes_to_hex_str(tx3_b.serialize()) + tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex'] + txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True) + assert(is_opt_in(self.nodes[0], txid_3b)) + + assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) + sync_mempools(self.nodes) + assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"}) + + # Check gettransaction as well: + for n in self.nodes[0:2]: + assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no") + assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no") + assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes") + assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes") + assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown") + + # After mining a transaction, it's no longer BIP125-replaceable + self.nodes[0].generate(1) + assert(txid_3b not in self.nodes[0].getrawmempool()) + assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no") + assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown") + + +if __name__ == '__main__': + ListTransactionsTest().main() + -- cgit v1.2.3 From 3db1ba01c783c1e35782405750c308be2b6171e3 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 16 Apr 2018 13:53:35 -0400 Subject: [tests] Set -deprecatedrpc=accounts in tests Future commits will deprecate the accounts RPC methods, arguments and return objects. Set the -deprecatedrpc=accounts switch now so tests don't break in intermediate commits. --- test/functional/wallet_basic.py | 11 ++++++----- test/functional/wallet_import_rescan.py | 2 +- test/functional/wallet_importprunedfunds.py | 1 + test/functional/wallet_keypool_topup.py | 2 +- test/functional/wallet_labels.py | 2 +- test/functional/wallet_listreceivedby.py | 1 + test/functional/wallet_listsinceblock.py | 1 + test/functional/wallet_listtransactions.py | 1 + test/functional/wallet_txn_clone.py | 1 + test/functional/wallet_txn_doublespend.py | 1 + 10 files changed, 15 insertions(+), 8 deletions(-) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 0436aca6a4..bfe90957a7 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -10,9 +10,10 @@ class WalletTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def setup_network(self): - self.add_nodes(4) + self.add_nodes(4, self.extra_args) self.start_node(0) self.start_node(1) self.start_node(2) @@ -376,9 +377,9 @@ class WalletTest(BitcoinTestFramework): self.log.info("check " + m) self.stop_nodes() # set lower ancestor limit for later - self.start_node(0, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(1, [m, "-limitancestorcount="+str(chainlimit)]) - self.start_node(2, [m, "-limitancestorcount="+str(chainlimit)]) + self.start_node(0, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) + self.start_node(1, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) + self.start_node(2, [m, "-deprecatedrpc=accounts", "-limitancestorcount="+str(chainlimit)]) if m == '-reindex': # reindex will leave rpc warm up "early"; Wait for it to finish wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)]) @@ -426,7 +427,7 @@ class WalletTest(BitcoinTestFramework): # Try with walletrejectlongchains # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf self.stop_node(0) - self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) + self.start_node(0, extra_args=["-deprecatedrpc=accounts", "-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) # wait for loadmempool timeout = 10 diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py index b66e9b5d91..6775d8b46d 100755 --- a/test/functional/wallet_import_rescan.py +++ b/test/functional/wallet_import_rescan.py @@ -119,7 +119,7 @@ class ImportRescanTest(BitcoinTestFramework): self.num_nodes = 2 + len(IMPORT_NODES) def setup_network(self): - extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)] + extra_args = [["-addresstype=legacy", '-deprecatedrpc=accounts'] for _ in range(self.num_nodes)] for i, import_node in enumerate(IMPORT_NODES, 2): if import_node.prune: extra_args[i] += ["-prune=1"] diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py index 4d349db23f..283acc8035 100755 --- a/test/functional/wallet_importprunedfunds.py +++ b/test/functional/wallet_importprunedfunds.py @@ -10,6 +10,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 def run_test(self): self.log.info("Mining blocks...") diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py index 30a0c9a760..ab1493dd04 100755 --- a/test/functional/wallet_keypool_topup.py +++ b/test/functional/wallet_keypool_topup.py @@ -25,7 +25,7 @@ class KeypoolRestoreTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 2 - self.extra_args = [[], ['-keypool=100', '-keypoolmin=20']] + self.extra_args = [['-deprecatedrpc=accounts'], ['-deprecatedrpc=accounts', '-keypool=100', '-keypoolmin=20']] def run_test(self): wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat") diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 90eefc0438..0def2f1643 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -21,7 +21,7 @@ class WalletLabelsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 - self.extra_args = [[]] + self.extra_args = [['-deprecatedrpc=accounts']] def run_test(self): node = self.nodes[0] diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index 7b34febddc..aba5d642bc 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -14,6 +14,7 @@ from test_framework.util import (assert_array_result, class ReceivedByTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 def run_test(self): # Generate block to get out of IBD diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index 0f2434ff0d..930bfcd7b0 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -11,6 +11,7 @@ class ListSinceBlockTest (BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 self.setup_clean_chain = True + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def run_test(self): self.nodes[2].generate(101) diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index 0dd7372e6b..5466bbf18b 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -18,6 +18,7 @@ def txFromHex(hexstring): class ListTransactionsTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts']] * 2 self.enable_mocktime() def run_test(self): diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index d742ec4618..3057d20d64 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -10,6 +10,7 @@ from test_framework.util import * class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py index f16756eeaa..53ba929b5d 100755 --- a/test/functional/wallet_txn_doublespend.py +++ b/test/functional/wallet_txn_doublespend.py @@ -10,6 +10,7 @@ from test_framework.util import * class TxnMallTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 + self.extra_args = [['-deprecatedrpc=accounts']] * 4 def add_options(self, parser): parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true", -- cgit v1.2.3 From 3576ab126121f9bfb4d4d6195cbbe7ba30619f77 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 16 Apr 2018 13:57:13 -0400 Subject: [wallet] [rpc] Deprecate account RPC methods All account RPC methods are now deprecated and can only be called if bitcoind has been started with the -deprecatedrpc=accounts switch. Affected RPC methods are: - getaccount - getaccountaddress - getaddressesbyaccount - getreceivedbyaccount - listaccouts - listreceivedbyaccount - move - setaccount --- src/wallet/rpcwallet.cpp | 56 +++++++++++++++++++++++++ test/functional/rpc_deprecated.py | 86 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b81e6c1213..37086f9b60 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -206,6 +206,13 @@ UniValue getlabeladdress(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "getaccountaddress") { + if (request.fHelp) { + throw std::runtime_error("getaccountaddress (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaccountaddress is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( "getlabeladdress \"label\" ( force ) \n" @@ -306,6 +313,13 @@ UniValue setlabel(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "setaccount") { + if (request.fHelp) { + throw std::runtime_error("setaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "setaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() != 2) throw std::runtime_error( "setlabel \"address\" \"label\"\n" @@ -353,6 +367,13 @@ UniValue getaccount(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts")) { + if (request.fHelp) { + throw std::runtime_error("getaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "getaccount \"address\"\n" @@ -389,6 +410,13 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts")) { + if (request.fHelp) { + throw std::runtime_error("getaddressbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "getaddressesbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "getaddressesbyaccount \"account\"\n" @@ -744,6 +772,13 @@ UniValue getreceivedbylabel(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "getreceivedbyaccount") { + if (request.fHelp) { + throw std::runtime_error("getreceivedbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "getreceivedbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) throw std::runtime_error( "getreceivedbylabel \"label\" ( minconf )\n" @@ -913,6 +948,13 @@ UniValue movecmd(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts")) { + if (request.fHelp) { + throw std::runtime_error("move (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "move is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() < 3 || request.params.size() > 5) throw std::runtime_error( "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n" @@ -1609,6 +1651,13 @@ UniValue listreceivedbylabel(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts") && request.strMethod == "listreceivedbyaccount") { + if (request.fHelp) { + throw std::runtime_error("listreceivedbyaccount (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "listreceivedbyaccount is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() > 3) throw std::runtime_error( "listreceivedbylabel ( minconf include_empty include_watchonly)\n" @@ -1908,6 +1957,13 @@ UniValue listaccounts(const JSONRPCRequest& request) return NullUniValue; } + if (!IsDeprecatedRPCEnabled("accounts")) { + if (request.fHelp) { + throw std::runtime_error("listaccounts (Deprecated, will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts)"); + } + throw JSONRPCError(RPC_METHOD_DEPRECATED, "listaccounts is deprecated and will be removed in V0.18. To use this command, start bitcoind with -deprecatedrpc=accounts."); + } + if (request.fHelp || request.params.size() > 2) throw std::runtime_error( "listaccounts ( minconf include_watchonly)\n" diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index b94b9d8fae..7b7c596506 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,12 +4,13 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=validateaddress"]] + self.extra_args = [[], ["-deprecatedrpc=validateaddress", "-deprecatedrpc=accounts"]] def run_test(self): # This test should be used to verify correct behaviour of deprecated @@ -20,11 +21,92 @@ class DeprecatedRpcTest(BitcoinTestFramework): # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) self.log.info("Test validateaddress deprecation") - SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress + SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress dep_validate_address = self.nodes[0].validateaddress(SOME_ADDRESS) assert "ismine" not in dep_validate_address not_dep_val = self.nodes[1].validateaddress(SOME_ADDRESS) assert "ismine" in not_dep_val + self.log.info("Test accounts deprecation") + # The following account RPC methods are deprecated: + # - getaccount + # - getaccountaddress + # - getaddressesbyaccount + # - getreceivedbyaccount + # - listaccouts + # - listreceivedbyaccount + # - move + # - setaccount + # + # The following 'label' RPC methods are usable both with and without the + # -deprecatedrpc=accounts switch enabled. + # - getlabeladdress + # - getaddressesbylabel + # - getreceivedbylabel + # - listlabels + # - listreceivedbylabel + # - setlabel + # + address0 = self.nodes[0].getnewaddress() + self.nodes[0].generatetoaddress(101, address0) + address1 = self.nodes[1].getnewaddress() + self.nodes[1].generatetoaddress(101, address1) + + self.log.info("- getaccount") + assert_raises_rpc_error(-32, "getaccount is deprecated", self.nodes[0].getaccount, address0) + self.nodes[1].getaccount(address1) + + self.log.info("- setaccount") + assert_raises_rpc_error(-32, "setaccount is deprecated", self.nodes[0].setaccount, address0, "label0") + self.nodes[1].setaccount(address1, "label1") + + self.log.info("- setlabel") + self.nodes[0].setlabel(address0, "label0") + self.nodes[1].setlabel(address1, "label1") + + self.log.info("- getaccountaddress") + assert_raises_rpc_error(-32, "getaccountaddress is deprecated", self.nodes[0].getaccountaddress, "label0") + self.nodes[1].getaccountaddress("label1") + + self.log.info("- getlabeladdress") + self.nodes[0].getlabeladdress("label0") + self.nodes[1].getlabeladdress("label1") + + self.log.info("- getaddressesbyaccount") + assert_raises_rpc_error(-32, "getaddressesbyaccount is deprecated", self.nodes[0].getaddressesbyaccount, "label0") + self.nodes[1].getaddressesbyaccount("label1") + + self.log.info("- getaddressesbylabel") + self.nodes[0].getaddressesbylabel("label0") + self.nodes[1].getaddressesbylabel("label1") + + self.log.info("- getreceivedbyaccount") + assert_raises_rpc_error(-32, "getreceivedbyaccount is deprecated", self.nodes[0].getreceivedbyaccount, "label0") + self.nodes[1].getreceivedbyaccount("label1") + + self.log.info("- getreceivedbylabel") + self.nodes[0].getreceivedbylabel("label0") + self.nodes[1].getreceivedbylabel("label1") + + self.log.info("- listaccounts") + assert_raises_rpc_error(-32, "listaccounts is deprecated", self.nodes[0].listaccounts) + self.nodes[1].listaccounts() + + self.log.info("- listlabels") + self.nodes[0].listlabels() + self.nodes[1].listlabels() + + self.log.info("- listreceivedbyaccount") + assert_raises_rpc_error(-32, "listreceivedbyaccount is deprecated", self.nodes[0].listreceivedbyaccount) + self.nodes[1].listreceivedbyaccount() + + self.log.info("- listreceivedbylabel") + self.nodes[0].listreceivedbylabel() + self.nodes[1].listreceivedbylabel() + + self.log.info("- move") + assert_raises_rpc_error(-32, "move is deprecated", self.nodes[0].move, "label0", "label0b", 10) + self.nodes[1].move("label1", "label1b", 10) + if __name__ == '__main__': DeprecatedRpcTest().main() -- cgit v1.2.3 From 109e05dcd163b8ddb7f4b3550db6b9ab833b2c04 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 16 Apr 2018 14:01:52 -0400 Subject: [wallet] [rpc] Deprecate wallet 'account' API This commit finalizes the deprecation of the wallet 'accounts' API by removing all account arguments and return values. RPC behaviour is slightly different if the 'accounts' or 'labels' API is being used. Those behaviour changes are fully documented in the RPC help text. --- src/wallet/rpcwallet.cpp | 220 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 164 insertions(+), 56 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 37086f9b60..c6b1034e45 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -234,7 +234,7 @@ UniValue getlabeladdress(const JSONRPCRequest& request) // Parse the label first so we don't generate a key if there's an error std::string label = LabelFromValue(request.params[0]); - bool force = request.strMethod == "getaccountaddress" ? true : false; + bool force = request.strMethod == "getaccountaddress"; if (!request.params[1].isNull()) { force = request.params[1].get_bool(); } @@ -844,7 +844,7 @@ UniValue getbalance(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 3) + if (request.fHelp || (request.params.size() > 3 && IsDeprecatedRPCEnabled("accounts")) || (request.params.size() != 0 && !IsDeprecatedRPCEnabled("accounts"))) throw std::runtime_error( "getbalance ( \"account\" minconf include_watchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" @@ -854,7 +854,8 @@ UniValue getbalance(const JSONRPCRequest& request) "Note that the account \"\" is not the same as leaving the parameter out.\n" "The server total may be different to the balance in the default \"\" account.\n" "\nArguments:\n" - "1. \"account\" (string, optional) DEPRECATED. The account string may be given as a\n" + "1. \"account\" (string, optional) DEPRECATED. This argument will be removed in V0.18. \n" + " To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. The account string may be given as a\n" " specific account name to find the balance associated with wallet keys in\n" " a named account, or as the empty string (\"\") to find the balance\n" " associated with wallet keys not in any named account, or as \"*\" to find\n" @@ -866,8 +867,8 @@ UniValue getbalance(const JSONRPCRequest& request) " balances. In general, account balance calculation is not considered\n" " reliable and has resulted in confusing outcomes, so it is recommended to\n" " avoid passing this argument.\n" - "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" - "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n" + "2. minconf (numeric, optional, default=1) DEPRECATED. Only valid when an account is specified. This argument will be removed in V0.18. To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. Only include transactions confirmed at least this many times.\n" + "3. include_watchonly (bool, optional, default=false) DEPRECATED. Only valid when an account is specified. This argument will be removed in V0.18. To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. Also include balance in watch-only addresses (see 'importaddress')\n" "\nResult:\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" @@ -887,34 +888,38 @@ UniValue getbalance(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - const UniValue& account_value = request.params[0]; - const UniValue& minconf = request.params[1]; - const UniValue& include_watchonly = request.params[2]; + if (IsDeprecatedRPCEnabled("accounts")) { + const UniValue& account_value = request.params[0]; + const UniValue& minconf = request.params[1]; + const UniValue& include_watchonly = request.params[2]; - if (account_value.isNull()) { - if (!minconf.isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "getbalance minconf option is only currently supported if an account is specified"); - } - if (!include_watchonly.isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "getbalance include_watchonly option is only currently supported if an account is specified"); + if (account_value.isNull()) { + if (!minconf.isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + "getbalance minconf option is only currently supported if an account is specified"); + } + if (!include_watchonly.isNull()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + "getbalance include_watchonly option is only currently supported if an account is specified"); + } + return ValueFromAmount(pwallet->GetBalance()); } - return ValueFromAmount(pwallet->GetBalance()); - } - const std::string& account_param = account_value.get_str(); - const std::string* account = account_param != "*" ? &account_param : nullptr; + const std::string& account_param = account_value.get_str(); + const std::string* account = account_param != "*" ? &account_param : nullptr; - int nMinDepth = 1; - if (!minconf.isNull()) - nMinDepth = minconf.get_int(); - isminefilter filter = ISMINE_SPENDABLE; - if(!include_watchonly.isNull()) - if(include_watchonly.get_bool()) - filter = filter | ISMINE_WATCH_ONLY; + int nMinDepth = 1; + if (!minconf.isNull()) + nMinDepth = minconf.get_int(); + isminefilter filter = ISMINE_SPENDABLE; + if(!include_watchonly.isNull()) + if(include_watchonly.get_bool()) + filter = filter | ISMINE_WATCH_ONLY; + + return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account)); + } - return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account)); + return ValueFromAmount(pwallet->GetBalance()); } UniValue getunconfirmedbalance(const JSONRPCRequest &request) @@ -1081,9 +1086,50 @@ UniValue sendmany(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) - throw std::runtime_error( - "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n" + std::string help_text; + if (!IsDeprecatedRPCEnabled("accounts")) { + help_text = "sendmany \"\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n" + "\nSend multiple times. Amounts are double-precision floating point numbers.\n" + "Note that the \"fromaccount\" argument has been removed in V0.17. To use this RPC with a \"fromaccount\" argument, restart\n" + "bitcoind with -deprecatedrpc=accounts\n" + + HelpRequiringPassphrase(pwallet) + "\n" + "\nArguments:\n" + "1. \"dummy\" (string, required) Must be set to \"\" for backwards compatibility.\n" + "2. \"amounts\" (string, required) A json object with addresses and amounts\n" + " {\n" + " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n" + " ,...\n" + " }\n" + "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" + "4. \"comment\" (string, optional) A comment\n" + "5. subtractfeefrom (array, optional) A json array with addresses.\n" + " The fee will be equally deducted from the amount of each selected address.\n" + " Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n" + " If no addresses are specified here, the sender pays the fee.\n" + " [\n" + " \"address\" (string) Subtract fee from this address\n" + " ,...\n" + " ]\n" + "6. replaceable (boolean, optional) Allow this transaction to be replaced by a transaction with higher fees via BIP 125\n" + "7. conf_target (numeric, optional) Confirmation target (in blocks)\n" + "8. \"estimate_mode\" (string, optional, default=UNSET) The fee estimate mode, must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\"\n" + "\nResult:\n" + "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" + " the number of addresses.\n" + "\nExamples:\n" + "\nSend two amounts to two different addresses:\n" + + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") + + "\nSend two amounts to two different addresses setting the confirmation and comment:\n" + + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") + + "\nSend two amounts to two different addresses, subtract fee from amount:\n" + + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") + + "\nAs a json rpc call\n" + + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\""); + } else { + help_text = "sendmany \"\" \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] replaceable conf_target \"estimate_mode\")\n" "\nSend multiple times. Amounts are double-precision floating point numbers." + HelpRequiringPassphrase(pwallet) + "\n" "\nArguments:\n" @@ -1120,8 +1166,10 @@ UniValue sendmany(const JSONRPCRequest& request) "\nSend two amounts to two different addresses, subtract fee from amount:\n" + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") + "\nAs a json rpc call\n" - + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"") - ); + + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\""); + } + + if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error(help_text); ObserveSafeMode(); @@ -1135,6 +1183,9 @@ UniValue sendmany(const JSONRPCRequest& request) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } + if (!IsDeprecatedRPCEnabled("accounts") && !request.params[0].get_str().empty()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"\""); + } std::string strAccount = LabelFromValue(request.params[0]); UniValue sendTo = request.params[1].get_obj(); int nMinDepth = 1; @@ -1735,7 +1786,7 @@ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::s if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) { entry.pushKV("involvesWatchonly", true); } - entry.pushKV("account", strSentAccount); + if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("account", strSentAccount); MaybePushAddress(entry, s.destination); entry.pushKV("category", "send"); entry.pushKV("amount", ValueFromAmount(-s.amount)); @@ -1766,7 +1817,7 @@ void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::s if (involvesWatchonly || (::IsMine(*pwallet, r.destination) & ISMINE_WATCH_ONLY)) { entry.pushKV("involvesWatchonly", true); } - entry.pushKV("account", account); + if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("account", account); MaybePushAddress(entry, r.destination); if (wtx.IsCoinBase()) { @@ -1805,7 +1856,7 @@ void AcentryToJSON(const CAccountingEntry& acentry, const std::string& strAccoun entry.pushKV("category", "move"); entry.pushKV("time", acentry.nTime); entry.pushKV("amount", ValueFromAmount(acentry.nCreditDebit)); - entry.pushKV("otheraccount", acentry.strOtherAccount); + if (IsDeprecatedRPCEnabled("accounts")) entry.pushKV("otheraccount", acentry.strOtherAccount); entry.pushKV("comment", acentry.strComment); ret.push_back(entry); } @@ -1818,19 +1869,64 @@ UniValue listtransactions(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) - throw std::runtime_error( - "listtransactions ( \"account\" count skip include_watchonly)\n" + std::string help_text {}; + if (!IsDeprecatedRPCEnabled("accounts")) { + help_text = "listtransactions (dummy count skip include_watchonly)\n" "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n" + "Note that the \"account\" argument and \"otheraccount\" return value have been removed in V0.17. To use this RPC with an \"account\" argument, restart\n" + "bitcoind with -deprecatedrpc=accounts\n" "\nArguments:\n" - "1. \"account\" (string, optional) DEPRECATED. The account name. Should be \"*\".\n" + "1. \"dummy\" (string, optional) If set, should be \"*\" for backwards compatibility.\n" "2. count (numeric, optional, default=10) The number of transactions to return\n" "3. skip (numeric, optional, default=0) The number of transactions to skip\n" "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n" "\nResult:\n" "[\n" " {\n" - " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. \n" + " \"address\":\"address\", (string) The bitcoin address of the transaction.\n" + " \"category\":\"send|receive\", (string) The transaction category.\n" + " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" + " for the 'receive' category,\n" + " \"label\": \"label\", (string) A comment for the address/transaction, if any\n" + " \"vout\": n, (numeric) the vout value\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" + " 'send' category of transactions.\n" + " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Negative confirmations indicate the\n" + " transaction conflicts with the block chain\n" + " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n" + " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n" + " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n" + " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" + " \"txid\": \"transactionid\", (string) The transaction id.\n" + " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n" + " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT).\n" + " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" + " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" + " may be unknown for unconfirmed transactions not in the mempool\n" + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + " 'send' category of transactions.\n" + " }\n" + "]\n" + + "\nExamples:\n" + "\nList the most recent 10 transactions in the systems\n" + + HelpExampleCli("listtransactions", "") + + "\nList transactions 100 to 120\n" + + HelpExampleCli("listtransactions", "\"*\" 20 100") + + "\nAs a json rpc call\n" + + HelpExampleRpc("listtransactions", "\"*\", 20, 100"); + } else { + help_text = "listtransactions ( \"account\" count skip include_watchonly)\n" + "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n" + "\nArguments:\n" + "1. \"account\" (string, optional) DEPRECATED. This argument will be removed in V0.18. The account name. Should be \"*\".\n" + "2. count (numeric, optional, default=10) The number of transactions to return\n" + "3. skip (numeric, optional, default=0) The number of transactions to skip\n" + "4. include_watchonly (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n" + "\nResult:\n" + "[\n" + " {\n" + " \"account\":\"accountname\", (string) DEPRECATED. This field will be removed in V0.18. The account name associated with the transaction. \n" " It will be \"\" for the default account.\n" " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for \n" " move transactions (category = move).\n" @@ -1859,7 +1955,7 @@ UniValue listtransactions(const JSONRPCRequest& request) " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n" " for 'send' and 'receive' category of transactions.\n" " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" - " \"otheraccount\": \"accountname\", (string) DEPRECATED. For the 'move' category of transactions, the account the funds came \n" + " \"otheraccount\": \"accountname\", (string) DEPRECATED. This field will be removed in V0.18. For the 'move' category of transactions, the account the funds came \n" " from (for receiving funds, positive amounts), or went to (for sending funds,\n" " negative amounts).\n" " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" @@ -1875,8 +1971,9 @@ UniValue listtransactions(const JSONRPCRequest& request) "\nList transactions 100 to 120\n" + HelpExampleCli("listtransactions", "\"*\" 20 100") + "\nAs a json rpc call\n" - + HelpExampleRpc("listtransactions", "\"*\", 20, 100") - ); + + HelpExampleRpc("listtransactions", "\"*\", 20, 100"); + } + if (request.fHelp || request.params.size() > 4) throw std::runtime_error(help_text); ObserveSafeMode(); @@ -1885,8 +1982,12 @@ UniValue listtransactions(const JSONRPCRequest& request) pwallet->BlockUntilSyncedToCurrentChain(); std::string strAccount = "*"; - if (!request.params[0].isNull()) + if (!request.params[0].isNull()) { strAccount = request.params[0].get_str(); + if (!IsDeprecatedRPCEnabled("accounts") && strAccount != "*") { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Dummy value must be set to \"*\""); + } + } int nCount = 10; if (!request.params[1].isNull()) nCount = request.params[1].get_int(); @@ -1916,9 +2017,10 @@ UniValue listtransactions(const JSONRPCRequest& request) CWalletTx *const pwtx = (*it).second.first; if (pwtx != nullptr) ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter); - CAccountingEntry *const pacentry = (*it).second.second; - if (pacentry != nullptr) - AcentryToJSON(*pacentry, strAccount, ret); + if (IsDeprecatedRPCEnabled("accounts")) { + CAccountingEntry *const pacentry = (*it).second.second; + if (pacentry != nullptr) AcentryToJSON(*pacentry, strAccount, ret); + } if ((int)ret.size() >= (nCount+nFrom)) break; } @@ -2067,7 +2169,7 @@ UniValue listsinceblock(const JSONRPCRequest& request) "\nResult:\n" "{\n" " \"transactions\": [\n" - " \"account\":\"accountname\", (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n" + " \"account\":\"accountname\", (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account name associated with the transaction. Will be \"\" for the default account.\n" " \"address\":\"address\", (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n" " \"category\":\"send|receive\", (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n" " \"amount\": x.xxx, (numeric) The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and for the 'move' category for moves \n" @@ -2216,7 +2318,7 @@ UniValue gettransaction(const JSONRPCRequest& request) " may be unknown for unconfirmed transactions not in the mempool\n" " \"details\" : [\n" " {\n" - " \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n" + " \"account\" : \"accountname\", (string) DEPRECATED. This field will be removed in a V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account name involved in the transaction, can be \"\" for the default account.\n" " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n" " \"category\" : \"send|receive\", (string) The category, either 'send' or 'receive'\n" " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" @@ -3004,7 +3106,7 @@ UniValue listunspent(const JSONRPCRequest& request) " \"vout\" : n, (numeric) the vout value\n" " \"address\" : \"address\", (string) the bitcoin address\n" " \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n" - " \"account\" : \"account\", (string) DEPRECATED. Backwards compatible alias for label.\n" + " \"account\" : \"account\", (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The associated account, or \"\" for the default account\n" " \"scriptPubKey\" : \"key\", (string) the script key\n" " \"amount\" : x.xxx, (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" @@ -3109,7 +3211,9 @@ UniValue listunspent(const JSONRPCRequest& request) if (pwallet->mapAddressBook.count(address)) { entry.pushKV("label", pwallet->mapAddressBook[address].name); - entry.pushKV("account", pwallet->mapAddressBook[address].name); + if (IsDeprecatedRPCEnabled("accounts")) { + entry.pushKV("account", pwallet->mapAddressBook[address].name); + } } if (scriptPubKey.IsPayToScriptHash()) { @@ -3837,7 +3941,8 @@ UniValue getaddressinfo(const JSONRPCRequest& request) " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n" " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" - " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n" + " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default account\n" + " \"account\" : \"account\" (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdmasterkeyid\" : \"\" (string, optional) The Hash160 of the HD master pubkey\n" @@ -3877,7 +3982,10 @@ UniValue getaddressinfo(const JSONRPCRequest& request) UniValue detail = DescribeWalletAddress(pwallet, dest); ret.pushKVs(detail); if (pwallet->mapAddressBook.count(dest)) { - ret.pushKV("account", pwallet->mapAddressBook[dest].name); + ret.pushKV("label", pwallet->mapAddressBook[dest].name); + if (IsDeprecatedRPCEnabled("accounts")) { + ret.pushKV("account", pwallet->mapAddressBook[dest].name); + } } const CKeyMetadata* meta = nullptr; CKeyID key_id = GetKeyForDestination(*pwallet, dest); @@ -4054,12 +4162,12 @@ static const CRPCCommand commands[] = { "wallet", "listlockunspent", &listlockunspent, {} }, { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, {"minconf","include_empty","include_watchonly","address_filter"} }, { "wallet", "listsinceblock", &listsinceblock, {"blockhash","target_confirmations","include_watchonly","include_removed"} }, - { "wallet", "listtransactions", &listtransactions, {"account","count","skip","include_watchonly"} }, + { "wallet", "listtransactions", &listtransactions, {"account|dummy","count","skip","include_watchonly"} }, { "wallet", "listunspent", &listunspent, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, { "wallet", "listwallets", &listwallets, {} }, { "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} }, { "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} }, - { "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} }, + { "wallet", "sendmany", &sendmany, {"fromaccount|dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} }, { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} }, { "wallet", "settxfee", &settxfee, {"amount"} }, { "wallet", "signmessage", &signmessage, {"address","message"} }, -- cgit v1.2.3 From 72c9575f7b793e3c77bd2d631ef7345a4c31cb0d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 17 Apr 2018 14:13:00 -0400 Subject: [wallet] [tests] Add tests for accounts/labels APIs --- test/functional/wallet_labels.py | 57 ++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 0def2f1643..705dd8985e 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -6,25 +6,38 @@ RPCs tested are: - getlabeladdress - - getaddressesbyaccount + - getaddressesbyaccount/getaddressesbylabel - listaddressgroupings - setlabel - sendfrom (with account arguments) - move (with account arguments) + +Run the test twice - once using the accounts API and once using the labels API. +The accounts API test can be removed in V0.18. """ from collections import defaultdict from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal +from test_framework.util import assert_equal, assert_raises_rpc_error class WalletLabelsTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True - self.num_nodes = 1 - self.extra_args = [['-deprecatedrpc=accounts']] + self.num_nodes = 2 + self.extra_args = [['-deprecatedrpc=accounts'], []] + + def setup_network(self): + """Don't connect nodes.""" + self.setup_nodes() def run_test(self): - node = self.nodes[0] + """Run the test twice - once using the accounts API and once using the labels API.""" + self.log.info("Test accounts API") + self._run_subtest(True, self.nodes[0]) + self.log.info("Test labels API") + self._run_subtest(False, self.nodes[1]) + + def _run_subtest(self, accounts_api, node): # Check that there's no UTXO on any of the nodes assert_equal(len(node.listunspent()), 0) @@ -77,7 +90,7 @@ class WalletLabelsTest(BitcoinTestFramework): # Create labels and make sure subsequent label API calls # recognize the label/address associations. - labels = [Label(name) for name in ("a", "b", "c", "d", "e")] + labels = [Label(name, accounts_api) for name in ("a", "b", "c", "d", "e")] for label in labels: label.add_receive_address(node.getlabeladdress(label=label.name, force=True)) label.verify(node) @@ -101,21 +114,23 @@ class WalletLabelsTest(BitcoinTestFramework): # Check that sendfrom label reduces listaccounts balances. for i, label in enumerate(labels): - to_label = labels[(i+1) % len(labels)] + to_label = labels[(i + 1) % len(labels)] node.sendfrom(label.name, to_label.receive_address, amount_to_send) node.generate(1) for label in labels: label.add_receive_address(node.getlabeladdress(label.name)) label.verify(node) assert_equal(node.getreceivedbylabel(label.name), 2) - node.move(label.name, "", node.getbalance(label.name)) + if accounts_api: + node.move(label.name, "", node.getbalance(label.name)) label.verify(node) node.generate(101) expected_account_balances = {"": 5200} for label in labels: expected_account_balances[label.name] = 0 - assert_equal(node.listaccounts(), expected_account_balances) - assert_equal(node.getbalance(""), 5200) + if accounts_api: + assert_equal(node.listaccounts(), expected_account_balances) + assert_equal(node.getbalance(""), 5200) # Check that setlabel can assign a label to a new unused address. for label in labels: @@ -123,7 +138,10 @@ class WalletLabelsTest(BitcoinTestFramework): node.setlabel(address, label.name) label.add_address(address) label.verify(node) - assert(address not in node.getaddressesbyaccount("")) + if accounts_api: + assert(address not in node.getaddressesbyaccount("")) + else: + assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "") # Check that addmultisigaddress can assign labels. for label in labels: @@ -136,8 +154,9 @@ class WalletLabelsTest(BitcoinTestFramework): label.verify(node) node.sendfrom("", multisig_address, 50) node.generate(101) - for label in labels: - assert_equal(node.getbalance(label.name), 50) + if accounts_api: + for label in labels: + assert_equal(node.getbalance(label.name), 50) # Check that setlabel can change the label of an address from a # different label. @@ -156,9 +175,10 @@ class WalletLabelsTest(BitcoinTestFramework): change_label(node, labels[2].receive_address, labels[2], labels[2]) class Label: - def __init__(self, name): + def __init__(self, name, accounts_api): # Label name self.name = name + self.accounts_api = accounts_api # Current receiving address associated with this label. self.receive_address = None # List of all addresses assigned with this label @@ -184,13 +204,16 @@ class Label: node.getaddressinfo(address)['labels'][0], {"name": self.name, "purpose": self.purpose[address]}) - assert_equal(node.getaccount(address), self.name) + if self.accounts_api: + assert_equal(node.getaccount(address), self.name) + else: + assert_equal(node.getaddressinfo(address)['label'], self.name) assert_equal( node.getaddressesbylabel(self.name), {address: {"purpose": self.purpose[address]} for address in self.addresses}) - assert_equal( - set(node.getaddressesbyaccount(self.name)), set(self.addresses)) + if self.accounts_api: + assert_equal(set(node.getaddressesbyaccount(self.name)), set(self.addresses)) def change_label(node, address, old_label, new_label): -- cgit v1.2.3 From cead28bbecf032b49c01ca3ae4f47aa2536cbc55 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 17 Apr 2018 14:20:28 -0400 Subject: [docs] Add release notes for deprecated 'account' API --- doc/release-notes-pr12892.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/release-notes-pr12892.md b/doc/release-notes-pr12892.md index 894bf19dee..8105eca5c0 100644 --- a/doc/release-notes-pr12892.md +++ b/doc/release-notes-pr12892.md @@ -1,8 +1,10 @@ -'label' API for wallet ----------------------- +'label' and 'account' APIs for wallet +------------------------------------- A new 'label' API has been introduced for the wallet. This is intended as a -replacement for the deprecated 'account' API. +replacement for the deprecated 'account' API. The 'account' can continue to +be used in V0.17 by starting bitcoind with the '-deprecatedrpc=accounts' +argument, and will be fully removed in V0.18. The label RPC methods mirror the account functionality, with the following functional differences: @@ -27,6 +29,9 @@ Here are the changes to RPC methods: | Changed Method | Notes | | :--------------------- | :------ | -| `addmultisigaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility. | -| `getnewaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility. | -| `listunspent` | Returns new `label` fields, along with `account` fields for backward compatibility. | +| `addmultisigaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility if running with '-deprecatedrpc=accounts'. | +| `getnewaddress` | Renamed `account` named parameter to `label`. Still accepts `account` for backward compatibility. if running with '-deprecatedrpc=accounts' | +| `listunspent` | Returns new `label` fields. `account` field will be returned for backward compatibility if running with '-deprecatedrpc=accounts' | +| `sendmany` | The `account` named parameter has been renamed to `dummy`. If provided, the `dummy` parameter must be set to the empty string, unless running with the `-deprecatedrpc=accounts` argument (in which case functionality is unchanged). | +| `listtransactions` | The `account` named parameter has been renamed to `dummy`. If provided, the `dummy` parameter must be set to the string `*`, unless running with the `-deprecatedrpc=accounts` argument (in which case functionality is unchanged). | +| `getbalance` | `account`, `minconf` and `include_watchonly` parameters are deprecated, and can only be used if running with '-deprecatedrpc=accounts' | -- cgit v1.2.3