Rename account to label where appropriate
This change only updates strings and adds RPC aliases, but should simplify the implementation of address labels in https://github.com/bitcoin/bitcoin/pull/7729, by getting renaming out of the way and letting it focus on semantics. The difference between accounts and labels is that labels apply only to addresses, while accounts apply to both addresses and transactions (transactions have "from" and "to" accounts). The code associating accounts with transactions is clumsy and unreliable so we would like get rid of it.
This commit is contained in:
parent
c39dd2ef59
commit
045eeb8870
10 changed files with 253 additions and 231 deletions
|
@ -63,6 +63,16 @@ RPC changes
|
|||
|
||||
- The `createrawtransaction` RPC will now accept an array or dictionary (kept for compatibility) for the `outputs` parameter. This means the order of transaction outputs can be specified by the client.
|
||||
- The `fundrawtransaction` RPC will reject the previously deprecated `reserveChangeKey` option.
|
||||
- Wallet `getnewaddress` and `addmultisigaddress` RPC `account` named
|
||||
parameters have been renamed to `label` with no change in behavior.
|
||||
- Wallet `getlabeladdress`, `getreceivedbylabel`, `listreceivedbylabel`, and
|
||||
`setlabel` RPCs have been added to replace `getaccountaddress`,
|
||||
`getreceivedbyaccount`, `listreceivedbyaccount`, and `setaccount` RPCs,
|
||||
which are now deprecated. There is no change in behavior between the
|
||||
new RPCs and deprecated RPCs.
|
||||
- Wallet `listreceivedbylabel`, `listreceivedbyaccount` and `listunspent` RPCs
|
||||
add `label` fields to returned JSON objects that previously only had
|
||||
`account` fields.
|
||||
|
||||
External wallet files
|
||||
---------------------
|
||||
|
|
|
@ -634,8 +634,6 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r
|
|||
payment.add_transactions(transaction.data(), transaction.size());
|
||||
|
||||
// Create a new refund address, or re-use:
|
||||
QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant);
|
||||
std::string strAccount = account.toStdString();
|
||||
CPubKey newKey;
|
||||
if (wallet->GetKeyFromPool(newKey)) {
|
||||
// BIP70 requests encode the scriptPubKey directly, so we are not restricted to address
|
||||
|
@ -646,7 +644,8 @@ void PaymentServer::fetchPaymentACK(CWallet* wallet, const SendCoinsRecipient& r
|
|||
const OutputType change_type = wallet->m_default_change_type != OutputType::NONE ? wallet->m_default_change_type : wallet->m_default_address_type;
|
||||
wallet->LearnRelatedScripts(newKey, change_type);
|
||||
CTxDestination dest = GetDestinationForKey(newKey, change_type);
|
||||
wallet->SetAddressBook(dest, strAccount, "refund");
|
||||
std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString();
|
||||
wallet->SetAddressBook(dest, label, "refund");
|
||||
|
||||
CScript s = GetScriptForDestination(dest);
|
||||
payments::Output* refund_to = payment.add_refund_to();
|
||||
|
|
|
@ -40,6 +40,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "settxfee", 0, "amount" },
|
||||
{ "getreceivedbyaddress", 1, "minconf" },
|
||||
{ "getreceivedbyaccount", 1, "minconf" },
|
||||
{ "getreceivedbylabel", 1, "minconf" },
|
||||
{ "listreceivedbyaddress", 0, "minconf" },
|
||||
{ "listreceivedbyaddress", 1, "include_empty" },
|
||||
{ "listreceivedbyaddress", 2, "include_watchonly" },
|
||||
|
@ -47,6 +48,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "listreceivedbyaccount", 0, "minconf" },
|
||||
{ "listreceivedbyaccount", 1, "include_empty" },
|
||||
{ "listreceivedbyaccount", 2, "include_watchonly" },
|
||||
{ "listreceivedbylabel", 0, "minconf" },
|
||||
{ "listreceivedbylabel", 1, "include_empty" },
|
||||
{ "listreceivedbylabel", 2, "include_watchonly" },
|
||||
{ "getbalance", 1, "minconf" },
|
||||
{ "getbalance", 2, "include_watchonly" },
|
||||
{ "getblockhash", 0, "height" },
|
||||
|
|
|
@ -76,7 +76,7 @@ enum RPCErrorCode
|
|||
//! Wallet errors
|
||||
RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.)
|
||||
RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account
|
||||
RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //!< Invalid account name
|
||||
RPC_WALLET_INVALID_LABEL_NAME = -11, //!< Invalid label name
|
||||
RPC_WALLET_KEYPOOL_RAN_OUT = -12, //!< Keypool ran out, call keypoolrefill first
|
||||
RPC_WALLET_UNLOCK_NEEDED = -13, //!< Enter the wallet passphrase with walletpassphrase first
|
||||
RPC_WALLET_PASSPHRASE_INCORRECT = -14, //!< The wallet passphrase entered was incorrect
|
||||
|
@ -85,6 +85,9 @@ enum RPCErrorCode
|
|||
RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked
|
||||
RPC_WALLET_NOT_FOUND = -18, //!< Invalid wallet specified
|
||||
RPC_WALLET_NOT_SPECIFIED = -19, //!< No wallet specified (error when there are multiple wallets loaded)
|
||||
|
||||
//! Backwards compatible aliases
|
||||
RPC_WALLET_INVALID_ACCOUNT_NAME = RPC_WALLET_INVALID_LABEL_NAME,
|
||||
};
|
||||
|
||||
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
|
||||
|
|
|
@ -124,12 +124,12 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
|
|||
entry.pushKV(item.first, item.second);
|
||||
}
|
||||
|
||||
std::string AccountFromValue(const UniValue& value)
|
||||
std::string LabelFromValue(const UniValue& value)
|
||||
{
|
||||
std::string strAccount = value.get_str();
|
||||
if (strAccount == "*")
|
||||
throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
|
||||
return strAccount;
|
||||
std::string label = value.get_str();
|
||||
if (label == "*")
|
||||
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, "Invalid label name");
|
||||
return label;
|
||||
}
|
||||
|
||||
UniValue getnewaddress(const JSONRPCRequest& request)
|
||||
|
@ -141,12 +141,12 @@ UniValue getnewaddress(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"getnewaddress ( \"account\" \"address_type\" )\n"
|
||||
"getnewaddress ( \"label\" \"address_type\" )\n"
|
||||
"\nReturns a new Bitcoin address for receiving payments.\n"
|
||||
"If 'account' is specified (DEPRECATED), it is added to the address book \n"
|
||||
"so payments received with the address will be credited to 'account'.\n"
|
||||
"If 'label' is specified, it is added to the address book \n"
|
||||
"so payments received with the address will be associated with 'label'.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"account\" (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
|
||||
"1. \"label\" (string, optional) The label name for the address to be linked to. If not provided, the default label \"\" is used. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created if there is no label by the given name.\n"
|
||||
"2. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
|
||||
"\nResult:\n"
|
||||
"\"address\" (string) The new bitcoin address\n"
|
||||
|
@ -157,10 +157,10 @@ UniValue getnewaddress(const JSONRPCRequest& request)
|
|||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
// Parse the account first so we don't generate a key if there's an error
|
||||
std::string strAccount;
|
||||
// Parse the label first so we don't generate a key if there's an error
|
||||
std::string label;
|
||||
if (!request.params[0].isNull())
|
||||
strAccount = AccountFromValue(request.params[0]);
|
||||
label = LabelFromValue(request.params[0]);
|
||||
|
||||
OutputType output_type = pwallet->m_default_address_type;
|
||||
if (!request.params[1].isNull()) {
|
||||
|
@ -182,23 +182,23 @@ UniValue getnewaddress(const JSONRPCRequest& request)
|
|||
pwallet->LearnRelatedScripts(newKey, output_type);
|
||||
CTxDestination dest = GetDestinationForKey(newKey, output_type);
|
||||
|
||||
pwallet->SetAddressBook(dest, strAccount, "receive");
|
||||
pwallet->SetAddressBook(dest, label, "receive");
|
||||
|
||||
return EncodeDestination(dest);
|
||||
}
|
||||
|
||||
|
||||
CTxDestination GetAccountDestination(CWallet* const pwallet, std::string strAccount, bool bForceNew=false)
|
||||
CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& label, bool bForceNew=false)
|
||||
{
|
||||
CTxDestination dest;
|
||||
if (!pwallet->GetAccountDestination(dest, strAccount, bForceNew)) {
|
||||
if (!pwallet->GetLabelDestination(dest, label, bForceNew)) {
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
UniValue getaccountaddress(const JSONRPCRequest& request)
|
||||
UniValue getlabeladdress(const JSONRPCRequest& request)
|
||||
{
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
|
@ -207,27 +207,27 @@ UniValue getaccountaddress(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"getaccountaddress \"account\"\n"
|
||||
"\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
|
||||
"getlabeladdress \"label\"\n"
|
||||
"\nReturns the current Bitcoin address for receiving payments to this label.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"account\" (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created if there is no account by the given name.\n"
|
||||
"1. \"label\" (string, required) The label name for the address. It can also be set to the empty string \"\" to represent the default label. The label does not need to exist, it will be created and a new address created if there is no label by the given name.\n"
|
||||
"\nResult:\n"
|
||||
"\"address\" (string) The account bitcoin address\n"
|
||||
"\"address\" (string) The label bitcoin address\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getaccountaddress", "")
|
||||
+ HelpExampleCli("getaccountaddress", "\"\"")
|
||||
+ HelpExampleCli("getaccountaddress", "\"myaccount\"")
|
||||
+ HelpExampleRpc("getaccountaddress", "\"myaccount\"")
|
||||
+ HelpExampleCli("getlabeladdress", "")
|
||||
+ HelpExampleCli("getlabeladdress", "\"\"")
|
||||
+ HelpExampleCli("getlabeladdress", "\"mylabel\"")
|
||||
+ HelpExampleRpc("getlabeladdress", "\"mylabel\"")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
// Parse the account first so we don't generate a key if there's an error
|
||||
std::string strAccount = AccountFromValue(request.params[0]);
|
||||
// Parse the label first so we don't generate a key if there's an error
|
||||
std::string label = LabelFromValue(request.params[0]);
|
||||
|
||||
UniValue ret(UniValue::VSTR);
|
||||
|
||||
ret = EncodeDestination(GetAccountDestination(pwallet, strAccount));
|
||||
ret = EncodeDestination(GetLabelDestination(pwallet, label));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -281,7 +281,7 @@ UniValue getrawchangeaddress(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
|
||||
UniValue setaccount(const JSONRPCRequest& request)
|
||||
UniValue setlabel(const JSONRPCRequest& request)
|
||||
{
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
|
@ -290,14 +290,14 @@ UniValue setaccount(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"setaccount \"address\" \"account\"\n"
|
||||
"\nDEPRECATED. Sets the account associated with the given address.\n"
|
||||
"setlabel \"address\" \"label\"\n"
|
||||
"\nSets the label associated with the given address.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"address\" (string, required) The bitcoin address to be associated with an account.\n"
|
||||
"2. \"account\" (string, required) The account to assign the address to.\n"
|
||||
"1. \"address\" (string, required) The bitcoin address to be associated with a label.\n"
|
||||
"2. \"label\" (string, required) The label to assign the address to.\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
|
||||
+ HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
|
||||
+ HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"")
|
||||
+ HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"")
|
||||
);
|
||||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
@ -307,23 +307,23 @@ UniValue setaccount(const JSONRPCRequest& request)
|
|||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
}
|
||||
|
||||
std::string strAccount;
|
||||
std::string label;
|
||||
if (!request.params[1].isNull())
|
||||
strAccount = AccountFromValue(request.params[1]);
|
||||
label = LabelFromValue(request.params[1]);
|
||||
|
||||
// Only add the account if the address is yours.
|
||||
// Only add the label if the address is yours.
|
||||
if (IsMine(*pwallet, dest)) {
|
||||
// Detect when changing the account of an address that is the 'unused current key' of another account:
|
||||
// Detect when changing the label of an address that is the 'unused current key' of another label:
|
||||
if (pwallet->mapAddressBook.count(dest)) {
|
||||
std::string strOldAccount = pwallet->mapAddressBook[dest].name;
|
||||
if (dest == GetAccountDestination(pwallet, strOldAccount)) {
|
||||
GetAccountDestination(pwallet, strOldAccount, true);
|
||||
std::string old_label = pwallet->mapAddressBook[dest].name;
|
||||
if (dest == GetLabelDestination(pwallet, old_label)) {
|
||||
GetLabelDestination(pwallet, old_label, true);
|
||||
}
|
||||
}
|
||||
pwallet->SetAddressBook(dest, strAccount, "receive");
|
||||
pwallet->SetAddressBook(dest, label, "receive");
|
||||
}
|
||||
else
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "setlabel can only be used with own address");
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request)
|
|||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
std::string strAccount = AccountFromValue(request.params[0]);
|
||||
std::string strAccount = LabelFromValue(request.params[0]);
|
||||
|
||||
// Find all addresses that have the given account
|
||||
UniValue ret(UniValue::VARR);
|
||||
|
@ -552,7 +552,7 @@ UniValue listaddressgroupings(const JSONRPCRequest& request)
|
|||
" [\n"
|
||||
" \"address\", (string) The bitcoin address\n"
|
||||
" amount, (numeric) The amount in " + CURRENCY_UNIT + "\n"
|
||||
" \"account\" (string, optional) DEPRECATED. The account\n"
|
||||
" \"label\" (string, optional) The label\n"
|
||||
" ]\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
|
@ -720,7 +720,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
|
||||
UniValue getreceivedbyaccount(const JSONRPCRequest& request)
|
||||
UniValue getreceivedbylabel(const JSONRPCRequest& request)
|
||||
{
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
|
@ -729,22 +729,22 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
"getreceivedbyaccount \"account\" ( minconf )\n"
|
||||
"\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
|
||||
"getreceivedbylabel \"label\" ( minconf )\n"
|
||||
"\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
|
||||
"1. \"label\" (string, required) The selected label, may be the default label using \"\".\n"
|
||||
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
|
||||
"\nResult:\n"
|
||||
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
|
||||
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this label.\n"
|
||||
"\nExamples:\n"
|
||||
"\nAmount received by the default account with at least 1 confirmation\n"
|
||||
+ HelpExampleCli("getreceivedbyaccount", "\"\"") +
|
||||
"\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
|
||||
+ HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
|
||||
"\nAmount received by the default label with at least 1 confirmation\n"
|
||||
+ HelpExampleCli("getreceivedbylabel", "\"\"") +
|
||||
"\nAmount received at the tabby label including unconfirmed amounts with zero confirmations\n"
|
||||
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 0") +
|
||||
"\nThe amount with at least 6 confirmations\n"
|
||||
+ HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
|
||||
+ HelpExampleCli("getreceivedbylabel", "\"tabby\" 6") +
|
||||
"\nAs a json rpc call\n"
|
||||
+ HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
|
||||
+ HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6")
|
||||
);
|
||||
|
||||
ObserveSafeMode();
|
||||
|
@ -760,9 +760,9 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
|
|||
if (!request.params[1].isNull())
|
||||
nMinDepth = request.params[1].get_int();
|
||||
|
||||
// Get the set of pub keys assigned to account
|
||||
std::string strAccount = AccountFromValue(request.params[0]);
|
||||
std::set<CTxDestination> setAddress = pwallet->GetAccountAddresses(strAccount);
|
||||
// Get the set of pub keys assigned to label
|
||||
std::string label = LabelFromValue(request.params[0]);
|
||||
std::set<CTxDestination> setAddress = pwallet->GetLabelAddresses(label);
|
||||
|
||||
// Tally
|
||||
CAmount nAmount = 0;
|
||||
|
@ -920,8 +920,8 @@ UniValue movecmd(const JSONRPCRequest& request)
|
|||
ObserveSafeMode();
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
std::string strFrom = AccountFromValue(request.params[0]);
|
||||
std::string strTo = AccountFromValue(request.params[1]);
|
||||
std::string strFrom = LabelFromValue(request.params[0]);
|
||||
std::string strTo = LabelFromValue(request.params[1]);
|
||||
CAmount nAmount = AmountFromValue(request.params[2]);
|
||||
if (nAmount <= 0)
|
||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send");
|
||||
|
@ -984,7 +984,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
|
|||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
std::string strAccount = AccountFromValue(request.params[0]);
|
||||
std::string strAccount = LabelFromValue(request.params[0]);
|
||||
CTxDestination dest = DecodeDestination(request.params[1].get_str());
|
||||
if (!IsValidDestination(dest)) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
|
||||
|
@ -1076,7 +1076,7 @@ UniValue sendmany(const JSONRPCRequest& request)
|
|||
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
|
||||
}
|
||||
|
||||
std::string strAccount = AccountFromValue(request.params[0]);
|
||||
std::string strAccount = LabelFromValue(request.params[0]);
|
||||
UniValue sendTo = request.params[1].get_obj();
|
||||
int nMinDepth = 1;
|
||||
if (!request.params[2].isNull())
|
||||
|
@ -1171,12 +1171,12 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
|
||||
std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" \"address_type\" )\n"
|
||||
std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"label\" \"address_type\" )\n"
|
||||
"\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
|
||||
"Each key is a Bitcoin address or hex-encoded public key.\n"
|
||||
"This functionality is only intended for use with non-watchonly addresses.\n"
|
||||
"See `importaddress` for watchonly p2sh address support.\n"
|
||||
"If 'account' is specified (DEPRECATED), assign address to that account.\n"
|
||||
"If 'label' is specified, assign address to that label.\n"
|
||||
|
||||
"\nArguments:\n"
|
||||
"1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
|
||||
|
@ -1185,7 +1185,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
" \"address\" (string) bitcoin address or hex-encoded public key\n"
|
||||
" ...,\n"
|
||||
" ]\n"
|
||||
"3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
|
||||
"3. \"label\" (string, optional) A label to assign the addresses to.\n"
|
||||
"4. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
|
||||
|
||||
"\nResult:\n"
|
||||
|
@ -1204,9 +1204,9 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
std::string strAccount;
|
||||
std::string label;
|
||||
if (!request.params[2].isNull())
|
||||
strAccount = AccountFromValue(request.params[2]);
|
||||
label = LabelFromValue(request.params[2]);
|
||||
|
||||
int required = request.params[0].get_int();
|
||||
|
||||
|
@ -1233,7 +1233,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
|
|||
CScript inner = CreateMultisigRedeemscript(required, pubkeys);
|
||||
pwallet->AddCScript(inner);
|
||||
CTxDestination dest = pwallet->AddAndGetDestinationForScript(inner, output_type);
|
||||
pwallet->SetAddressBook(dest, strAccount, "send");
|
||||
pwallet->SetAddressBook(dest, label, "send");
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("address", EncodeDestination(dest));
|
||||
|
@ -1385,14 +1385,14 @@ struct tallyitem
|
|||
}
|
||||
};
|
||||
|
||||
UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByAccounts)
|
||||
UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label)
|
||||
{
|
||||
// Minimum confirmations
|
||||
int nMinDepth = 1;
|
||||
if (!params[0].isNull())
|
||||
nMinDepth = params[0].get_int();
|
||||
|
||||
// Whether to include empty accounts
|
||||
// Whether to include empty labels
|
||||
bool fIncludeEmpty = false;
|
||||
if (!params[1].isNull())
|
||||
fIncludeEmpty = params[1].get_bool();
|
||||
|
@ -1404,7 +1404,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
|
||||
bool has_filtered_address = false;
|
||||
CTxDestination filtered_address = CNoDestination();
|
||||
if (!fByAccounts && params.size() > 3) {
|
||||
if (!by_label && params.size() > 3) {
|
||||
if (!IsValidDestinationString(params[3].get_str())) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "address_filter parameter was invalid");
|
||||
}
|
||||
|
@ -1449,7 +1449,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
|
||||
// Reply
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::map<std::string, tallyitem> mapAccountTally;
|
||||
std::map<std::string, tallyitem> label_tally;
|
||||
|
||||
// Create mapAddressBook iterator
|
||||
// If we aren't filtering, go from begin() to end()
|
||||
|
@ -1466,7 +1466,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
for (auto item_it = start; item_it != end; ++item_it)
|
||||
{
|
||||
const CTxDestination& address = item_it->first;
|
||||
const std::string& strAccount = item_it->second.name;
|
||||
const std::string& label = item_it->second.name;
|
||||
auto it = mapTally.find(address);
|
||||
if (it == mapTally.end() && !fIncludeEmpty)
|
||||
continue;
|
||||
|
@ -1481,9 +1481,9 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
fIsWatchonly = (*it).second.fIsWatchonly;
|
||||
}
|
||||
|
||||
if (fByAccounts)
|
||||
if (by_label)
|
||||
{
|
||||
tallyitem& _item = mapAccountTally[strAccount];
|
||||
tallyitem& _item = label_tally[label];
|
||||
_item.nAmount += nAmount;
|
||||
_item.nConf = std::min(_item.nConf, nConf);
|
||||
_item.fIsWatchonly = fIsWatchonly;
|
||||
|
@ -1494,11 +1494,10 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
if(fIsWatchonly)
|
||||
obj.pushKV("involvesWatchonly", true);
|
||||
obj.pushKV("address", EncodeDestination(address));
|
||||
obj.pushKV("account", strAccount);
|
||||
obj.pushKV("account", label);
|
||||
obj.pushKV("amount", ValueFromAmount(nAmount));
|
||||
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
|
||||
if (!fByAccounts)
|
||||
obj.pushKV("label", strAccount);
|
||||
obj.pushKV("label", label);
|
||||
UniValue transactions(UniValue::VARR);
|
||||
if (it != mapTally.end())
|
||||
{
|
||||
|
@ -1512,9 +1511,9 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
}
|
||||
}
|
||||
|
||||
if (fByAccounts)
|
||||
if (by_label)
|
||||
{
|
||||
for (const auto& entry : mapAccountTally)
|
||||
for (const auto& entry : label_tally)
|
||||
{
|
||||
CAmount nAmount = entry.second.nAmount;
|
||||
int nConf = entry.second.nConf;
|
||||
|
@ -1524,6 +1523,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA
|
|||
obj.pushKV("account", entry.first);
|
||||
obj.pushKV("amount", ValueFromAmount(nAmount));
|
||||
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
|
||||
obj.pushKV("label", entry.first);
|
||||
ret.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
@ -1552,10 +1552,10 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
|
|||
" {\n"
|
||||
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
|
||||
" \"address\" : \"receivingaddress\", (string) The receiving address\n"
|
||||
" \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
|
||||
" \"account\" : \"accountname\", (string) DEPRECATED. Backwards compatible alias for label.\n"
|
||||
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
|
||||
" \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
|
||||
" \"label\" : \"label\", (string) The label of the receiving address. The default label is \"\".\n"
|
||||
" \"txids\": [\n"
|
||||
" n, (numeric) The ids of transactions received with the address \n"
|
||||
" ...\n"
|
||||
|
@ -1582,7 +1582,7 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
|
|||
return ListReceived(pwallet, request.params, false);
|
||||
}
|
||||
|
||||
UniValue listreceivedbyaccount(const JSONRPCRequest& request)
|
||||
UniValue listreceivedbylabel(const JSONRPCRequest& request)
|
||||
{
|
||||
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
|
@ -1591,29 +1591,29 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request)
|
|||
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
"listreceivedbyaccount ( minconf include_empty include_watchonly)\n"
|
||||
"\nDEPRECATED. List balances by account.\n"
|
||||
"listreceivedbylabel ( minconf include_empty include_watchonly)\n"
|
||||
"\nList received transactions by label.\n"
|
||||
"\nArguments:\n"
|
||||
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
|
||||
"2. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
|
||||
"2. include_empty (bool, optional, default=false) Whether to include labels that haven't received any payments.\n"
|
||||
"3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
|
||||
|
||||
"\nResult:\n"
|
||||
"[\n"
|
||||
" {\n"
|
||||
" \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n"
|
||||
" \"account\" : \"accountname\", (string) The account name of the receiving account\n"
|
||||
" \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n"
|
||||
" \"account\" : \"accountname\", (string) DEPRECATED. Backwards compatible alias for label.\n"
|
||||
" \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n"
|
||||
" \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n"
|
||||
" \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
|
||||
" \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
"]\n"
|
||||
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("listreceivedbyaccount", "")
|
||||
+ HelpExampleCli("listreceivedbyaccount", "6 true")
|
||||
+ HelpExampleRpc("listreceivedbyaccount", "6, true, true")
|
||||
+ HelpExampleCli("listreceivedbylabel", "")
|
||||
+ HelpExampleCli("listreceivedbylabel", "6 true")
|
||||
+ HelpExampleRpc("listreceivedbylabel", "6, true, true")
|
||||
);
|
||||
|
||||
ObserveSafeMode();
|
||||
|
@ -2935,7 +2935,8 @@ UniValue listunspent(const JSONRPCRequest& request)
|
|||
" \"txid\" : \"txid\", (string) the transaction id \n"
|
||||
" \"vout\" : n, (numeric) the vout value\n"
|
||||
" \"address\" : \"address\", (string) the bitcoin address\n"
|
||||
" \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n"
|
||||
" \"label\" : \"label\", (string) The associated label, or \"\" for the default label\n"
|
||||
" \"account\" : \"account\", (string) DEPRECATED. Backwards compatible alias for label.\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"
|
||||
|
@ -3039,6 +3040,7 @@ UniValue listunspent(const JSONRPCRequest& request)
|
|||
entry.pushKV("address", EncodeDestination(address));
|
||||
|
||||
if (pwallet->mapAddressBook.count(address)) {
|
||||
entry.pushKV("label", pwallet->mapAddressBook[address].name);
|
||||
entry.pushKV("account", pwallet->mapAddressBook[address].name);
|
||||
}
|
||||
|
||||
|
@ -3834,21 +3836,23 @@ static const CRPCCommand commands[] =
|
|||
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
|
||||
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
|
||||
{ "wallet", "abortrescan", &abortrescan, {} },
|
||||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account","address_type"} },
|
||||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label|account","address_type"} },
|
||||
{ "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
|
||||
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
|
||||
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
|
||||
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
|
||||
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
|
||||
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
|
||||
{ "wallet", "getaccountaddress", &getaccountaddress, {"account"} },
|
||||
{ "wallet", "getlabeladdress", &getlabeladdress, {"label"} },
|
||||
{ "wallet", "getaccountaddress", &getlabeladdress, {"account"} },
|
||||
{ "wallet", "getaccount", &getaccount, {"address"} },
|
||||
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, {"account"} },
|
||||
{ "wallet", "getaddressinfo", &getaddressinfo, {"address"} },
|
||||
{ "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} },
|
||||
{ "wallet", "getnewaddress", &getnewaddress, {"account","address_type"} },
|
||||
{ "wallet", "getnewaddress", &getnewaddress, {"label|account","address_type"} },
|
||||
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} },
|
||||
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, {"account","minconf"} },
|
||||
{ "wallet", "getreceivedbylabel", &getreceivedbylabel, {"label","minconf"} },
|
||||
{ "wallet", "getreceivedbyaccount", &getreceivedbylabel, {"account","minconf"} },
|
||||
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} },
|
||||
{ "wallet", "gettransaction", &gettransaction, {"txid","include_watchonly"} },
|
||||
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, {} },
|
||||
|
@ -3863,7 +3867,8 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "listaccounts", &listaccounts, {"minconf","include_watchonly"} },
|
||||
{ "wallet", "listaddressgroupings", &listaddressgroupings, {} },
|
||||
{ "wallet", "listlockunspent", &listlockunspent, {} },
|
||||
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, {"minconf","include_empty","include_watchonly"} },
|
||||
{ "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"} },
|
||||
|
@ -3874,7 +3879,8 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "sendfrom", &sendfrom, {"fromaccount","toaddress","amount","minconf","comment","comment_to"} },
|
||||
{ "wallet", "sendmany", &sendmany, {"fromaccount","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
|
||||
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode"} },
|
||||
{ "wallet", "setaccount", &setaccount, {"address","account"} },
|
||||
{ "wallet", "setlabel", &setlabel, {"address","label"} },
|
||||
{ "wallet", "setaccount", &setlabel, {"address","account"} },
|
||||
{ "wallet", "settxfee", &settxfee, {"amount"} },
|
||||
{ "wallet", "signmessage", &signmessage, {"address","message"} },
|
||||
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
|
||||
|
|
|
@ -809,12 +809,12 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::GetAccountDestination(CTxDestination &dest, std::string strAccount, bool bForceNew)
|
||||
bool CWallet::GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew)
|
||||
{
|
||||
CWalletDB walletdb(*dbw);
|
||||
|
||||
CAccount account;
|
||||
walletdb.ReadAccount(strAccount, account);
|
||||
walletdb.ReadAccount(label, account);
|
||||
|
||||
if (!bForceNew) {
|
||||
if (!account.vchPubKey.IsValid())
|
||||
|
@ -840,8 +840,8 @@ bool CWallet::GetAccountDestination(CTxDestination &dest, std::string strAccount
|
|||
|
||||
LearnRelatedScripts(account.vchPubKey, m_default_address_type);
|
||||
dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
|
||||
SetAddressBook(dest, strAccount, "receive");
|
||||
walletdb.WriteAccount(strAccount, account);
|
||||
SetAddressBook(dest, label, "receive");
|
||||
walletdb.WriteAccount(label, account);
|
||||
} else {
|
||||
dest = GetDestinationForKey(account.vchPubKey, m_default_address_type);
|
||||
}
|
||||
|
@ -2220,7 +2220,7 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons
|
|||
for (const CTxOut& out : wtx.tx->vout) {
|
||||
if (outgoing && IsChange(out)) {
|
||||
debit -= out.nValue;
|
||||
} else if (IsMine(out) & filter && depth >= minDepth && (!account || *account == GetAccountName(out.scriptPubKey))) {
|
||||
} else if (IsMine(out) & filter && depth >= minDepth && (!account || *account == GetLabelName(out.scriptPubKey))) {
|
||||
balance += out.nValue;
|
||||
}
|
||||
}
|
||||
|
@ -3251,7 +3251,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
|
|||
return CWalletDB(*dbw).EraseName(EncodeDestination(address));
|
||||
}
|
||||
|
||||
const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const
|
||||
const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const
|
||||
{
|
||||
CTxDestination address;
|
||||
if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) {
|
||||
|
@ -3261,9 +3261,9 @@ const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const
|
|||
}
|
||||
}
|
||||
// A scriptPubKey that doesn't have an entry in the address book is
|
||||
// associated with the default account ("").
|
||||
const static std::string DEFAULT_ACCOUNT_NAME;
|
||||
return DEFAULT_ACCOUNT_NAME;
|
||||
// associated with the default label ("").
|
||||
const static std::string DEFAULT_LABEL_NAME;
|
||||
return DEFAULT_LABEL_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3619,7 +3619,7 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAccount) const
|
||||
std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
std::set<CTxDestination> result;
|
||||
|
@ -3627,7 +3627,7 @@ std::set<CTxDestination> CWallet::GetAccountAddresses(const std::string& strAcco
|
|||
{
|
||||
const CTxDestination& address = item.first;
|
||||
const std::string& strName = item.second.name;
|
||||
if (strName == strAccount)
|
||||
if (strName == label)
|
||||
result.insert(address);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -929,7 +929,7 @@ public:
|
|||
int64_t IncOrderPosNext(CWalletDB *pwalletdb = nullptr);
|
||||
DBErrors ReorderTransactions();
|
||||
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "");
|
||||
bool GetAccountDestination(CTxDestination &dest, std::string strAccount, bool bForceNew = false);
|
||||
bool GetLabelDestination(CTxDestination &dest, const std::string& label, bool bForceNew = false);
|
||||
|
||||
void MarkDirty();
|
||||
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
|
||||
|
@ -1007,7 +1007,7 @@ public:
|
|||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
||||
std::map<CTxDestination, CAmount> GetAddressBalances();
|
||||
|
||||
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
|
||||
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
|
||||
|
||||
isminetype IsMine(const CTxIn& txin) const;
|
||||
/**
|
||||
|
@ -1037,7 +1037,7 @@ public:
|
|||
|
||||
bool DelAddressBook(const CTxDestination& address);
|
||||
|
||||
const std::string& GetAccountName(const CScript& scriptPubKey) const;
|
||||
const std::string& GetLabelName(const CScript& scriptPubKey) const;
|
||||
|
||||
void Inventory(const uint256 &hash) override
|
||||
{
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
# Copyright (c) 2016-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 account RPCs.
|
||||
"""Test label RPCs.
|
||||
|
||||
RPCs tested are:
|
||||
- getaccountaddress
|
||||
- getlabeladdress
|
||||
- getaddressesbyaccount
|
||||
- listaddressgroupings
|
||||
- setaccount
|
||||
- setlabel
|
||||
- sendfrom (with account arguments)
|
||||
- move (with account arguments)
|
||||
"""
|
||||
|
@ -16,7 +16,7 @@ RPCs tested are:
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal
|
||||
|
||||
class WalletAccountsTest(BitcoinTestFramework):
|
||||
class WalletLabelsTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
@ -68,97 +68,97 @@ class WalletAccountsTest(BitcoinTestFramework):
|
|||
|
||||
node.generate(1)
|
||||
|
||||
# we want to reset so that the "" account has what's expected.
|
||||
# we want to reset so that the "" label has what's expected.
|
||||
# otherwise we're off by exactly the fee amount as that's mined
|
||||
# and matures in the next 100 blocks
|
||||
node.sendfrom("", common_address, fee)
|
||||
amount_to_send = 1.0
|
||||
|
||||
# Create accounts and make sure subsequent account API calls
|
||||
# recognize the account/address associations.
|
||||
accounts = [Account(name) for name in ("a", "b", "c", "d", "e")]
|
||||
for account in accounts:
|
||||
account.add_receive_address(node.getaccountaddress(account.name))
|
||||
account.verify(node)
|
||||
# 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")]
|
||||
for label in labels:
|
||||
label.add_receive_address(node.getlabeladdress(label.name))
|
||||
label.verify(node)
|
||||
|
||||
# Send a transaction to each account, and make sure this forces
|
||||
# getaccountaddress to generate a new receiving address.
|
||||
for account in accounts:
|
||||
node.sendtoaddress(account.receive_address, amount_to_send)
|
||||
account.add_receive_address(node.getaccountaddress(account.name))
|
||||
account.verify(node)
|
||||
# Send a transaction to each label, and make sure this forces
|
||||
# getlabeladdress to generate a new receiving address.
|
||||
for label in labels:
|
||||
node.sendtoaddress(label.receive_address, amount_to_send)
|
||||
label.add_receive_address(node.getlabeladdress(label.name))
|
||||
label.verify(node)
|
||||
|
||||
# Check the amounts received.
|
||||
node.generate(1)
|
||||
for account in accounts:
|
||||
for label in labels:
|
||||
assert_equal(
|
||||
node.getreceivedbyaddress(account.addresses[0]), amount_to_send)
|
||||
assert_equal(node.getreceivedbyaccount(account.name), amount_to_send)
|
||||
|
||||
# Check that sendfrom account reduces listaccounts balances.
|
||||
for i, account in enumerate(accounts):
|
||||
to_account = accounts[(i+1) % len(accounts)]
|
||||
node.sendfrom(account.name, to_account.receive_address, amount_to_send)
|
||||
node.getreceivedbyaddress(label.addresses[0]), amount_to_send)
|
||||
assert_equal(node.getreceivedbylabel(label.name), amount_to_send)
|
||||
|
||||
# Check that sendfrom label reduces listaccounts balances.
|
||||
for i, label in enumerate(labels):
|
||||
to_label = labels[(i+1) % len(labels)]
|
||||
node.sendfrom(label.name, to_label.receive_address, amount_to_send)
|
||||
node.generate(1)
|
||||
for account in accounts:
|
||||
account.add_receive_address(node.getaccountaddress(account.name))
|
||||
account.verify(node)
|
||||
assert_equal(node.getreceivedbyaccount(account.name), 2)
|
||||
node.move(account.name, "", node.getbalance(account.name))
|
||||
account.verify(node)
|
||||
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))
|
||||
label.verify(node)
|
||||
node.generate(101)
|
||||
expected_account_balances = {"": 5200}
|
||||
for account in accounts:
|
||||
expected_account_balances[account.name] = 0
|
||||
for label in labels:
|
||||
expected_account_balances[label.name] = 0
|
||||
assert_equal(node.listaccounts(), expected_account_balances)
|
||||
assert_equal(node.getbalance(""), 5200)
|
||||
|
||||
# Check that setaccount can assign an account to a new unused address.
|
||||
for account in accounts:
|
||||
address = node.getaccountaddress("")
|
||||
node.setaccount(address, account.name)
|
||||
account.add_address(address)
|
||||
account.verify(node)
|
||||
|
||||
# Check that setlabel can assign a label to a new unused address.
|
||||
for label in labels:
|
||||
address = node.getlabeladdress("")
|
||||
node.setlabel(address, label.name)
|
||||
label.add_address(address)
|
||||
label.verify(node)
|
||||
assert(address not in node.getaddressesbyaccount(""))
|
||||
|
||||
# Check that addmultisigaddress can assign accounts.
|
||||
for account in accounts:
|
||||
|
||||
# Check that addmultisigaddress can assign labels.
|
||||
for label in labels:
|
||||
addresses = []
|
||||
for x in range(10):
|
||||
addresses.append(node.getnewaddress())
|
||||
multisig_address = node.addmultisigaddress(5, addresses, account.name)['address']
|
||||
account.add_address(multisig_address)
|
||||
account.verify(node)
|
||||
multisig_address = node.addmultisigaddress(5, addresses, label.name)['address']
|
||||
label.add_address(multisig_address)
|
||||
label.verify(node)
|
||||
node.sendfrom("", multisig_address, 50)
|
||||
node.generate(101)
|
||||
for account in accounts:
|
||||
assert_equal(node.getbalance(account.name), 50)
|
||||
for label in labels:
|
||||
assert_equal(node.getbalance(label.name), 50)
|
||||
|
||||
# Check that setaccount can change the account of an address from a
|
||||
# different account.
|
||||
change_account(node, accounts[0].addresses[0], accounts[0], accounts[1])
|
||||
# Check that setlabel can change the label of an address from a
|
||||
# different label.
|
||||
change_label(node, labels[0].addresses[0], labels[0], labels[1])
|
||||
|
||||
# Check that setaccount can change the account of an address which
|
||||
# is the receiving address of a different account.
|
||||
change_account(node, accounts[0].receive_address, accounts[0], accounts[1])
|
||||
# Check that setlabel can change the label of an address which
|
||||
# is the receiving address of a different label.
|
||||
change_label(node, labels[0].receive_address, labels[0], labels[1])
|
||||
|
||||
# Check that setaccount can set the account of an address already
|
||||
# in the account. This is a no-op.
|
||||
change_account(node, accounts[2].addresses[0], accounts[2], accounts[2])
|
||||
# Check that setlabel can set the label of an address already
|
||||
# in the label. This is a no-op.
|
||||
change_label(node, labels[2].addresses[0], labels[2], labels[2])
|
||||
|
||||
# Check that setaccount can set the account of an address which is
|
||||
# already the receiving address of the account. It would probably make
|
||||
# Check that setlabel can set the label of an address which is
|
||||
# already the receiving address of the label. It would probably make
|
||||
# sense for this to be a no-op, but right now it resets the receiving
|
||||
# address, causing getaccountaddress to return a brand new address.
|
||||
change_account(node, accounts[2].receive_address, accounts[2], accounts[2])
|
||||
# address, causing getlabeladdress to return a brand new address.
|
||||
change_label(node, labels[2].receive_address, labels[2], labels[2])
|
||||
|
||||
class Account:
|
||||
class Label:
|
||||
def __init__(self, name):
|
||||
# Account name
|
||||
# Label name
|
||||
self.name = name
|
||||
# Current receiving address associated with this account.
|
||||
# Current receiving address associated with this label.
|
||||
self.receive_address = None
|
||||
# List of all addresses assigned with this account
|
||||
# List of all addresses assigned with this label
|
||||
self.addresses = []
|
||||
|
||||
def add_address(self, address):
|
||||
|
@ -172,7 +172,7 @@ class Account:
|
|||
def verify(self, node):
|
||||
if self.receive_address is not None:
|
||||
assert self.receive_address in self.addresses
|
||||
assert_equal(node.getaccountaddress(self.name), self.receive_address)
|
||||
assert_equal(node.getlabeladdress(self.name), self.receive_address)
|
||||
|
||||
for address in self.addresses:
|
||||
assert_equal(node.getaccount(address), self.name)
|
||||
|
@ -181,26 +181,26 @@ class Account:
|
|||
set(node.getaddressesbyaccount(self.name)), set(self.addresses))
|
||||
|
||||
|
||||
def change_account(node, address, old_account, new_account):
|
||||
assert_equal(address in old_account.addresses, True)
|
||||
node.setaccount(address, new_account.name)
|
||||
def change_label(node, address, old_label, new_label):
|
||||
assert_equal(address in old_label.addresses, True)
|
||||
node.setlabel(address, new_label.name)
|
||||
|
||||
old_account.addresses.remove(address)
|
||||
new_account.add_address(address)
|
||||
old_label.addresses.remove(address)
|
||||
new_label.add_address(address)
|
||||
|
||||
# Calling setaccount on an address which was previously the receiving
|
||||
# address of a different account should reset the receiving address of
|
||||
# the old account, causing getaccountaddress to return a brand new
|
||||
# Calling setlabel on an address which was previously the receiving
|
||||
# address of a different label should reset the receiving address of
|
||||
# the old label, causing getlabeladdress to return a brand new
|
||||
# address.
|
||||
if address == old_account.receive_address:
|
||||
new_address = node.getaccountaddress(old_account.name)
|
||||
assert_equal(new_address not in old_account.addresses, True)
|
||||
assert_equal(new_address not in new_account.addresses, True)
|
||||
old_account.add_receive_address(new_address)
|
||||
if address == old_label.receive_address:
|
||||
new_address = node.getlabeladdress(old_label.name)
|
||||
assert_equal(new_address not in old_label.addresses, True)
|
||||
assert_equal(new_address not in new_label.addresses, True)
|
||||
old_label.add_receive_address(new_address)
|
||||
|
||||
old_account.verify(node)
|
||||
new_account.verify(node)
|
||||
old_label.verify(node)
|
||||
new_label.verify(node)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletAccountsTest().main()
|
||||
WalletLabelsTest().main()
|
||||
|
|
|
@ -78,7 +78,7 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
|
|||
|
||||
if txid is not None:
|
||||
tx, = [tx for tx in txs if tx["txid"] == txid]
|
||||
assert_equal(tx["account"], self.label)
|
||||
assert_equal(tx["label"], self.label)
|
||||
assert_equal(tx["address"], self.address["address"])
|
||||
assert_equal(tx["amount"], amount)
|
||||
assert_equal(tx["category"], "receive")
|
||||
|
|
|
@ -36,11 +36,11 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
self.sync_all()
|
||||
assert_array_result(self.nodes[1].listreceivedbyaddress(),
|
||||
{"address": addr},
|
||||
{"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
|
||||
{"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
|
||||
# With min confidence < 10
|
||||
assert_array_result(self.nodes[1].listreceivedbyaddress(5),
|
||||
{"address": addr},
|
||||
{"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
|
||||
{"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
|
||||
# With min confidence > 10, should not find Tx
|
||||
assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True)
|
||||
|
||||
|
@ -48,11 +48,11 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
empty_addr = self.nodes[1].getnewaddress()
|
||||
assert_array_result(self.nodes[1].listreceivedbyaddress(0, True),
|
||||
{"address": empty_addr},
|
||||
{"address": empty_addr, "account": "", "amount": 0, "confirmations": 0, "txids": []})
|
||||
{"address": empty_addr, "label": "", "amount": 0, "confirmations": 0, "txids": []})
|
||||
|
||||
#Test Address filtering
|
||||
#Only on addr
|
||||
expected = {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}
|
||||
expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}
|
||||
res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
|
||||
assert_array_result(res, {"address":addr}, expected)
|
||||
assert_equal(len(res), 1)
|
||||
|
@ -66,12 +66,12 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
#Same test as above should still pass
|
||||
expected = {"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":11, "txids":[txid,]}
|
||||
expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":11, "txids":[txid,]}
|
||||
res = self.nodes[1].listreceivedbyaddress(0, True, True, addr)
|
||||
assert_array_result(res, {"address":addr}, expected)
|
||||
assert_equal(len(res), 1)
|
||||
#Same test as above but with other_addr should still pass
|
||||
expected = {"address":other_addr, "account":"", "amount":Decimal("0.1"), "confirmations":1, "txids":[txid2,]}
|
||||
expected = {"address":other_addr, "label":"", "amount":Decimal("0.1"), "confirmations":1, "txids":[txid2,]}
|
||||
res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
|
||||
assert_array_result(res, {"address":other_addr}, expected)
|
||||
assert_equal(len(res), 1)
|
||||
|
@ -108,46 +108,46 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
# Trying to getreceivedby for an address the wallet doesn't own should return an error
|
||||
assert_raises_rpc_error(-4, "Address not found in wallet", self.nodes[0].getreceivedbyaddress, addr)
|
||||
|
||||
self.log.info("listreceivedbyaccount + getreceivedbyaccount Test")
|
||||
self.log.info("listreceivedbylabel + getreceivedbylabel Test")
|
||||
|
||||
# set pre-state
|
||||
addrArr = self.nodes[1].getnewaddress()
|
||||
account = self.nodes[1].getaccount(addrArr)
|
||||
received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount() if r["account"] == account][0]
|
||||
balance_by_account = self.nodes[1].getreceivedbyaccount(account)
|
||||
label = self.nodes[1].getaccount(addrArr)
|
||||
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
|
||||
balance_by_label = self.nodes[1].getreceivedbylabel(label)
|
||||
|
||||
txid = self.nodes[0].sendtoaddress(addr, 0.1)
|
||||
self.sync_all()
|
||||
|
||||
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
|
||||
assert_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||
{"account": account},
|
||||
received_by_account_json)
|
||||
# listreceivedbylabel should return received_by_label_json because of 0 confirmations
|
||||
assert_array_result(self.nodes[1].listreceivedbylabel(),
|
||||
{"label": label},
|
||||
received_by_label_json)
|
||||
|
||||
# getreceivedbyaddress should return same balance because of 0 confirmations
|
||||
balance = self.nodes[1].getreceivedbyaccount(account)
|
||||
assert_equal(balance, balance_by_account)
|
||||
balance = self.nodes[1].getreceivedbylabel(label)
|
||||
assert_equal(balance, balance_by_label)
|
||||
|
||||
self.nodes[1].generate(10)
|
||||
self.sync_all()
|
||||
# listreceivedbyaccount should return updated account balance
|
||||
assert_array_result(self.nodes[1].listreceivedbyaccount(),
|
||||
{"account": account},
|
||||
{"account": received_by_account_json["account"], "amount": (received_by_account_json["amount"] + Decimal("0.1"))})
|
||||
# listreceivedbylabel should return updated received list
|
||||
assert_array_result(self.nodes[1].listreceivedbylabel(),
|
||||
{"label": label},
|
||||
{"label": received_by_label_json["label"], "amount": (received_by_label_json["amount"] + Decimal("0.1"))})
|
||||
|
||||
# getreceivedbyaddress should return updates balance
|
||||
balance = self.nodes[1].getreceivedbyaccount(account)
|
||||
assert_equal(balance, balance_by_account + Decimal("0.1"))
|
||||
# getreceivedbylabel should return updated receive total
|
||||
balance = self.nodes[1].getreceivedbylabel(label)
|
||||
assert_equal(balance, balance_by_label + Decimal("0.1"))
|
||||
|
||||
# Create a new account named "mynewaccount" that has a 0 balance
|
||||
self.nodes[1].getaccountaddress("mynewaccount")
|
||||
received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount(0, True) if r["account"] == "mynewaccount"][0]
|
||||
# Create a new label named "mynewlabel" that has a 0 balance
|
||||
self.nodes[1].getlabeladdress("mynewlabel")
|
||||
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][0]
|
||||
|
||||
# Test includeempty of listreceivedbyaccount
|
||||
assert_equal(received_by_account_json["amount"], Decimal("0.0"))
|
||||
# Test includeempty of listreceivedbylabel
|
||||
assert_equal(received_by_label_json["amount"], Decimal("0.0"))
|
||||
|
||||
# Test getreceivedbyaccount for 0 amount accounts
|
||||
balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
|
||||
# Test getreceivedbylabel for 0 amount labels
|
||||
balance = self.nodes[1].getreceivedbylabel("mynewlabel")
|
||||
assert_equal(balance, Decimal("0.0"))
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in a new issue