Skip to content

Commit

Permalink
Merge pull request ElementsProject#217 from AkioNak/fix-rpc-listrecei…
Browse files Browse the repository at this point in the history
…vedbyaddress

fix listreceivedbyaddress to sum amounts for each asset.
  • Loading branch information
instagibbs authored Jul 19, 2017
2 parents d6a9a01 + 7485b36 commit 4d65c0c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 31 deletions.
14 changes: 12 additions & 2 deletions qa/rpc-tests/confidential_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def run_test(self):
assert_equal(self.nodes[2].getbalance()["bitcoin"], node2)

# Check 2's listreceivedbyaddress
received_by_address = self.nodes[2].listreceivedbyaddress()
received_by_address = self.nodes[2].listreceivedbyaddress(0, False, False, "bitcoin")
validate_by_address = [(unconfidential_address2, value1 + value3), (unconfidential_address, value0 + value2)]
assert_equal(sorted([(ele['address'], ele['amount']) for ele in received_by_address], key=lambda t: t[0]),
sorted(validate_by_address, key = lambda t: t[0]))
Expand All @@ -131,7 +131,7 @@ def run_test(self):
assert_equal(list_unspent[0]['amount']+list_unspent[1]['amount'], value1+value3)
received_by_address = self.nodes[1].listreceivedbyaddress(1, False, True)
assert_equal(len(received_by_address), 1)
assert_equal((received_by_address[0]['address'], received_by_address[0]['amount']),
assert_equal((received_by_address[0]['address'], received_by_address[0]['amount']['bitcoin']),
(unconfidential_address2, value1 + value3))

# Spending a single confidential output and sending it to a
Expand Down Expand Up @@ -368,6 +368,16 @@ def run_test(self):
assert_equal(self.nodes[0].getwalletinfo()["balance"][issued["token"]], 1)


# Check for value when receiving defferent assets by same address.
self.nodes[0].sendtoaddress(unconfidential_address2, Decimal('0.00000001'), "", "", False, test_asset)
self.nodes[0].sendtoaddress(unconfidential_address2, Decimal('0.00000002'), "", "", False, test_asset)
self.nodes[0].generate(1)
self.sync_all()
received_by_address = self.nodes[1].listreceivedbyaddress(0, False, True)
multi_asset_amount = [x for x in received_by_address if x['address'] == unconfidential_address2][0]['amount']
assert_equal(multi_asset_amount['bitcoin'], value1 + value3 )
assert_equal(multi_asset_amount[test_asset], Decimal('0.00000003'))

# Check blinded multisig functionality
# Get two pubkeys
blinded_addr = self.nodes[0].getnewaddress()
Expand Down
18 changes: 9 additions & 9 deletions qa/rpc-tests/receivedby.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ def run_test(self):
self.sync_all()
assert_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":unblinded},
{"address":unblinded, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
{"address":unblinded, "account":"", "amount":{"bitcoin":Decimal("0.1")}, "confirmations":10, "txids":[txid,]})
#With min confidence < 10
assert_array_result(self.nodes[1].listreceivedbyaddress(5),
{"address":unblinded},
{"address":unblinded, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
{"address":unblinded, "account":"", "amount":{"bitcoin":Decimal("0.1")}, "confirmations":10, "txids":[txid,]})
#With min confidence > 10, should not find Tx
assert_array_result(self.nodes[1].listreceivedbyaddress(11),{"blindedaddress":addr},{ },True)

Expand All @@ -69,7 +69,7 @@ def run_test(self):
unblinded = self.nodes[1].validateaddress(addr)['unconfidential']
assert_array_result(self.nodes[1].listreceivedbyaddress(0,True),
{"address":unblinded},
{"address":unblinded, "account":"", "amount":0, "confirmations":0, "txids":[]})
{"address":unblinded, "account":"", "amount":{}, "confirmations":0, "txids":[]})

'''
getreceivedbyaddress Test
Expand Down Expand Up @@ -106,7 +106,7 @@ def run_test(self):
received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(),{"account":account})
if len(received_by_account_json) == 0:
raise AssertionError("No accounts found in node")
balance_by_account = self.nodes[1].getreceivedbyaccount(account)
balance_by_account = self.nodes[1].getreceivedbyaccount(account)["bitcoin"]

txid = self.nodes[0].sendtoaddress(addr, 0.1)
self.sync_all()
Expand All @@ -117,7 +117,7 @@ def run_test(self):
received_by_account_json)

# getreceivedbyaddress should return same balance because of 0 confirmations
balance = self.nodes[1].getreceivedbyaccount(account)
balance = self.nodes[1].getreceivedbyaccount(account)["bitcoin"]
if balance != balance_by_account:
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))

Expand All @@ -126,10 +126,10 @@ def run_test(self):
# 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"))})
{"account":received_by_account_json["account"], "amount":{"bitcoin":(received_by_account_json["amount"]["bitcoin"] + Decimal("0.1"))}})

# getreceivedbyaddress should return updates balance
balance = self.nodes[1].getreceivedbyaccount(account)
balance = self.nodes[1].getreceivedbyaccount(account)["bitcoin"]
if balance != balance_by_account + Decimal("0.1"):
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))

Expand All @@ -140,12 +140,12 @@ def run_test(self):
raise AssertionError("No accounts found in node")

# Test includeempty of listreceivedbyaccount
if received_by_account_json["amount"] != Decimal("0.0"):
if received_by_account_json["amount"] != {}:
raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"]))

# Test getreceivedbyaccount for 0 amount accounts
balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
if balance != Decimal("0.0"):
if balance != {}:
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))

if __name__ == '__main__':
Expand Down
45 changes: 25 additions & 20 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);

// Tally
CAmount nAmount = 0;
CAmountMap mapAmount;
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
Expand All @@ -849,13 +849,17 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++)
{
CTxDestination address;
if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
if (wtx.GetDepthInMainChain() >= nMinDepth && wtx.GetOutputValueOut(i) >= 0)
nAmount += wtx.GetOutputValueOut(i);
if (ExtractDestination(wtx.tx->vout[i].scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address)) {
if (wtx.GetDepthInMainChain() >= nMinDepth && wtx.GetOutputValueOut(i) >= 0) {
CAmountMap wtxValue;
wtxValue[wtx.GetOutputAsset(i)] = wtx.GetOutputValueOut(i);
mapAmount += wtxValue;
}
}
}
}

return ValueFromAmount(nAmount);
return PushAssetBalance(mapAmount, pwalletMain, "");
}


Expand Down Expand Up @@ -1380,12 +1384,12 @@ struct tallyitem
{
CBitcoinAddress address;
CAmount nAmount;
CAmountMap mapAmount;
int nConf;
vector<uint256> txids;
bool fIsWatchonly;
tallyitem()
{
nAmount = 0;
nConf = std::numeric_limits<int>::max();
fIsWatchonly = false;
}
Expand All @@ -1408,14 +1412,14 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
if(params[2].get_bool())
filter = filter | ISMINE_WATCH_ONLY;

std::string strasset = "bitcoin";
std::string strasset = "";
if (params.size() > 3 && params[3].isStr()) {
if (fByAccounts)
throw JSONRPCError(RPC_WALLET_ERROR, "Accounts are completely disabled for assets.");
strasset = params[3].get_str();
}
CAsset asset;
if (strasset != "*")
if (strasset != "")
asset = GetAssetFromString(strasset);

// Tally
Expand Down Expand Up @@ -1444,14 +1448,16 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
if (wtx.GetOutputValueOut(i) < 0)
continue;

if (strasset != "*" && wtx.GetOutputAsset(i) != asset)
if (strasset != "" && wtx.GetOutputAsset(i) != asset)
continue;

CBitcoinAddress bitcoinaddress(address);

tallyitem& item = mapTally[address];
item.address = bitcoinaddress;
item.nAmount += wtx.GetOutputValueOut(i);
CAmountMap wtxValue;
wtxValue[wtx.GetOutputAsset(i)] = wtx.GetOutputValueOut(i);
item.mapAmount += wtxValue;
item.nConf = min(item.nConf, nDepth);
item.txids.push_back(wtx.GetHash());
if (mine & ISMINE_WATCH_ONLY)
Expand All @@ -1471,21 +1477,21 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
continue;

CBitcoinAddress fulladdress = address;
CAmount nAmount = 0;
CAmountMap mapAmount;
int nConf = std::numeric_limits<int>::max();
bool fIsWatchonly = false;
if (it != mapTally.end())
{
fulladdress = (*it).second.address;
nAmount = (*it).second.nAmount;
mapAmount = (*it).second.mapAmount;
nConf = (*it).second.nConf;
fIsWatchonly = (*it).second.fIsWatchonly;
}

if (fByAccounts)
{
tallyitem& _item = mapAccountTally[strAccount];
_item.nAmount += nAmount;
_item.mapAmount += mapAmount;
_item.nConf = min(_item.nConf, nConf);
_item.fIsWatchonly = fIsWatchonly;
}
Expand All @@ -1498,10 +1504,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
fulladdress = fulladdress.GetUnblinded();
obj.push_back(Pair("address", fulladdress.ToString()));
obj.push_back(Pair("account", strAccount));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("amount", PushAssetBalance(mapAmount, pwalletMain, strasset)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
if (!fByAccounts)
obj.push_back(Pair("label", strAccount));
obj.push_back(Pair("label", strAccount));
UniValue transactions(UniValue::VARR);
if (it != mapTally.end())
{
Expand All @@ -1519,13 +1524,13 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
{
for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
{
CAmount nAmount = (*it).second.nAmount;
CAmountMap mapAmount = (*it).second.mapAmount;
int nConf = (*it).second.nConf;
UniValue obj(UniValue::VOBJ);
if((*it).second.fIsWatchonly)
obj.push_back(Pair("involvesWatchonly", true));
obj.push_back(Pair("account", (*it).first));
obj.push_back(Pair("amount", ValueFromAmount(nAmount)));
obj.push_back(Pair("amount", PushAssetBalance(mapAmount, pwalletMain, strasset)));
obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
ret.push_back(obj);
}
Expand All @@ -1541,13 +1546,13 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)

if (request.fHelp || request.params.size() > 4)
throw runtime_error(
"listreceivedbyaddress ( minconf include_empty include_watchonly, asset)\n"
"listreceivedbyaddress ( minconf include_empty include_watchonly, \"assetlabel\" )\n"
"\nList balances by receiving address.\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 addresses that haven't received any payments.\n"
"3. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
"4. \"asset\" (string, optional, default=bitcoin) The hex asset id or label to filter for. \"*\" is used to list all results.\n"
"4. \"assetlabel\" (string, optional) The hex asset id or asset label to filter for.\n"
"\nResult:\n"
"[\n"
" {\n"
Expand Down

0 comments on commit 4d65c0c

Please sign in to comment.