$ bitcoin-cli help listreceivedbyaccount
listreceivedbyaccount ( minconf includeempty includeWatchonly )

已过时。列出账户余额。

参数:
1. minconf         (数字,可选,默认为 1)包含支付前的最小确认数
2. includeempty    (布尔型,可选,默认为 false)是否包含未收到任何付款的账户
3. includeWatchonly(布尔型,可选,默认为 false)是否包含 watchonly 地址(见 'importaddress')

结果:
[
  {
    "involvesWatchonly" : true,(布尔型)如果导入的地址包含在交易中,则只返回该项
    "account" : "accountname", (字符串)接收账户的帐户名
    "amount" : x.xxx,          (数字)这个账户下地址接收的总金额
    "confirmations" : n,       (数字)包含最多最近交易的确认数
    "label" : "label"          (字符串)一条地址/交易的备注,如果存在
  }
  ,...
]

例子:
> bitcoin-cli listreceivedbyaccount
> bitcoin-cli listreceivedbyaccount 6 true
> curl --user myusername:mypassword --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "listreceivedbyaccount", "params": [6, true, true] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/

源码剖析

listreceivedbyaccount 对应的函数在文件 rpcserver.h 中被引用。

extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp);

实现在文件 rpcwallet.cpp 中。

UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
{
    if (!EnsureWalletIsAvailable(fHelp)) // 1. 确保钱包可用
        return NullUniValue;
    
    if (fHelp || params.size() > 3)
        throw runtime_error(
            "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
            "\nDEPRECATED. List balances by account.\n"
            "\nArguments:\n"
            "1. minconf      (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
            "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
            "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly 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"
            "    \"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"
            "  }\n"
            "  ,...\n"
            "]\n"

            "\nExamples:\n"
            + HelpExampleCli("listreceivedbyaccount", "")
            + HelpExampleCli("listreceivedbyaccount", "6 true")
            + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
        ); // 2. 帮助内容

    LOCK2(cs_main, pwalletMain->cs_wallet);

    return ListReceived(params, true); // 3. 列出账户余额
}

1. 确保钱包可用

参考比特币 RPC 命令「fundrawtransaction」1. 确保钱包可用

2. 帮助内容

参考比特币 RPC 命令「getbestblockhash」1. 帮助内容

3. 列出账户余额

函数 ListReceived(params, true) 定义在文件 rpcwallet.cpp 中。

struct tallyitem // 账目类
{
    CAmount nAmount; // 金额,默认为 0
    int nConf; // 确认数,默认 int 的最大值
    vector<uint256> txids; // 交易索引列表
    bool fIsWatchonly; // 开启 watchonly 标志,默认关闭
    tallyitem() // 无参构造
    {
        nAmount = 0;
        nConf = std::numeric_limits<int>::max();
        fIsWatchonly = false;
    }
};

UniValue ListReceived(const UniValue& params, bool fByAccounts) // fByAccounts = true
{
    // Minimum confirmations // 最低确认数
    int nMinDepth = 1; // 最小深度,默认为 1
    if (params.size() > 0)
        nMinDepth = params[0].get_int(); // 获取最小深度

    // Whether to include empty accounts
    bool fIncludeEmpty = false; // 包含空余额的账户标志,默认为 false
    if (params.size() > 1)
        fIncludeEmpty = params[1].get_bool(); // 获取是否包含空余额的账户标志

    isminefilter filter = ISMINE_SPENDABLE; // 可花费
    if(params.size() > 2)
        if(params[2].get_bool())
            filter = filter | ISMINE_WATCH_ONLY; // 设置挖矿 watchonly

    // Tally // 记账
    map<CBitcoinAddress, tallyitem> mapTally; // 地址账目映射列表
    for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
    { // 遍历钱包交易映射列表
        const CWalletTx& wtx = (*it).second; // 获取钱包交易

        if (wtx.IsCoinBase() || !CheckFinalTx(wtx)) // 非创币交易 且 为最终交易
            continue;

        int nDepth = wtx.GetDepthInMainChain(); // 获取该交易的链深度
        if (nDepth < nMinDepth) // 深度不能小于最小深度(最低确认数)
            continue;

        BOOST_FOREACH(const CTxOut& txout, wtx.vout)
        { // 遍历交易输出列表
            CTxDestination address;
            if (!ExtractDestination(txout.scriptPubKey, address)) // 通过交易输出公钥脚本获取公钥地址
                continue;

            isminefilter mine = IsMine(*pwalletMain, address);
            if(!(mine & filter))
                continue;

            tallyitem& item = mapTally[address]; // 获取地址对应的账目
            item.nAmount += txout.nValue; // 累加交易输出金额
            item.nConf = min(item.nConf, nDepth); // 获取交易深度
            item.txids.push_back(wtx.GetHash()); // 加入交易索引列表
            if (mine & ISMINE_WATCH_ONLY)
                item.fIsWatchonly = true;
        }
    }

    // Reply
    UniValue ret(UniValue::VARR); // 创建数组类型的结果对象
    map<string, tallyitem> mapAccountTally; // 账户账目映射列表
    BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook) // 遍历地址簿映射列表
    {
        const CBitcoinAddress& address = item.first; // 获取地址
        const string& strAccount = item.second.name; // 获取帐户名
        map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address); // 获取地址对应的账目
        if (it == mapTally.end() && !fIncludeEmpty) // 未找到 且 包含空余额账户标志为 false
            continue; // 跳过

        CAmount nAmount = 0; // 金额
        int nConf = std::numeric_limits<int>::max(); // 确认数,默认最大值
        bool fIsWatchonly = false; // watchonly 标志,默认为 false
        if (it != mapTally.end()) // 找到
        { // 地址对应账目
            nAmount = (*it).second.nAmount; // 获取地址金额
            nConf = (*it).second.nConf; // 获取地址确认数
            fIsWatchonly = (*it).second.fIsWatchonly; // 获取地址 watchonly 标志
        }

        if (fByAccounts) // true
        {
            tallyitem& item = mapAccountTally[strAccount]; // 获取账户名对应的账目
            item.nAmount += nAmount; // 累加金额
            item.nConf = min(item.nConf, nConf); // 获取最小确认数
            item.fIsWatchonly = fIsWatchonly; // 获取 watchonly 标志
        }
        else
        {
            UniValue obj(UniValue::VOBJ);
            if(fIsWatchonly)
                obj.push_back(Pair("involvesWatchonly", true));
            obj.push_back(Pair("address",       address.ToString()));
            obj.push_back(Pair("account",       strAccount));
            obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
            obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
            if (!fByAccounts)
                obj.push_back(Pair("label", strAccount));
            UniValue transactions(UniValue::VARR);
            if (it != mapTally.end())
            {
                BOOST_FOREACH(const uint256& item, (*it).second.txids)
                {
                    transactions.push_back(item.GetHex());
                }
            }
            obj.push_back(Pair("txids", transactions));
            ret.push_back(obj);
        }
    }

    if (fByAccounts) // true
    {
        for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
        { // 遍历账户账目映射列表
            CAmount nAmount = (*it).second.nAmount; // 获取余额
            int nConf = (*it).second.nConf; // 获取确认数
            UniValue obj(UniValue::VOBJ); 
            if((*it).second.fIsWatchonly)
                obj.push_back(Pair("involvesWatchonly", true)); // watchonly 标志
            obj.push_back(Pair("account",       (*it).first)); // 帐户名
            obj.push_back(Pair("amount",        ValueFromAmount(nAmount))); // 余额
            obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf))); // 确认数
            ret.push_back(obj); // 加入结果集
        }
    }

    return ret;
}

参考链接