Gavin's TEST network as -testnet switch, misc fixes
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Tue, 19 Oct 2010 17:16:51 +0000 (17:16 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Tue, 19 Oct 2010 17:16:51 +0000 (17:16 +0000)
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@168 1a98c847-1fd6-4fd8-948a-caf3550aa51b

14 files changed:
base58.h
db.cpp
db.h
init.cpp
irc.cpp
main.cpp
main.h
net.cpp
net.h
script.cpp
serialize.h
ui.cpp
util.cpp
util.h

index 4163f29..828f8d5 100644 (file)
--- a/base58.h
+++ b/base58.h
@@ -152,7 +152,7 @@ inline bool DecodeBase58Check(const string& str, vector<unsigned char>& vchRet)
 
 
 
-static const unsigned char ADDRESSVERSION = 0;
+#define ADDRESSVERSION   ((unsigned char)(fTestNet ? 111 : 0))
 
 inline string Hash160ToAddress(uint160 hash160)
 {
diff --git a/db.cpp b/db.cpp
index 336d5a5..e606e5d 100644 (file)
--- a/db.cpp
+++ b/db.cpp
@@ -846,10 +846,13 @@ void BackupWallet(const string& strDest)
     }
 }
 
+
 void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 {
     nIndex = -1;
     keypool.vchPubKey.clear();
+    CRITICAL_BLOCK(cs_main)
+    CRITICAL_BLOCK(cs_mapWallet)
     CRITICAL_BLOCK(cs_setKeyPool)
     {
         // Top up key pool
@@ -881,7 +884,11 @@ void CWalletDB::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
 void CWalletDB::KeepKey(int64 nIndex)
 {
     // Remove from key pool
-    Erase(make_pair(string("pool"), nIndex));
+    CRITICAL_BLOCK(cs_main)
+    CRITICAL_BLOCK(cs_mapWallet)
+    {
+        Erase(make_pair(string("pool"), nIndex));
+    }
     printf("keypool keep %"PRI64d"\n", nIndex);
 }
 
diff --git a/db.h b/db.h
index dac277a..385b898 100644 (file)
--- a/db.h
+++ b/db.h
@@ -455,7 +455,8 @@ public:
 
     ~CReserveKey()
     {
-        ReturnKey();
+        if (!fShutdown)
+            ReturnKey();
     }
 
     vector<unsigned char> GetReservedKey()
index 63ebfb0..98410d1 100644 (file)
--- a/init.cpp
+++ b/init.cpp
@@ -165,22 +165,22 @@ bool AppInit2(int argc, char* argv[])
             "  bitcoin [options] help              \t\t  " + _("List commands\n") +
             "  bitcoin [options] help <command>    \t\t  " + _("Get help for a command\n") +
           _("Options:\n") +
-            "  -conf=<file>     \t  " + _("Specify configuration file (default: bitcoin.conf)\n") +
-            "  -gen             \t  " + _("Generate coins\n") +
-            "  -gen=0           \t  " + _("Don't generate coins\n") +
-            "  -min             \t  " + _("Start minimized\n") +
-            "  -datadir=<dir>   \t  " + _("Specify data directory\n") +
-            "  -proxy=<ip:port> \t  " + _("Connect through socks4 proxy\n") +
-            "  -addnode=<ip>    \t  " + _("Add a node to connect to\n") +
-            "  -connect=<ip>    \t  " + _("Connect only to the specified node\n") +
-            "  -server          \t  " + _("Accept command line and JSON-RPC commands\n") +
-            "  -daemon          \t  " + _("Run in the background as a daemon and accept commands\n") +
-            "  -rpcuser=<user>  \t  " + _("Username for JSON-RPC connections\n") +
-            "  -rpcpassword=<pw>\t  " + _("Password for JSON-RPC connections\n") +
-            "  -rpcport=<port>  \t  " + _("Listen for JSON-RPC connections on <port>\n") +
-            "  -rpcallowip=<ip> \t  " + _("Allow JSON-RPC connections from specified IP address\n") +
-            "  -rpcconnect=<ip> \t  " + _("Send commands to node running on <ip>\n") +
-            "  -?               \t  " + _("This help message\n");
+            "  -conf=<file>     \t\t  " + _("Specify configuration file (default: bitcoin.conf)\n") +
+            "  -gen             \t\t  " + _("Generate coins\n") +
+            "  -gen=0           \t\t  " + _("Don't generate coins\n") +
+            "  -min             \t\t  " + _("Start minimized\n") +
+            "  -datadir=<dir>   \t\t  " + _("Specify data directory\n") +
+            "  -proxy=<ip:port> \t  "   + _("Connect through socks4 proxy\n") +
+            "  -addnode=<ip>    \t  "   + _("Add a node to connect to\n") +
+            "  -connect=<ip>    \t\t  " + _("Connect only to the specified node\n") +
+            "  -server          \t\t  " + _("Accept command line and JSON-RPC commands\n") +
+            "  -daemon          \t\t  " + _("Run in the background as a daemon and accept commands\n") +
+            "  -testnet         \t\t  " + _("Use the test network\n") +
+            "  -rpcuser=<user>  \t  "   + _("Username for JSON-RPC connections\n") +
+            "  -rpcpassword=<pw>\t  "   + _("Password for JSON-RPC connections\n") +
+            "  -rpcport=<port>  \t\t  " + _("Listen for JSON-RPC connections on <port>\n") +
+            "  -rpcallowip=<ip> \t\t  " + _("Allow JSON-RPC connections from specified IP address\n") +
+            "  -rpcconnect=<ip> \t  "   + _("Send commands to node running on <ip>\n");
 
 #ifdef USE_SSL
         strUsage += string() +
@@ -191,6 +191,9 @@ bool AppInit2(int argc, char* argv[])
             "  -rpcsslciphers=<ciphers>              \t  " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
 #endif
 
+        strUsage += string() +
+            "  -?               \t\t  " + _("This help message\n");
+
 #if defined(__WXMSW__) && defined(GUI)
         // Tabs make the columns line up in the message box
         wxMessageBox(strUsage, "Bitcoin", wxOK);
@@ -208,6 +211,9 @@ bool AppInit2(int argc, char* argv[])
     if (mapArgs.count("-printtodebugger"))
         fPrintToDebugger = true;
 
+    if (mapArgs.count("-testnet"))
+        fTestNet = true;
+
     if (fCommandLine)
     {
         int ret = CommandLineRPC(argc, argv);
diff --git a/irc.cpp b/irc.cpp
index 0675d18..4c839c4 100644 (file)
--- a/irc.cpp
+++ b/irc.cpp
@@ -252,8 +252,8 @@ void ThreadIRCSeed2(void* parg)
         }
         Sleep(500);
 
-        Send(hSocket, "JOIN #bitcoin\r");
-        Send(hSocket, "WHO #bitcoin\r");
+        Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r");
+        Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r"  : "WHO #bitcoin\r");
 
         int64 nStart = GetTime();
         string strLine;
index 569ea53..2d950ee 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -21,7 +21,8 @@ unsigned int nTransactionsUpdated = 0;
 map<COutPoint, CInPoint> mapNextTx;
 
 map<uint256, CBlockIndex*> mapBlockIndex;
-const uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
+uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
+CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
 CBlockIndex* pindexGenesisBlock = NULL;
 int nBestHeight = -1;
 CBigNum bnBestChainWork = 0;
@@ -1487,12 +1488,13 @@ bool CBlock::AcceptBlock()
             return error("AcceptBlock() : contains a non-final transaction");
 
     // Check that the block chain matches the known block chain up to a checkpoint
-    if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
-        (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
-        (nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
-        (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
-        (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
-        return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
+    if (!fTestNet)
+        if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
+            (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
+            (nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
+            (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
+            (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
+            return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
 
     // Write block to history file
     if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
@@ -1683,6 +1685,16 @@ FILE* AppendBlockFile(unsigned int& nFileRet)
 
 bool LoadBlockIndex(bool fAllowNew)
 {
+    if (fTestNet)
+    {
+        hashGenesisBlock = uint256("0x0000000224b1593e3ff16a0e3b61285bbc393a39f78c8aa48c456142671f7110");
+        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 28);
+        pchMessageStart[0] = 0xfa;
+        pchMessageStart[1] = 0xbf;
+        pchMessageStart[2] = 0xb5;
+        pchMessageStart[3] = 0xda;
+    }
+
     //
     // Load block index
     //
@@ -1723,13 +1735,19 @@ bool LoadBlockIndex(bool fAllowNew)
         block.nBits    = 0x1d00ffff;
         block.nNonce   = 2083236893;
 
-            //// debug print
-            printf("%s\n", block.GetHash().ToString().c_str());
-            printf("%s\n", hashGenesisBlock.ToString().c_str());
-            printf("%s\n", block.hashMerkleRoot.ToString().c_str());
-            assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
-            block.print();
+        if (fTestNet)
+        {
+            block.nTime    = 1279232055;
+            block.nBits    = 0x1d07fff8;
+            block.nNonce   = 81622180;
+        }
 
+        //// debug print
+        printf("%s\n", block.GetHash().ToString().c_str());
+        printf("%s\n", hashGenesisBlock.ToString().c_str());
+        printf("%s\n", block.hashMerkleRoot.ToString().c_str());
+        assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
+        block.print();
         assert(block.GetHash() == hashGenesisBlock);
 
         // Start new block file
@@ -1963,7 +1981,10 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
 
 
 
-
+// The message start string is designed to be unlikely to occur in normal data.
+// The characters are rarely used upper ascii, not valid as UTF-8, and produce
+// a large 4-byte int at any alignment.
+char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
 
 
 bool ProcessMessages(CNode* pfrom)
@@ -2022,19 +2043,14 @@ bool ProcessMessages(CNode* pfrom)
         if (nMessageSize > vRecv.size())
         {
             // Rewind and wait for rest of message
-            ///// need a mechanism to give up waiting for overlong message size error
             vRecv.insert(vRecv.begin(), vHeaderSave.begin(), vHeaderSave.end());
             break;
         }
 
-        // Copy message to its own buffer
-        CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
-        vRecv.ignore(nMessageSize);
-
         // Checksum
         if (vRecv.GetVersion() >= 209)
         {
-            uint256 hash = Hash(vMsg.begin(), vMsg.end());
+            uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
             unsigned int nChecksum = 0;
             memcpy(&nChecksum, &hash, sizeof(nChecksum));
             if (nChecksum != hdr.nChecksum)
@@ -2045,6 +2061,10 @@ bool ProcessMessages(CNode* pfrom)
             }
         }
 
+        // Copy message to its own buffer
+        CDataStream vMsg(vRecv.begin(), vRecv.begin() + nMessageSize, vRecv.nType, vRecv.nVersion);
+        vRecv.ignore(nMessageSize);
+
         // Process message
         bool fRet = false;
         try
@@ -2208,20 +2228,27 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                 addr.nTime -= 5 * 24 * 60 * 60;
             AddAddress(addr);
             pfrom->AddAddressKnown(addr);
-            if (!pfrom->fGetAddr && addr.IsRoutable())
+            if (!pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
             {
                 // Relay to a limited number of other nodes
                 CRITICAL_BLOCK(cs_vNodes)
                 {
-                    // Use deterministic randomness to send to
-                    // the same places for 12 hours at a time
+                    // Use deterministic randomness to send to the same nodes for 24 hours
+                    // at a time so the setAddrKnowns of the chosen nodes prevent repeats
                     static uint256 hashSalt;
                     if (hashSalt == 0)
                         RAND_bytes((unsigned char*)&hashSalt, sizeof(hashSalt));
-                    uint256 hashRand = addr.ip ^ ((GetTime()+addr.ip)/(12*60*60)) ^ hashSalt;
+                    uint256 hashRand = hashSalt ^ (((int64)addr.ip)<<32) ^ ((GetTime()+addr.ip)/(24*60*60));
+                    hashRand = Hash(BEGIN(hashRand), END(hashRand));
                     multimap<uint256, CNode*> mapMix;
                     foreach(CNode* pnode, vNodes)
-                        mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode));
+                    {
+                        unsigned int nPointer;
+                        memcpy(&nPointer, &pnode, sizeof(nPointer));
+                        uint256 hashKey = hashRand ^ nPointer;
+                        hashKey = Hash(BEGIN(hashKey), END(hashKey));
+                        mapMix.insert(make_pair(hashKey, pnode));
+                    }
                     int nRelayNodes = 2;
                     for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
                         ((*mi).second)->PushAddress(addr);
@@ -2446,7 +2473,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
             {
                 const CAddress& addr = item.second;
-                if (addr.nTime > nSince && GetRand(nCount) < 2000)
+                if (addr.nTime > nSince && GetRand(nCount) < 2500)
                     pfrom->PushAddress(addr);
             }
         }
@@ -2931,10 +2958,12 @@ void BitcoinMiner()
         f4WaySSE2 = (mapArgs["-4way"] != "0");
 
     CReserveKey reservekey;
-    CBigNum bnExtraNonce = 0;
+    unsigned int nExtraNonce = 0;
+    int64 nPrevTime = 0;
     while (fGenerateBitcoins)
     {
-        Sleep(50);
+        if (AffinityBugWorkaround(ThreadBitcoinMiner))
+            return;
         if (fShutdown)
             return;
         while (vNodes.empty() || IsInitialBlockDownload())
@@ -2957,7 +2986,13 @@ void BitcoinMiner()
         CTransaction txNew;
         txNew.vin.resize(1);
         txNew.vin[0].prevout.SetNull();
-        txNew.vin[0].scriptSig << ++bnExtraNonce;
+        int64 nNow = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+        if (nNow > nPrevTime+1 && ++nExtraNonce >= 0x7f)
+        {
+            nExtraNonce = 1;
+            nPrevTime = nNow;
+        }
+        txNew.vin[0].scriptSig << nBits << CBigNum(nExtraNonce);
         txNew.vout.resize(1);
         txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
 
@@ -3045,9 +3080,9 @@ void BitcoinMiner()
         tmpworkspace& tmp = *(tmpworkspace*)alignup<16>(tmpbuf);
 
         tmp.block.nVersion       = pblock->nVersion;
-        tmp.block.hashPrevBlock  = pblock->hashPrevBlock  = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
+        tmp.block.hashPrevBlock  = pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
         tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
-        tmp.block.nTime          = pblock->nTime          = max((pindexPrev ? pindexPrev->GetMedianTimePast()+1 : 0), GetAdjustedTime());
+        tmp.block.nTime          = pblock->nTime          = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
         tmp.block.nBits          = pblock->nBits          = nBits;
         tmp.block.nNonce         = pblock->nNonce         = 0;
 
@@ -3177,10 +3212,7 @@ void BitcoinMiner()
                 break;
 
             // Update nTime every few seconds
-            int64 nNewTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
-            if (nNewTime != pblock->nTime && bnExtraNonce > 10)
-                bnExtraNonce = 0;
-            pblock->nTime = nNewTime;
+            pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
             tmp.block.nTime = ByteReverse(pblock->nTime);
         }
     }
diff --git a/main.h b/main.h
index d4293b1..af552a5 100644 (file)
--- a/main.h
+++ b/main.h
@@ -22,7 +22,6 @@ static const int64 CENT = 1000000;
 static const int64 MAX_MONEY = 21000000 * COIN;
 inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
 static const int COINBASE_MATURITY = 100;
-static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
 
 
 
@@ -31,7 +30,8 @@ static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
 
 extern CCriticalSection cs_main;
 extern map<uint256, CBlockIndex*> mapBlockIndex;
-extern const uint256 hashGenesisBlock;
+extern uint256 hashGenesisBlock;
+extern CBigNum bnProofOfWorkLimit;
 extern CBlockIndex* pindexGenesisBlock;
 extern int nBestHeight;
 extern CBigNum bnBestChainWork;
diff --git a/net.cpp b/net.cpp
index 82b3ffb..82def0b 100644 (file)
--- a/net.cpp
+++ b/net.cpp
@@ -937,7 +937,7 @@ void ThreadOpenConnections2(void* parg)
             // Add seed nodes if IRC isn't working
             static bool fSeedUsed;
             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
-            if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR))
+            if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
             {
                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
                 {
diff --git a/net.h b/net.h
index 372e57f..698bd0b 100644 (file)
--- a/net.h
+++ b/net.h
@@ -48,10 +48,7 @@ bool StopNode();
 //  (4) size
 //  (4) checksum
 
-// The message start string is designed to be unlikely to occur in normal data.
-// The characters are rarely used upper ascii, not valid as UTF-8, and produce
-// a large 4-byte int at any alignment.
-static const char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
+extern char pchMessageStart[4];
 
 class CMessageHeader
 {
index 730c498..a09031b 100644 (file)
@@ -776,16 +776,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                         return false;
 
                     int nKeysCount = CastToBigNum(stacktop(-i)).getint();
-                    if (nKeysCount < 0)
+                    if (nKeysCount < 0 || nKeysCount > 20)
+                        return false;
+                    nOpCount += nKeysCount;
+                    if (nOpCount > 201)
                         return false;
-                    if (nBestHeight > 84000)
-                    {
-                        if (nKeysCount > 20)
-                            return false;
-                        nOpCount += nKeysCount;
-                        if (nOpCount > 201)
-                            return false;
-                    }
                     int ikey = ++i;
                     i += nKeysCount;
                     if (stack.size() < i)
index d6e715d..44b647f 100644 (file)
@@ -22,7 +22,7 @@ class CDataStream;
 class CAutoFile;
 static const unsigned int MAX_SIZE = 0x02000000;
 
-static const int VERSION = 31304;
+static const int VERSION = 31305;
 static const char* pszSubVer = "";
 
 
diff --git a/ui.cpp b/ui.cpp
index d72e1a0..ed5ccde 100644 (file)
--- a/ui.cpp
+++ b/ui.cpp
@@ -763,6 +763,7 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                            SingleLine(strDescription),
                            FormatMoney(-nValue, true),
                            "");
+                nIndex = -1;
                 wtx.nLinesDisplayed++;
             }
         }
index 5d81262..b784084 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -16,6 +16,7 @@ bool fShutdown = false;
 bool fDaemon = false;
 bool fCommandLine = false;
 string strMiscWarning;
+bool fTestNet = false;
 
 
 
@@ -649,15 +650,11 @@ string GetDefaultDataDir()
 void GetDataDir(char* pszDir)
 {
     // pszDir must be at least MAX_PATH length.
+    int nVariation;
     if (pszSetDataDir[0] != 0)
     {
         strlcpy(pszDir, pszSetDataDir, MAX_PATH);
-        static bool fMkdirDone;
-        if (!fMkdirDone)
-        {
-            fMkdirDone = true;
-            filesystem::create_directory(pszDir);
-        }
+        nVariation = 0;
     }
     else
     {
@@ -665,11 +662,23 @@ void GetDataDir(char* pszDir)
         // value so we don't have to do memory allocations after that.
         static char pszCachedDir[MAX_PATH];
         if (pszCachedDir[0] == 0)
-        {
             strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir));
-            filesystem::create_directory(pszCachedDir);
-        }
         strlcpy(pszDir, pszCachedDir, MAX_PATH);
+        nVariation = 1;
+    }
+    if (fTestNet)
+    {
+        char* p = pszDir + strlen(pszDir);
+        if (p > pszDir && p[-1] != '/' && p[-1] != '\\')
+            *p++ = '/';
+        strcpy(p, "testnet");
+        nVariation += 2;
+    }
+    static bool pfMkdir[4];
+    if (!pfMkdir[nVariation])
+    {
+        pfMkdir[nVariation] = true;
+        filesystem::create_directory(pszDir);
     }
 }
 
diff --git a/util.h b/util.h
index 09af956..31ba4f5 100644 (file)
--- a/util.h
+++ b/util.h
@@ -145,6 +145,7 @@ extern bool fShutdown;
 extern bool fDaemon;
 extern bool fCommandLine;
 extern string strMiscWarning;
+extern bool fTestNet;
 
 void RandAddSeed();
 void RandAddSeedPerfmon();
@@ -621,3 +622,27 @@ inline void ExitThread(unsigned int nExitCode)
     pthread_exit((void*)nExitCode);
 }
 #endif
+
+
+
+
+
+inline bool AffinityBugWorkaround(void(*pfn)(void*))
+{
+#ifdef __WXMSW__
+    // Sometimes after a few hours affinity gets stuck on one processor
+    DWORD dwProcessAffinityMask = -1;
+    DWORD dwSystemAffinityMask = -1;
+    GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
+    DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
+    DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
+    if (dwPrev2 != dwProcessAffinityMask)
+    {
+        printf("AffinityBugWorkaround() : SetThreadAffinityMask=%d, ProcessAffinityMask=%d, restarting thread\n", dwPrev2, dwProcessAffinityMask);
+        if (!CreateThread(pfn, NULL))
+            printf("Error: CreateThread() failed\n");
+        return true;
+    }
+#endif
+    return false;
+}