8 #if defined(HAVE_CONFIG_H)
29 #ifdef _POSIX_C_SOURCE
30 #undef _POSIX_C_SOURCE
33 #define _POSIX_C_SOURCE 200112L
40 #include <sys/resource.h>
46 #pragma warning(disable : 4786)
47 #pragma warning(disable : 4804)
48 #pragma warning(disable : 4805)
49 #pragma warning(disable : 4717)
55 #define _WIN32_WINNT 0x0501
60 #define _WIN32_IE 0x0501
62 #define WIN32_LEAN_AND_MEAN 1
73 #ifdef HAVE_SYS_PRCTL_H
74 #include <sys/prctl.h>
78 #include <CoreFoundation/CoreFoundation.h>
95 constexpr uint64_t min_disk_space = 52428800;
97 uint64_t free_bytes_available = fs::space(dir).available;
98 return free_bytes_available >= min_disk_space + additional_bytes;
106 static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks;
108 static std::mutex cs_dir_locks;
110 bool LockDirectory(
const fs::path& directory,
const std::string& lockfile_name,
bool probe_only)
112 std::lock_guard<std::mutex> ulock(cs_dir_locks);
113 fs::path pathLockFile = directory / lockfile_name;
116 if (dir_locks.count(pathLockFile.string())) {
122 if (file) fclose(file);
123 auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
124 if (!lock->TryLock()) {
125 return error(
"Error while attempting to lock directory %s: %s", directory.string(), lock->GetReason());
129 dir_locks.emplace(pathLockFile.string(), std::move(lock));
136 std::lock_guard<std::mutex> ulock(cs_dir_locks);
142 fs::path tmpFile = directory / fs::unique_path();
145 if (!file)
return false;
170 static bool InterpretBool(
const std::string& strValue)
172 if (strValue.empty())
174 return (
atoi(strValue) != 0);
180 typedef std::map<std::string, std::vector<std::string>>
MapArgs;
192 assert(arg.length() > 1 && arg[0] ==
'-');
193 return "-" + am.
m_network +
"." + arg.substr(1);
197 static inline void AddArgs(std::vector<std::string>& res,
const MapArgs& map_args,
const std::string& arg)
199 auto it = map_args.find(arg);
200 if (it != map_args.end()) {
201 res.insert(res.end(), it->second.begin(), it->second.end());
208 static inline std::pair<bool,std::string>
GetArgHelper(
const MapArgs& map_args,
const std::string& arg,
bool getLast =
false)
210 auto it = map_args.find(arg);
212 if (it == map_args.end() || it->second.empty()) {
213 return std::make_pair(
false, std::string());
217 return std::make_pair(
true, it->second.back());
219 return std::make_pair(
true, it->second.front());
230 std::pair<bool,std::string> found_result(
false, std::string());
236 if (found_result.first) {
245 if (found_result.first) {
252 if (found_result.first) {
265 std::pair<bool,std::string> found_result(
false,std::string());
267 if (!found_result.first) {
269 if (!found_result.first) {
273 return InterpretBool(found_result.second);
298 static bool InterpretNegatedOption(std::string& key, std::string& val)
300 assert(key[0] ==
'-');
302 size_t option_index = key.find(
'.');
303 if (option_index == std::string::npos) {
308 if (key.substr(option_index, 2) ==
"no") {
309 bool bool_val = InterpretBool(val);
310 key.erase(option_index, 2);
313 LogPrintf(
"Warning: parsed potentially confusing double-negative %s=%s\n", key, val);
329 "-addnode",
"-connect",
331 "-rpcport",
"-rpcbind",
347 std::pair<bool, std::string> found_result;
351 if (found_result.first)
continue;
355 if (found_result.first)
continue;
359 if (!found_result.first)
continue;
362 LogPrintf(
"Warning: Config setting for %s only applied on %s network when in [%s] section.\n", arg,
m_network,
m_network);
376 for (
int i = 1; i < argc; i++) {
377 std::string key(
argv[i]);
379 size_t is_index = key.find(
'=');
380 if (is_index != std::string::npos) {
381 val = key.substr(is_index + 1);
385 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
394 if (key.length() > 1 && key[1] ==
'-')
398 if (InterpretNegatedOption(key, val)) {
408 std::vector<std::string> result = {};
453 if (found_res.first)
return found_res.second;
461 if (found_res.first)
return atoi64(found_res.second);
469 if (found_res.first)
return InterpretBool(found_res.second);
495 static const int screenWidth = 79;
496 static const int optIndent = 2;
497 static const int msgIndent = 7;
500 return std::string(message) + std::string(
"\n\n");
503 std::string
HelpMessageOpt(
const std::string &option,
const std::string &message) {
504 return std::string(optIndent,
' ') + std::string(option) +
505 std::string(
"\n") + std::string(msgIndent,
' ') +
510 static std::string FormatException(
const std::exception* pex,
const char* pszThread)
514 GetModuleFileNameA(
nullptr, pszModule,
sizeof(pszModule));
516 const char* pszModule =
"pivx";
520 "EXCEPTION: %s \n%s \n%s in %s \n",
typeid(*pex).name(), pex->what(), pszModule, pszThread);
523 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
528 std::string message = FormatException(pex, pszThread);
529 LogPrintf(
"\n\n************************\n%s\n", message);
530 fprintf(stderr,
"\n\n************************\n%s\n", message.c_str());
541 return GetSpecialFolderPath(CSIDL_APPDATA) /
"PIVX";
544 char* pszHome = getenv(
"HOME");
545 if (pszHome ==
nullptr || strlen(pszHome) == 0)
546 pathRet = fs::path(
"/");
548 pathRet = fs::path(pszHome);
551 pathRet /=
"Library/Application Support";
553 return pathRet /
"PIVX";
556 return pathRet /
".pivx";
561 static fs::path g_blocks_path_cache_net_specific;
562 static fs::path pathCached;
563 static fs::path pathCachedNetSpecific;
564 static fs::path zc_paramsPathCached;
567 static fs::path ZC_GetBaseParamsDir()
576 return GetSpecialFolderPath(CSIDL_APPDATA) /
"PIVXParams";
579 char* pszHome = getenv(
"HOME");
580 if (pszHome ==
nullptr || strlen(pszHome) == 0)
581 pathRet = fs::path(
"/");
583 pathRet = fs::path(pszHome);
586 pathRet /=
"Library/Application Support";
588 return pathRet /
"PIVXParams";
591 return pathRet /
".pivx-params";
600 fs::path &path = zc_paramsPathCached;
607 #ifdef USE_CUSTOM_PARAMS
611 path = fs::system_complete(
gArgs.
GetArg(
"-paramsdir",
""));
612 if (!fs::is_directory(path)) {
617 path = ZC_GetBaseParamsDir();
627 fs::path sapling_spend = path /
"sapling-spend.params";
628 fs::path sapling_output = path /
"sapling-output.params";
630 bool fParamsFound =
false;
631 if (fs::exists(sapling_spend) && fs::exists(sapling_output)) {
639 LogPrintf(
"Attempting to find params in app bundle...\n");
640 CFBundleRef mainBundle = CFBundleGetMainBundle();
641 CFURLRef bundleURL = CFBundleCopyBundleURL(mainBundle);
643 CFStringRef strBundlePath = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
644 const char* pathBundle = CFStringGetCStringPtr(strBundlePath, CFStringGetSystemEncoding());
646 fs::path bundle_path = fs::path(pathBundle);
647 LogPrintf(
"App bundle Resources path: %s\n", bundle_path);
648 sapling_spend = bundle_path /
"Contents/Resources/sapling-spend.params";
649 sapling_output = bundle_path /
"Contents/Resources/sapling-output.params";
652 CFRelease(strBundlePath);
653 CFRelease(bundleURL);
654 CFRelease(mainBundle);
657 sapling_spend =
"/usr/share/pivx/sapling-spend.params";
658 sapling_output =
"/usr/share/pivx/sapling-output.params";
659 if (fs::exists(sapling_spend) && fs::exists(sapling_output)) {
663 sapling_spend =
"/usr/local/share/pivx/sapling-spend.params";
664 sapling_output =
"/usr/local/share/pivx/sapling-output.params";
667 if (fs::exists(sapling_spend) && fs::exists(sapling_output))
671 throw std::runtime_error(
"Sapling params don't exist");
674 sizeof(fs::path::value_type) ==
sizeof(
codeunit),
675 "librustzcash not configured correctly");
676 auto sapling_spend_str = sapling_spend.native();
677 auto sapling_output_str = sapling_output.native();
682 reinterpret_cast<const codeunit*
>(sapling_spend_str.c_str()),
683 sapling_spend_str.length(),
684 "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c",
685 reinterpret_cast<const codeunit*
>(sapling_output_str.c_str()),
686 sapling_output_str.length(),
687 "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028",
701 fs::path &path = g_blocks_path_cache_net_specific;
709 path = fs::system_complete(
gArgs.
GetArg(
"-blocksdir",
""));
710 if (!fs::is_directory(path)) {
720 fs::create_directories(path);
728 fs::path& path = fNetSpecific ? pathCachedNetSpecific : pathCached;
732 if (!path.empty())
return path;
734 std::string datadir =
gArgs.
GetArg(
"-datadir",
"");
735 if (!datadir.empty()) {
736 path = fs::system_complete(datadir);
737 if (!fs::is_directory(path)) {
747 if (fs::create_directories(path)) {
749 fs::create_directories(path /
"wallets");
757 std::string datadir =
gArgs.
GetArg(
"-datadir",
"");
758 return datadir.empty() || fs::is_directory(fs::system_complete(datadir));
765 pathCached = fs::path();
766 pathCachedNetSpecific = fs::path();
767 g_blocks_path_cache_net_specific = fs::path();
772 fs::path pathConfigFile(confPath);
782 static std::string TrimString(
const std::string& str,
const std::string& pattern)
784 std::string::size_type front = str.find_first_not_of(pattern);
785 if (front == std::string::npos) {
786 return std::string();
788 std::string::size_type end = str.find_last_not_of(pattern);
789 return str.substr(front, end - front + 1);
792 static std::vector<std::pair<std::string, std::string>> GetConfigOptions(std::istream& stream)
794 std::vector<std::pair<std::string, std::string>> options;
796 std::string::size_type pos;
797 while (std::getline(stream, str)) {
798 if ((pos = str.find(
'#')) != std::string::npos) {
799 str = str.substr(0, pos);
801 const static std::string pattern =
" \t\r\n";
802 str = TrimString(str, pattern);
804 if (*str.begin() ==
'[' && *str.rbegin() ==
']') {
805 prefix = str.substr(1, str.size() - 2) +
'.';
806 }
else if ((pos = str.find(
'=')) != std::string::npos) {
807 std::string
name =
prefix + TrimString(str.substr(0, pos), pattern);
808 std::string value = TrimString(str.substr(pos + 1), pattern);
809 options.emplace_back(
name, value);
820 for (
const std::pair<std::string, std::string>& option : GetConfigOptions(stream)) {
821 std::string strKey = std::string(
"-") + option.first;
822 std::string strValue = option.second;
824 if (InterpretNegatedOption(strKey, strValue)) {
849 throw std::runtime_error(
strprintf(
"specified data directory \"%s\" does not exist.",
gArgs.
GetArg(
"-datadir",
"").c_str()));
855 if (path.is_absolute()) {
858 return fs::absolute(path,
GetDataDir(net_specific));
866 if (fTestNet && fRegTest)
867 throw std::runtime_error(
"Invalid combination of -regtest and -testnet.");
878 return MoveFileExW(src.wstring().c_str(), dest.wstring().c_str(),
879 MOVEFILE_REPLACE_EXISTING) != 0;
881 int rc = std::rename(src.string().c_str(), dest.string().c_str());
894 return fs::create_directories(p);
895 }
catch (
const fs::filesystem_error&) {
896 if (!fs::exists(p) || !fs::is_directory(p))
906 if (fflush(file) != 0) {
907 LogPrintf(
"%s: fflush failed: %d\n", __func__, errno);
911 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
912 if (FlushFileBuffers(hFile) == 0) {
913 LogPrintf(
"%s: FlushFileBuffers failed: %d\n", __func__, GetLastError());
917 #if defined(__linux__) || defined(__NetBSD__)
918 if (fdatasync(fileno(file)) != 0 && errno != EINVAL) {
919 LogPrintf(
"%s: fdatasync failed: %d\n", __func__, errno);
922 #elif defined(MAC_OSX) && defined(F_FULLFSYNC)
923 if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) {
924 LogPrintf(
"%s: fcntl F_FULLFSYNC failed: %d\n", __func__, errno);
928 if (fsync(fileno(file)) != 0 && errno != EINVAL) {
929 LogPrintf(
"%s: fsync failed: %d\n", __func__, errno);
940 return _chsize(_fileno(file), length) == 0;
942 return ftruncate(fileno(file), length) == 0;
955 struct rlimit limitFD;
956 if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
957 if (limitFD.rlim_cur < (rlim_t)nMinFD) {
958 limitFD.rlim_cur = nMinFD;
959 if (limitFD.rlim_cur > limitFD.rlim_max)
960 limitFD.rlim_cur = limitFD.rlim_max;
961 setrlimit(RLIMIT_NOFILE, &limitFD);
962 getrlimit(RLIMIT_NOFILE, &limitFD);
964 return limitFD.rlim_cur;
978 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
979 LARGE_INTEGER nFileSize;
980 int64_t nEndPos = (int64_t)offset + length;
981 nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
982 nFileSize.u.HighPart = nEndPos >> 32;
983 SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
985 #elif defined(MAC_OSX)
988 fst.fst_flags = F_ALLOCATECONTIG;
989 fst.fst_posmode = F_PEOFPOSMODE;
991 fst.fst_length = (off_t)offset + length;
992 fst.fst_bytesalloc = 0;
993 if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
994 fst.fst_flags = F_ALLOCATEALL;
995 fcntl(fileno(file), F_PREALLOCATE, &fst);
997 ftruncate(fileno(file), fst.fst_length);
998 #elif defined(__linux__)
1000 off_t nEndPos = (off_t)offset + length;
1001 posix_fallocate(fileno(file), 0, nEndPos);
1005 static const char buf[65536] = {};
1006 fseek(file, offset, SEEK_SET);
1007 while (length > 0) {
1008 unsigned int now = 65536;
1011 fwrite(buf, 1, now, file);
1018 fs::path GetSpecialFolderPath(
int nFolder,
bool fCreate)
1022 if (SHGetSpecialFolderPathW(
nullptr, pszPath, nFolder, fCreate)) {
1023 return fs::path(pszPath);
1026 LogPrintf(
"SHGetSpecialFolderPathW() failed, could not obtain requested path.\n");
1027 return fs::path(
"");
1033 if (strCommand.empty())
return;
1035 int nErr = ::system(strCommand.c_str());
1037 int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,
wchar_t>().from_bytes(strCommand).c_str());
1040 LogPrintf(
"runCommand error: system(%s) returned %d\n", strCommand, nErr);
1047 #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
1050 }
catch (
const std::runtime_error&) {
1051 setenv(
"LC_ALL",
"C", 1);
1053 #elif defined(WIN32)
1055 SetConsoleCP(CP_UTF8);
1056 SetConsoleOutputCP(CP_UTF8);
1062 std::locale loc = fs::path::imbue(std::locale::classic());
1064 fs::path::imbue(loc);
1066 fs::path::imbue(std::locale(loc,
new std::codecvt_utf8_utf16<wchar_t>()));
1075 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1076 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2)
1088 setpriority(PRIO_THREAD, 0, nPriority);
1090 setpriority(PRIO_PROCESS, 0, nPriority);
1097 return std::thread::hardware_concurrency();
1104 const static sched_param param{0};
1105 if (
int ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, ¶m)) {
1106 LogPrintf(
"Failed to pthread_setschedparam: %s\n", strerror(errno));
1117 WinCmdLineArgs::WinCmdLineArgs()
1119 wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
1120 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,
wchar_t> utf8_cvt;
1121 argv =
new char*[argc];
1123 for (
int i = 0; i < argc; i++) {
1124 args[i] = utf8_cvt.to_bytes(wargv[i]);
1125 argv[i] = &*args[i].begin();
1130 WinCmdLineArgs::~WinCmdLineArgs()
1135 std::pair<int, char**> WinCmdLineArgs::get()
1137 return std::make_pair(argc,
argv);
const CBaseChainParams & BaseParams()
Return the currently selected parameters.
Internal helper functions for ArgsManager.
static std::pair< bool, std::string > GetArgHelper(const MapArgs &map_args, const std::string &arg, bool getLast=false)
Return true/false if an argument is set in a map, and also return the first (or last) of the possibly...
std::map< std::string, std::vector< std::string > > MapArgs
static void AddArgs(std::vector< std::string > &res, const MapArgs &map_args, const std::string &arg)
Find arguments in a map and add them to a vector.
static std::string NetworkArg(const ArgsManager &am, const std::string &arg)
Convert regular argument into the network-specific setting.
static std::pair< bool, std::string > GetArg(const ArgsManager &am, const std::string &arg)
static bool UseDefaultSection(const ArgsManager &am, const std::string &arg)
Determine whether to use config settings in the default section, See also comments around ArgsManager...
static bool GetNetBoolArg(const ArgsManager &am, const std::string &net_arg)
void ReadConfigFile(const std::string &confPath)
bool IsArgNegated(const std::string &strArg) const
Return true if the argument was originally passed as a negated option, i.e.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
void ParseParameters(int argc, const char *const argv[])
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
std::map< std::string, std::vector< std::string > > m_override_args
std::set< std::string > m_network_only_args
bool SoftSetArg(const std::string &strArg, const std::string &strValue)
Set an argument if it doesn't already have a value.
void SelectConfigNetwork(const std::string &network)
Select the network in use.
std::map< std::string, std::vector< std::string > > m_config_args
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
void WarnForSectionOnlyArgs()
Log warnings for options in m_section_only_args when they are specified in the default section but no...
void ReadConfigStream(std::istream &stream)
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
std::string GetChainName() const
Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
static const std::string REGTEST
const std::string & DataDir() const
static const std::string TESTNET
static const std::string MAIN
Chain name strings.
Server/client environment: argument handling, config file parsing, thread wrappers.
#define L(x0, x1, x2, x3, x4, x5, x6, x7)
void librustzcash_init_zksnark_params(const codeunit *spend_path, size_t spend_path_len, const char *spend_hash, const codeunit *output_path, size_t output_path_len, const char *output_hash, const codeunit *sprout_path, size_t sprout_path_len, const char *sprout_hash)
Loads the zk-SNARK parameters into memory and saves paths as necessary.
FILE * fopen(const fs::path &p, const char *mode)
CTranslationInterface translationInterface
fs::path GetDefaultDataDir()
fs::path AbsPathForConfigVal(const fs::path &path, bool net_specific)
const char *const PIVX_CONF_FILENAME
bool CheckDataDirOption()
bool DirIsWritable(const fs::path &directory)
bool RenameOver(fs::path src, fs::path dest)
const fs::path & ZC_GetParamsDir()
int RaiseFileDescriptorLimit(int nMinFD)
this function tries to raise the file descriptor limit to the requested number.
const fs::path & GetDataDir(bool fNetSpecific)
void ReleaseDirectoryLocks()
Release all directory locks.
int ScheduleBatchPriority(void)
On platforms that support it, tell the kernel the calling thread is CPU-intensive and non-interactive...
void SetThreadPriority(int nPriority)
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists.
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length)
this function tries to make a particular range of a file allocated (corresponding to disk space) it i...
const char *const PIVX_MASTERNODE_CONF_FILENAME
std::atomic< bool > fMasterNode
fs::path GetConfigFile(const std::string &confPath)
void PrintExceptionContinue(const std::exception *pex, const char *pszThread)
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
bool CheckDiskSpace(const fs::path &dir, uint64_t additional_bytes)
bool LockDirectory(const fs::path &directory, const std::string &lockfile_name, bool probe_only)
fs::path GetMasternodeConfigFile()
bool TruncateFile(FILE *file, unsigned int length)
const fs::path & GetBlocksDir()
void runCommand(std::string strCommand)
int GetNumCores()
Return the number of cores available on the current system.
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
bool FileCommit(FILE *file)
bool error(const char *fmt, const Args &... args)
int64_t atoi64(const char *psz)
std::string FormatParagraph(const std::string in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.
int atoi(const std::string &str)