diff --git a/db.cpp b/db.cpp index 40998fb7..8f02fffa 100644 --- a/db.cpp +++ b/db.cpp @@ -132,6 +132,8 @@ void CDB::Close() // Flush database activity from memory pool to disk log unsigned int nMinutes = 0; + if (fReadOnly) + nMinutes = 1; if (strFile == "addr.dat") nMinutes = 2; if (strFile == "blkindex.dat" && IsInitialBlockDownload() && nBestHeight % 500 != 0) @@ -654,6 +656,7 @@ bool CWalletDB::LoadWallet() { vchDefaultKey.clear(); int nFileVersion = 0; + vector vWalletUpgrade; // Modify defaults #ifndef __WXMSW__ @@ -703,6 +706,25 @@ bool CWalletDB::LoadWallet() if (wtx.GetHash() != hash) printf("Error in wallet.dat, hash mismatch\n"); + // Undo serialize changes in 31600 + if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) + { + if (!ssValue.empty()) + { + char fTmp; + char fUnused; + ssValue >> fTmp >> fUnused >> wtx.strFromAccount; + printf("LoadWallet() upgrading tx ver=%d %d '%s' %s\n", wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = fTmp; + } + else + { + printf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = 0; + } + vWalletUpgrade.push_back(hash); + } + //// debug print //printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str()); //printf(" %12I64d %s %s %s\n", @@ -772,6 +794,9 @@ bool CWalletDB::LoadWallet() pcursor->close(); } + foreach(uint256 hash, vWalletUpgrade) + WriteTx(hash, mapWallet[hash]); + printf("nFileVersion = %d\n", nFileVersion); printf("fGenerateBitcoins = %d\n", fGenerateBitcoins); printf("nTransactionFee = %"PRI64d"\n", nTransactionFee); @@ -792,6 +817,7 @@ bool CWalletDB::LoadWallet() WriteVersion(VERSION); } + return true; } diff --git a/db.h b/db.h index e3ffc40c..72fe0d9f 100644 --- a/db.h +++ b/db.h @@ -265,7 +265,7 @@ public: class CTxDB : public CDB { public: - CTxDB(const char* pszMode="r+") : CDB(!fClient ? "blkindex.dat" : NULL, pszMode) { } + CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { } private: CTxDB(const CTxDB&); void operator=(const CTxDB&); diff --git a/init.cpp b/init.cpp index 78e842b5..61ca4d2b 100644 --- a/init.cpp +++ b/init.cpp @@ -206,14 +206,11 @@ bool AppInit2(int argc, char* argv[]) return false; } - if (mapArgs.count("-debug")) - fDebug = true; + fDebug = GetBoolArg("-debug"); - if (mapArgs.count("-printtodebugger")) - fPrintToDebugger = true; + fPrintToDebugger = GetBoolArg("-printtodebugger"); - if (mapArgs.count("-testnet")) - fTestNet = true; + fTestNet = GetBoolArg("-testnet"); if (fCommandLine) { @@ -232,7 +229,7 @@ bool AppInit2(int argc, char* argv[]) #endif printf("Default data directory %s\n", GetDefaultDataDir().c_str()); - if (mapArgs.count("-loadblockindextest")) + if (GetBoolArg("-loadblockindextest")) { CTxDB txdb("r"); txdb.LoadBlockIndex(); @@ -348,7 +345,7 @@ bool AppInit2(int argc, char* argv[]) // // Parameters // - if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree")) + if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) { PrintBlockTree(); return false; @@ -377,13 +374,7 @@ bool AppInit2(int argc, char* argv[]) return false; } - if (mapArgs.count("-gen")) - { - if (mapArgs["-gen"].empty()) - fGenerateBitcoins = true; - else - fGenerateBitcoins = (atoi(mapArgs["-gen"].c_str()) != 0); - } + fGenerateBitcoins = GetBoolArg("-gen"); if (mapArgs.count("-proxy")) { @@ -434,7 +425,7 @@ bool AppInit2(int argc, char* argv[]) if (!CreateThread(StartNode, NULL)) wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin"); - if (mapArgs.count("-server") || fDaemon) + if (GetBoolArg("-server") || fDaemon) CreateThread(ThreadRPCServer, NULL); #if defined(__WXMSW__) && defined(GUI) diff --git a/irc.cpp b/irc.cpp index e246fcd1..1734d76f 100644 --- a/irc.cpp +++ b/irc.cpp @@ -173,6 +173,68 @@ bool Wait(int nSeconds) return true; } +bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet) +{ + strRet.clear(); + loop + { + string strLine; + if (!RecvLineIRC(hSocket, strLine)) + return false; + + vector vWords; + ParseString(strLine, ' ', vWords); + if (vWords.size() < 2) + continue; + + if (vWords[1] == psz1) + { + printf("IRC %s\n", strLine.c_str()); + strRet = strLine; + return true; + } + } +} + +bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) +{ + Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str()); + + string strLine; + if (!RecvCodeLine(hSocket, "302", strLine)) + return false; + + vector vWords; + ParseString(strLine, ' ', vWords); + if (vWords.size() < 4) + return false; + + string str = vWords[3]; + if (str.rfind("@") == string::npos) + return false; + string strHost = str.substr(str.rfind("@")+1); + + unsigned int a=0, b=0, c=0, d=0; + if (sscanf(strHost.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) == 4 && + inet_addr(strHost.c_str()) != INADDR_NONE) + { + printf("GetIPFromIRC() userhost is IP %s\n", strHost.c_str()); + ipRet = CAddress(strHost).ip; + } + else + { + printf("GetIPFromIRC() got userhost %s\n", strHost.c_str()); + if (fUseProxy) + return false; + struct hostent* phostent = gethostbyname(strHost.c_str()); + if (!phostent || !phostent->h_addr_list || !phostent->h_addr_list[0]) + return false; + ipRet = *(u_long*)phostent->h_addr_list[0]; + } + + return true; +} + void ThreadIRCSeed(void* parg) @@ -194,7 +256,7 @@ void ThreadIRCSeed2(void* parg) { if (mapArgs.count("-connect")) return; - if (mapArgs.count("-noirc")) + if (GetBoolArg("-noirc")) return; printf("ThreadIRCSeed started\n"); int nErrorWait = 10; @@ -265,6 +327,20 @@ void ThreadIRCSeed2(void* parg) } Sleep(500); + // Get my external IP from IRC server + CAddress addrFromIRC; + if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip)) + { + // Just using it as a backup for now + printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str()); + if (addrFromIRC.IsRoutable() && !fUseProxy && !addrLocalHost.IsRoutable()) + { + addrLocalHost.ip = addrFromIRC.ip; + strMyName = EncodeAddress(addrLocalHost); + Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); + } + } + Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r"); Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r" : "WHO #bitcoin\r"); diff --git a/main.cpp b/main.cpp index a1865a46..be29ceb9 100644 --- a/main.cpp +++ b/main.cpp @@ -870,6 +870,11 @@ void ResendWalletTransactions() bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) { + if (!fReadTransactions) + { + *this = pindex->GetBlockHeader(); + return true; + } if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions)) return false; if (GetHash() != pindex->GetBlockHash()) @@ -1425,7 +1430,10 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork(); CTxDB txdb; + txdb.TxnBegin(); txdb.WriteBlockIndex(CDiskBlockIndex(pindexNew)); + if (!txdb.TxnCommit()) + return false; // New best if (pindexNew->bnChainWork > bnBestChainWork) @@ -1529,9 +1537,9 @@ bool CBlock::AcceptBlock() // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK))) return error("AcceptBlock() : out of disk space"); - unsigned int nFile; - unsigned int nBlockPos; - if (!WriteToDisk(!fClient, nFile, nBlockPos)) + unsigned int nFile = -1; + unsigned int nBlockPos = 0; + if (!WriteToDisk(nFile, nBlockPos)) return error("AcceptBlock() : WriteToDisk failed"); if (!AddToBlockIndex(nFile, nBlockPos)) return error("AcceptBlock() : AddToBlockIndex failed"); @@ -1777,7 +1785,7 @@ bool LoadBlockIndex(bool fAllowNew) // Start new block file unsigned int nFile; unsigned int nBlockPos; - if (!block.WriteToDisk(!fClient, nFile, nBlockPos)) + if (!block.WriteToDisk(nFile, nBlockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); if (!block.AddToBlockIndex(nFile, nBlockPos)) return error("LoadBlockIndex() : genesis block not accepted"); @@ -1891,7 +1899,7 @@ string GetWarnings(string strFor) int nPriority = 0; string strStatusBar; string strRPC; - if (mapArgs.count("-testsafemode")) + if (GetBoolArg("-testsafemode")) strRPC = "test"; // Misc warnings like out of disk space and clock is wrong @@ -2181,11 +2189,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } pfrom->fClient = !(pfrom->nServices & NODE_NETWORK); - if (pfrom->fClient) - { - pfrom->vSend.nType |= SER_BLOCKHEADERONLY; - pfrom->vRecv.nType |= SER_BLOCKHEADERONLY; - } AddTimeData(pfrom->addr.ip, nTime); @@ -2359,9 +2362,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) map::iterator mi = mapBlockIndex.find(inv.hash); if (mi != mapBlockIndex.end()) { - //// could optimize this to send header straight from blockindex for client CBlock block; - block.ReadFromDisk((*mi).second, !pfrom->fClient); + block.ReadFromDisk((*mi).second); pfrom->PushMessage("block", block); // Trigger them to send a getblocks request for the next batch of inventory @@ -2405,7 +2407,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) uint256 hashStop; vRecv >> locator >> hashStop; - // Find the first block the caller has in the main chain + // Find the last block the caller has in the main chain CBlockIndex* pindex = locator.GetBlockIndex(); // Send the rest of the chain @@ -2433,6 +2435,42 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } + else if (strCommand == "getheaders") + { + CBlockLocator locator; + uint256 hashStop; + vRecv >> locator >> hashStop; + + CBlockIndex* pindex = NULL; + if (locator.IsNull()) + { + // If locator is null, return the hashStop block + map::iterator mi = mapBlockIndex.find(hashStop); + if (mi == mapBlockIndex.end()) + return true; + pindex = (*mi).second; + } + else + { + // Find the last block the caller has in the main chain + pindex = locator.GetBlockIndex(); + if (pindex) + pindex = pindex->pnext; + } + + vector vHeaders; + int nLimit = 2000 + locator.GetDistanceBack(); + printf("getheaders %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit); + for (; pindex; pindex = pindex->pnext) + { + vHeaders.push_back(pindex->GetBlockHeader()); + if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop) + break; + } + pfrom->PushMessage("headers", vHeaders); + } + + else if (strCommand == "tx") { vector vWorkQueue; @@ -2488,17 +2526,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else if (strCommand == "block") { - auto_ptr pblock(new CBlock); - vRecv >> *pblock; + CBlock block; + vRecv >> block; - //// debug print - printf("received block %s\n", pblock->GetHash().ToString().substr(0,20).c_str()); - // pblock->print(); + printf("received block %s\n", block.GetHash().ToString().substr(0,20).c_str()); + // block.print(); - CInv inv(MSG_BLOCK, pblock->GetHash()); + CInv inv(MSG_BLOCK, block.GetHash()); pfrom->AddInventoryKnown(inv); - if (ProcessBlock(pfrom, pblock.get())) + if (ProcessBlock(pfrom, &block)) mapAlreadyAskedFor.erase(inv); } @@ -3123,7 +3160,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) dPriority += (double)nValueIn * nConf; - if (fDebug && mapArgs.count("-printpriority")) + if (fDebug && GetBoolArg("-printpriority")) printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority); } @@ -3135,7 +3172,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey) else mapPriority.insert(make_pair(-dPriority, &(*mi).second)); - if (fDebug && mapArgs.count("-printpriority")) + if (fDebug && GetBoolArg("-printpriority")) { printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str()); if (porphan) @@ -3312,7 +3349,7 @@ void BitcoinMiner() SetThreadPriority(THREAD_PRIORITY_LOWEST); bool f4WaySSE2 = Detect128BitSSE2(); if (mapArgs.count("-4way")) - f4WaySSE2 = (mapArgs["-4way"] != "0"); + f4WaySSE2 = GetBoolArg(mapArgs["-4way"]); // Each thread has its own key and counter CReserveKey reservekey; diff --git a/main.h b/main.h index 2c24eba2..b221e62a 100644 --- a/main.h +++ b/main.h @@ -751,11 +751,10 @@ public: vector vtxPrev; map mapValue; vector > vOrderForm; + unsigned int fTimeReceivedIsTxTime; unsigned int nTimeReceived; // time received by this node char fFromMe; char fSpent; - char fTimeReceivedIsTxTime; - char fUnused; string strFromAccount; // memory only @@ -792,11 +791,10 @@ public: vtxPrev.clear(); mapValue.clear(); vOrderForm.clear(); + fTimeReceivedIsTxTime = false; nTimeReceived = 0; fFromMe = false; fSpent = false; - fTimeReceivedIsTxTime = false; - fUnused = false; strFromAccount.clear(); fDebitCached = false; fCreditCached = false; @@ -811,24 +809,23 @@ public: IMPLEMENT_SERIALIZE ( + CWalletTx* pthis = const_cast(this); if (fRead) - const_cast(this)->Init(); + pthis->Init(); nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action); READWRITE(vtxPrev); + + pthis->mapValue["fromaccount"] = pthis->strFromAccount; READWRITE(mapValue); + pthis->strFromAccount = pthis->mapValue["fromaccount"]; + pthis->mapValue.erase("fromaccount"); + pthis->mapValue.erase("version"); + READWRITE(vOrderForm); - READWRITE(nVersion); - if (fRead && nVersion < 100) - const_cast(this)->fTimeReceivedIsTxTime = nVersion; + READWRITE(fTimeReceivedIsTxTime); READWRITE(nTimeReceived); READWRITE(fFromMe); READWRITE(fSpent); - if (nVersion >= 31404) - { - READWRITE(fTimeReceivedIsTxTime); - READWRITE(fUnused); - READWRITE(strFromAccount); - } ) int64 GetDebit() const @@ -865,11 +862,6 @@ public: return nChangeCached; } - bool IsFromMe() const - { - return (GetDebit() > 0); - } - void GetAccountAmounts(string strAccount, const set& setPubKey, int64& nGenerated, int64& nReceived, int64& nSent, int64& nFee) const { @@ -901,6 +893,11 @@ public: } } + bool IsFromMe() const + { + return (GetDebit() > 0); + } + bool IsConfirmed() const { // Quick answer in most cases @@ -1158,14 +1155,12 @@ public: } - bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet) + bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet) { // Open history file to append CAutoFile fileout = AppendBlockFile(nFileRet); if (!fileout) return error("CBlock::WriteToDisk() : AppendBlockFile failed"); - if (!fWriteTransactions) - fileout.nType |= SER_BLOCKHEADERONLY; // Write index header unsigned int nSize = fileout.GetSerializeSize(*this); @@ -1310,6 +1305,19 @@ public: nNonce = block.nNonce; } + CBlock GetBlockHeader() const + { + CBlock block; + block.nVersion = nVersion; + if (pprev) + block.hashPrevBlock = pprev->GetBlockHash(); + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; + } + uint256 GetBlockHash() const { return *phashBlock; @@ -1511,6 +1519,16 @@ public: READWRITE(vHave); ) + void SetNull() + { + vHave.clear(); + } + + bool IsNull() + { + return vHave.empty(); + } + void Set(const CBlockIndex* pindex) { vHave.clear(); diff --git a/rpc.cpp b/rpc.cpp index 0d00f4cc..b9ed61de 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -1525,7 +1525,7 @@ void ThreadRPCServer2(void* parg) return; } - bool fUseSSL = (mapArgs.count("-rpcssl") > 0); + bool fUseSSL = GetBoolArg("-rpcssl"); asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback(); asio::io_service io_service; @@ -1552,7 +1552,7 @@ void ThreadRPCServer2(void* parg) } #else if (fUseSSL) - throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries."); + throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries."); #endif loop @@ -1642,7 +1642,7 @@ void ThreadRPCServer2(void* parg) // Observe safe mode string strWarning = GetWarnings("rpc"); - if (strWarning != "" && !mapArgs.count("-disablesafemode") && !setAllowInSafeMode.count(strMethod)) + if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod)) throw JSONRPCError(-2, string("Safe mode: ") + strWarning); try @@ -1692,7 +1692,7 @@ Object CallRPC(const string& strMethod, const Array& params) GetConfigFile().c_str())); // Connect to localhost - bool fUseSSL = (mapArgs.count("-rpcssl") > 0); + bool fUseSSL = GetBoolArg("-rpcssl"); #ifdef USE_SSL asio::io_service io_service; ssl::context context(io_service, ssl::context::sslv23); @@ -1704,7 +1704,7 @@ Object CallRPC(const string& strMethod, const Array& params) throw runtime_error("couldn't connect to server"); #else if (fUseSSL) - throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries."); + throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries."); ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")); if (stream.fail()) diff --git a/serialize.h b/serialize.h index 3debdf08..eccea8f7 100644 --- a/serialize.h +++ b/serialize.h @@ -25,7 +25,7 @@ class CDataStream; class CAutoFile; static const unsigned int MAX_SIZE = 0x02000000; -static const int VERSION = 31701; +static const int VERSION = 31704; static const char* pszSubVer = ""; diff --git a/ui.cpp b/ui.cpp index 213cf766..bf436444 100644 --- a/ui.cpp +++ b/ui.cpp @@ -391,7 +391,7 @@ void CMainFrame::OnIconize(wxIconizeEvent& event) if (!event.Iconized()) fClosedToTray = false; #if defined(__WXGTK__) || defined(__WXMAC_OSX__) - if (mapArgs.count("-minimizetotray")) { + if (GetBoolArg("-minimizetotray")) { #endif // The tray icon sometimes disappears on ubuntu karmic // Hiding the taskbar button doesn't work cleanly on ubuntu lucid @@ -1633,7 +1633,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent) #endif #if defined(__WXGTK__) || defined(__WXMAC_OSX__) m_checkBoxStartOnSystemStartup->SetLabel(_("&Start Bitcoin on window system startup")); - if (!mapArgs.count("-minimizetotray")) + if (!GetBoolArg("-minimizetotray")) { // Minimize to tray is just too buggy on Linux fMinimizeToTray = false; @@ -2741,10 +2741,10 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu() void CreateMainWindow() { pframeMain = new CMainFrame(NULL); - if (mapArgs.count("-min")) + if (GetBoolArg("-min")) pframeMain->Iconize(true); #if defined(__WXGTK__) || defined(__WXMAC_OSX__) - if (!mapArgs.count("-minimizetotray")) + if (!GetBoolArg("-minimizetotray")) fMinimizeToTray = false; #endif pframeMain->Show(true); // have to show first to get taskbar button to hide diff --git a/util.h b/util.h index 31ba4f52..f57e4010 100644 --- a/util.h +++ b/util.h @@ -417,6 +417,17 @@ inline int64 GetArg(const string& strArg, int64 nDefault) return nDefault; } +inline bool GetBoolArg(const string& strArg) +{ + if (mapArgs.count(strArg)) + { + if (mapArgs[strArg].empty()) + return true; + return (atoi(mapArgs[strArg]) != 0); + } + return false; +} + inline string FormatVersion(int nVersion) { if (nVersion%100 == 0)