changeset 368:081ecda945e6 draft

Merge remote branch 'refs/remotes/svn/trunk' into svn
author Gavin Andresen <gavinandresen@gmail.com>
date Mon, 06 Dec 2010 18:58:31 -0500
parents 746115300830 (current diff) dd6bfb810b35 (diff)
children de1d4056a8ed
files db.cpp db.h init.cpp irc.cpp main.cpp main.h rpc.cpp serialize.h ui.cpp util.h
diffstat 10 files changed, 234 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/db.cpp
+++ b/db.cpp
@@ -132,6 +132,8 @@
 
     // 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 @@
 {
     vchDefaultKey.clear();
     int nFileVersion = 0;
+    vector<uint256> vWalletUpgrade;
 
     // Modify defaults
 #ifndef __WXMSW__
@@ -703,6 +706,25 @@
                 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 @@
         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 @@
         WriteVersion(VERSION);
     }
 
+
     return true;
 }
 
--- a/db.h
+++ b/db.h
@@ -265,7 +265,7 @@
 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&);
--- a/init.cpp
+++ b/init.cpp
@@ -206,14 +206,11 @@
         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 @@
 #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 @@
     //
     // Parameters
     //
-    if (mapArgs.count("-printblockindex") || mapArgs.count("-printblocktree"))
+    if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
     {
         PrintBlockTree();
         return false;
@@ -377,13 +374,7 @@
         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 @@
     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)
--- a/irc.cpp
+++ b/irc.cpp
@@ -173,6 +173,68 @@
     return true;
 }
 
+bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet)
+{
+    strRet.clear();
+    loop
+    {
+        string strLine;
+        if (!RecvLineIRC(hSocket, strLine))
+            return false;
+
+        vector<string> 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<string> 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 @@
 {
     if (mapArgs.count("-connect"))
         return;
-    if (mapArgs.count("-noirc"))
+    if (GetBoolArg("-noirc"))
         return;
     printf("ThreadIRCSeed started\n");
     int nErrorWait = 10;
@@ -265,6 +327,20 @@
         }
         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");
 
--- a/main.cpp
+++ b/main.cpp
@@ -870,6 +870,11 @@
 
 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 @@
     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 @@
     // 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 @@
         // 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 @@
     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 @@
         }
 
         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 @@
                 map<uint256, CBlockIndex*>::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 @@
         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 @@
     }
 
 
+    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<uint256, CBlockIndex*>::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<CBlock> 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<uint256> vWorkQueue;
@@ -2488,17 +2526,16 @@
 
     else if (strCommand == "block")
     {
-        auto_ptr<CBlock> pblock(new CBlock);
-        vRecv >> *pblock;
-
-        //// debug print
-        printf("received block %s\n", pblock->GetHash().ToString().substr(0,20).c_str());
-        // pblock->print();
-
-        CInv inv(MSG_BLOCK, pblock->GetHash());
+        CBlock block;
+        vRecv >> block;
+
+        printf("received block %s\n", block.GetHash().ToString().substr(0,20).c_str());
+        // block.print();
+
+        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 @@
 
                 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 @@
             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 @@
     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;
--- a/main.h
+++ b/main.h
@@ -751,11 +751,10 @@
     vector<CMerkleTx> vtxPrev;
     map<string, string> mapValue;
     vector<pair<string, string> > 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 @@
         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 @@
 
     IMPLEMENT_SERIALIZE
     (
+        CWalletTx* pthis = const_cast<CWalletTx*>(this);
         if (fRead)
-            const_cast<CWalletTx*>(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<CWalletTx*>(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 @@
         return nChangeCached;
     }
 
-    bool IsFromMe() const
-    {
-        return (GetDebit() > 0);
-    }
-
     void GetAccountAmounts(string strAccount, const set<CScript>& setPubKey,
                            int64& nGenerated, int64& nReceived, int64& nSent, int64& nFee) const
     {
@@ -901,6 +893,11 @@
         }
     }
 
+    bool IsFromMe() const
+    {
+        return (GetDebit() > 0);
+    }
+
     bool IsConfirmed() const
     {
         // Quick answer in most cases
@@ -1158,14 +1155,12 @@
     }
 
 
-    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 @@
         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 @@
         READWRITE(vHave);
     )
 
+    void SetNull()
+    {
+        vHave.clear();
+    }
+
+    bool IsNull()
+    {
+        return vHave.empty();
+    }
+
     void Set(const CBlockIndex* pindex)
     {
         vHave.clear();
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -1525,7 +1525,7 @@
         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 @@
     }
 #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 @@
 
             // 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 @@
                 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 @@
         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())
--- a/serialize.h
+++ b/serialize.h
@@ -25,7 +25,7 @@
 class CAutoFile;
 static const unsigned int MAX_SIZE = 0x02000000;
 
-static const int VERSION = 31701;
+static const int VERSION = 31704;
 static const char* pszSubVer = "";
 
 
--- a/ui.cpp
+++ b/ui.cpp
@@ -391,7 +391,7 @@
     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 @@
 #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 @@
 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
--- a/util.h
+++ b/util.h
@@ -417,6 +417,17 @@
     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)