diff options
Diffstat (limited to 'src/wallet.cpp')
-rw-r--r-- | src/wallet.cpp | 144 |
1 files changed, 137 insertions, 7 deletions
diff --git a/src/wallet.cpp b/src/wallet.cpp index 9b472cd78f..a10f187309 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -291,8 +291,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } -CWallet::TxItems -CWallet::OrderedTxItems(std::string strAccount) +int64 CWallet::IncOrderPosNext() +{ + int64 nRet = nOrderPosNext; + CWalletDB(strWalletFile).WriteOrderPosNext(++nOrderPosNext); + return nRet; +} + +CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount) { CWalletDB walletdb(strWalletFile); @@ -306,7 +312,7 @@ CWallet::OrderedTxItems(std::string strAccount) CWalletTx* wtx = &((*it).second); txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0))); } - list<CAccountingEntry> acentries; + acentries.clear(); walletdb.ListAccountCreditDebit(strAccount, acentries); BOOST_FOREACH(CAccountingEntry& entry, acentries) { @@ -363,7 +369,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) if (fInsertedNew) { wtx.nTimeReceived = GetAdjustedTime(); - wtx.nOrderPos = nOrderPosNext++; + wtx.nOrderPos = IncOrderPosNext(); wtx.nTimeSmart = wtx.nTimeReceived; if (wtxIn.hashBlock != 0) @@ -375,7 +381,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) { // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future int64 latestTolerated = latestNow + 300; - TxItems txOrdered = OrderedTxItems(); + std::list<CAccountingEntry> acentries; + TxItems txOrdered = OrderedTxItems(acentries); for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; @@ -1367,7 +1374,7 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nVal int CWallet::LoadWallet(bool& fFirstRunRet) { if (!fFileBacked) - return false; + return DB_LOAD_OK; fFirstRunRet = false; int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); if (nLoadWalletRet == DB_NEED_REWRITE) @@ -1385,7 +1392,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet) return nLoadWalletRet; fFirstRunRet = !vchDefaultKey.IsValid(); - CreateThread(ThreadFlushWalletDB, &strWalletFile); + NewThread(ThreadFlushWalletDB, &strWalletFile); return DB_LOAD_OK; } @@ -1608,6 +1615,129 @@ int64 CWallet::GetOldestKeyPoolTime() return keypool.nTime; } +std::map<CTxDestination, int64> CWallet::GetAddressBalances() +{ + map<CTxDestination, 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 (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; + + if (!balances.count(addr)) + balances[addr] = 0; + balances[addr] += n; + } + } + } + + return balances; +} + +set< set<CTxDestination> > CWallet::GetAddressGroupings() +{ + set< set<CTxDestination> > groupings; + set<CTxDestination> grouping; + + BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + { + CWalletTx *pcoin = &walletEntry.second; + + if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0])) + { + // group all input addresses with each other + BOOST_FOREACH(CTxIn txin, pcoin->vin) + { + 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]; + CTxDestination txoutAddr; + if(!ExtractDestination(txout.scriptPubKey, txoutAddr)) + continue; + grouping.insert(txoutAddr); + } + groupings.insert(grouping); + grouping.clear(); + } + + // group lone addrs by themselves + for (unsigned int i = 0; i < pcoin->vout.size(); i++) + if (IsMine(pcoin->vout[i])) + { + CTxDestination address; + if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address)) + continue; + grouping.insert(address); + groupings.insert(grouping); + grouping.clear(); + } + } + + 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<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<CTxDestination>* merged = new set<CTxDestination>(grouping); + BOOST_FOREACH(set<CTxDestination>* hit, hits) + { + merged->insert(hit->begin(), hit->end()); + uniqueGroupings.erase(hit); + delete hit; + } + uniqueGroupings.insert(merged); + + // update setmap + BOOST_FOREACH(CTxDestination element, *merged) + setmap[element] = merged; + } + + set< set<CTxDestination> > ret; + BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings) + { + ret.insert(*uniqueGrouping); + delete uniqueGrouping; + } + + return ret; +} + CPubKey CReserveKey::GetReservedKey() { if (nIndex == -1) |