1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
7 #include <boost/algorithm/string/join.hpp>
8 #include <boost/program_options/detail/config_file.hpp>
9 #include <boost/program_options/parsers.hpp>
10 #include <boost/filesystem.hpp>
11 #include <boost/filesystem/fstream.hpp>
12 #include <boost/interprocess/sync/interprocess_mutex.hpp>
13 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
14 #include <boost/foreach.hpp>
17 using namespace boost
;
19 map
<string
, string
> mapArgs
;
20 map
<string
, vector
<string
> > mapMultiArgs
;
22 bool fPrintToConsole
= false;
23 bool fPrintToDebugger
= false;
24 char pszSetDataDir
[MAX_PATH
] = "";
25 bool fRequestShutdown
= false;
26 bool fShutdown
= false;
29 bool fCommandLine
= false;
30 string strMiscWarning
;
31 bool fTestNet
= false;
32 bool fNoListen
= false;
33 bool fLogTimestamps
= false;
34 CMedianFilter
<int64
> vTimeOffsets(200,0);
38 // Workaround for "multiple definition of `_tls_used'"
39 // http://svn.boost.org/trac/boost/ticket/4258
40 extern "C" void tss_cleanup_implemented() { }
46 // Init openssl library multithreading support
47 static boost::interprocess::interprocess_mutex
** ppmutexOpenSSL
;
48 void locking_callback(int mode
, int i
, const char* file
, int line
)
50 if (mode
& CRYPTO_LOCK
)
51 ppmutexOpenSSL
[i
]->lock();
53 ppmutexOpenSSL
[i
]->unlock();
62 // Init openssl library multithreading support
63 ppmutexOpenSSL
= (boost::interprocess::interprocess_mutex
**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex
*));
64 for (int i
= 0; i
< CRYPTO_num_locks(); i
++)
65 ppmutexOpenSSL
[i
] = new boost::interprocess::interprocess_mutex();
66 CRYPTO_set_locking_callback(locking_callback
);
69 // Seed random number generator with screen scrape and other hardware sources
73 // Seed random number generator with performance counter
78 // Shutdown openssl library multithreading support
79 CRYPTO_set_locking_callback(NULL
);
80 for (int i
= 0; i
< CRYPTO_num_locks(); i
++)
81 delete ppmutexOpenSSL
[i
];
82 OPENSSL_free(ppmutexOpenSSL
);
96 // Seed with CPU performance counter
97 int64 nCounter
= GetPerformanceCounter();
98 RAND_add(&nCounter
, sizeof(nCounter
), 1.5);
99 memset(&nCounter
, 0, sizeof(nCounter
));
102 void RandAddSeedPerfmon()
106 // This can take up to 2 seconds, so only do it every 10 minutes
107 static int64 nLastPerfmon
;
108 if (GetTime() < nLastPerfmon
+ 10 * 60)
110 nLastPerfmon
= GetTime();
113 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
114 // Seed with the entire set of perfmon data
115 unsigned char pdata
[250000];
116 memset(pdata
, 0, sizeof(pdata
));
117 unsigned long nSize
= sizeof(pdata
);
118 long ret
= RegQueryValueExA(HKEY_PERFORMANCE_DATA
, "Global", NULL
, NULL
, pdata
, &nSize
);
119 RegCloseKey(HKEY_PERFORMANCE_DATA
);
120 if (ret
== ERROR_SUCCESS
)
122 RAND_add(pdata
, nSize
, nSize
/100.0);
123 memset(pdata
, 0, nSize
);
124 printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize
);
129 uint64
GetRand(uint64 nMax
)
134 // The range of the random source must be a multiple of the modulus
135 // to give every possible output value an equal possibility
136 uint64 nRange
= (std::numeric_limits
<uint64
>::max() / nMax
) * nMax
;
139 RAND_bytes((unsigned char*)&nRand
, sizeof(nRand
));
140 while (nRand
>= nRange
);
141 return (nRand
% nMax
);
144 int GetRandInt(int nMax
)
146 return GetRand(nMax
);
159 inline int OutputDebugStringF(const char* pszFormat
, ...)
166 va_start(arg_ptr
, pszFormat
);
167 ret
= vprintf(pszFormat
, arg_ptr
);
172 // print to debug.log
173 static FILE* fileout
= NULL
;
177 char pszFile
[MAX_PATH
+100];
179 strlcat(pszFile
, "/debug.log", sizeof(pszFile
));
180 fileout
= fopen(pszFile
, "a");
181 if (fileout
) setbuf(fileout
, NULL
); // unbuffered
185 static bool fStartedNewLine
= true;
187 // Debug print useful for profiling
188 if (fLogTimestamps
&& fStartedNewLine
)
189 fprintf(fileout
, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
190 if (pszFormat
[strlen(pszFormat
) - 1] == '\n')
191 fStartedNewLine
= true;
193 fStartedNewLine
= false;
196 va_start(arg_ptr
, pszFormat
);
197 ret
= vfprintf(fileout
, pszFormat
, arg_ptr
);
203 if (fPrintToDebugger
)
205 static CCriticalSection cs_OutputDebugStringF
;
207 // accumulate a line at a time
208 CRITICAL_BLOCK(cs_OutputDebugStringF
)
210 static char pszBuffer
[50000];
215 va_start(arg_ptr
, pszFormat
);
216 int limit
= END(pszBuffer
) - pend
- 2;
217 int ret
= _vsnprintf(pend
, limit
, pszFormat
, arg_ptr
);
219 if (ret
< 0 || ret
>= limit
)
221 pend
= END(pszBuffer
) - 2;
227 char* p1
= pszBuffer
;
229 while (p2
= strchr(p1
, '\n'))
234 OutputDebugStringA(p1
);
239 memmove(pszBuffer
, p1
, pend
- p1
+ 1);
240 pend
-= (p1
- pszBuffer
);
249 // - prints up to limit-1 characters
250 // - output string is always null terminated even if limit reached
251 // - return value is the number of characters actually printed
252 int my_snprintf(char* buffer
, size_t limit
, const char* format
, ...)
257 va_start(arg_ptr
, format
);
258 int ret
= _vsnprintf(buffer
, limit
, format
, arg_ptr
);
260 if (ret
< 0 || ret
>= limit
)
268 string
strprintf(const std::string
&format
, ...)
272 int limit
= sizeof(buffer
);
277 va_start(arg_ptr
, format
);
278 ret
= _vsnprintf(p
, limit
, format
.c_str(), arg_ptr
);
280 if (ret
>= 0 && ret
< limit
)
287 throw std::bad_alloc();
289 string
str(p
, p
+ret
);
295 bool error(const std::string
&format
, ...)
298 int limit
= sizeof(buffer
);
300 va_start(arg_ptr
, format
);
301 int ret
= _vsnprintf(buffer
, limit
, format
.c_str(), arg_ptr
);
303 if (ret
< 0 || ret
>= limit
)
308 printf("ERROR: %s\n", buffer
);
313 void ParseString(const string
& str
, char c
, vector
<string
>& v
)
317 string::size_type i1
= 0;
318 string::size_type i2
;
321 i2
= str
.find(c
, i1
);
324 v
.push_back(str
.substr(i1
));
327 v
.push_back(str
.substr(i1
, i2
-i1
));
333 string
FormatMoney(int64 n
, bool fPlus
)
335 // Note: not using straight sprintf here because we do NOT want
336 // localized number formatting.
337 int64 n_abs
= (n
> 0 ? n
: -n
);
338 int64 quotient
= n_abs
/COIN
;
339 int64 remainder
= n_abs
%COIN
;
340 string str
= strprintf("%"PRI64d
".%08"PRI64d
, quotient
, remainder
);
342 // Right-trim excess 0's before the decimal point:
344 for (int i
= str
.size()-1; (str
[i
] == '0' && isdigit(str
[i
-2])); --i
)
347 str
.erase(str
.size()-nTrim
, nTrim
);
350 str
.insert((unsigned int)0, 1, '-');
351 else if (fPlus
&& n
> 0)
352 str
.insert((unsigned int)0, 1, '+');
357 bool ParseMoney(const string
& str
, int64
& nRet
)
359 return ParseMoney(str
.c_str(), nRet
);
362 bool ParseMoney(const char* pszIn
, int64
& nRet
)
366 const char* p
= pszIn
;
374 int64 nMult
= CENT
*10;
375 while (isdigit(*p
) && (nMult
> 0))
377 nUnits
+= nMult
* (*p
++ - '0');
386 strWhole
.insert(strWhole
.end(), *p
);
391 if (strWhole
.size() > 10) // guard against 63 bit overflow
393 if (nUnits
< 0 || nUnits
> COIN
)
395 int64 nWhole
= atoi64(strWhole
);
396 int64 nValue
= nWhole
*COIN
+ nUnits
;
403 static char phexdigit
[256] =
404 { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
405 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
406 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
407 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
408 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
409 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
410 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1
411 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
412 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
413 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
414 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
415 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
416 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
417 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
418 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
419 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
421 bool IsHex(const string
& str
)
423 BOOST_FOREACH(unsigned char c
, str
)
425 if (phexdigit
[c
] < 0)
428 return (str
.size() > 0) && (str
.size()%2 == 0);
431 vector
<unsigned char> ParseHex(const char* psz
)
433 // convert hex dump to vector
434 vector
<unsigned char> vch
;
437 while (isspace(*psz
))
439 char c
= phexdigit
[(unsigned char)*psz
++];
442 unsigned char n
= (c
<< 4);
443 c
= phexdigit
[(unsigned char)*psz
++];
452 vector
<unsigned char> ParseHex(const string
& str
)
454 return ParseHex(str
.c_str());
457 static void InterpretNegativeSetting(string name
, map
<string
, string
>& mapSettingsRet
)
459 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
460 if (name
.find("-no") == 0)
462 std::string
positive("-");
463 positive
.append(name
.begin()+3, name
.end());
464 if (mapSettingsRet
.count(positive
) == 0)
466 bool value
= !GetBoolArg(name
);
467 mapSettingsRet
[positive
] = (value
? "1" : "0");
472 void ParseParameters(int argc
, const char*const argv
[])
475 mapMultiArgs
.clear();
476 for (int i
= 1; i
< argc
; i
++)
479 strlcpy(psz
, argv
[i
], sizeof(psz
));
480 char* pszValue
= (char*)"";
481 if (strchr(psz
, '='))
483 pszValue
= strchr(psz
, '=');
494 mapArgs
[psz
] = pszValue
;
495 mapMultiArgs
[psz
].push_back(pszValue
);
499 BOOST_FOREACH(const PAIRTYPE(string
,string
)& entry
, mapArgs
)
501 string name
= entry
.first
;
503 // interpret --foo as -foo (as long as both are not set)
504 if (name
.find("--") == 0)
506 std::string
singleDash(name
.begin()+1, name
.end());
507 if (mapArgs
.count(singleDash
) == 0)
508 mapArgs
[singleDash
] = entry
.second
;
512 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
513 InterpretNegativeSetting(name
, mapArgs
);
517 std::string
GetArg(const std::string
& strArg
, const std::string
& strDefault
)
519 if (mapArgs
.count(strArg
))
520 return mapArgs
[strArg
];
524 int64
GetArg(const std::string
& strArg
, int64 nDefault
)
526 if (mapArgs
.count(strArg
))
527 return atoi64(mapArgs
[strArg
]);
531 bool GetBoolArg(const std::string
& strArg
, bool fDefault
)
533 if (mapArgs
.count(strArg
))
535 if (mapArgs
[strArg
].empty())
537 return (atoi(mapArgs
[strArg
]) != 0);
542 bool SoftSetArg(const std::string
& strArg
, const std::string
& strValue
)
544 if (mapArgs
.count(strArg
))
546 mapArgs
[strArg
] = strValue
;
550 bool SoftSetBoolArg(const std::string
& strArg
, bool fValue
)
553 return SoftSetArg(strArg
, std::string("1"));
555 return SoftSetArg(strArg
, std::string("0"));
559 string
EncodeBase64(const unsigned char* pch
, size_t len
)
561 static const char *pbase64
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
564 strRet
.reserve((len
+2)/3*4);
567 const unsigned char *pchEnd
= pch
+len
;
574 case 0: // we have no bits
575 strRet
+= pbase64
[enc
>> 2];
576 left
= (enc
& 3) << 4;
580 case 1: // we have two bits
581 strRet
+= pbase64
[left
| (enc
>> 4)];
582 left
= (enc
& 15) << 2;
586 case 2: // we have four bits
587 strRet
+= pbase64
[left
| (enc
>> 6)];
588 strRet
+= pbase64
[enc
& 63];
596 strRet
+= pbase64
[left
];
605 string
EncodeBase64(const string
& str
)
607 return EncodeBase64((const unsigned char*)str
.c_str(), str
.size());
610 vector
<unsigned char> DecodeBase64(const char* p
, bool* pfInvalid
)
612 static const int decode64_table
[256] =
614 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
615 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
616 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
617 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
618 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
619 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
620 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
621 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
622 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
623 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
624 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
625 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
626 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
632 vector
<unsigned char> vchRet
;
633 vchRet
.reserve(strlen(p
)*3/4);
640 int dec
= decode64_table
[*p
];
641 if (dec
== -1) break;
645 case 0: // we have no bits and get 6
650 case 1: // we have 6 bits and keep 4
651 vchRet
.push_back((left
<<2) | (dec
>>4));
656 case 2: // we have 4 bits and get 6, we keep 2
657 vchRet
.push_back((left
<<4) | (dec
>>2));
662 case 3: // we have 2 bits and get 6
663 vchRet
.push_back((left
<<6) | dec
);
672 case 0: // 4n base64 characters processed: ok
675 case 1: // 4n+1 base64 character processed: impossible
679 case 2: // 4n+2 base64 characters processed: require '=='
680 if (left
|| p
[0] != '=' || p
[1] != '=' || decode64_table
[p
[2]] != -1)
684 case 3: // 4n+3 base64 characters processed: require '='
685 if (left
|| p
[0] != '=' || decode64_table
[p
[1]] != -1)
693 string
DecodeBase64(const string
& str
)
695 vector
<unsigned char> vchRet
= DecodeBase64(str
.c_str());
696 return string((const char*)&vchRet
[0], vchRet
.size());
700 bool WildcardMatch(const char* psz
, const char* mask
)
707 return (*psz
== '\0');
709 return WildcardMatch(psz
, mask
+1) || (*psz
&& WildcardMatch(psz
+1, mask
));
724 bool WildcardMatch(const string
& str
, const string
& mask
)
726 return WildcardMatch(str
.c_str(), mask
.c_str());
736 void FormatException(char* pszMessage
, std::exception
* pex
, const char* pszThread
)
739 char pszModule
[MAX_PATH
];
741 GetModuleFileNameA(NULL
, pszModule
, sizeof(pszModule
));
743 const char* pszModule
= "bitcoin";
746 snprintf(pszMessage
, 1000,
747 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex
).name(), pex
->what(), pszModule
, pszThread
);
749 snprintf(pszMessage
, 1000,
750 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule
, pszThread
);
753 void LogException(std::exception
* pex
, const char* pszThread
)
755 char pszMessage
[10000];
756 FormatException(pszMessage
, pex
, pszThread
);
757 printf("\n%s", pszMessage
);
760 void PrintException(std::exception
* pex
, const char* pszThread
)
762 char pszMessage
[10000];
763 FormatException(pszMessage
, pex
, pszThread
);
764 printf("\n\n************************\n%s\n", pszMessage
);
765 fprintf(stderr
, "\n\n************************\n%s\n", pszMessage
);
766 strMiscWarning
= pszMessage
;
770 void ThreadOneMessageBox(string strMessage
)
772 // Skip message boxes if one is already open
773 static bool fMessageBoxOpen
;
776 fMessageBoxOpen
= true;
777 ThreadSafeMessageBox(strMessage
, "Bitcoin", wxOK
| wxICON_EXCLAMATION
);
778 fMessageBoxOpen
= false;
781 void PrintExceptionContinue(std::exception
* pex
, const char* pszThread
)
783 char pszMessage
[10000];
784 FormatException(pszMessage
, pex
, pszThread
);
785 printf("\n\n************************\n%s\n", pszMessage
);
786 fprintf(stderr
, "\n\n************************\n%s\n", pszMessage
);
787 strMiscWarning
= pszMessage
;
798 typedef WINSHELLAPI
BOOL (WINAPI
*PSHGETSPECIALFOLDERPATHA
)(HWND hwndOwner
, LPSTR lpszPath
, int nFolder
, BOOL fCreate
);
800 string
MyGetSpecialFolderPath(int nFolder
, bool fCreate
)
802 char pszPath
[MAX_PATH
+100] = "";
804 // SHGetSpecialFolderPath isn't always available on old Windows versions
805 HMODULE hShell32
= LoadLibraryA("shell32.dll");
808 PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath
=
809 (PSHGETSPECIALFOLDERPATHA
)GetProcAddress(hShell32
, "SHGetSpecialFolderPathA");
810 if (pSHGetSpecialFolderPath
)
811 (*pSHGetSpecialFolderPath
)(NULL
, pszPath
, nFolder
, fCreate
);
812 FreeModule(hShell32
);
816 if (pszPath
[0] == '\0')
818 if (nFolder
== CSIDL_STARTUP
)
820 strcpy(pszPath
, getenv("USERPROFILE"));
821 strcat(pszPath
, "\\Start Menu\\Programs\\Startup");
823 else if (nFolder
== CSIDL_APPDATA
)
825 strcpy(pszPath
, getenv("APPDATA"));
833 string
GetDefaultDataDir()
835 // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
836 // Mac: ~/Library/Application Support/Bitcoin
840 return MyGetSpecialFolderPath(CSIDL_APPDATA
, true) + "\\Bitcoin";
842 char* pszHome
= getenv("HOME");
843 if (pszHome
== NULL
|| strlen(pszHome
) == 0)
844 pszHome
= (char*)"/";
845 string strHome
= pszHome
;
846 if (strHome
[strHome
.size()-1] != '/')
850 strHome
+= "Library/Application Support/";
851 filesystem::create_directory(strHome
.c_str());
852 return strHome
+ "Bitcoin";
855 return strHome
+ ".bitcoin";
860 void GetDataDir(char* pszDir
)
862 // pszDir must be at least MAX_PATH length.
864 if (pszSetDataDir
[0] != 0)
866 strlcpy(pszDir
, pszSetDataDir
, MAX_PATH
);
871 // This can be called during exceptions by printf, so we cache the
872 // value so we don't have to do memory allocations after that.
873 static char pszCachedDir
[MAX_PATH
];
874 if (pszCachedDir
[0] == 0)
875 strlcpy(pszCachedDir
, GetDefaultDataDir().c_str(), sizeof(pszCachedDir
));
876 strlcpy(pszDir
, pszCachedDir
, MAX_PATH
);
881 char* p
= pszDir
+ strlen(pszDir
);
882 if (p
> pszDir
&& p
[-1] != '/' && p
[-1] != '\\')
884 strcpy(p
, "testnet");
887 static bool pfMkdir
[4];
888 if (!pfMkdir
[nVariation
])
890 pfMkdir
[nVariation
] = true;
891 boost::filesystem::create_directory(pszDir
);
897 char pszDir
[MAX_PATH
];
902 string
GetConfigFile()
904 namespace fs
= boost::filesystem
;
905 fs::path
pathConfig(GetArg("-conf", "bitcoin.conf"));
906 if (!pathConfig
.is_complete())
907 pathConfig
= fs::path(GetDataDir()) / pathConfig
;
908 return pathConfig
.string();
911 void ReadConfigFile(map
<string
, string
>& mapSettingsRet
,
912 map
<string
, vector
<string
> >& mapMultiSettingsRet
)
914 namespace fs
= boost::filesystem
;
915 namespace pod
= boost::program_options::detail
;
917 fs::ifstream
streamConfig(GetConfigFile());
918 if (!streamConfig
.good())
921 set
<string
> setOptions
;
922 setOptions
.insert("*");
924 for (pod::config_file_iterator
it(streamConfig
, setOptions
), end
; it
!= end
; ++it
)
926 // Don't overwrite existing settings so command line settings override bitcoin.conf
927 string strKey
= string("-") + it
->string_key
;
928 if (mapSettingsRet
.count(strKey
) == 0)
930 mapSettingsRet
[strKey
] = it
->value
[0];
931 // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
932 InterpretNegativeSetting(strKey
, mapSettingsRet
);
934 mapMultiSettingsRet
[strKey
].push_back(it
->value
[0]);
940 namespace fs
= boost::filesystem
;
941 fs::path
pathConfig(GetArg("-pid", "bitcoind.pid"));
942 if (!pathConfig
.is_complete())
943 pathConfig
= fs::path(GetDataDir()) / pathConfig
;
944 return pathConfig
.string();
947 void CreatePidFile(string pidFile
, pid_t pid
)
949 FILE* file
= fopen(pidFile
.c_str(), "w");
952 fprintf(file
, "%d\n", pid
);
957 int GetFilesize(FILE* file
)
959 int nSavePos
= ftell(file
);
961 if (fseek(file
, 0, SEEK_END
) == 0)
962 nFilesize
= ftell(file
);
963 fseek(file
, nSavePos
, SEEK_SET
);
967 void ShrinkDebugFile()
969 // Scroll debug.log if it's getting too big
970 string strFile
= GetDataDir() + "/debug.log";
971 FILE* file
= fopen(strFile
.c_str(), "r");
972 if (file
&& GetFilesize(file
) > 10 * 1000000)
974 // Restart the file with some of the end
976 fseek(file
, -sizeof(pch
), SEEK_END
);
977 int nBytes
= fread(pch
, 1, sizeof(pch
), file
);
980 file
= fopen(strFile
.c_str(), "w");
983 fwrite(pch
, 1, nBytes
, file
);
997 // "Never go to sea with two chronometers; take one or three."
998 // Our three time sources are:
1000 // - Median of other nodes's clocks
1001 // - The user (asking the user to fix the system clock if the first two disagree)
1003 static int64 nMockTime
= 0; // For unit testing
1007 if (nMockTime
) return nMockTime
;
1012 void SetMockTime(int64 nMockTimeIn
)
1014 nMockTime
= nMockTimeIn
;
1017 static int64 nTimeOffset
= 0;
1019 int64
GetAdjustedTime()
1021 return GetTime() + nTimeOffset
;
1024 void AddTimeData(const CNetAddr
& ip
, int64 nTime
)
1026 int64 nOffsetSample
= nTime
- GetTime();
1028 // Ignore duplicates
1029 static set
<CNetAddr
> setKnown
;
1030 if (!setKnown
.insert(ip
).second
)
1034 vTimeOffsets
.input(nOffsetSample
);
1035 printf("Added time data, samples %d, offset %+"PRI64d
" (%+"PRI64d
" minutes)\n", vTimeOffsets
.size(), nOffsetSample
, nOffsetSample
/60);
1036 if (vTimeOffsets
.size() >= 5 && vTimeOffsets
.size() % 2 == 1)
1038 int64 nMedian
= vTimeOffsets
.median();
1039 std::vector
<int64
> vSorted
= vTimeOffsets
.sorted();
1040 // Only let other nodes change our time by so much
1041 if (abs64(nMedian
) < 70 * 60)
1043 nTimeOffset
= nMedian
;
1052 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
1053 bool fMatch
= false;
1054 BOOST_FOREACH(int64 nOffset
, vSorted
)
1055 if (nOffset
!= 0 && abs64(nOffset
) < 5 * 60)
1061 string strMessage
= _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
1062 strMiscWarning
= strMessage
;
1063 printf("*** %s\n", strMessage
.c_str());
1064 boost::thread(boost::bind(ThreadSafeMessageBox
, strMessage
+" ", string("Bitcoin"), wxOK
| wxICON_EXCLAMATION
, (wxWindow
*)NULL
, -1, -1));
1069 BOOST_FOREACH(int64 n
, vSorted
)
1070 printf("%+"PRI64d
" ", n
);
1073 printf("nTimeOffset = %+"PRI64d
" (%+"PRI64d
" minutes)\n", nTimeOffset
, nTimeOffset
/60);
1084 string
FormatVersion(int nVersion
)
1086 if (nVersion
%100 == 0)
1087 return strprintf("%d.%d.%d", nVersion
/1000000, (nVersion
/10000)%100, (nVersion
/100)%100);
1089 return strprintf("%d.%d.%d.%d", nVersion
/1000000, (nVersion
/10000)%100, (nVersion
/100)%100, nVersion
%100);
1092 string
FormatFullVersion()
1094 string s
= FormatVersion(CLIENT_VERSION
);
1095 if (VERSION_IS_BETA
) {
1102 // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
1103 std::string
FormatSubVersion(const std::string
& name
, int nClientVersion
, const std::vector
<std::string
>& comments
)
1105 std::ostringstream ss
;
1107 ss
<< name
<< ":" << FormatVersion(nClientVersion
);
1108 if (!comments
.empty())
1109 ss
<< "(" << boost::algorithm::join(comments
, "; ") << ")";
1116 #ifdef DEBUG_LOCKORDER
1118 // Early deadlock detection.
1119 // Problem being solved:
1120 // Thread 1 locks A, then B, then C
1121 // Thread 2 locks D, then C, then A
1122 // --> may result in deadlock between the two threads, depending on when they run.
1123 // Solution implemented here:
1124 // Keep track of pairs of locks: (A before B), (A before C), etc.
1125 // Complain if any thread trys to lock in a different order.
1128 struct CLockLocation
1130 CLockLocation(const char* pszName
, const char* pszFile
, int nLine
)
1132 mutexName
= pszName
;
1133 sourceFile
= pszFile
;
1137 std::string
ToString() const
1139 return mutexName
+" "+sourceFile
+":"+itostr(sourceLine
);
1143 std::string mutexName
;
1144 std::string sourceFile
;
1148 typedef std::vector
< std::pair
<CCriticalSection
*, CLockLocation
> > LockStack
;
1150 static boost::interprocess::interprocess_mutex dd_mutex
;
1151 static std::map
<std::pair
<CCriticalSection
*, CCriticalSection
*>, LockStack
> lockorders
;
1152 static boost::thread_specific_ptr
<LockStack
> lockstack
;
1155 static void potential_deadlock_detected(const std::pair
<CCriticalSection
*, CCriticalSection
*>& mismatch
, const LockStack
& s1
, const LockStack
& s2
)
1157 printf("POTENTIAL DEADLOCK DETECTED\n");
1158 printf("Previous lock order was:\n");
1159 BOOST_FOREACH(const PAIRTYPE(CCriticalSection
*, CLockLocation
)& i
, s2
)
1161 if (i
.first
== mismatch
.first
) printf(" (1)");
1162 if (i
.first
== mismatch
.second
) printf(" (2)");
1163 printf(" %s\n", i
.second
.ToString().c_str());
1165 printf("Current lock order is:\n");
1166 BOOST_FOREACH(const PAIRTYPE(CCriticalSection
*, CLockLocation
)& i
, s1
)
1168 if (i
.first
== mismatch
.first
) printf(" (1)");
1169 if (i
.first
== mismatch
.second
) printf(" (2)");
1170 printf(" %s\n", i
.second
.ToString().c_str());
1174 static void push_lock(CCriticalSection
* c
, const CLockLocation
& locklocation
)
1176 bool fOrderOK
= true;
1177 if (lockstack
.get() == NULL
)
1178 lockstack
.reset(new LockStack
);
1180 if (fDebug
) printf("Locking: %s\n", locklocation
.ToString().c_str());
1183 (*lockstack
).push_back(std::make_pair(c
, locklocation
));
1185 BOOST_FOREACH(const PAIRTYPE(CCriticalSection
*, CLockLocation
)& i
, (*lockstack
))
1187 if (i
.first
== c
) break;
1189 std::pair
<CCriticalSection
*, CCriticalSection
*> p1
= std::make_pair(i
.first
, c
);
1190 if (lockorders
.count(p1
))
1192 lockorders
[p1
] = (*lockstack
);
1194 std::pair
<CCriticalSection
*, CCriticalSection
*> p2
= std::make_pair(c
, i
.first
);
1195 if (lockorders
.count(p2
))
1197 potential_deadlock_detected(p1
, lockorders
[p2
], lockorders
[p1
]);
1204 static void pop_lock()
1208 const CLockLocation
& locklocation
= (*lockstack
).rbegin()->second
;
1209 printf("Unlocked: %s\n", locklocation
.ToString().c_str());
1212 (*lockstack
).pop_back();
1216 void CCriticalSection::Enter(const char* pszName
, const char* pszFile
, int nLine
)
1218 push_lock(this, CLockLocation(pszName
, pszFile
, nLine
));
1219 #ifdef DEBUG_LOCKCONTENTION
1220 bool result
= mutex
.try_lock();
1223 printf("LOCKCONTENTION: %s\n", pszName
);
1224 printf("Locker: %s:%d\n", pszFile
, nLine
);
1232 void CCriticalSection::Leave()
1237 bool CCriticalSection::TryEnter(const char* pszName
, const char* pszFile
, int nLine
)
1239 push_lock(this, CLockLocation(pszName
, pszFile
, nLine
));
1240 bool result
= mutex
.try_lock();
1241 if (!result
) pop_lock();
1247 void CCriticalSection::Enter(const char* pszName
, const char* pszFile
, int nLine
)
1249 #ifdef DEBUG_LOCKCONTENTION
1250 bool result
= mutex
.try_lock();
1253 printf("LOCKCONTENTION: %s\n", pszName
);
1254 printf("Locker: %s:%d\n", pszFile
, nLine
);
1262 void CCriticalSection::Leave()
1267 bool CCriticalSection::TryEnter(const char*, const char*, int)
1269 bool result
= mutex
.try_lock();
1273 #endif /* DEBUG_LOCKORDER */