Satoshi MailBeta Open in Satoshi Mail

flush wallet.dat, multi-proc, reorg options, revert to startup folder shortcut

Commit by Satoshi Nakamoto (s_nakamoto) on 21 October 2009 · SVN r15 · release v0.2.0 · 20 files, +1,968 −1,373

Open in Satoshi Mail View on GitHub

Files changed

build.txt
@@ -1,4 +1,4 @@
-BitCoin v0.1.5 ALPHA
+BitCoin v0.1.6 ALPHA
 
 Copyright (c) 2009 Satoshi Nakamoto
 Distributed under the MIT/X11 software license, see the accompanying
@@ -10,7 +10,7 @@ cryptographic software written by Eric Young (eay@cryptsoft.com).
 
 Compilers Supported
 -------------------
-MinGW GCC (v3.4.5)
+MinGW GCC (currently v3.4.5)
 Microsoft Visual C++ 6.0 SP6
 
 
@@ -31,6 +31,16 @@ Berkeley DB    New BSD license with additional requirement that linked software
 Boost          MIT-like license
 
 
+Notes
+-----
+The UI layout is edited with wxFormBuilder.  Open the project file
+uiproject.fbp.  It generates uibase.cpp and uibase.h, which define base
+classes that do the rote work of constructing all the UI elements.
+
+The release is built with GCC and then "strip bitcoin.exe" to strip the debug
+symbols, which reduces the executable size by about 90%.
+
+
 OpenSSL
 -------
 Bitcoin does not use any encryption.  If you want to do a no-everything
@@ -47,7 +57,7 @@ Add this to crypto\err\err_all.c before the ERR_load_crypto_strings line:
 
 Edit ms\mingw32.bat and replace the Configure line's parameters with this
 no-everything list.  You have to put this in the batch file because batch
-files can't handle more than 9 parameters.
+files can't take more than 9 command line parameters.
   perl Configure mingw threads no-rc2 no-rc4 no-rc5 no-idea no-des no-bf no-cast no-aes no-camellia no-seed no-rsa no-dh
 
 Also REM out the following line in ms\mingw32.bat.  The build fails after it's
@@ -64,7 +74,7 @@ If you want to use it with MSVC, generate the .lib file
 
 Berkeley DB
 -----------
-MinGW with MSYS:
+Using MinGW and MSYS:
 cd \DB\build_unix
 sh ../dist/configure --enable-mingw --enable-cxx
 make
@@ -72,5 +82,6 @@ make
 
 Boost
 -----
-You may need Boost version 1.35 to build with MSVC 6.0.  I couldn't get
-version 1.37 to compile with MSVC 6.0.
+If you have trouble compiling Boost with Microsoft Visual C++ 6.0, try going
+back to Boost version 1.35.  It looks like they may be starting to reduce
+support for MSVC 6.0.
db.cpp
@@ -453,11 +453,7 @@ bool CAddrDB::LoadAddresses()
             }
         }
 
-        //// debug print
-        printf("mapAddresses:\n");
-        foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
-            item.second.print();
-        printf("-----\n");
+        printf("Loaded %d addresses\n", mapAddresses.size());
 
         // Fix for possible bug that manifests in mapAddresses.count in irc.cpp,
         // just need to call count here and it doesn't happen there.  The bug was the
@@ -501,6 +497,26 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
 // CWalletDB
 //
 
+CWalletDB::~CWalletDB()
+{
+    // Flush whenever all handles to wallet.dat are closed
+    Close();
+    CRITICAL_BLOCK(cs_db)
+    {
+        map<string, int>::iterator mi = mapFileUseCount.find(strFile);
+        if (mi != mapFileUseCount.end())
+        {
+            int nRefCount = (*mi).second;
+            if (nRefCount == 0)
+            {
+                dbenv.txn_checkpoint(0, 0, 0);
+                dbenv.lsn_reset(strFile.c_str(), 0);
+                mapFileUseCount.erase(mi++);
+            }
+        }
+    }
+}
+
 bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
 {
     vchDefaultKeyRet.clear();
@@ -568,34 +584,51 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
             {
                 ssValue >> vchDefaultKeyRet;
             }
-            else if (strType == "setting")  /// or settings or option or options or config?
+            else if (strType == "setting")
             {
                 string strKey;
                 ssKey >> strKey;
+
+                // Menu state
+                if (strKey == "fShowGenerated")     ssValue >> fShowGenerated;
                 if (strKey == "fGenerateBitcoins")  ssValue >> fGenerateBitcoins;
+
+                // Options
                 if (strKey == "nTransactionFee")    ssValue >> nTransactionFee;
                 if (strKey == "addrIncoming")       ssValue >> addrIncoming;
-                if (strKey == "minimizeToTray")       ssValue >> minimizeToTray;
-                if (strKey == "closeToTray")       ssValue >> closeToTray;
-                if (strKey == "startOnSysBoot")       ssValue >> startOnSysBoot;
-                if (strKey == "askBeforeClosing")       ssValue >> askBeforeClosing;
-                if (strKey == "alwaysShowTrayIcon")       ssValue >> alwaysShowTrayIcon;
+                if (strKey == "fLimitProcessors")   ssValue >> fLimitProcessors;
+                if (strKey == "nLimitProcessors")   ssValue >> nLimitProcessors;
+                if (strKey == "fMinimizeToTray")    ssValue >> fMinimizeToTray;
+                if (strKey == "fMinimizeOnClose")   ssValue >> fMinimizeOnClose;
             }
         }
     }
 
+    printf("fShowGenerated = %d\n", fShowGenerated);
     printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
     printf("nTransactionFee = %I64d\n", nTransactionFee);
     printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
+    printf("fMinimizeToTray = %d\n", fMinimizeToTray);
+    printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
+
+    // The transaction fee setting won't be needed for many years to come.
+    // Setting it to zero here in case they set it to something in an earlier version.
+    if (nTransactionFee != 0)
+    {
+        nTransactionFee = 0;
+        WriteSetting("nTransactionFee", nTransactionFee);
+    }
 
     return true;
 }
 
-bool LoadWallet()
+bool LoadWallet(bool& fFirstRunRet)
 {
+    fFirstRunRet = false;
     vector<unsigned char> vchDefaultKey;
     if (!CWalletDB("cr").LoadWallet(vchDefaultKey))
         return false;
+    fFirstRunRet = vchDefaultKey.empty();
 
     if (mapKeys.count(vchDefaultKey))
     {
db.h
@@ -338,6 +338,7 @@ class CWalletDB : public CDB
 {
 public:
     CWalletDB(const char* pszMode="r+", bool fTxn=false) : CDB("wallet.dat", pszMode, fTxn) { }
+    ~CWalletDB();
 private:
     CWalletDB(const CWalletDB&);
     void operator=(const CWalletDB&);
@@ -412,7 +413,7 @@ public:
     bool LoadWallet(vector<unsigned char>& vchDefaultKeyRet);
 };
 
-bool LoadWallet();
+bool LoadWallet(bool& fFirstRunRet);
 
 inline bool SetAddressBookName(const string& strAddress, const string& strName)
 {
headers.h
@@ -10,11 +10,11 @@
 #ifdef _WIN32_WINNT
 #undef _WIN32_WINNT
 #endif
-#define _WIN32_WINNT 0x0500
+#define _WIN32_WINNT 0x0400
 #ifdef _WIN32_IE
 #undef _WIN32_IE
 #endif
-#define _WIN32_IE 0x0500
+#define _WIN32_IE 0x0400
 #define WIN32_LEAN_AND_MEAN 1
 #include <wx/wx.h>
 #include <wx/clipbrd.h>
@@ -28,6 +28,8 @@
 #include <windows.h>
 #include <winsock2.h>
 #include <mswsock.h>
+#include <shlobj.h>
+#include <shlwapi.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <io.h>
irc.cpp
@@ -52,7 +52,7 @@ bool DecodeAddress(string str, CAddress& addr)
 static bool Send(SOCKET hSocket, const char* pszSend)
 {
     if (strstr(pszSend, "PONG") != pszSend)
-        printf("SENDING: %s\n", pszSend);
+        printf("IRC SENDING: %s\n", pszSend);
     const char* psz = pszSend;
     const char* pszEnd = psz + strlen(psz);
     while (psz < pszEnd)
@@ -145,7 +145,7 @@ bool Wait(int nSeconds)
 {
     if (fShutdown)
         return false;
-    printf("Waiting %d seconds to reconnect to IRC\n", nSeconds);
+    printf("IRC waiting %d seconds to reconnect\n", nSeconds);
     for (int i = 0; i < nSeconds; i++)
     {
         if (fShutdown)
@@ -220,7 +220,6 @@ void ThreadIRCSeed(void* parg)
         {
             if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
                 continue;
-            printf("IRC %s\n", strLine.c_str());
 
             vector<string> vWords;
             ParseString(strLine, ' ', vWords);
@@ -235,7 +234,7 @@ void ThreadIRCSeed(void* parg)
                 // index 7 is limited to 16 characters
                 // could get full length name at index 10, but would be different from join messages
                 strcpy(pszName, vWords[7].c_str());
-                printf("GOT WHO: [%s]  ", pszName);
+                printf("IRC got who\n");
             }
 
             if (vWords[1] == "JOIN" && vWords[0].size() > 1)
@@ -244,7 +243,7 @@ void ThreadIRCSeed(void* parg)
                 strcpy(pszName, vWords[0].c_str() + 1);
                 if (strchr(pszName, '!'))
                     *strchr(pszName, '!') = '\0';
-                printf("GOT JOIN: [%s]  ", pszName);
+                printf("IRC got join\n");
             }
 
             if (pszName[0] == 'u')
@@ -254,7 +253,7 @@ void ThreadIRCSeed(void* parg)
                 {
                     CAddrDB addrdb;
                     if (AddAddress(addrdb, addr))
-                        printf("new  ");
+                        printf("IRC got new address\n");
                     else
                     {
                         // make it try connecting again
@@ -262,14 +261,13 @@ void ThreadIRCSeed(void* parg)
                             if (mapAddresses.count(addr.GetKey()))
                                 mapAddresses[addr.GetKey()].nLastFailed = 0;
                     }
-                    addr.print();
 
                     CRITICAL_BLOCK(cs_mapIRCAddresses)
                         mapIRCAddresses.insert(make_pair(addr.GetKey(), addr));
                 }
                 else
                 {
-                    printf("decode failed\n");
+                    printf("IRC decode failed\n");
                 }
             }
         }
key.h
@@ -44,6 +44,7 @@ class CKey
 {
 protected:
     EC_KEY* pkey;
+    bool fSet;
 
 public:
     CKey()
@@ -51,6 +52,7 @@ public:
         pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
         if (pkey == NULL)
             throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
+        fSet = false;
     }
 
     CKey(const CKey& b)
@@ -58,12 +60,14 @@ public:
         pkey = EC_KEY_dup(b.pkey);
         if (pkey == NULL)
             throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
+        fSet = b.fSet;
     }
 
     CKey& operator=(const CKey& b)
     {
         if (!EC_KEY_copy(pkey, b.pkey))
             throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
+        fSet = b.fSet;
         return (*this);
     }
 
@@ -72,10 +76,16 @@ public:
         EC_KEY_free(pkey);
     }
 
+    bool IsNull() const
+    {
+        return !fSet;
+    }
+
     void MakeNewKey()
     {
         if (!EC_KEY_generate_key(pkey))
             throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
+        fSet = true;
     }
 
     bool SetPrivKey(const CPrivKey& vchPrivKey)
@@ -83,6 +93,7 @@ public:
         const unsigned char* pbegin = &vchPrivKey[0];
         if (!d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
             return false;
+        fSet = true;
         return true;
     }
 
@@ -103,6 +114,7 @@ public:
         const unsigned char* pbegin = &vchPubKey[0];
         if (!o2i_ECPublicKey(&pkey, &pbegin, vchPubKey.size()))
             return false;
+        fSet = true;
         return true;
     }
 
main.cpp
@@ -34,7 +34,7 @@ map<uint256, CDataStream*> mapOrphanTransactions;
 multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
 
 map<uint256, CWalletTx> mapWallet;
-vector<pair<uint256, bool> > vWalletUpdated;
+vector<uint256> vWalletUpdated;
 CCriticalSection cs_mapWallet;
 
 map<vector<unsigned char>, CPrivKey> mapKeys;
@@ -46,9 +46,12 @@ string strSetDataDir;
 int nDropMessagesTest = 0;
 
 // Settings
-int fGenerateBitcoins;
+int fGenerateBitcoins = false;
 int64 nTransactionFee = 0;
 CAddress addrIncoming;
+int fLimitProcessors = false;
+int nLimitProcessors = 1;
+
 
 
 
@@ -135,7 +138,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
             return false;
 
         // Notify UI
-        vWalletUpdated.push_back(make_pair(hash, fInsertedNew));
+        vWalletUpdated.push_back(hash);
     }
 
     // Refresh UI
@@ -1126,6 +1129,9 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
             }
         }
 
+        // Notify UI to update prev block coinbase if it was ours
+        vWalletUpdated.push_back(hashBestChain);
+
         // New best link
         hashBestChain = hash;
         pindexBest = pindexNew;
@@ -1702,7 +1708,7 @@ bool ProcessMessages(CNode* pfrom)
         }
         CATCH_PRINT_EXCEPTION("ProcessMessage()")
         if (!fRet)
-            printf("ProcessMessage(%s, %d bytes) from %s to %s FAILED\n", strCommand.c_str(), nMessageSize, pfrom->addr.ToString().c_str(), addrLocalHost.ToString().c_str());
+            printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);
     }
 
     vRecv.Compact();
@@ -1715,10 +1721,7 @@ bool ProcessMessages(CNode* pfrom)
 bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 {
     static map<unsigned int, vector<unsigned char> > mapReuseKey;
-    printf("received: %-12s (%d bytes)  ", strCommand.c_str(), vRecv.size());
-    for (int i = 0; i < min(vRecv.size(), (unsigned int)20); i++)
-        printf("%02x ", vRecv[i] & 0xff);
-    printf("\n");
+    printf("received: %-12s (%d bytes)\n", strCommand.c_str(), vRecv.size());
     if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
     {
         printf("dropmessages DROPPING RECV MESSAGE\n");
@@ -1759,7 +1762,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
         }
 
-        printf("version message: %s has version %d, addrMe=%s\n", pfrom->addr.ToString().c_str(), pfrom->nVersion, addrMe.ToString().c_str());
+        printf("version message: version %d\n", pfrom->nVersion);
     }
 
 
@@ -1775,13 +1778,24 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vector<CAddress> vAddr;
         vRecv >> vAddr;
 
+        // Clear addrknown lists periodically to allow refresh broadcasts
+        static int64 nLastClearedAddrKnown;
+        if (nLastClearedAddrKnown < GetAdjustedTime() - 24 * 60 * 60)
+        {
+            nLastClearedAddrKnown = GetAdjustedTime();
+            CRITICAL_BLOCK(cs_vNodes)
+                foreach(CNode* pnode, vNodes)
+                    pnode->setAddrKnown.clear();
+        }
+
         // Store the new addresses
         CAddrDB addrdb;
         foreach(const CAddress& addr, vAddr)
         {
             if (fShutdown)
                 return true;
-            if (AddAddress(addrdb, addr))
+            AddAddress(addrdb, addr);
+            if (addr.IsRoutable() && addr.ip != addrLocalHost.ip)
             {
                 // Put on lists to send to other nodes
                 pfrom->setAddrKnown.insert(addr);
@@ -1989,8 +2003,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                 if (fShutdown)
                     return true;
                 const CAddress& addr = item.second;
-                //// will need this if we lose IRC
-                //if (addr.nTime > nSince || (rand() % nSize) < 500)
                 if (addr.nTime > nSince)
                     pfrom->vAddrToSend.push_back(addr);
             }
@@ -2132,9 +2144,11 @@ bool SendMessages(CNode* pto)
         while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
         {
             const CInv& inv = (*pto->mapAskFor.begin()).second;
-            printf("sending getdata: %s\n", inv.ToString().c_str());
             if (!AlreadyHave(txdb, inv))
+            {
+                printf("sending getdata: %s\n", inv.ToString().c_str());
                 vAskFor.push_back(inv);
+            }
             pto->mapAskFor.erase(pto->mapAskFor.begin());
         }
         if (!vAskFor.empty())
@@ -2162,6 +2176,49 @@ bool SendMessages(CNode* pto)
 // BitcoinMiner
 //
 
+void GenerateBitcoins(bool fGenerate)
+{
+    if (fGenerateBitcoins != fGenerate)
+    {
+        fGenerateBitcoins = fGenerate;
+        CWalletDB().WriteSetting("fGenerateBitcoins", fGenerateBitcoins);
+        MainFrameRepaint();
+    }
+    if (fGenerateBitcoins)
+    {
+        int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+        printf("%d processors\n", nProcessors);
+        if (nProcessors < 1)
+            nProcessors = 1;
+        if (fLimitProcessors && nProcessors > nLimitProcessors)
+            nProcessors = nLimitProcessors;
+        int nAddThreads = nProcessors - vnThreadsRunning[3];
+        printf("starting %d bitcoinminer threads\n", nAddThreads);
+        for (int i = 0; i < nAddThreads; i++)
+            if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
+                printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
+    }
+}
+
+void ThreadBitcoinMiner(void* parg)
+{
+    vnThreadsRunning[3]++;
+    CheckForShutdown(3);
+    try
+    {
+        bool fRet = BitcoinMiner();
+        printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
+        vnThreadsRunning[3]--;
+    }
+    catch (std::exception& e) {
+        vnThreadsRunning[3]--;
+        PrintException(&e, "ThreadBitcoinMiner()");
+    } catch (...) {
+        vnThreadsRunning[3]--;
+        PrintException(NULL, "ThreadBitcoinMiner()");
+    }
+}
+
 int FormatHashBlocks(void* pbuffer, unsigned int len)
 {
     unsigned char* pdata = (unsigned char*)pbuffer;
@@ -2210,13 +2267,13 @@ void BlockSHA256(const void* pin, unsigned int nBlocks, void* pout)
 bool BitcoinMiner()
 {
     printf("BitcoinMiner started\n");
-    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
 
     CKey key;
     key.MakeNewKey();
     CBigNum bnExtraNonce = 0;
     while (fGenerateBitcoins)
     {
+        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
         Sleep(50);
         CheckForShutdown(3);
         while (vNodes.empty())
@@ -2338,7 +2395,6 @@ bool BitcoinMiner()
             BlockSHA256(&tmp.block, nBlocks0, &tmp.hash1);
             BlockSHA256(&tmp.hash1, nBlocks1, &hash);
 
-
             if (hash <= hashTarget)
             {
                 pblock->nNonce = tmp.block.nNonce;
@@ -2352,6 +2408,12 @@ bool BitcoinMiner()
                 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
                 CRITICAL_BLOCK(cs_main)
                 {
+                    if (pindexPrev != pindexBest)
+                    {
+                        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
+                        break;
+                    }
+
                     // Save key
                     if (!AddKey(key))
                         return false;
@@ -2368,7 +2430,7 @@ bool BitcoinMiner()
             }
 
             // Update nTime every few seconds
-            if ((++tmp.block.nNonce & 0x3ffff) == 0)
+            if ((++tmp.block.nNonce & 0xffff) == 0)
             {
                 CheckForShutdown(3);
                 if (tmp.block.nNonce == 0)
@@ -2379,6 +2441,8 @@ bool BitcoinMiner()
                     break;
                 if (!fGenerateBitcoins)
                     break;
+                if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
+                    return true;
                 tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
             }
         }
@@ -2538,7 +2602,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
 
 
 
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, int64& nFeeRequiredRet)
+bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet)
 {
     nFeeRequiredRet = 0;
     CRITICAL_BLOCK(cs_main)
@@ -2565,30 +2629,28 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
                 foreach(CWalletTx* pcoin, setCoins)
                     nValueIn += pcoin->GetCredit();
 
-                // Fill vout[0] to the payee
-                wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
+                // Fill a vout to the payee
+                bool fChangeFirst = GetRand(2);
+                if (!fChangeFirst)
+                    wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
 
-                // Fill vout[1] back to self with any change
+                // Fill a vout back to self with any change
                 if (nValueIn > nValue)
                 {
-                    /// todo: for privacy, should randomize the order of outputs,
-                    //        would also have to use a new key for the change.
-                    // Use the same key as one of the coins
-                    vector<unsigned char> vchPubKey;
-                    CTransaction& txFirst = *(*setCoins.begin());
-                    foreach(const CTxOut& txout, txFirst.vout)
-                        if (txout.IsMine())
-                            if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
-                                break;
-                    if (vchPubKey.empty())
-                        return false;
+                    // New private key
+                    if (keyRet.IsNull())
+                        keyRet.MakeNewKey();
 
-                    // Fill vout[1] to ourself
+                    // Fill a vout to ourself
                     CScript scriptPubKey;
-                    scriptPubKey << vchPubKey << OP_CHECKSIG;
+                    scriptPubKey << keyRet.GetPubKey() << OP_CHECKSIG;
                     wtxNew.vout.push_back(CTxOut(nValueIn - nValue, scriptPubKey));
                 }
 
+                // Fill a vout to the payee
+                if (fChangeFirst)
+                    wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey));
+
                 // Fill vin
                 foreach(CWalletTx* pcoin, setCoins)
                     for (int nOut = 0; nOut < pcoin->vout.size(); nOut++)
@@ -2621,13 +2683,24 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, in
 }
 
 // Call after CreateTransaction unless you want to abort
-bool CommitTransactionSpent(const CWalletTx& wtxNew)
+bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
 {
     CRITICAL_BLOCK(cs_main)
     CRITICAL_BLOCK(cs_mapWallet)
     {
-        //// todo: make this transactional, never want to add a transaction
-        ////  without marking spent transactions
+        //// todo: eventually should make this transactional, never want to add a
+        ////  transaction without marking spent transactions, although the risk of
+        ////  interruption during this step is remote.
+
+        // This is only to keep the database open to defeat the auto-flush for the
+        // duration of this scope.  This is the only place where this optimization
+        // maybe makes sense; please don't do it anywhere else.  Keeping databases
+        // open longer than necessary can create deadlocks.
+        CWalletDB walletdb("r");
+
main.h
@@ -41,6 +41,9 @@ extern int nDropMessagesTest;
 extern int fGenerateBitcoins;
 extern int64 nTransactionFee;
 extern CAddress addrIncoming;
+extern int fLimitProcessors;
+extern int nLimitProcessors;
+
 
 
 
@@ -58,14 +61,17 @@ void ReacceptWalletTransactions();
 void RelayWalletTransactions();
 bool LoadBlockIndex(bool fAllowNew=true);
 void PrintBlockTree();
-bool BitcoinMiner();
 bool ProcessMessages(CNode* pfrom);
 bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
 bool SendMessages(CNode* pto);
 int64 GetBalance();
-bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& txNew, int64& nFeeRequiredRet);
-bool CommitTransactionSpent(const CWalletTx& wtxNew);
+bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
+bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key);
 bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
+void GenerateBitcoins(bool fGenerate);
+void ThreadBitcoinMiner(void* parg);
+bool BitcoinMiner();
+
 
 
 
@@ -1320,7 +1326,7 @@ public:
 
 extern map<uint256, CTransaction> mapTransactions;
 extern map<uint256, CWalletTx> mapWallet;
-extern vector<pair<uint256, bool> > vWalletUpdated;
+extern vector<uint256> vWalletUpdated;
 extern CCriticalSection cs_mapWallet;
 extern map<vector<unsigned char>, CPrivKey> mapKeys;
 extern map<uint160, vector<unsigned char> > mapPubKeys;
makefile
@@ -12,7 +12,7 @@ ifeq "$(BUILD)" "debug"
 D=d
 # note: gcc 3.x profile doesn't work
 #DEBUGFLAGS=-O0 -g -pg -D__WXDEBUG__
-DEBUGFLAGS=-g -D__WXDEBUG__ -Wall -Wextra
+DEBUGFLAGS=-g -D__WXDEBUG__
 endif
 
 
@@ -23,7 +23,7 @@ LIBS= \
  -l db_cxx \
  -l eay32 \
  -l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxmsw28$(D)_adv -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \
- -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32
+ -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
 WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
 CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
 HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
makefile.vc
@@ -18,8 +18,8 @@ LIBPATHS=/LIBPATH:"/DB/build_windows/$(BUILD)" /LIBPATH:"/OpenSSL/out" /LIBPATH:
 LIBS= \
     libdb47s$(D).lib \
     libeay32.lib \
-    wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
-    kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib
+    wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxmsw28$(D)_adv.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
+    kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
 WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
 CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
 HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
net.cpp
@@ -23,7 +23,8 @@ CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
 CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
 CNode* pnodeLocalHost = &nodeLocalHost;
 bool fShutdown = false;
-array<bool, 10> vfThreadRunning;
+array<int, 10> vnThreadsRunning;
+
 vector<CNode*> vNodes;
 CCriticalSection cs_vNodes;
 map<vector<unsigned char>, CAddress> mapAddresses;
@@ -57,7 +58,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
 
     if (fProxy)
     {
-        printf("Proxy connecting to %s\n", addrConnect.ToString().c_str());
+        printf("Proxy connecting %s\n", addrConnect.ToStringLog().c_str());
         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
@@ -81,7 +82,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
             closesocket(hSocket);
             return error("Proxy returned error %d\n", pchRet[1]);
         }
-        printf("Proxy connection established %s\n", addrConnect.ToString().c_str());
+        printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());
     }
 
     hSocketRet = hSocket;
@@ -219,6 +220,13 @@ bool AddAddress(CAddrDB& addrdb, const CAddress& addr)
                 addrdb.WriteAddress(addrFound);
                 return true;
             }
+            else if (addrFound.nTime < GetAdjustedTime() - 24 * 60 * 60)
+            {
+                // Periodically update most recently seen time
+                addrFound.nTime = GetAdjustedTime();
+                addrdb.WriteAddress(addrFound);
+                return false;
+            }
         }
     }
     return false;
@@ -373,14 +381,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
     }
 
     /// debug print
-    printf("trying %s\n", addrConnect.ToString().c_str());
+    printf("trying connection %s\n", addrConnect.ToStringLog().c_str());
 
     // Connect
     SOCKET hSocket;
     if (ConnectSocket(addrConnect, hSocket))
     {
         /// debug print
-        printf("connected %s\n", addrConnect.ToString().c_str());
+        printf("connected %s\n", addrConnect.ToStringLog().c_str());
 
         // Set to nonblocking
         u_long nOne = 1;
@@ -410,7 +418,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
 
 void CNode::Disconnect()
 {
-    printf("disconnecting node %s\n", addr.ToString().c_str());
+    printf("disconnecting node %s\n", addr.ToStringLog().c_str());
 
     closesocket(hSocket);
 
@@ -450,14 +458,20 @@ void ThreadSocketHandler(void* parg)
 
     loop
     {
-        vfThreadRunning[0] = true;
+        vnThreadsRunning[0] = true;
         CheckForShutdown(0);
         try
         {
             ThreadSocketHandler2(parg);
+            vnThreadsRunning[0] = false;
+        }
+        catch (std::exception& e) {
+            vnThreadsRunning[0] = false;
+            PrintException(&e, "ThreadSocketHandler()");
+        } catch (...) {
+            vnThreadsRunning[0] = false;
+            PrintException(NULL, "ThreadSocketHandler()");
         }
-        CATCH_PRINT_EXCEPTION("ThreadSocketHandler()")
-        vfThreadRunning[0] = false;
         Sleep(5000);
     }
 }
@@ -548,9 +562,9 @@ void ThreadSocketHandler2(void* parg)
             }
         }
 
-        vfThreadRunning[0] = false;
+        vnThreadsRunning[0] = false;
         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
-        vfThreadRunning[0] = true;
+        vnThreadsRunning[0] = true;
         CheckForShutdown(0);
         if (nSelect == SOCKET_ERROR)
         {
@@ -590,7 +604,7 @@ void ThreadSocketHandler2(void* parg)
             }
             else
             {
-                printf("accepted connection from %s\n", addr.ToString().c_str());
+                printf("accepted connection %s\n", addr.ToStringLog().c_str());
                 CNode* pnode = new CNode(hSocket, addr, true);
                 pnode->AddRef();
                 CRITICAL_BLOCK(cs_vNodes)
@@ -697,14 +711,20 @@ void ThreadOpenConnections(void* parg)
 
     loop
     {
-        vfThreadRunning[1] = true;
+        vnThreadsRunning[1] = true;
         CheckForShutdown(1);
         try
         {
             ThreadOpenConnections2(parg);
+            vnThreadsRunning[1] = false;
+        }
+        catch (std::exception& e) {
+            vnThreadsRunning[1] = false;
+            PrintException(&e, "ThreadOpenConnections()");
+        } catch (...) {
+            vnThreadsRunning[1] = false;
+            PrintException(NULL, "ThreadOpenConnections()");
         }
-        CATCH_PRINT_EXCEPTION("ThreadOpenConnections()")
-        vfThreadRunning[1] = false;
         Sleep(5000);
     }
 }
@@ -720,14 +740,14 @@ void ThreadOpenConnections2(void* parg)
     loop
     {
         // Wait
-        vfThreadRunning[1] = false;
+        vnThreadsRunning[1] = false;
         Sleep(500);
         while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
         {
             CheckForShutdown(1);
             Sleep(2000);
         }
-        vfThreadRunning[1] = true;
+        vnThreadsRunning[1] = true;
         CheckForShutdown(1);
 
 
@@ -823,9 +843,9 @@ void ThreadOpenConnections2(void* parg)
             if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
                 continue;
 
-            vfThreadRunning[1] = false;
+            vnThreadsRunning[1] = false;
             CNode* pnode = ConnectNode(addrConnect);
-            vfThreadRunning[1] = true;
+            vnThreadsRunning[1] = true;
             CheckForShutdown(1);
             if (!pnode)
                 continue;
@@ -867,14 +887,20 @@ void ThreadMessageHandler(void* parg)
 
     loop
     {
-        vfThreadRunning[2] = true;
+        vnThreadsRunning[2] = true;
         CheckForShutdown(2);
         try
         {
             ThreadMessageHandler2(parg);
+            vnThreadsRunning[2] = false;
+        }
+        catch (std::exception& e) {
+            vnThreadsRunning[2] = false;
+            PrintException(&e, "ThreadMessageHandler()");
+        } catch (...) {
+            vnThreadsRunning[2] = false;
+            PrintException(NULL, "ThreadMessageHandler()");
         }
-        CATCH_PRINT_EXCEPTION("ThreadMessageHandler()")
-        vfThreadRunning[2] = false;
         Sleep(5000);
     }
 }
@@ -905,9 +931,9 @@ void ThreadMessageHandler2(void* parg)
         }
 
         // Wait and allow messages to bunch up
-        vfThreadRunning[2] = false;
+        vnThreadsRunning[2] = false;
         Sleep(100);
-        vfThreadRunning[2] = true;
+        vnThreadsRunning[2] = true;
         CheckForShutdown(2);
     }
 }
@@ -920,29 +946,6 @@ void ThreadMessageHandler2(void* parg)
 
 
 
-//// todo: start one thread per processor, use getenv("NUMBER_OF_PROCESSORS")
-void ThreadBitcoinMiner(void* parg)
-{
-    vfThreadRunning[3] = true;
-    CheckForShutdown(3);
-    try
-    {
-        bool fRet = BitcoinMiner();
-        printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
-    }
-    CATCH_PRINT_EXCEPTION("BitcoinMiner()")
-    vfThreadRunning[3] = false;
-}
-
-
-
-
-
-
-
-
-
-
 
 bool StartNode(string& strError)
 {
@@ -1067,17 +1070,17 @@ bool StopNode()
     fShutdown = true;
     nTransactionsUpdated++;
     int64 nStart = GetTime();
-    while (vfThreadRunning[0] || vfThreadRunning[2] || vfThreadRunning[3])
+    while (vnThreadsRunning[0] || vnThreadsRunning[2] || vnThreadsRunning[3])
     {
         if (GetTime() - nStart > 15)
             break;
         Sleep(20);
     }
-    if (vfThreadRunning[0]) printf("ThreadSocketHandler still running\n");
-    if (vfThreadRunning[1]) printf("ThreadOpenConnections still running\n");
-    if (vfThreadRunning[2]) printf("ThreadMessageHandler still running\n");
-    if (vfThreadRunning[3]) printf("ThreadBitcoinMiner still running\n");
-    while (vfThreadRunning[2])
+    if (vnThreadsRunning[0]) printf("ThreadSocketHandler still running\n");
+    if (vnThreadsRunning[1]) printf("ThreadOpenConnections still running\n");
+    if (vnThreadsRunning[2]) printf("ThreadMessageHandler still running\n");
+    if (vnThreadsRunning[3]) printf("ThreadBitcoinMiner still running\n");
+    while (vnThreadsRunning[2])
         Sleep(20);
     Sleep(50);
 
@@ -1091,7 +1094,7 @@ void CheckForShutdown(int n)
     if (fShutdown)
     {
         if (n != -1)
-            vfThreadRunning[n] = false;
+            vnThreadsRunning[n] = false;
         if (n == 0)
             foreach(CNode* pnode, vNodes)
                 closesocket(pnode->hSocket);
net.h
@@ -20,8 +20,6 @@ enum
 
 
 
-
-
 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
 bool GetMyExternalIP(unsigned int& ipRet);
 bool AddAddress(CAddrDB& addrdb, const CAddress& addr);
@@ -29,7 +27,6 @@ CNode* FindNode(unsigned int ip);
 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
 bool AnySubscribed(unsigned int nChannel);
-void ThreadBitcoinMiner(void* parg);
 bool StartNode(string& strError=REF(string()));
 bool StopNode();
 void CheckForShutdown(int n);
@@ -206,7 +203,7 @@ public:
             READWRITE(nTime);
         }
         READWRITE(nServices);
-        READWRITE(FLATDATA(pchReserved));
+        READWRITE(FLATDATA(pchReserved)); // for IPv6
         READWRITE(ip);
         READWRITE(port);
     )
@@ -280,10 +277,14 @@ public:
         return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
     }
 
+    string ToStringLog() const
+    {
+        return "";
+    }
+
     string ToString() const
     {
         return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
-        //return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
     }
 
     void print() const
@@ -416,7 +417,7 @@ extern uint64 nLocalServices;
 extern CAddress addrLocalHost;
 extern CNode* pnodeLocalHost;
 extern bool fShutdown;
-extern array<bool, 10> vfThreadRunning;
+extern array<int, 10> vnThreadsRunning;
 extern vector<CNode*> vNodes;
 extern CCriticalSection cs_vNodes;
 extern map<vector<unsigned char>, CAddress> mapAddresses;
@@ -599,9 +600,7 @@ public:
         unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
         memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
 
-        printf("(%d bytes)  ", nSize);
-        //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++)
-        //    printf("%02x ", vSend[i] & 0xff);
+        printf("(%d bytes) ", nSize);
         printf("\n");
 
         nPushPos = -1;
readme.txt
serialize.h
@@ -19,7 +19,7 @@ class CScript;
 class CDataStream;
 class CAutoFile;
 
-static const int VERSION = 105;
+static const int VERSION = 106;
 
 
 
ui.cpp
@@ -7,6 +7,13 @@
 #include <crtdbg.h>
 #endif
 
+void ThreadRequestProductDetails(void* parg);
+void ThreadRandSendTest(void* parg);
+bool GetStartOnSystemStartup();
+void SetStartOnSystemStartup(bool fAutoStart);
+
+
+
 DEFINE_EVENT_TYPE(wxEVT_CROSSTHREADCALL)
 DEFINE_EVENT_TYPE(wxEVT_REPLY1)
 DEFINE_EVENT_TYPE(wxEVT_REPLY2)
@@ -16,22 +23,21 @@ DEFINE_EVENT_TYPE(wxEVT_TABLEUPDATED)
 DEFINE_EVENT_TYPE(wxEVT_TABLEDELETED)
 
 CMainFrame* pframeMain = NULL;
+CMyTaskBarIcon* ptaskbaricon = NULL;
 map<string, string> mapAddressBook;
-CBitcoinTBIcon* taskBarIcon = NULL; // Tray icon
-
-
-void ThreadRequestProductDetails(void* parg);
-void ThreadRandSendTest(void* parg);
+map<string, string> mapArgs;
 bool fRandSendTest = false;
 void RandSend();
 extern int g_isPainting;
 
-// UI settings and their default values
-int minimizeToTray = 1;
-int closeToTray = 1;
-int startOnSysBoot = 1;
-int askBeforeClosing = 1;
-int alwaysShowTrayIcon = 1;
+// Settings
+int fShowGenerated = true;
+int fMinimizeToTray = true;
+int fMinimizeOnClose = true;
+
+
+
+
 
 
 
@@ -282,7 +288,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + "  ");
     m_listCtrl->SetFocus();
     SetIcon(wxICON(bitcoin));
-    m_menuOptions->Check(wxID_OPTIONSGENERATEBITCOINS, fGenerateBitcoins);
+    ptaskbaricon = new CMyTaskBarIcon();
 
     // Init toolbar with transparency masked bitmaps
     m_toolBar->ClearTools();
@@ -327,7 +333,7 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
     //m_listCtrlOrdersReceived->InsertColumn(4, "",                wxLIST_FORMAT_LEFT,  100);
 
     // Init status bar
-    int pnWidths[3] = { -100, 81, 286 };
+    int pnWidths[3] = { -100, 88, 290 };
     m_statusBar->SetFieldsCount(3, pnWidths);
 
     // Fill your address text box
@@ -342,6 +348,8 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent)
 CMainFrame::~CMainFrame()
 {
     pframeMain = NULL;
+    delete ptaskbaricon;
+    ptaskbaricon = NULL;
 }
 
 void Shutdown(void* parg)
@@ -362,28 +370,24 @@ void Shutdown(void* parg)
 
 void CMainFrame::OnClose(wxCloseEvent& event)
 {
-	if (closeToTray && event.CanVeto()) {
-		event.Veto();
-		SendToTray();
-	}
-	else if (!event.CanVeto() || !askBeforeClosing || wxMessageBox("Quit program?", "Confirm", wxYES_NO, this) == wxYES) {
-		delete taskBarIcon;
-	    Destroy();
-	    _beginthread(Shutdown, 0, NULL);
-	}
+    if (fMinimizeToTray && fMinimizeOnClose && event.CanVeto() && !IsIconized())
+    {
+        // Divert close to minimize
+        event.Veto();
+        Iconize(true);
+    }
+    else
+    {
+        Destroy();
+        _beginthread(Shutdown, 0, NULL);
+    }
 }
 
 void CMainFrame::OnIconize(wxIconizeEvent& event)
 {
-	if (minimizeToTray) {
-		SendToTray();
-	}
-}
-
-void CMainFrame::SendToTray()
-{
-	Hide();
-	taskBarIcon->Show();
+    // Hide the task bar button when minimized.
+    // Event is sent when the frame is minimized or restored.
+    Show(!fMinimizeToTray || !event.Iconized());
 }
 
 void CMainFrame::OnMouseEvents(wxMouseEvent& event)
@@ -405,25 +409,21 @@ void CMainFrame::InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSo
     string str0 = strSort;
     long nData = *(long*)&hashKey;
 
-    if (fNew)
+    // Find item
+    if (!fNew && nIndex == -1)
+    {
+        while ((nIndex = m_listCtrl->FindItem(nIndex, nData)) != -1)
+            if (GetItemText(m_listCtrl, nIndex, 1) == hashKey.ToString())
+                break;
+    }
+
+    // fNew is for blind insert, only use if you're sure it's new
+    if (fNew || nIndex == -1)
     {
         nIndex = m_listCtrl->InsertItem(0, str0);
     }
     else
     {
-        if (nIndex == -1)
-        {
-            // Find item
-            while ((nIndex = m_listCtrl->FindItem(nIndex, nData)) != -1)
-                if (GetItemText(m_listCtrl, nIndex, 1) == hashKey.ToString())
-                    break;
-            if (nIndex == -1)
-            {
-                printf("CMainFrame::InsertLine : Couldn't find item to be updated\n");
-                return;
-            }
-        }
-
         // If sort key changed, must delete and reinsert to make it relocate
         if (GetItemText(m_listCtrl, nIndex, 0) != str0)
         {
@@ -484,6 +484,28 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
     string strStatus = FormatTxStatus(wtx);
     map<string, string> mapValue = wtx.mapValue;
 
+    // Filter
+    if (wtx.IsCoinBase())
+    {
+        // View->Show Generated
+        if (!fShowGenerated)
+            return;
+
+        // Don't show generated coin until confirmed by at least one block after it
+        // so we don't get the user's hopes up until it looks like it's probably accepted.
+        //
+        // It is not an error when generated blocks are not accepted.  By design,
+        // some percentage of blocks, like 10% or more, will end up not accepted.
+        // This is the normal mechanism by which the network copes with latency.
+        //
+        // We display regular transactions right away before any confirmation
+        // because they can always get into some block eventually.  Generated coins
+        // are special because if their block is not accepted, they are not valid.
+        //
+        if (wtx.GetDepthInMainChain() < 2)
+            return;
+    }
+
     // Find the block the tx is in
     CBlockIndex* pindex = NULL;
     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
@@ -785,16 +807,11 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     {
         TRY_CRITICAL_BLOCK(cs_mapWallet)
         {
-            pair<uint256, bool> item;
-            foreach(item, vWalletUpdated)
+            foreach(uint256 hash, vWalletUpdated)
             {
-                bool fNew = item.second;
-                map<uint256, CWalletTx>::iterator mi = mapWallet.find(item.first);
+                map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
                 if (mi != mapWallet.end())
-                {
-                    printf("vWalletUpdated: %s %s\n", (*mi).second.GetHash().ToString().substr(0,6).c_str(), fNew ? "new" : "");
-                    InsertTransaction((*mi).second, fNew);
-                }
+                    InsertTransaction((*mi).second, false);
             }
             m_listCtrl->ScrollList(0, INT_MAX);
             vWalletUpdated.clear();
@@ -807,7 +824,7 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     // Update status bar
     string strGen = "";
     if (fGenerateBitcoins)
-        strGen = "    Generating";
+        strGen = "     Generating";
     if (fGenerateBitcoins && vNodes.empty())
         strGen = "(not connected)";
     m_statusBar->SetStatusText(strGen, 1);
@@ -856,39 +873,54 @@ void CMainFrame::OnCrossThreadCall(wxCommandEvent& event)
 
 void CMainFrame::OnMenuFileExit(wxCommandEvent& event)
 {
+    // File->Exit
     Close(true);
 }
 
+void CMainFrame::OnMenuViewShowGenerated(wxCommandEvent& event)
+{
+    // View->Show Generated
+    fShowGenerated = event.IsChecked();
+    CWalletDB().WriteSetting("fShowGenerated", fShowGenerated);
+    RefreshListCtrl();
+}
+
+void CMainFrame::OnUpdateUIViewShowGenerated(wxUpdateUIEvent& event)
+{
+    event.Check(fShowGenerated);
+}
+
 void CMainFrame::OnMenuOptionsGenerate(wxCommandEvent& event)
 {
+    // Options->Generate Coins
     GenerateBitcoins(event.IsChecked());
+}
 
-    Refresh();
-    wxPaintEvent eventPaint;
-    AddPendingEvent(eventPaint);
+void CMainFrame::OnUpdateUIOptionsGenerate(wxUpdateUIEvent& event)
+{
+    event.Check(fGenerateBitcoins);
 }
 
 void CMainFrame::OnMenuOptionsChangeYourAddress(wxCommandEvent& event)
 {
+    // Options->Change Your Address
     OnButtonChange(event);
 }
 
 void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event)
 {
+    // Options->Options
     COptionsDialog dialog(this);
     dialog.ShowModal();
 }
 
 void CMainFrame::OnMenuHelpAbout(wxCommandEvent& event)
 {
+    // Help->About
     CAboutDialog dialog(this);
     dialog.ShowModal();
 }
 
-void CMainFrame::OnUpdateMenuGenerate( wxUpdateUIEvent& event ) {
-	event.Check(fGenerateBitcoins);
-}
-
 void CMainFrame::OnButtonSend(wxCommandEvent& event)
 {
     /// debug test
@@ -1252,58 +1284,74 @@ void CTxDetailsDialog::OnButtonOK(wxCommandEvent& event)
 
 COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
 {
+    // Set up list box of page choices
+    m_listBox->Append("Main");
+    //m_listBox->Append("Test 2");
+    m_listBox->SetSelection(0);
+    SelectPage(0);
+
+    // Init values
+    m_textCtrlTransactionFee->SetValue(FormatMoney(nTransactionFee));
+    m_checkBoxLimitProcessors->SetValue(fLimitProcessors);
+    m_spinCtrlLimitProcessors->Enable(fLimitProcessors);
+    m_spinCtrlLimitProcessors->SetValue(nLimitProcessors);
+    int nProcessors = atoi(getenv("NUMBER_OF_PROCESSORS"));
+    if (nProcessors < 1)
+        nProcessors = 999;
+    m_spinCtrlLimitProcessors->SetRange(1, nProcessors);
+    m_checkBoxStartOnSystemStartup->SetValue(fTmpStartOnSystemStartup = GetStartOnSystemStartup());
+    m_checkBoxMinimizeToTray->SetValue(fMinimizeToTray);
+    m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);
+    m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);
+    fTmpMinimizeOnClose = fMinimizeOnClose;
     m_buttonOK->SetFocus();
-    m_treeCtrl->AddRoot(wxT("Settings"));
-    m_treeCtrl->AppendItem(m_treeCtrl->GetRootItem(), wxT("Bitcoin"));
ui.h
@@ -21,21 +21,25 @@ enum
 
 
 
+
+extern map<string, string> mapArgs;
+
+// Settings
+extern int fShowGenerated;
+extern int fMinimizeToTray;
+extern int fMinimizeOnClose;
+
+
+
 extern void HandleCtrlA(wxKeyEvent& event);
 extern string DateTimeStr(int64 nTime);
 extern string FormatTxStatus(const CWalletTx& wtx);
 extern void CrossThreadCall(int nID, void* pdata);
 extern void MainFrameRepaint();
 extern void Shutdown(void* parg);
-void ApplyUISettings();
-void GenerateBitcoins(bool flag);
 
-// UI settings
-extern int minimizeToTray;
-extern int closeToTray;
-extern int startOnSysBoot;
-extern int askBeforeClosing;
-extern int alwaysShowTrayIcon;
+
+
 
 
 
@@ -44,14 +48,17 @@ class CMainFrame : public CMainFrameBase
 protected:
     // Event handlers
     void OnClose(wxCloseEvent& event);
-    void OnIconize( wxIconizeEvent& event );
+    void OnIconize(wxIconizeEvent& event);
     void OnMouseEvents(wxMouseEvent& event);
     void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
     void OnIdle(wxIdleEvent& event);
     void OnPaint(wxPaintEvent& event);
     void OnPaintListCtrl(wxPaintEvent& event);
     void OnMenuFileExit(wxCommandEvent& event);
+    void OnMenuViewShowGenerated(wxCommandEvent& event);
+    void OnUpdateUIViewShowGenerated(wxUpdateUIEvent& event);
     void OnMenuOptionsGenerate(wxCommandEvent& event);
+    void OnUpdateUIOptionsGenerate(wxUpdateUIEvent& event);
     void OnMenuOptionsChangeYourAddress(wxCommandEvent& event);
     void OnMenuOptionsOptions(wxCommandEvent& event);
     void OnMenuHelpAbout(wxCommandEvent& event);
@@ -66,7 +73,6 @@ protected:
     void OnListItemActivatedProductsSent(wxListEvent& event);
     void OnListItemActivatedOrdersSent(wxListEvent& event);
     void OnListItemActivatedOrdersReceived(wxListEvent& event);
-    void OnUpdateMenuGenerate( wxUpdateUIEvent& event );
 	
 public:
     /** Constructor */
@@ -85,7 +91,6 @@ public:
     void InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
     void RefreshListCtrl();
     void RefreshStatus();
-    void SendToTray();
 };
 
 
@@ -107,47 +112,26 @@ public:
 
 
 
-class COptionsPanelBitcoin : public COptionsPanelBitcoinBase
-{
-protected:
-    // Event handlers
-	void OnKillFocusTransactionFee( wxFocusEvent& event );
-
-public:
-    /** Constructor */
-    COptionsPanelBitcoin(wxWindow* parent);
-};
-
-
-
-class COptionsPanelUI : public COptionsPanelUIBase
-{
-protected:
-    // Event handlers
-	void OnOptionsChanged( wxCommandEvent& event );
-
-public:
-    /** Constructor */
-    COptionsPanelUI(wxWindow* parent);
-};
-
-
-
 class COptionsDialog : public COptionsDialogBase
 {
 protected:
     // Event handlers
-	void MenuSelChanged( wxTreeEvent& event );
+    void OnListBox(wxCommandEvent& event);
+    void OnKillFocusTransactionFee(wxFocusEvent& event);
+    void OnCheckBoxLimitProcessors(wxCommandEvent& event);
+    void OnCheckBoxMinimizeToTray(wxCommandEvent& event);
     void OnButtonOK(wxCommandEvent& event);
     void OnButtonCancel(wxCommandEvent& event);
+    void OnButtonApply(wxCommandEvent& event);
 
-    // Panels
-    COptionsPanelBitcoin* panelBitcoin;
-    COptionsPanelUI* panelUI;
-    wxPanel* currentPanel;
 public:
     /** Constructor */
     COptionsDialog(wxWindow* parent);
+
+    // Custom
+    bool fTmpStartOnSystemStartup;
+    bool fTmpMinimizeOnClose;
+    void SelectPage(int nPage);
 };
 
 
@@ -180,6 +164,11 @@ protected:
 public:
     /** Constructor */
     CSendDialog(wxWindow* parent, const wxString& strAddress="");
+
+    // Custom
+    bool fEnabledPrev;
+    string strFromSave;
+    string strMessageSave;
 };
 
 
@@ -455,22 +444,33 @@ public:
 
 
 
-class CBitcoinTBIcon : public wxTaskBarIcon
+class CMyTaskBarIcon : public wxTaskBarIcon
 {
 protected:
-	void Restore();
-
-	// Event handlers
-	void OnLeftButtonDClick(wxTaskBarIconEvent&);
-	void OnMenuExit(wxCommandEvent&);
-	void OnMenuGenerate(wxCommandEvent&);
-	void OnMenuRestore(wxCommandEvent&);
+    // Event handlers
+    void OnLeftButtonDClick(wxTaskBarIconEvent& event);
+    void OnMenuRestore(wxCommandEvent& event);
+    void OnUpdateUIGenerate(wxUpdateUIEvent& event);
+    void OnMenuGenerate(wxCommandEvent& event);
+    void OnMenuExit(wxCommandEvent& event);
 
 public:
-	void Show();
-	void Hide();
uibase.cpp
uibase.h
uiproject.fbp
util.cpp