diff --git a/.gitignore b/.gitignore index c08baa7ccb..542627e9de 100644 --- a/.gitignore +++ b/.gitignore @@ -112,18 +112,15 @@ contrib/debian/files contrib/debian/substvars src/rpcmisc~.cpp -src/komodo-cli src/pirate-cli -src/komodod src/pirated -src/komodo-tx src/pirate-tx -src/komodo-test src/pirate-test src/wallet-utility -src/komodo-cli.exe -src/komodod.exe -src/komodo-tx.exe +src/pirate-cli.exe +src/pirated.exe +src/pirate-tx.exe +src/pirate-test.exe src/wallet-utility.exe pirate-qt-win.exe pirate-qt-linux @@ -137,7 +134,7 @@ src/qt/*.moc src/qt/forms/ui_*.h #Mac Packaged App -PirateWallet.app +PirateOcean.app #output during builds, symbol tables? *.dSYM diff --git a/configure.ac b/configure.ac index 300c471b73..3e1c766b41 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_REVISION, 1) +define(_CLIENT_VERSION_REVISION, 2) define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/src/init.cpp b/src/init.cpp index b6ded2fda6..84417a359a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -402,7 +402,7 @@ std::string HelpMessage(HelpMessageMode mode) // strUsage += HelpMessageOpt("-prune=", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode disables wallet support and is incompatible with -txindex. " // "Warning: Reverting this setting requires re-downloading the entire blockchain. " // "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); - strUsage += HelpMessageOpt("-bootstrap", _("Download and install bootstrap on startup")); + strUsage += HelpMessageOpt("-bootstrap", _("Download and install bootstrap on startup (1 to show GUI prompt, 2 to force download when using CLI)")); strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files on startup")); #if !defined(WIN32) strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); @@ -1672,7 +1672,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!boost::filesystem::exists(GetDataDir() / "blocks") || !boost::filesystem::exists(GetDataDir() / "chainstate")) newInstall = true; - if (newInstall) { + //Prompt on new install + if (newInstall && !GetBoolArg("-bootstrap", false)) { bool fBoot = uiInterface.ThreadSafeMessageBox( "\n\n" + _("New install detected.\n\nPress OK to download the blockchain bootstrap."), "", CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL | CClientUIInterface::BTN_OK | CClientUIInterface::BTN_CANCEL); @@ -1681,7 +1682,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (GetBoolArg("-bootstrap", false) && !useBootstrap) { + //Prompt GUI + if (GetBoolArg("-bootstrap", false) && GetArg("-bootstrap", "1") != "2" && !useBootstrap) { bool fBoot = uiInterface.ThreadSafeMessageBox( "\n\n" + _("Bootstrap option detected.\n\nPress OK to download the blockchain bootstrap."), "", CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL | CClientUIInterface::BTN_OK | CClientUIInterface::BTN_CANCEL); @@ -1690,6 +1692,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } + //Force Download- used for CLI + if (GetBoolArg("-bootstrap", false) && GetArg("-bootstrap", "1") == "2") { + useBootstrap = true; + } + if (useBootstrap) { fReindex = false; //wipe transactions from wallet to create a clean slate @@ -1700,7 +1707,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) boost::filesystem::remove(GetDataDir() / "komodostate"); boost::filesystem::remove(GetDataDir() / "signedmasks"); boost::filesystem::remove(GetDataDir() / "komodostate.ind"); - getBootstrap(); + if (!getBootstrap() && !fRequestShutdown ) { + bool keepRunning = uiInterface.ThreadSafeMessageBox( + "\n\n" + _("Bootstrap download failed!!!\n\nPress OK to continue and sync from the network."), + "", CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL | CClientUIInterface::BTN_OK | CClientUIInterface::BTN_CANCEL); + + if (!keepRunning) { + fRequestShutdown = true; + } + } } if (fRequestShutdown) diff --git a/src/params.cpp b/src/params.cpp index b6e238cce4..79bf92f81c 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -3,56 +3,55 @@ #include "ui_interface.h" std::map mapParams; +static const int K_READ_BUF_SIZE{ 1024 * 16 }; -void sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65]) +std::string CalcSha256(std::string filename) { - int i = 0; - - for(i = 0; i < SHA256_DIGEST_LENGTH; i++) - { - sprintf(outputBuffer + (i * 2), "%02x", hash[i]); + // Initialize openssl + SHA256_CTX context; + if(!SHA256_Init(&context)) { + return ""; } - outputBuffer[64] = 0; -} - -int sha256_file(const char *path, char outputBuffer[65]) -{ - errno = 0; - FILE *file = fopen(path, "rb"); - if (!file) { - return -534; + // Read file and update calculated SHA + char buf[K_READ_BUF_SIZE]; + std::ifstream file(filename, std::ifstream::binary); + while (file.good()) { + file.read(buf, sizeof(buf)); + if(!SHA256_Update(&context, buf, file.gcount())) { + return ""; + } } - unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - const int bufSize = 32768; - unsigned char *buffer = (unsigned char *)malloc(bufSize); - int bytesRead = 0; - if(!buffer) return ENOMEM; - while((bytesRead = fread(buffer, 1, bufSize, file))) - { - SHA256_Update(&sha256, buffer, bytesRead); + // Get Final SHA + unsigned char result[SHA256_DIGEST_LENGTH]; + if(!SHA256_Final(result, &context)) { + return ""; } - SHA256_Final(hash, &sha256); - sha256_hash_string(hash, outputBuffer); - fclose(file); - free(buffer); - return 0; + // Transform byte-array to string + std::stringstream shastr; + shastr << std::hex << std::setfill('0'); + for (const auto &byte: result) { + shastr << std::setw(2) << (int)byte; + } + return shastr.str(); } + bool checkParams() { bool allVerified = true; for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { std::string uiMessage = "Verifying " + it->second.name + "...."; uiInterface.InitMessage(_(uiMessage.c_str())); - const char *path = it->second.path.string().c_str(); - char calc_hash[65]; - sha256_file(path ,calc_hash); - if (calc_hash == it->second.hash) { + + std::string sha256Sum = CalcSha256(it->second.path.string()); + + LogPrintf("sha256Sum %s\n", sha256Sum); + LogPrintf("checkSum %s\n", it->second.hash); + + if (sha256Sum == it->second.hash) { it->second.verified = true; } else { allVerified = false; @@ -164,184 +163,219 @@ void initalizeMapParam() { bool downloadFiles(std::string title) { - bool downloadComplete = true; - curl_global_init(CURL_GLOBAL_ALL); - CURLM *multi_handle; - multi_handle = curl_multi_init(); - int still_running = 0; /* keep number of running handles */ if (!exists(ZC_GetParamsDir())) { create_directory(ZC_GetParamsDir()); } for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { - if (!it->second.verified) { - /* init the curl session */ - it->second.curl = curl_easy_init(); - if(it->second.curl) { - it->second.prog.lastruntime = 0; - it->second.prog.curl = it->second.curl; - } - //open file for writing - const char *path = it->second.path.string().c_str(); - it->second.file = fopen(path, "wb"); + it->second.file = fopen(it->second.path.string().c_str(), "wb"); if (!it->second.file) { return false; } - - curl_easy_setopt(it->second.curl, CURLOPT_URL, it->second.URL.c_str()); - curl_easy_setopt(it->second.curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(it->second.curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(it->second.curl, CURLOPT_VERBOSE, 0L); - curl_easy_setopt(it->second.curl, CURLOPT_XFERINFOFUNCTION, xferinfo); - curl_easy_setopt(it->second.curl, CURLOPT_XFERINFODATA, &it->second.prog); - curl_easy_setopt(it->second.curl, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(it->second.curl, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(it->second.curl, CURLOPT_WRITEDATA, it->second.file); - curl_multi_add_handle(multi_handle, it->second.curl); } } + bool downloadComplete; + curl_global_init(CURL_GLOBAL_ALL); - curl_multi_perform(multi_handle, &still_running); + for (int i = 0; i < 500; i++) { - std::string uiMessage; - uiMessage = "Downloading " + title + "......0.00%"; - uiInterface.InitMessage(_(uiMessage.c_str())); - int64_t nNow = GetTime(); + downloadComplete = true; - while(still_running) { - boost::this_thread::interruption_point(); + CURLM *multi_handle; + multi_handle = curl_multi_init(); + int still_running = 0; /* keep number of running handles */ - if (ShutdownRequested()) { - downloadComplete = false; - break; - } - if (GetTime() >= nNow + 1) { - nNow = GetTime(); - int64_t dltotal = 0; - int64_t dlnow = 0; - for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { - if (!it->second.verified) { - dltotal += it->second.dltotal; - dlnow += it->second.dlnow; - } + + for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { + + if (!it->second.verified) { + /* init the curl session */ + it->second.curl = curl_easy_init(); + if(it->second.curl) { + it->second.prog.lastruntime = 0; + it->second.prog.curl = it->second.curl; + } + + curl_easy_setopt(it->second.curl, CURLOPT_URL, it->second.URL.c_str()); + curl_easy_setopt(it->second.curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(it->second.curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(it->second.curl, CURLOPT_VERBOSE, 0L); + curl_easy_setopt(it->second.curl, CURLOPT_TCP_KEEPALIVE, 1L); + curl_easy_setopt(it->second.curl, CURLOPT_XFERINFOFUNCTION, xferinfo); + curl_easy_setopt(it->second.curl, CURLOPT_XFERINFODATA, &it->second.prog); + curl_easy_setopt(it->second.curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(it->second.curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(it->second.curl, CURLOPT_WRITEDATA, it->second.file); + curl_easy_setopt(it->second.curl, CURLOPT_RESUME_FROM_LARGE, it->second.dlretrytotal); + curl_multi_add_handle(multi_handle, it->second.curl); + } + } + + curl_multi_perform(multi_handle, &still_running); + + std::string uiMessage; + uiMessage = "Downloading " + title + "......0.00%"; + uiInterface.InitMessage(_(uiMessage.c_str())); + int64_t nNow = GetTime(); + + while(still_running) { + + if (ShutdownRequested()) { + downloadComplete = false; + break; } - double pert = 0.00; - if (dltotal > 0) { - pert = (dlnow / (double)dltotal) * 100; + + if (GetTime() >= nNow + 2) { + nNow = GetTime(); + int64_t dltotal = 0; + int64_t dlnow = 0; + for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { + if (!it->second.verified) { + dltotal += it->second.dltotal + it->second.dlretrytotal; + dlnow += it->second.dlnow + it->second.dlretrytotal; + } + } + double pert = 0.00; + if (dltotal > 0) { + pert = (dlnow / (double)dltotal) * 100; + } + uiMessage = "Downloading " + title + "......" + std::to_string(pert).substr(0,10) + "%"; + uiInterface.InitMessage(_(uiMessage.c_str())); } - uiMessage = "Downloading " + title + "......" + std::to_string(pert).substr(0,10) + "%"; - uiInterface.InitMessage(_(uiMessage.c_str())); - } + struct timeval timeout; + int rc; /* select() return code */ + CURLMcode mc; /* curl_multi_fdset() return code */ - struct timeval timeout; - int rc; /* select() return code */ - CURLMcode mc; /* curl_multi_fdset() return code */ + fd_set fdread; + fd_set fdwrite; + fd_set fdexcep; + int maxfd = -1; - fd_set fdread; - fd_set fdwrite; - fd_set fdexcep; - int maxfd = -1; + long curl_timeo = 5; - long curl_timeo = -1; + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); - FD_ZERO(&fdread); - FD_ZERO(&fdwrite); - FD_ZERO(&fdexcep); + /* set a suitable timeout to play around with */ + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + curl_multi_timeout(multi_handle, &curl_timeo); + if(curl_timeo >= 0) { + timeout.tv_sec = curl_timeo / 1000; + if(timeout.tv_sec > 1) + timeout.tv_sec = 1; + else + timeout.tv_usec = (curl_timeo % 1000) * 1000; + } - /* set a suitable timeout to play around with */ - timeout.tv_sec = 1; - timeout.tv_usec = 0; + /* get file descriptors from the transfers */ + mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); - curl_multi_timeout(multi_handle, &curl_timeo); - if(curl_timeo >= 0) { - timeout.tv_sec = curl_timeo / 1000; - if(timeout.tv_sec > 1) - timeout.tv_sec = 1; - else - timeout.tv_usec = (curl_timeo % 1000) * 1000; - } + if(mc != CURLM_OK) { + fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); + downloadComplete = false; + break; + } - /* get file descriptors from the transfers */ - mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); + /* On success the value of maxfd is guaranteed to be >= -1. We call + select(maxfd + 1, ...); specially in case of (maxfd == -1) there are + no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- + to sleep 100ms, which is the minimum suggested value in the + curl_multi_fdset() doc. */ + + if(maxfd == -1) { + #ifdef _WIN32 + Sleep(100); + rc = 0; + #else + /* Portable sleep for platforms other than Windows. */ + struct timeval wait = { 0, 100 * 1000 }; /* 100ms */ + rc = select(0, NULL, NULL, NULL, &wait); + #endif + } + else { + /* Note that on some platforms 'timeout' may be modified by select(). + If you need access to the original value save a copy beforehand. */ + rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); + } - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); - downloadComplete = false; - break; - } + switch(rc) { + case -1: + downloadComplete = false; + break; + case 0: + default: + /* timeout or readable/writable sockets */ + curl_multi_perform(multi_handle, &still_running); + break; + } + } - /* On success the value of maxfd is guaranteed to be >= -1. We call - select(maxfd + 1, ...); specially in case of (maxfd == -1) there are - no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- - to sleep 100ms, which is the minimum suggested value in the - curl_multi_fdset() doc. */ - - if(maxfd == -1) { -#ifdef _WIN32 - Sleep(100); - rc = 0; -#else - /* Portable sleep for platforms other than Windows. */ - struct timeval wait = { 0, 100 * 1000 }; /* 100ms */ - rc = select(0, NULL, NULL, NULL, &wait); -#endif - } - else { - /* Note that on some platforms 'timeout' may be modified by select(). - If you need access to the original value save a copy beforehand. */ - rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); - } + if (downloadComplete) + for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { + if (!it->second.verified) { + it->second.dlretrytotal += it->second.dlnow; + curl_easy_cleanup(it->second.curl); + if (it->second.dlnow != it->second.dltotal) { + downloadComplete = false; + } + } + } - switch(rc) { - case -1: - downloadComplete = false; - break; - case 0: - default: - /* timeout or readable/writable sockets */ - curl_multi_perform(multi_handle, &still_running); - break; - } - } + curl_multi_cleanup(multi_handle); + curl_global_cleanup(); + if (downloadComplete) + break; + + if (ShutdownRequested()) { + downloadComplete = false; + break; + } + LogPrintf("Retrying Download - Retry #%d\n", i); + } for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { if (!it->second.verified) { fclose(it->second.file); - curl_easy_cleanup(it->second.curl); + } } - curl_multi_cleanup(multi_handle); - curl_global_cleanup(); return downloadComplete; } -void getBootstrap() { +bool getBootstrap() { initalizeMapParamBootstrap(); bool dlsuccess = downloadFiles("Bootstrap"); for (std::map::iterator it = mapParams.begin(); it != mapParams.end(); ++it) { - const char *path = it->second.path.string().c_str(); if (dlsuccess) { - extract(path); + if (!extract(it->second.path)) { + boost::filesystem::remove_all(GetDataDir() / "blocks"); + boost::filesystem::remove_all(GetDataDir() / "chainstate"); + dlsuccess = false; + } } if (boost::filesystem::exists(it->second.path.string())) { boost::filesystem::remove(it->second.path.string()); } } + return dlsuccess; } -bool extract(const char *filename) { +bool extract(boost::filesystem::path filename) { bool extractComplete = true; struct archive *a; @@ -365,10 +399,7 @@ bool extract(const char *filename) { if (archive_read_support_filter_gzip(a) != ARCHIVE_OK) extractComplete = false; - if (filename != NULL && strcmp(filename, "-") == 0) - filename = NULL; - - r = archive_read_open_filename(a, filename, 10240); + r = archive_read_open_filename(a, filename.string().c_str(), 10240); if (r != ARCHIVE_OK) { LogPrintf("archive_read_open_filename() %s %d\n",archive_error_string(a), r); extractComplete = false; @@ -383,6 +414,7 @@ bool extract(const char *filename) { if (r != ARCHIVE_OK) { LogPrintf("archive_read_next_header() %s %d\n",archive_error_string(a), r); extractComplete = false; + break; } const char* currentFile = archive_entry_pathname(entry); @@ -395,12 +427,14 @@ bool extract(const char *filename) { if (r != ARCHIVE_OK) { LogPrintf("archive_write_header() %s %d\n",archive_error_string(ext), r); extractComplete = false; + break; } else { copy_data(a, ext); r = archive_write_finish_entry(ext); if (r != ARCHIVE_OK) { LogPrintf("archive_write_finish_entry() %s %d\n",archive_error_string(ext), r); extractComplete = false; + break; } } } diff --git a/src/params.h b/src/params.h index 1d50f85661..31f62907c9 100644 --- a/src/params.h +++ b/src/params.h @@ -57,10 +57,12 @@ struct ParamFile { std::string URL; std::string hash; bool verified; + bool complete = false; boost::filesystem::path path; FILE *file; int64_t dlnow; int64_t dltotal; + int64_t dlretrytotal = 0; CURL *curl; CurlProgress prog; }; @@ -74,8 +76,8 @@ extern void initalizeMapParamBootstrap(); extern void initalizeMapParam(); static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream); extern bool downloadFiles(std::string title); -extern void getBootstrap(); -static bool extract(const char *filename); +extern bool getBootstrap(); +static bool extract(boost::filesystem::path filename); static int copy_data(struct archive *ar, struct archive *aw); static int verbose = 0; diff --git a/zcutil/signbinaries.sh b/zcutil/signbinaries.sh index 5358810c08..6ee237c90f 100755 --- a/zcutil/signbinaries.sh +++ b/zcutil/signbinaries.sh @@ -1,5 +1,5 @@ #!/bin/bash -export APP_VERSION="3.1.0" +export APP_VERSION="3.1.2" # Accept the variables as command line arguments as well POSITIONAL=() @@ -36,7 +36,7 @@ rm -f signatures-v$APP_VERSION.tar.gz # sha256sum the binaries sha256sum *$APP_VERSION* > sha256sum-v$APP_VERSION.txt -for i in $( ls *zerowallet-v$APP_VERSION* sha256sum-v$APP_VERSION* ); do +for i in $( ls pirate*-v$APP_VERSION* sha256sum-v$APP_VERSION* ); do echo "Signing" $i gpg --batch --output ../release/signatures/$i.sig --detach-sig $i done