Browse Source

Change CWallet addressgrouping to use CTxDestination instead of strings.

This is cleanup for the listaddressgroupings code. Also add some
real help text.
try
Gregory Maxwell 12 years ago
parent
commit
b1093efa83
  1. 17
      src/rpcrawtransaction.cpp
  2. 14
      src/rpcwallet.cpp
  3. 68
      src/wallet.cpp
  4. 12
      src/wallet.h

17
src/rpcrawtransaction.cpp

@ -140,7 +140,7 @@ Value listunspent(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 3)
throw runtime_error(
"listunspent [minconf=1] [maxconf=9999999] ['addr1','addr2',...]\n"
"listunspent [minconf=1] [maxconf=9999999] [\"address\",...]\n"
"Returns array of unspent transaction outputs\n"
"with between minconf and maxconf (inclusive) confirmations.\n"
"Optionally filtered to only include txouts paid to specified addresses.\n"
@ -165,7 +165,7 @@ Value listunspent(const Array& params, bool fHelp)
{
CBitcoinAddress address(input.get_str());
if (!address.IsValid())
throw JSONRPCError(-5, string("Invalid Bitcoin address:")+input.get_str());
throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+input.get_str());
if (setAddress.count(address))
throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+input.get_str());
setAddress.insert(address);
@ -180,8 +180,15 @@ Value listunspent(const Array& params, bool fHelp)
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
continue;
if (setAddress.size() && !setAddress.count(out.tx->GetAddressOfTxOut(out.i)))
continue;
if(setAddress.size())
{
CTxDestination address;
if(!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
continue;
if (!setAddress.count(address))
continue;
}
int64 nValue = out.tx->vout[out.i].nValue;
const CScript& pk = out.tx->vout[out.i].scriptPubKey;
@ -243,7 +250,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
{
CBitcoinAddress address(s.name_);
if (!address.IsValid())
throw JSONRPCError(-5, string("Invalid Bitcoin address:")+s.name_);
throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+s.name_);
if (setAddress.count(address))
throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);

14
src/rpcwallet.cpp

@ -277,17 +277,21 @@ Value sendtoaddress(const Array& params, bool fHelp)
Value listaddressgroupings(const Array& params, bool fHelp)
{
if (fHelp)
throw runtime_error("listaddressgroupings");
throw runtime_error(
"listaddressgroupings\n"
"Lists groups of addresses which have had their common ownership\n"
"made public by common use as inputs or as the resulting change\n"
"in past transactions");
Array jsonGroupings;
map<string, int64> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<string> grouping, pwalletMain->GetAddressGroupings())
map<CTxDestination, int64> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
{
Array jsonGrouping;
BOOST_FOREACH(string address, grouping)
BOOST_FOREACH(CTxDestination address, grouping)
{
Array addressInfo;
addressInfo.push_back(address);
addressInfo.push_back(CBitcoinAddress(address).ToString());
addressInfo.push_back(ValueFromAmount(balances[address]));
{
LOCK(pwalletMain->cs_wallet);

68
src/wallet.cpp

@ -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()
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()
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()
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;

12
src/wallet.h

@ -10,7 +10,6 @@
#include <stdlib.h>
#include "base58.h"
#include "main.h"
#include "key.h"
#include "keystore.h"
@ -177,8 +176,8 @@ public:
int64 GetOldestKeyPoolTime();
void GetAllReserveKeys(std::set<CKeyID>& setAddress);
std::set< std::set<std::string> > GetAddressGroupings();
std::map<std::string, int64> GetAddressBalances();
std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, int64> GetAddressBalances();
bool IsMine(const CTxIn& txin) const;
int64 GetDebit(const CTxIn& txin) const;
@ -647,13 +646,6 @@ public:
return true;
}
std::string GetAddressOfTxOut(int n) const
{
CTxDestination addr;
ExtractDestination(vout[n].scriptPubKey, addr);
return CBitcoinAddress(addr).ToString();
}
bool WriteToDisk();
int64 GetTxTime() const;

Loading…
Cancel
Save