diff options
-rw-r--r-- | db.cpp | 2 | ||||
-rw-r--r-- | init.cpp | 24 | ||||
-rw-r--r-- | main.cpp | 208 | ||||
-rw-r--r-- | main.h | 124 | ||||
-rw-r--r-- | net.cpp | 1 | ||||
-rw-r--r-- | rpc.cpp | 92 | ||||
-rw-r--r-- | ui.cpp | 35 |
7 files changed, 320 insertions, 166 deletions
@@ -668,8 +668,8 @@ bool CWalletDB::LoadWallet() #endif //// todo: shouldn't we catch exceptions and try to recover and continue? - CRITICAL_BLOCK(cs_mapKeys) CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(cs_mapKeys) { // Get cursor Dbc* pcursor = GetCursor(); @@ -78,7 +78,9 @@ int main(int argc, char* argv[]) fRet = AppInit(argc, argv); if (fRet && fDaemon) - pthread_exit((void*)0); + return 0; + + return 1; } #endif @@ -167,6 +169,8 @@ bool AppInit2(int argc, char* argv[]) " -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send\n") + #ifdef GUI " -server \t\t " + _("Accept command line and JSON-RPC commands\n") + +#endif +#ifndef __WXMSW__ " -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") + #endif " -testnet \t\t " + _("Use the test network\n") + @@ -203,17 +207,20 @@ bool AppInit2(int argc, char* argv[]) fDebug = GetBoolArg("-debug"); +#ifndef __WXMSW__ fDaemon = GetBoolArg("-daemon"); +#else + fDaemon = false; +#endif if (fDaemon) fServer = true; else fServer = GetBoolArg("-server"); - /* force fServer and fDaemon when running without GUI */ + /* force fServer when running without GUI */ #ifndef GUI fServer = true; - fDaemon = true; #endif fPrintToConsole = GetBoolArg("-printtoconsole"); @@ -233,7 +240,7 @@ bool AppInit2(int argc, char* argv[]) exit(ret); } -#ifndef GUI +#ifndef __WXMSW__ if (fDaemon) { // Daemonize @@ -490,10 +497,11 @@ bool AppInit2(int argc, char* argv[]) if (fFirstRun) SetStartOnSystemStartup(true); #endif - - if (fDaemon) - while (!fShutdown) - Sleep(5000); + +#ifndef GUI + while (1) + Sleep(5000); +#endif return true; } @@ -144,11 +144,7 @@ bool AddToWallet(const CWalletTx& wtxIn) wtx.fFromMe = wtxIn.fFromMe; fUpdated = true; } - if (wtxIn.fSpent && wtxIn.fSpent != wtx.fSpent) - { - wtx.fSpent = wtxIn.fSpent; - fUpdated = true; - } + fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent); } //// debug print @@ -229,10 +225,10 @@ void WalletUpdateSpent(const COutPoint& prevout) if (mi != mapWallet.end()) { CWalletTx& wtx = (*mi).second; - if (!wtx.fSpent && wtx.vout[prevout.n].IsMine()) + if (!wtx.IsSpent(prevout.n) && wtx.vout[prevout.n].IsMine()) { printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); - wtx.fSpent = true; + wtx.MarkSpent(prevout.n); wtx.WriteToDisk(); vWalletUpdated.push_back(prevout.hash); } @@ -947,34 +943,34 @@ void ReacceptWalletTransactions() foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) { CWalletTx& wtx = item.second; - if (wtx.fSpent && wtx.IsCoinBase()) + if (wtx.IsCoinBase() && wtx.IsSpent(0)) continue; CTxIndex txindex; + bool fUpdated = false; if (txdb.ReadTxIndex(wtx.GetHash(), txindex)) { // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat - if (!wtx.fSpent) + if (txindex.vSpent.size() != wtx.vout.size()) { - if (txindex.vSpent.size() != wtx.vout.size()) - { - printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size()); - continue; - } - for (int i = 0; i < txindex.vSpent.size(); i++) - { - if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine()) - { - wtx.fSpent = true; - vMissingTx.push_back(txindex.vSpent[i]); - } - } - if (wtx.fSpent) + printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size()); + continue; + } + for (int i = 0; i < txindex.vSpent.size(); i++) + { + if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine()) { - printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); - wtx.WriteToDisk(); + wtx.MarkSpent(i); + fUpdated = true; + vMissingTx.push_back(txindex.vSpent[i]); } } + if (fUpdated) + { + printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + wtx.MarkDirty(); + wtx.WriteToDisk(); + } } else { @@ -3740,9 +3736,9 @@ int64 GetBalance() for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { CWalletTx* pcoin = &(*it).second; - if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed()) + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) continue; - nTotal += pcoin->GetCredit(); + nTotal += pcoin->GetAvailableCredit(); } } @@ -3751,14 +3747,16 @@ int64 GetBalance() } -bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<CWalletTx*>& setCoinsRet) +bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) { setCoinsRet.clear(); + nValueRet = 0; // List of values less than target - int64 nLowestLarger = INT64_MAX; - CWalletTx* pcoinLowestLarger = NULL; - vector<pair<int64, CWalletTx*> > vValue; + pair<int64, pair<CWalletTx*,unsigned int> > coinLowestLarger; + coinLowestLarger.first = INT64_MAX; + coinLowestLarger.second.first = NULL; + vector<pair<int64, pair<CWalletTx*,unsigned int> > > vValue; int64 nTotalLower = 0; CRITICAL_BLOCK(cs_mapWallet) @@ -3771,30 +3769,43 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< foreach(CWalletTx* pcoin, vCoins) { - if (!pcoin->IsFinal() || pcoin->fSpent || !pcoin->IsConfirmed()) + if (!pcoin->IsFinal() || !pcoin->IsConfirmed()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) continue; int nDepth = pcoin->GetDepthInMainChain(); if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) continue; - int64 n = pcoin->GetCredit(); - if (n <= 0) - continue; - if (n == nTargetValue) - { - setCoinsRet.insert(pcoin); - return true; - } - else if (n < nTargetValue + CENT) + for (int i = 0; i < pcoin->vout.size(); i++) { - vValue.push_back(make_pair(n, pcoin)); - nTotalLower += n; - } - else if (n < nLowestLarger) - { - nLowestLarger = n; - pcoinLowestLarger = pcoin; + if (pcoin->IsSpent(i) || !pcoin->vout[i].IsMine()) + continue; + + int64 n = pcoin->vout[i].nValue; + + if (n <= 0) + continue; + + pair<int64,pair<CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i)); + + if (n == nTargetValue) + { + setCoinsRet.insert(coin.second); + nValueRet += coin.first; + return true; + } + else if (n < nTargetValue + CENT) + { + vValue.push_back(coin); + nTotalLower += n; + } + else if (n < coinLowestLarger.first) + { + coinLowestLarger = coin; + } } } } @@ -3802,15 +3813,19 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT) { for (int i = 0; i < vValue.size(); ++i) + { setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } return true; } - if (nTotalLower < nTargetValue + (pcoinLowestLarger ? CENT : 0)) + if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0)) { - if (pcoinLowestLarger == NULL) + if (coinLowestLarger.second.first == NULL) return false; - setCoinsRet.insert(pcoinLowestLarger); + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; return true; } @@ -3853,13 +3868,18 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< } // If the next larger is still closer, return it - if (pcoinLowestLarger && nLowestLarger - nTargetValue <= nBest - nTargetValue) - setCoinsRet.insert(pcoinLowestLarger); - else + if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue) { + setCoinsRet.insert(coinLowestLarger.second); + nValueRet += coinLowestLarger.first; + } + else { for (int i = 0; i < vValue.size(); i++) if (vfBest[i]) + { setCoinsRet.insert(vValue[i].second); + nValueRet += vValue[i].first; + } //// debug print printf("SelectCoins() best subset: "); @@ -3872,11 +3892,11 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< return true; } -bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) +bool SelectCoins(int64 nTargetValue, set<pair<CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) { - return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet) || - SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet) || - SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet)); + return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) || + SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet)); } @@ -3914,15 +3934,14 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew.vout.push_back(CTxOut(s.second, s.first)); // Choose coins to use - set<CWalletTx*> setCoins; - if (!SelectCoins(nTotalValue, setCoins)) - return false; + set<pair<CWalletTx*,unsigned int> > setCoins; int64 nValueIn = 0; - foreach(CWalletTx* pcoin, setCoins) + if (!SelectCoins(nTotalValue, setCoins, nValueIn)) + return false; + foreach(PAIRTYPE(CWalletTx*, unsigned int) pcoin, setCoins) { - int64 nCredit = pcoin->GetCredit(); - nValueIn += nCredit; - dPriority += (double)nCredit * pcoin->GetDepthInMainChain(); + int64 nCredit = pcoin.first->vout[pcoin.second].nValue; + dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain(); } // Fill a vout back to self with any change @@ -3955,18 +3974,14 @@ bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& reservekey.ReturnKey(); // Fill vin - foreach(CWalletTx* pcoin, setCoins) - for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) - if (pcoin->vout[nOut].IsMine()) - wtxNew.vin.push_back(CTxIn(pcoin->GetHash(), nOut)); + foreach(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins) + wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); // Sign int nIn = 0; - foreach(CWalletTx* pcoin, setCoins) - for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) - if (pcoin->vout[nOut].IsMine()) - if (!SignSignature(*pcoin, wtxNew, nIn++)) - return false; + foreach(const PAIRTYPE(CWalletTx*,unsigned int)& coin, setCoins) + if (!SignSignature(*coin.first, wtxNew, nIn++)) + return false; // Limit size unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK); @@ -4025,12 +4040,11 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) // Mark old coins as spent set<CWalletTx*> setCoins; foreach(const CTxIn& txin, wtxNew.vin) - setCoins.insert(&mapWallet[txin.prevout.hash]); - foreach(CWalletTx* pcoin, setCoins) { - pcoin->fSpent = true; - pcoin->WriteToDisk(); - vWalletUpdated.push_back(pcoin->GetHash()); + CWalletTx &pcoin = mapWallet[txin.prevout.hash]; + pcoin.MarkSpent(txin.prevout.n); + pcoin.WriteToDisk(); + vWalletUpdated.push_back(pcoin.GetHash()); } } @@ -4054,35 +4068,35 @@ bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +// requires cs_main lock string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee) { - CRITICAL_BLOCK(cs_main) + CReserveKey reservekey; + int64 nFeeRequired; + if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired)) { - CReserveKey reservekey; - int64 nFeeRequired; - if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired)) - { - string strError; - if (nValue + nFeeRequired > GetBalance()) - strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str()); - else - strError = _("Error: Transaction creation failed "); - printf("SendMoney() : %s", strError.c_str()); - return strError; - } + string strError; + if (nValue + nFeeRequired > GetBalance()) + strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str()); + else + strError = _("Error: Transaction creation failed "); + printf("SendMoney() : %s", strError.c_str()); + return strError; + } - if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL)) - return "ABORTED"; + if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL)) + return "ABORTED"; + + if (!CommitTransaction(wtxNew, reservekey)) + return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); - if (!CommitTransaction(wtxNew, reservekey)) - return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); - } MainFrameRepaint(); return ""; } +// requires cs_main lock string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee) { // Check amount @@ -744,6 +744,7 @@ public: fMerkleVerified = false; } + IMPLEMENT_SERIALIZE ( nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action); @@ -780,15 +781,17 @@ public: unsigned int fTimeReceivedIsTxTime; unsigned int nTimeReceived; // time received by this node char fFromMe; - char fSpent; string strFromAccount; + vector<char> vfSpent; // memory only mutable char fDebitCached; mutable char fCreditCached; + mutable char fAvailableCreditCached; mutable char fChangeCached; mutable int64 nDebitCached; mutable int64 nCreditCached; + mutable int64 nAvailableCreditCached; mutable int64 nChangeCached; // memory only UI hints @@ -820,13 +823,15 @@ public: fTimeReceivedIsTxTime = false; nTimeReceived = 0; fFromMe = false; - fSpent = false; strFromAccount.clear(); + vfSpent.clear(); fDebitCached = false; fCreditCached = false; + fAvailableCreditCached = false; fChangeCached = false; nDebitCached = 0; nCreditCached = 0; + nAvailableCreditCached = 0; nChangeCached = 0; nTimeDisplayed = 0; nLinesDisplayed = 0; @@ -838,22 +843,96 @@ public: CWalletTx* pthis = const_cast<CWalletTx*>(this); if (fRead) pthis->Init(); - nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action); - READWRITE(vtxPrev); + char fSpent = false; - pthis->mapValue["fromaccount"] = pthis->strFromAccount; - READWRITE(mapValue); - pthis->strFromAccount = pthis->mapValue["fromaccount"]; - pthis->mapValue.erase("fromaccount"); - pthis->mapValue.erase("version"); + if (!fRead) + { + pthis->mapValue["fromaccount"] = pthis->strFromAccount; + + string str; + foreach(char f, vfSpent) + { + str += (f ? '1' : '0'); + if (f) + fSpent = true; + } + pthis->mapValue["spent"] = str; + } + nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action); + READWRITE(vtxPrev); + READWRITE(mapValue); READWRITE(vOrderForm); READWRITE(fTimeReceivedIsTxTime); READWRITE(nTimeReceived); READWRITE(fFromMe); READWRITE(fSpent); + + if (fRead) + { + pthis->strFromAccount = pthis->mapValue["fromaccount"]; + + if (mapValue.count("spent")) + foreach(char c, pthis->mapValue["spent"]) + pthis->vfSpent.push_back(c != '0'); + else + pthis->vfSpent.assign(vout.size(), fSpent); + } + + pthis->mapValue.erase("fromaccount"); + pthis->mapValue.erase("version"); + pthis->mapValue.erase("spent"); ) + // marks certain txout's as spent + // returns true if any update took place + bool UpdateSpent(const vector<char>& vfNewSpent) + { + bool fReturn = false; + for (int i=0; i < vfNewSpent.size(); i++) + { + if (i == vfSpent.size()) + break; + + if (vfNewSpent[i] && !vfSpent[i]) + { + vfSpent[i] = true; + fReturn = true; + fAvailableCreditCached = false; + } + } + return fReturn; + } + + void MarkDirty() + { + fCreditCached = false; + fAvailableCreditCached = false; + fDebitCached = false; + fChangeCached = false; + } + + void MarkSpent(unsigned int nOut) + { + if (nOut >= vout.size()) + throw runtime_error("CWalletTx::MarkSpent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (!vfSpent[nOut]) + { + vfSpent[nOut] = true; + fAvailableCreditCached = false; + } + } + + bool IsSpent(unsigned int nOut) const + { + if (nOut >= vout.size()) + throw runtime_error("CWalletTx::IsSpent() : nOut out of range"); + if (nOut >= vfSpent.size()) + return false; + return (!!vfSpent[nOut]); + } + int64 GetDebit() const { if (vin.empty()) @@ -879,6 +958,33 @@ public: return nCreditCached; } + int64 GetAvailableCredit(bool fUseCache=true) const + { + // Must wait until coinbase is safely deep enough in the chain before valuing it + if (IsCoinBase() && GetBlocksToMaturity() > 0) + return 0; + + if (fUseCache && fAvailableCreditCached) + return nAvailableCreditCached; + + int64 nCredit = 0; + for (int i = 0; i < vout.size(); i++) + { + if (!IsSpent(i)) + { + const CTxOut &txout = vout[i]; + nCredit += txout.GetCredit(); + if (!MoneyRange(nCredit)) + throw runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); + } + } + + nAvailableCreditCached = nCredit; + fAvailableCreditCached = true; + return nCredit; + } + + int64 GetChange() const { if (fChangeCached) @@ -972,6 +972,7 @@ void MapPort(bool fMapPort) static const char *strDNSSeed[] = { "bitseed.xf2.org", + "bitseed.bitcoin.org.uk", }; void DNSAddressSeed() @@ -315,46 +315,45 @@ Value getnewaddress(const Array& params, bool fHelp) } +// requires cs_main, cs_mapWallet locks string GetAccountAddress(string strAccount, bool bForceNew=false) { string strAddress; - CRITICAL_BLOCK(cs_mapWallet) - { - CWalletDB walletdb; - walletdb.TxnBegin(); - - CAccount account; - walletdb.ReadAccount(strAccount, account); + CWalletDB walletdb; + walletdb.TxnBegin(); - // Check if the current key has been used - if (!account.vchPubKey.empty()) - { - CScript scriptPubKey; - scriptPubKey.SetBitcoinAddress(account.vchPubKey); - for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); - it != mapWallet.end() && !account.vchPubKey.empty(); - ++it) - { - const CWalletTx& wtx = (*it).second; - foreach(const CTxOut& txout, wtx.vout) - if (txout.scriptPubKey == scriptPubKey) - account.vchPubKey.clear(); - } - } + CAccount account; + walletdb.ReadAccount(strAccount, account); - // Generate a new key - if (account.vchPubKey.empty() || bForceNew) + // Check if the current key has been used + if (!account.vchPubKey.empty()) + { + CScript scriptPubKey; + scriptPubKey.SetBitcoinAddress(account.vchPubKey); + for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); + it != mapWallet.end() && !account.vchPubKey.empty(); + ++it) { - account.vchPubKey = GetKeyFromKeyPool(); - string strAddress = PubKeyToAddress(account.vchPubKey); - SetAddressBookName(strAddress, strAccount); - walletdb.WriteAccount(strAccount, account); + const CWalletTx& wtx = (*it).second; + foreach(const CTxOut& txout, wtx.vout) + if (txout.scriptPubKey == scriptPubKey) + account.vchPubKey.clear(); } + } - walletdb.TxnCommit(); - strAddress = PubKeyToAddress(account.vchPubKey); + // Generate a new key + if (account.vchPubKey.empty() || bForceNew) + { + account.vchPubKey = GetKeyFromKeyPool(); + string strAddress = PubKeyToAddress(account.vchPubKey); + SetAddressBookName(strAddress, strAccount); + walletdb.WriteAccount(strAccount, account); } + + walletdb.TxnCommit(); + strAddress = PubKeyToAddress(account.vchPubKey); + return strAddress; } @@ -368,7 +367,15 @@ Value getaccountaddress(const Array& params, bool fHelp) // Parse the account first so we don't generate a key if there's an error string strAccount = AccountFromValue(params[0]); - return GetAccountAddress(strAccount); + Value ret; + + CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(cs_mapWallet) + { + ret = GetAccountAddress(strAccount); + } + + return ret; } @@ -392,6 +399,8 @@ Value setaccount(const Array& params, bool fHelp) strAccount = AccountFromValue(params[1]); // Detect when changing the account of an address that is the 'unused current key' of another account: + CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(cs_mapAddressBook) { if (mapAddressBook.count(strAddress)) @@ -475,9 +484,13 @@ Value sendtoaddress(const Array& params, bool fHelp) if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) wtx.mapValue["to"] = params[3].get_str(); - string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); - if (strError != "") - throw JSONRPCError(-4, strError); + CRITICAL_BLOCK(cs_main) + { + string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx); + if (strError != "") + throw JSONRPCError(-4, strError); + } + return wtx.GetHash().GetHex(); } @@ -752,6 +765,7 @@ Value sendfrom(const Array& params, bool fHelp) if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty()) wtx.mapValue["to"] = params[5].get_str(); + CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_mapWallet) { // Check funds @@ -808,6 +822,7 @@ Value sendmany(const Array& params, bool fHelp) vecSend.push_back(make_pair(scriptPubKey, nAmount)); } + CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_mapWallet) { // Check funds @@ -1135,8 +1150,11 @@ Value listaccounts(const Array& params, bool fHelp) CRITICAL_BLOCK(cs_mapWallet) CRITICAL_BLOCK(cs_mapAddressBook) { - foreach(const PAIRTYPE(string, string)& entry, mapAddressBook) - mapAccountBalances[entry.second] = 0; + foreach(const PAIRTYPE(string, string)& entry, mapAddressBook) { + uint160 hash160; + if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me + mapAccountBalances[entry.second] = 0; + } for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { @@ -1468,7 +1486,7 @@ string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeader string rfc1123Time() { - char buffer[32]; + char buffer[64]; time_t now; time(&now); struct tm* now_gmt = gmtime(&now); @@ -1945,20 +1945,23 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) if (fBitcoinAddress) { - // Send to bitcoin address - CScript scriptPubKey; - scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; - - string strError = SendMoney(scriptPubKey, nValue, wtx, true); - if (strError == "") - wxMessageBox(_("Payment sent "), _("Sending...")); - else if (strError == "ABORTED") - return; // leave send dialog open - else - { - wxMessageBox(strError + " ", _("Sending...")); - EndModal(false); - } + CRITICAL_BLOCK(cs_main) + { + // Send to bitcoin address + CScript scriptPubKey; + scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; + + string strError = SendMoney(scriptPubKey, nValue, wtx, true); + if (strError == "") + wxMessageBox(_("Payment sent "), _("Sending...")); + else if (strError == "ABORTED") + return; // leave send dialog open + else + { + wxMessageBox(strError + " ", _("Sending...")); + EndModal(false); + } + } } else { @@ -2816,6 +2819,10 @@ bool CMyApp::Initialize(int& argc, wxChar** argv) } if (pid > 0) pthread_exit((void*)0); + + pid_t sid = setsid(); + if (sid < 0) + fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); } return true; |