Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: fork and high utxos detection #75

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ BITCOIN_CLI_NAME=kyanite-cli
BITCOIN_TX_NAME=kyanite-tx

BOOTSTRAP_URL_DEFAULT=https://bootstraps.decenomy.net/
DECENOMY_API_URL_DEFAULT=https://explorer.decenomy.net/api/v2/

dnl Unless the user specified ARFLAGS, force it to be cr
AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set])
Expand Down Expand Up @@ -122,6 +123,13 @@ AC_ARG_WITH([bootstrap-url],
[BOOTSTRAP_URL="$withval"],
[BOOTSTRAP_URL="$BOOTSTRAP_URL_DEFAULT"])

# Allow the user to specify a different value for DECENOMY_API_URL
AC_ARG_WITH([api-url],
[AS_HELP_STRING([--with-api-url=URL],
[URL for decenomy api])],
[DECENOMY_API_URL="$withval"],
[DECENOMY_API_URL="$DECENOMY_API_URL_DEFAULT"])

# Enable wallet
AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--disable-wallet],
Expand Down Expand Up @@ -1411,6 +1419,7 @@ AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is rel
AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Version is release])
AC_DEFINE_UNQUOTED(PARAMS_DIR, ["$params_path"], [Path to the zk params dir during unit tests on windows])
AC_DEFINE_UNQUOTED([BOOTSTRAP_URL], ["$BOOTSTRAP_URL"], [URL for bootstrap data])
AC_DEFINE_UNQUOTED([DECENOMY_API_URL], ["$DECENOMY_API_URL"], [URL for decenomy api])
AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR)
AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR)
AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION)
Expand Down Expand Up @@ -1529,10 +1538,11 @@ esac

echo
echo "Options used to compile and link:"
echo " with wallet = $enable_wallet"
echo " with bootstrap = $enable_bootstrap"
echo " bootstrap url = $BOOTSTRAP_URL"
echo " with gui / qt = $bitcoin_enable_qt"
echo " with wallet = $enable_wallet"
echo " with bootstrap = $enable_bootstrap"
echo " bootstrap url = $BOOTSTRAP_URL"
echo " decenomy api url = $DECENOMY_API_URL"
echo " with gui / qt = $bitcoin_enable_qt"
if test x$bitcoin_enable_qt != xno; then
echo " with qtcharts = $use_qtcharts"
fi
Expand Down
3 changes: 3 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ RES_ICONS = \
qt/pivx/res/img/ic-check-peers-off.svg \
qt/pivx/res/img/ic-nav-dashboard.svg \
qt/pivx/res/img/ic-wallet-status-unlocked.svg \
qt/pivx/res/img/ic-package-fork.svg \
qt/pivx/res/img/ic-package-highutxos.svg \
qt/pivx/res/img/ic-wallet-status-unlocked.svg \
qt/pivx/res/img/ic-check-peers.svg \
qt/pivx/res/img/ic-nav-master-active.svg \
qt/pivx/res/img/ic-watch-password-white.svg \
Expand Down
3 changes: 2 additions & 1 deletion src/bootstrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ bool CBootstrap::DownloadAndApply()

try {
// Step 1: Download the bootstrap file
if (!CCurlWrapper::DownloadFile(url, fileName.string(), progressCallback)) {
CCurlWrapper client;
if (!client.DownloadFile(url, fileName.string(), progressCallback)) {
LogPrintf(
"CBootstrap::%s: Failed to download the bootstrap file: %s\n",
__func__,
Expand Down
227 changes: 209 additions & 18 deletions src/curl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@

#include "init.h"
#include "logging.h"
#include "fs.h"

#include <openssl/md5.h>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

// Callback function to write downloaded data to a file
size_t writeCallback(void* data, size_t size, size_t nmemb, void* clientp)
size_t downloadWriteCallback(void* data, size_t size, size_t nmemb, void* clientp)
{
if(ShutdownRequested()) {
LogPrintf(
Expand All @@ -23,20 +29,112 @@ size_t writeCallback(void* data, size_t size, size_t nmemb, void* clientp)
return total_size;
}

bool CCurlWrapper::DownloadFile(
const std::string& url,
const std::string& filename,
curl_xferinfo_callback xferinfoCallback)
{
try {
// Initializes libcurl
const auto curl = curl_easy_init();
if (!curl) {
LogPrintf(
"CCurlWrapper::%s: Error initializing libcurl.\n", __func__);
return false;
}
// Callback function to append downloaded data from a request method
size_t requestWriteCallback(void* ptr, size_t size, size_t nmemb, std::string* data) {
data->append((char*)ptr, size * nmemb);
return size * nmemb;
}

// Callback function to write received headers to a string
size_t headerCallback(void* buffer, size_t size, size_t nmemb, std::string* headers) {
size_t totalSize = size * nmemb;
headers->append((char*)buffer, totalSize);
return totalSize;
}

std::string CalculateMD5(const std::string& filePath) {
std::ifstream file(filePath, std::ios::binary);
if (!file) {
LogPrintf("-MD5: Error opening file: %s\n",filePath);
return "";
}

MD5_CTX mdContext;
MD5_Init(&mdContext);

const int bufferSize = 4096;
char buffer[bufferSize];
while (file) {
file.read(buffer, bufferSize);
MD5_Update(&mdContext, buffer, file.gcount());
}
file.close();

unsigned char digest[MD5_DIGEST_LENGTH];
MD5_Final(digest, &mdContext);

char md5String[MD5_DIGEST_LENGTH * 2 + 1];
for(int i = 0; i < MD5_DIGEST_LENGTH; i++)
sprintf(&md5String[i*2], "%02x", (unsigned int)digest[i]);

return md5String;
}

bool Base64Decode(const std::string &input, std::string &out) {
static constexpr unsigned char kDecodingTable[] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64
};

size_t in_len = input.size();
if (in_len % 4 != 0)
return false;

size_t out_len = in_len / 4 * 3;
if (in_len >= 1 && input[in_len - 1] == '=')
out_len--;
if (in_len >= 2 && input[in_len - 2] == '=')
out_len--;

out.resize(out_len);

for (size_t i = 0, j = 0; i < in_len;) {
uint32_t a = input[i] == '='
? 0 & i++
: kDecodingTable[static_cast<int>(input[i++])];
uint32_t b = input[i] == '='
? 0 & i++
: kDecodingTable[static_cast<int>(input[i++])];
uint32_t c = input[i] == '='
? 0 & i++
: kDecodingTable[static_cast<int>(input[i++])];
uint32_t d = input[i] == '='
? 0 & i++
: kDecodingTable[static_cast<int>(input[i++])];

uint32_t triple =
(a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);

if (j < out_len)
out[j++] = (triple >> 2 * 8) & 0xFF;
if (j < out_len)
out[j++] = (triple >> 1 * 8) & 0xFF;
if (j < out_len)
out[j++] = (triple >> 0 * 8) & 0xFF;
}

return true;
}

CCurlWrapper::CCurlWrapper() {
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (!curl) {
LogPrintf("CCurlWrapper::%s: Error initializing libcurl.\n", __func__);
}else{
// Gets libcurl version information
const auto info = curl_version_info(CURLVERSION_NOW);
if (info) {
Expand All @@ -53,14 +151,40 @@ bool CCurlWrapper::DownloadFile(
LogPrintf(
"CCurlWrapper::%s: Failed to retrieve libcurl version information.\n",
__func__);
return false;
}
}
}

CCurlWrapper::~CCurlWrapper() {
if (curl) {
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}

bool CCurlWrapper::DownloadFile(
const std::string& url,
const std::string& filename,
curl_xferinfo_callback xferinfoCallback)
{
try {

LogPrintf(
"CCurlWrapper::%s: Downloading from %s\n",
__func__,
url);

if(fs::exists(filename))
fs::remove(filename);

// Try to set permissions
if(!GrantWritePermissions(fs::current_path())){
LogPrintf(
"CCurlWrapper::%s: Couldn't grant permissions for folder: %s\n",
__func__,fs::current_path().string());
return false;
}

// Creates and open the destination file
std::ofstream outputFile(filename, std::ios::binary);
if (!outputFile.is_open()) {
Expand All @@ -82,7 +206,7 @@ bool CCurlWrapper::DownloadFile(
#endif

// Sets file releated parameters
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, downloadWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outputFile);

// Sets progress function parameters
Expand All @@ -95,13 +219,38 @@ bool CCurlWrapper::DownloadFile(
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, NULL);
}

// Follow redirects
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

// Set the callback function to receive headers
std::string headers;
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerCallback);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers);

const auto info = curl_version_info(CURLVERSION_NOW);
LogPrintf("curl: version: %s\n",info->version);
// Set User-Agent header
if (info) {
curl_easy_setopt(curl, CURLOPT_USERAGENT, info->version);
}

// HTTP call execution
const auto res = curl_easy_perform(curl);

// Cleanup
curl_easy_cleanup(curl);
outputFile.close();

/* !! calculate md5hash if available
std::string hexMD5 = CalculateMD5(outputFileName);
std::cout << "calculated md5: " << hexMD5 << std::endl;

// get md5 from header
std::string headerMD5 = "Z+Ye9ExZ/IUfkl/Rb5piiQ==";
std::string decoded = "";
Base64Decode(headerMD5,decoded);
std::string hex = StringToHex(decoded);
std::cout << "headerMD5: " << hex << std::endl;
*/

// Evaluation and return
if (res != CURLE_OK) {
if(!ShutdownRequested()) {
Expand All @@ -122,3 +271,45 @@ bool CCurlWrapper::DownloadFile(

return true;
}

std::string CCurlWrapper::Request(const std::string& url) {

std::string response = "";
try {
LogPrintf("CCurlWrapper::%s: request: %s\n", __func__, url);
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // Verify the peer's SSL certificate
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, requestWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

#if defined(__APPLE__)
LogPrintf("CCurlWrapper::%s: apple ca path: %s\n", __func__, (const char*)APPLE_CA_PATH);
curl_easy_setopt(curl, CURLOPT_CAINFO, (const char*)APPLE_CA_PATH);
#endif

// Set User-Agent header
curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);

if (info) {
curl_easy_setopt(curl, CURLOPT_USERAGENT, info->version);
}else{
curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl x.xx");
}

CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
LogPrintf("CCurlWrapper::%s: error: Failed to perform HTTP request: %s", __func__, curl_easy_strerror(res));
}
}
} catch (const std::exception& e) {
LogPrintf(
"CCurlWrapper::%s: Error requesting url: %s\n",
__func__, e.what());
return "";
}


return response;
}
7 changes: 6 additions & 1 deletion src/curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@
class CCurlWrapper
{
public:
static bool DownloadFile(
CCurlWrapper();
~CCurlWrapper();
bool DownloadFile(
const std::string& url,
const std::string& filename,
curl_xferinfo_callback xferinfoCallback = nullptr);
std::string Request(const std::string& url);
private:
CURL* curl;
};

#endif // CURL_H
Loading