From 22dfd7359863217eb8caef75084cfa8fa8e1d8fb Mon Sep 17 00:00:00 2001 From: coderrr Date: Wed, 1 Aug 2012 12:48:42 -0400 Subject: Add address groupings RPC from the coincontrol patches. Signed-off-by: Gregory Maxwell --- src/wallet.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'src/wallet.cpp') diff --git a/src/wallet.cpp b/src/wallet.cpp index 07a5047cef..87792e50ee 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1620,6 +1620,129 @@ int64 CWallet::GetOldestKeyPoolTime() return keypool.nTime; } +std::map CWallet::GetAddressBalances() +{ + map balances; + + { + LOCK(cs_wallet); + BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + { + CWalletTx *pcoin = &walletEntry.second; + + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) + continue; + + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) + continue; + + for (int i = 0; i < pcoin->vout.size(); i++) + { + if (!IsMine(pcoin->vout[i])) + continue; + + int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue; + + string addr = pcoin->GetAddressOfTxOut(i); + if (!balances.count(addr)) + balances[addr] = 0; + balances[addr] += n; + } + } + } + + return balances; +} + +set< set > CWallet::GetAddressGroupings() +{ + set< set > groupings; + set grouping; + + BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + { + CWalletTx *pcoin = &walletEntry.second; + + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) + continue; + + int nDepth = pcoin->GetDepthInMainChain(); + if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) + continue; + + if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0])) + { + // group all input addresses with each other + BOOST_FOREACH(CTxIn txin, pcoin->vin) + grouping.insert(mapWallet[txin.prevout.hash].GetAddressOfTxOut(txin.prevout.n)); + + // group change with input addresses + BOOST_FOREACH(CTxOut txout, pcoin->vout) + if (IsChange(txout)) + { + CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash]; + string addr = tx.GetAddressOfTxOut(pcoin->vin[0].prevout.n); + CTxDestination txoutAddr; + ExtractDestination(txout.scriptPubKey, txoutAddr); + grouping.insert(CBitcoinAddress(txoutAddr).ToString()); + } + groupings.insert(grouping); + grouping.clear(); + } + + // group lone addrs by themselves + for (int i = 0; i < pcoin->vout.size(); i++) + if (IsMine(pcoin->vout[i])) + { + grouping.insert(pcoin->GetAddressOfTxOut(i)); + groupings.insert(grouping); + grouping.clear(); + } + } + + set< set* > uniqueGroupings; // a set of pointers to groups of addresses + map< string, set* > setmap; // map addresses to the unique group containing it + BOOST_FOREACH(set grouping, groupings) + { + // make a set of all the groups hit by this new group + set< set* > hits; + map< string, set* >::iterator it; + BOOST_FOREACH(string address, grouping) + if ((it = setmap.find(address)) != setmap.end()) + hits.insert((*it).second); + + // merge all hit groups into a new single group and delete old groups + set* merged = new set(grouping); + BOOST_FOREACH(set* hit, hits) + { + merged->insert(hit->begin(), hit->end()); + uniqueGroupings.erase(hit); + delete hit; + } + uniqueGroupings.insert(merged); + + // update setmap + BOOST_FOREACH(string element, *merged) + setmap[element] = merged; + } + + set< set > ret; + BOOST_FOREACH(set* uniqueGrouping, uniqueGroupings) + { + ret.insert(*uniqueGrouping); + delete uniqueGrouping; + } + + return ret; +} + CPubKey CReserveKey::GetReservedKey() { if (nIndex == -1) -- cgit v1.2.3