Merge #12953: Deprecate accounts

cead28b [docs] Add release notes for deprecated 'account' API (John Newbery)
72c9575 [wallet] [tests] Add tests for accounts/labels APIs (John Newbery)
109e05d [wallet] [rpc] Deprecate wallet 'account' API (John Newbery)
3576ab1 [wallet] [rpc] Deprecate account RPC methods (John Newbery)
3db1ba0 [tests] Set -deprecatedrpc=accounts in tests (John Newbery)
4e671f0 [tests] Rename rpc_listtransactions.py to wallet_listtransactions.py (John Newbery)
a28b907 [wallet] [rpc] Remove duplicate entries in rpcwallet.cpp's CRPCCommand table (John Newbery)

Pull request description:

  Deprecate all accounts functionality and make it only accessible by using `-deprecatedrpc=accounts`.

  Accounts specific RPCs, account arguments, and account related results all require the `-deprecatedrpc=accunts` startup option now in order to see account things.

  Several wallet functional tests use the accounts system. Those tests are unchanged, except to start the nodes with `-deprecatedrpc=accounts`. We can slowly migrate those tests to use the 'label' API instead of the 'account' API before accounts are fully removed.

Tree-SHA512: 89f4ae2fe6de4a1422f1817b0997ae22d63ab5a1a558362ce923a3871f3e42963405d6573c69c27f1764679cdee5b51bf52202cc407f1361bfd8066d652f3f37
This commit is contained in:
Wladimir J. van der Laan 2018-04-24 14:27:55 +02:00
commit d1d54ae6a3
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D
14 changed files with 371 additions and 92 deletions

View File

@ -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' |

View File

@ -205,6 +205,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"
@ -226,7 +233,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();
}
@ -305,6 +312,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"
@ -352,6 +366,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"
@ -388,6 +409,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"
@ -743,6 +771,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"
@ -808,7 +843,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"
@ -818,7 +853,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"
@ -830,8 +866,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"
@ -851,6 +887,7 @@ UniValue getbalance(const JSONRPCRequest& request)
LOCK2(cs_main, pwallet->cs_wallet);
if (IsDeprecatedRPCEnabled("accounts")) {
const UniValue& account_value = request.params[0];
const UniValue& minconf = request.params[1];
const UniValue& include_watchonly = request.params[2];
@ -881,6 +918,9 @@ UniValue getbalance(const JSONRPCRequest& request)
return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account));
}
return ValueFromAmount(pwallet->GetBalance());
}
UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
@ -912,6 +952,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"
@ -1038,9 +1085,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"
@ -1077,8 +1165,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();
@ -1092,6 +1182,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;
@ -1608,6 +1701,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"
@ -1685,7 +1785,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));
@ -1716,7 +1816,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())
{
@ -1755,7 +1855,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);
}
@ -1768,19 +1868,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"
@ -1809,7 +1954,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"
@ -1825,8 +1970,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();
@ -1835,8 +1981,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();
@ -1866,9 +2016,10 @@ UniValue listtransactions(const JSONRPCRequest& request)
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != nullptr)
ListTransactions(pwallet, *pwtx, strAccount, 0, true, ret, filter);
if (IsDeprecatedRPCEnabled("accounts")) {
CAccountingEntry *const pacentry = (*it).second.second;
if (pacentry != nullptr)
AcentryToJSON(*pacentry, strAccount, ret);
if (pacentry != nullptr) AcentryToJSON(*pacentry, strAccount, ret);
}
if ((int)ret.size() >= (nCount+nFrom)) break;
}
@ -1907,6 +2058,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"
@ -2010,7 +2168,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"
@ -2159,7 +2317,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"
@ -2946,7 +3104,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"
@ -3051,8 +3209,10 @@ UniValue listunspent(const JSONRPCRequest& request)
if (pwallet->mapAddressBook.count(address)) {
entry.pushKV("label", pwallet->mapAddressBook[address].name);
if (IsDeprecatedRPCEnabled("accounts")) {
entry.pushKV("account", pwallet->mapAddressBook[address].name);
}
}
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID& hash = boost::get<CScriptID>(address);
@ -3779,7 +3939,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\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
@ -3819,8 +3980,11 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
UniValue detail = DescribeWalletAddress(pwallet, dest);
ret.pushKVs(detail);
if (pwallet->mapAddressBook.count(dest)) {
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);
if (!key_id.IsNull()) {
@ -3994,16 +4158,14 @@ 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"} },
{ "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"} },

View File

@ -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
@ -26,5 +27,86 @@ class DeprecatedRpcTest(BitcoinTestFramework):
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()

View File

@ -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',

View File

@ -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

View File

@ -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"]

View File

@ -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...")

View File

@ -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")

View File

@ -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 = [[]]
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)
@ -108,12 +121,14 @@ class WalletLabelsTest(BitcoinTestFramework):
label.add_receive_address(node.getlabeladdress(label.name))
label.verify(node)
assert_equal(node.getreceivedbylabel(label.name), 2)
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
if accounts_api:
assert_equal(node.listaccounts(), expected_account_balances)
assert_equal(node.getbalance(""), 5200)
@ -123,7 +138,10 @@ class WalletLabelsTest(BitcoinTestFramework):
node.setlabel(address, label.name)
label.add_address(address)
label.verify(node)
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,6 +154,7 @@ class WalletLabelsTest(BitcoinTestFramework):
label.verify(node)
node.sendfrom("", multisig_address, 50)
node.generate(101)
if accounts_api:
for label in labels:
assert_equal(node.getbalance(label.name), 50)
@ -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]})
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):

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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",

View File

@ -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",