|
|
|
@ -1620,9 +1620,9 @@ int64 CWallet::GetOldestKeyPoolTime()
@@ -1620,9 +1620,9 @@ int64 CWallet::GetOldestKeyPoolTime()
|
|
|
|
|
return keypool.nTime; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::map<std::string, int64> CWallet::GetAddressBalances() |
|
|
|
|
std::map<CTxDestination, int64> CWallet::GetAddressBalances() |
|
|
|
|
{ |
|
|
|
|
map<string, int64> balances; |
|
|
|
|
map<CTxDestination, int64> balances; |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
LOCK(cs_wallet); |
|
|
|
@ -1640,14 +1640,16 @@ std::map<std::string, int64> CWallet::GetAddressBalances()
@@ -1640,14 +1640,16 @@ std::map<std::string, int64> CWallet::GetAddressBalances()
|
|
|
|
|
if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < pcoin->vout.size(); i++) |
|
|
|
|
for (unsigned int i = 0; i < pcoin->vout.size(); i++) |
|
|
|
|
{ |
|
|
|
|
CTxDestination addr; |
|
|
|
|
if (!IsMine(pcoin->vout[i])) |
|
|
|
|
continue; |
|
|
|
|
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr)) |
|
|
|
|
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; |
|
|
|
@ -1658,69 +1660,67 @@ std::map<std::string, int64> CWallet::GetAddressBalances()
@@ -1658,69 +1660,67 @@ std::map<std::string, int64> CWallet::GetAddressBalances()
|
|
|
|
|
return balances; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
set< set<string> > CWallet::GetAddressGroupings() |
|
|
|
|
set< set<CTxDestination> > CWallet::GetAddressGroupings() |
|
|
|
|
{ |
|
|
|
|
set< set<string> > groupings; |
|
|
|
|
set<string> grouping; |
|
|
|
|
set< set<CTxDestination> > groupings; |
|
|
|
|
set<CTxDestination> 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)); |
|
|
|
|
{ |
|
|
|
|
CTxDestination address; |
|
|
|
|
if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) |
|
|
|
|
continue; |
|
|
|
|
grouping.insert(address); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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()); |
|
|
|
|
if(!ExtractDestination(txout.scriptPubKey, txoutAddr)) |
|
|
|
|
continue; |
|
|
|
|
grouping.insert(txoutAddr); |
|
|
|
|
} |
|
|
|
|
groupings.insert(grouping); |
|
|
|
|
grouping.clear(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// group lone addrs by themselves
|
|
|
|
|
for (int i = 0; i < pcoin->vout.size(); i++) |
|
|
|
|
for (unsigned int i = 0; i < pcoin->vout.size(); i++) |
|
|
|
|
if (IsMine(pcoin->vout[i])) |
|
|
|
|
{ |
|
|
|
|
grouping.insert(pcoin->GetAddressOfTxOut(i)); |
|
|
|
|
CTxDestination address; |
|
|
|
|
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address)) |
|
|
|
|
continue; |
|
|
|
|
grouping.insert(address); |
|
|
|
|
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) |
|
|
|
|
set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
|
|
|
|
|
map< CTxDestination, set<CTxDestination>* > setmap; // map addresses to the unique group containing it
|
|
|
|
|
BOOST_FOREACH(set<CTxDestination> 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) |
|
|
|
|
set< set<CTxDestination>* > hits; |
|
|
|
|
map< CTxDestination, set<CTxDestination>* >::iterator it; |
|
|
|
|
BOOST_FOREACH(CTxDestination 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) |
|
|
|
|
set<CTxDestination>* merged = new set<CTxDestination>(grouping); |
|
|
|
|
BOOST_FOREACH(set<CTxDestination>* hit, hits) |
|
|
|
|
{ |
|
|
|
|
merged->insert(hit->begin(), hit->end()); |
|
|
|
|
uniqueGroupings.erase(hit); |
|
|
|
@ -1729,12 +1729,12 @@ set< set<string> > CWallet::GetAddressGroupings()
@@ -1729,12 +1729,12 @@ set< set<string> > CWallet::GetAddressGroupings()
|
|
|
|
|
uniqueGroupings.insert(merged); |
|
|
|
|
|
|
|
|
|
// update setmap
|
|
|
|
|
BOOST_FOREACH(string element, *merged) |
|
|
|
|
BOOST_FOREACH(CTxDestination element, *merged) |
|
|
|
|
setmap[element] = merged; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
set< set<string> > ret; |
|
|
|
|
BOOST_FOREACH(set<string>* uniqueGrouping, uniqueGroupings) |
|
|
|
|
set< set<CTxDestination> > ret; |
|
|
|
|
BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings) |
|
|
|
|
{ |
|
|
|
|
ret.insert(*uniqueGrouping); |
|
|
|
|
delete uniqueGrouping; |
|
|
|
|