X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fwallet.cpp;h=91407109a037b2d545d3552bce7c8b7b5f18e6a2;hp=7b43f95e54c0c41e52b934bd6e067d6d7b2dff19;hb=4ca0237ec0d2825004fa3aa2b00a94da2a083b8b;hpb=3d5fa3073b359acdd8e4d7de46d24e2dcacf211f diff --git a/src/wallet.cpp b/src/wallet.cpp index 7b43f95..9140710 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -773,7 +773,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl CWalletTx wtx(this,tx); // Get merkle branch if transaction was found in a block if (pblock) - wtx.SetMerkleBranch(*pblock); + wtx.SetMerkleBranch(pblock); return AddToWallet(wtx); } else @@ -810,6 +810,74 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return MINE_NO; } +// marks certain txout's as spent +// returns true if any update took place +bool CWalletTx::UpdateSpent(const std::vector& vfNewSpent) +{ + bool fReturn = false; + for (unsigned int i = 0; i < vfNewSpent.size(); i++) + { + if (i == vfSpent.size()) + break; + + if (vfNewSpent[i] && !vfSpent[i]) + { + vfSpent[i] = true; + fReturn = true; + fAvailableCreditCached = fAvailableWatchCreditCached = false; + } + } + return fReturn; +} + +// make sure balances are recalculated +void CWalletTx::MarkDirty() +{ + fCreditCached = false; + fAvailableCreditCached = fAvailableWatchCreditCached = false; + fDebitCached = fWatchDebitCached = false; + fChangeCached = false; +} + +void CWalletTx::BindWallet(CWallet *pwalletIn) +{ + pwallet = pwalletIn; + MarkDirty(); +} + +void CWalletTx::MarkSpent(unsigned int nOut) +{ + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (!vfSpent[nOut]) + { + vfSpent[nOut] = true; + fAvailableCreditCached = fAvailableWatchCreditCached = false; + } +} + +void CWalletTx::MarkUnspent(unsigned int nOut) +{ + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (vfSpent[nOut]) + { + vfSpent[nOut] = false; + fAvailableCreditCached = fAvailableWatchCreditCached = false; + } +} + +bool CWalletTx::IsSpent(unsigned int nOut) const +{ + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range"); + if (nOut >= vfSpent.size()) + return false; + return (!!vfSpent[nOut]); +} + int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { @@ -1417,83 +1485,83 @@ void CWallet::ReacceptWalletTransactions() } } -void CWalletTx::RelayWalletTransaction(CTxDB& txdb) +bool CWalletTx::RelayWalletTransaction(CTxDB& txdb) { - BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) - { - if (!(tx.IsCoinBase() || tx.IsCoinStake())) - { - uint256 hash = tx.GetHash(); - if (!txdb.ContainsTx(hash)) - RelayTransaction((CTransaction)tx, hash); - } - } - if (!(IsCoinBase() || IsCoinStake())) + uint256 hash = GetHash(); + if (IsCoinBase() || IsCoinStake() || txdb.ContainsTx(hash) || !InMempool()) + return false; + + for(std::vector::const_iterator it = vtxPrev.begin(); it != vtxPrev.end(); it++) { - uint256 hash = GetHash(); + const CMerkleTx& tx = *it; + uint256 hash = tx.GetHash(); + + if (tx.IsCoinBase() || tx.IsCoinStake()) + continue; + if (!txdb.ContainsTx(hash)) - { - printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str()); - RelayTransaction((CTransaction)*this, hash); - } + RelayTransaction((CTransaction)tx, hash); } + + printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str()); + RelayTransaction((CTransaction)*this, hash); + return true; } -void CWalletTx::RelayWalletTransaction() +bool CWalletTx::RelayWalletTransaction() { CTxDB txdb("r"); - RelayWalletTransaction(txdb); + return RelayWalletTransaction(txdb); } -void CWallet::ResendWalletTransactions(bool fForceResend) +std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) { - if (!fForceResend) { - // Do this infrequently and randomly to avoid giving away - // that these are our transactions. - static int64_t nNextTime = GetRand(GetTime() + 30 * 60); - if (GetTime() < nNextTime) - return; - bool fFirst = (nNextTime == 0); - nNextTime = GetTime() + GetRand(30 * 60); - if (fFirst) - return; + std::vector result; - // Only do it if there's been a new block since last time - static int64_t nLastTime = 0; - if (nTimeBestReceived < nLastTime) - return; - nLastTime = GetTime(); + LOCK(cs_wallet); + // Sort them in chronological order + map mapSorted; + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + { + CWalletTx& wtx = item.second; + // Don't rebroadcast if newer than nTime: + if (wtx.nTimeReceived > nTime) + continue; + mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx)); } - - // Rebroadcast any of our txes that aren't in a block yet - printf("ResendWalletTransactions()\n"); - CTxDB txdb("r"); + BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) { - LOCK(cs_wallet); - // Sort them in chronological order - multimap mapSorted; - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) - { - CWalletTx& wtx = item.second; - // Don't rebroadcast until it's had plenty of time that - // it should have gotten in already by now. - if (fForceResend || nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60) - mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx)); - } - BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) - { - CWalletTx& wtx = *item.second; - if (wtx.CheckTransaction()) - wtx.RelayWalletTransaction(txdb); - else - printf("ResendWalletTransactions() : CheckTransaction failed for transaction %s\n", wtx.GetHash().ToString().c_str()); - } + CWalletTx& wtx = *item.second; + if (wtx.RelayWalletTransaction()) + result.push_back(wtx.GetHash()); } + return result; } +void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) +{ + int64_t nNow = GetTime(); + // Do this infrequently and randomly to avoid giving away + // that these are our transactions. + if (nNow < nNextResend) + return; + bool fFirst = (nNextResend == 0); + nNextResend = PoissonNextSend(nNow, 5*60); + if (fFirst) + return; + // Only do it if there's been a new block since last time + if (nBestBlockTime < nLastResend) + return; + nLastResend = nNow; + // Rebroadcast unconfirmed txes older than 5 minutes before the last + // block was found: + std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime - 5*60); + if (!relayed.empty()) + printf("CWallet::ResendWalletTransactions: rebroadcast %" PRIszu " unconfirmed transactions\n", relayed.size()); +} ////////////////////////////////////////////////////////////////////////////// @@ -2817,29 +2885,38 @@ set< set > CWallet::GetAddressGroupings() { CWalletTx *pcoin = &walletEntry.second; - if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0])) + if (pcoin->vin.size() > 0) { + bool any_mine = false; // group all input addresses with each other BOOST_FOREACH(CTxIn txin, pcoin->vin) { CBitcoinAddress address; + if(!IsMine(txin)) // If this input isn't mine, ignore it + continue; if(!ExtractAddress(*this, mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) continue; grouping.insert(address); + any_mine = true; } // group change with input addresses - BOOST_FOREACH(CTxOut txout, pcoin->vout) + if (any_mine) + { + BOOST_FOREACH(CTxOut txout, pcoin->vout) if (IsChange(txout)) { - CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash]; CBitcoinAddress txoutAddr; if(!ExtractAddress(*this, txout.scriptPubKey, txoutAddr)) continue; grouping.insert(txoutAddr); } - groupings.insert(grouping); - grouping.clear(); + } + if (!grouping.empty()) + { + groupings.insert(grouping); + grouping.clear(); + } } // group lone addrs by themselves