Add address groupings RPC from the coincontrol patches.

Signed-off-by: Gregory Maxwell <greg@xiph.org>
This commit is contained in:
coderrr
2012-08-01 12:48:42 -04:00
committed by Gregory Maxwell
parent 47753fa369
commit 22dfd73598
5 changed files with 163 additions and 0 deletions

View File

@@ -1620,6 +1620,129 @@ int64 CWallet::GetOldestKeyPoolTime()
return keypool.nTime;
}
std::map<std::string, int64> CWallet::GetAddressBalances()
{
map<string, int64> 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<string> > CWallet::GetAddressGroupings()
{
set< set<string> > groupings;
set<string> 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<string>* > uniqueGroupings; // a set of pointers to groups of addresses
map< string, set<string>* > setmap; // map addresses to the unique group containing it
BOOST_FOREACH(set<string> grouping, groupings)
{
// make a set of all the groups hit by this new group
set< set<string>* > hits;
map< string, set<string>* >::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<string>* merged = new set<string>(grouping);
BOOST_FOREACH(set<string>* 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<string> > ret;
BOOST_FOREACH(set<string>* uniqueGrouping, uniqueGroupings)
{
ret.insert(*uniqueGrouping);
delete uniqueGrouping;
}
return ret;
}
CPubKey CReserveKey::GetReservedKey()
{
if (nIndex == -1)