From 7ae7594d4aa5dd5ee5450a298bbca6c9954dbd50 Mon Sep 17 00:00:00 2001 From: retsediv Date: Thu, 2 Aug 2018 12:52:07 +0300 Subject: [PATCH 01/22] Add console argument for solo mining and path to the meritd --- src/minerd.cpp | 68 +++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/src/minerd.cpp b/src/minerd.cpp index d6b7053..3be886b 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -55,11 +55,15 @@ int main(int argc, char** argv) std::string url; std::vector gpu_devices; std::string address; + bool solo_mining; + std::string path_to_meritd_folder; desc.add_options() ("help", "show the help message") ("infogpu", "show the info about GPU in your system") ("url", po::value(&url)->default_value("stratum+tcp://pool.merit.me:3333"), "The stratum pool url") ("address", po::value(&address), "The address to send mining rewards to.") + ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") + ("meritd", po::value(&path_to_meritd_folder)->default_value("./"), "Path to the folder with meritd daemon") ("gpu", po::value>(&gpu_devices)->multitoken(), "Index of GPU device to use in mining(can use multiple times). For more info check --infogpu") ("cores", po::value()->default_value(merit::number_of_cores()), "The number of CPU cores to use."); @@ -99,39 +103,45 @@ int main(int argc, char** argv) cores = std::max(0, cores); auto utilization = determine_utilization(cores); - std::unique_ptr c{ - merit::create_context(), &merit::delete_context}; + if(solo_mining){ + std::cout << "info: " << "Starting solo mining..." << std::endl; + std::cout << "info: " << "Path to meritd: " << path_to_meritd_folder << std::endl; - merit::set_agent(c.get(), "merit-minerd", "0.2"); + } else { + std::unique_ptr c{ + merit::create_context(), &merit::delete_context}; - if(!merit::connect_stratum(c.get(), url.c_str(), address.c_str(), "")) { - std::cerr << "Error connecting" << std::endl; - return 1; - } - merit::run_stratum(c.get()); - merit::run_miner(c.get(), utilization.first ,utilization.second, gpu_devices); - - int prev_graphs = 0; - while(true) { - using namespace std::chrono_literals; - std::this_thread::sleep_for(5s); - - auto stats = merit::get_miner_stats(c.get()); - auto graphs = stats.total.attempts + stats.current.attempts; - auto cycles = stats.total.cycles + stats.current.cycles; - auto shares = stats.total.shares + stats.current.shares; - auto graphps = stats.total.attempts_per_second; - auto cyclesps = stats.total.cycles_per_second; - auto sharesps = stats.total.shares_per_second; - if(graphs > prev_graphs) { - std::cout << "graphs: " << graphs << " cycles: " << cycles << " shares: " << shares; - if(stats.total.attempts > 0) { - std::cout << " graphs/s: " << graphps << " cycles/s: " << cyclesps << " shares/s: " << sharesps << std::endl; + merit::set_agent(c.get(), "merit-minerd", "0.2"); + + if (!merit::connect_stratum(c.get(), url.c_str(), address.c_str(), "")) { + std::cerr << "Error connecting" << std::endl; + return 1; + } + merit::run_stratum(c.get()); + merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices); + + int prev_graphs = 0; + while (true) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(5s); + + auto stats = merit::get_miner_stats(c.get()); + auto graphs = stats.total.attempts + stats.current.attempts; + auto cycles = stats.total.cycles + stats.current.cycles; + auto shares = stats.total.shares + stats.current.shares; + auto graphps = stats.total.attempts_per_second; + auto cyclesps = stats.total.cycles_per_second; + auto sharesps = stats.total.shares_per_second; + if (graphs > prev_graphs) { + std::cout << "graphs: " << graphs << " cycles: " << cycles << " shares: " << shares; + if (stats.total.attempts > 0) { + std::cout << " graphs/s: " << graphps << " cycles/s: " << cyclesps << " shares/s: " << sharesps + << std::endl; + } + std::cout << std::endl; } - std::cout << std::endl; + prev_graphs = graphs; } - prev_graphs = graphs; } - return 0; } From 0f6c4326be0676cebead04d4da68073b634f120f Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 6 Aug 2018 12:40:13 +0300 Subject: [PATCH 02/22] Connecting to the solo mining server --- include/merit/miner.hpp | 8 +- include/merit/stratum/stratum.hpp | 1 + src/minerd.cpp | 88 +++++----- src/public.cpp | 281 +++++++++++++++++------------- src/stratum/stratum.cpp | 5 + 5 files changed, 217 insertions(+), 166 deletions(-) diff --git a/include/merit/miner.hpp b/include/merit/miner.hpp index 28031f5..b87bd04 100644 --- a/include/merit/miner.hpp +++ b/include/merit/miner.hpp @@ -23,6 +23,12 @@ namespace merit const char* user, const char* pass); + bool connect_solo_stratum( + Context* c, + const char* url, + const char* user, + const char* pass); + void disconnect_stratum(Context* c); bool is_stratum_connected(Context* c); @@ -40,7 +46,7 @@ namespace merit int fan_speed; }; - bool run_miner(Context*, int workers, int threads_per_worker, const std::vector& gpu_devices); + bool run_miner(Context*, int workers, int threads_per_worker, const std::vector& gpu_devices, bool solo_mining); void stop_miner(Context*); bool is_stratum_running(Context*); bool is_miner_running(Context*); diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index 4971a0f..ef6cdbd 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -95,6 +95,7 @@ namespace merit bool stopping() const; MaybeJob get_job(); + MaybeJob get_solo_job(const std::string& path_to_meritd); void submit_work(const util::Work&); diff --git a/src/minerd.cpp b/src/minerd.cpp index 3be886b..813d476 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -56,21 +56,24 @@ int main(int argc, char** argv) std::vector gpu_devices; std::string address; bool solo_mining; - std::string path_to_meritd_folder; + std::string solo_url; desc.add_options() - ("help", "show the help message") - ("infogpu", "show the info about GPU in your system") - ("url", po::value(&url)->default_value("stratum+tcp://pool.merit.me:3333"), "The stratum pool url") - ("address", po::value(&address), "The address to send mining rewards to.") - ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") - ("meritd", po::value(&path_to_meritd_folder)->default_value("./"), "Path to the folder with meritd daemon") - ("gpu", po::value>(&gpu_devices)->multitoken(), "Index of GPU device to use in mining(can use multiple times). For more info check --infogpu") - ("cores", po::value()->default_value(merit::number_of_cores()), "The number of CPU cores to use."); + ("help", "show the help message") + ("infogpu", "show the info about GPU in your system") + ("url", po::value(&url)->default_value("stratum+tcp://pool.merit.me:3333"), + "The stratum pool url") + ("address", po::value(&address), "The address to send mining rewards to.") + ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") + ("soloaddress", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), + "Solo mining stratum server url") + ("gpu", po::value>(&gpu_devices)->multitoken(), + "Index of GPU device to use in mining(can use multiple times). For more info check --infogpu") + ("cores", po::value()->default_value(merit::number_of_cores()), "The number of CPU cores to use."); po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); + po::notify(vm); if (vm.count("help")) { std::cout << desc << std::endl;; @@ -80,7 +83,7 @@ int main(int argc, char** argv) if (vm.count("infogpu")) { auto info = merit::gpus_info(); std::cout << "GPU info:" << std::endl; - for(const auto &item: info){ + for (const auto &item: info) { std::cout << "Device number: " << item.id << std::endl; std::cout << "Total memory: " << item.total_memory << std::endl; std::cout << "Title: " << item.title << std::endl; @@ -93,7 +96,7 @@ int main(int argc, char** argv) return 1; } - if(address.empty()) { + if (address.empty()) { std::cout << "forgot to set your reward address. use --address" << std::endl; return 1; } @@ -103,45 +106,48 @@ int main(int argc, char** argv) cores = std::max(0, cores); auto utilization = determine_utilization(cores); - if(solo_mining){ - std::cout << "info: " << "Starting solo mining..." << std::endl; - std::cout << "info: " << "Path to meritd: " << path_to_meritd_folder << std::endl; + std::unique_ptr c{ + merit::create_context(), &merit::delete_context}; - } else { - std::unique_ptr c{ - merit::create_context(), &merit::delete_context}; + merit::set_agent(c.get(), "merit-minerd", "0.2"); - merit::set_agent(c.get(), "merit-minerd", "0.2"); + if(!solo_mining){ if (!merit::connect_stratum(c.get(), url.c_str(), address.c_str(), "")) { std::cerr << "Error connecting" << std::endl; return 1; } merit::run_stratum(c.get()); - merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices); - - int prev_graphs = 0; - while (true) { - using namespace std::chrono_literals; - std::this_thread::sleep_for(5s); - - auto stats = merit::get_miner_stats(c.get()); - auto graphs = stats.total.attempts + stats.current.attempts; - auto cycles = stats.total.cycles + stats.current.cycles; - auto shares = stats.total.shares + stats.current.shares; - auto graphps = stats.total.attempts_per_second; - auto cyclesps = stats.total.cycles_per_second; - auto sharesps = stats.total.shares_per_second; - if (graphs > prev_graphs) { - std::cout << "graphs: " << graphs << " cycles: " << cycles << " shares: " << shares; - if (stats.total.attempts > 0) { - std::cout << " graphs/s: " << graphps << " cycles/s: " << cyclesps << " shares/s: " << sharesps - << std::endl; - } - std::cout << std::endl; + } else { + if (!merit::connect_solo_stratum(c.get(), solo_url.c_str(), address.c_str(), "")) { + std::cerr << "Error connecting" << std::endl; + return 1; + } + } + + merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining); + + int prev_graphs = 0; + while (true) { + using namespace std::chrono_literals; + std::this_thread::sleep_for(5s); + + auto stats = merit::get_miner_stats(c.get()); + auto graphs = stats.total.attempts + stats.current.attempts; + auto cycles = stats.total.cycles + stats.current.cycles; + auto shares = stats.total.shares + stats.current.shares; + auto graphps = stats.total.attempts_per_second; + auto cyclesps = stats.total.cycles_per_second; + auto sharesps = stats.total.shares_per_second; + if (graphs > prev_graphs) { + std::cout << "graphs: " << graphs << " cycles: " << cycles << " shares: " << shares; + if (stats.total.attempts > 0) { + std::cout << " graphs/s: " << graphps << " cycles/s: " << cyclesps << " shares/s: " << sharesps + << std::endl; } - prev_graphs = graphs; + std::cout << std::endl; } + prev_graphs = graphs; } return 0; } diff --git a/src/public.cpp b/src/public.cpp index 0da23de..ad31a43 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -33,19 +33,13 @@ #include "merit/miner/miner.hpp" #include -#include -#include -#include -#include //forward declare SetupBuffers which is in kernel.cu int SetupKernelBuffers(); -namespace merit -{ +namespace merit { - struct Context - { + struct Context { stratum::Client stratum; std::unique_ptr miner; util::SubmitWorkFunc submit_work_func; @@ -55,247 +49,286 @@ namespace merit std::thread collab_thread; }; - Context* create_context() - { + Context *create_context() { return new Context; } - void delete_context(Context* c) - { - if(c) { delete c;} + void delete_context(Context *c) { + if (c) { delete c; } } - void set_agent(Context* c, const char* software, const char* version) - { + void set_agent(Context *c, const char *software, const char *version) { assert(c); c->stratum.set_agent(software, version); } bool connect_stratum( - Context* c, - const char* url, - const char* user, - const char* pass) - try - { + Context *c, + const char *url, + const char *user, + const char *pass) + try { assert(c); - std::cerr << "info: " << "connecting to: " << url<< std::endl; - if(!c->stratum.connect(url, user, pass)) { - std::cerr << "error: " << "error connecting to stratum server: " << url<< std::endl; + std::cerr << "info: " << "connecting to: " << url << " with user = " << user << " pass = " << pass << std::endl; + if (!c->stratum.connect(url, user, pass)) { + std::cerr << "error: " << "error connecting to stratum server: " << url << std::endl; return false; } - std::cerr << "info: " << "subscribing to: " << url<< std::endl; - if(!c->stratum.subscribe()) { - std::cerr << "error: " << "error subscribing to stratum server: " << url<< std::endl; + std::cerr << "info: " << "subscribing to: " << url << std::endl; + if (!c->stratum.subscribe()) { + std::cerr << "error: " << "error subscribing to stratum server: " << url << std::endl; return false; } - std::cerr << "info: " << "authorizing as: " << user<< std::endl; - if(!c->stratum.authorize()) { - std::cerr << "error: " << "error authorize to stratum server: " << url<< std::endl; + std::cerr << "info: " << "authorizing as: " << user << std::endl; + if (!c->stratum.authorize()) { + std::cerr << "error: " << "error authorize to stratum server: " << url << std::endl; return false; } - c->submit_work_func = [c](const util::Work& w) { + c->submit_work_func = [c](const util::Work &w) { c->stratum.submit_work(w); }; - std::cerr << "info: " << "connected to: " << url<< std::endl; + std::cerr << "info: " << "connected to: " << url << std::endl; return true; } - catch(std::exception& e) - { - std::cerr << "error: " << "error connecting to stratum server: " << e.what()<< std::endl; + catch (std::exception &e) { + std::cerr << "error: " << "error connecting to stratum server: " << e.what() << std::endl; c->stratum.disconnect(); return false; } - void disconnect_stratum(Context* c) + bool connect_solo_stratum( + Context *c, + const char *url, + const char *user, + const char *pass) { assert(c); + + std::cerr << "info: " << "connecting to: " << url << " with user = " << user << " pass = " << pass << std::endl; + if (!c->stratum.connect(url, user, pass)) { + std::cerr << "error: " << "error connecting to stratum server: " << url << std::endl; + return false; + } + + return true; + } + + void disconnect_stratum(Context *c) { + assert(c); c->stratum.disconnect(); } - bool is_stratum_connected(Context* c) - { + bool is_stratum_connected(Context *c) { assert(c); return c->stratum.connected(); } - - void init() - { + + void init() { ::SetupKernelBuffers(); } - bool run_stratum(Context* c) - { + bool run_stratum(Context *c) { assert(c); - if(c->stratum.running()) { + if (c->stratum.running()) { stop_stratum(c); return false; } - if(c->stratum_thread.joinable()) { + if (c->stratum_thread.joinable()) { c->stratum_thread.join(); } c->stratum_thread = std::thread([c]() { - try { - c->stratum.run(); - } catch(std::exception& e) { - std::cerr << "error: " << "error running stratum: " << e.what()<< std::endl; - } - c->stratum.disconnect(); - std::cerr << "info: " << "stopped stratum."<< std::endl; + try { + c->stratum.run(); + } catch (std::exception &e) { + std::cerr << "error: " << "error running stratum: " << e.what() << std::endl; + } + c->stratum.disconnect(); + std::cerr << "info: " << "stopped stratum." << std::endl; }); return true; } - void stop_stratum(Context* c) - { + void stop_stratum(Context *c) { assert(c); - std::cerr << "info: " << "stopping stratum..."<< std::endl; + std::cerr << "info: " << "stopping stratum..." << std::endl; c->stratum.stop(); } - bool run_miner(Context* c, int workers, int threads_per_worker, const std::vector& gpu_devices) - try - { + bool run_miner(Context *c, int workers, int threads_per_worker, + const std::vector &gpu_devices, bool solo_mining) + try { assert(c); using namespace std::chrono_literals; - if(c->miner && c->miner->running()) { + if (c->miner && c->miner->running()) { stop_miner(c); return false; } c->miner.reset(); - std::cerr << "info: " << "setting up miner..."<< std::endl; + std::cerr << "info: " << "setting up miner..." << std::endl; c->miner = std::make_unique( workers, threads_per_worker, gpu_devices, c->submit_work_func); - std::cerr << "info: " << "starting miner..."<< std::endl; - if(c->mining_thread.joinable()) { + std::cerr << "info: " << "starting miner..." << std::endl; + if (c->mining_thread.joinable()) { c->mining_thread.join(); } c->mining_thread = std::thread([c]() { - try { - c->miner->run(); - } catch(std::exception& e) { - c->miner->stop(); - std::cerr << "error: " << e.what() << std::endl; - - return false; - } + try { + c->miner->run(); + } catch (std::exception &e) { + c->miner->stop(); + std::cerr << "error: " << e.what() << std::endl; + + return false; + } }); //TODO: different logic depending on stratum vs solo - std::cerr << "info: " << "starting collab thread..."<< std::endl; - if(c->collab_thread.joinable()) { + std::cerr << "info: " << "starting collab thread..." << std::endl; + if (c->collab_thread.joinable()) { c->collab_thread.join(); } - c->collab_thread = std::thread([c]() { - while(c->miner->state() != miner::Miner::Running) {} - while(c->miner->running()) - try { - auto j = c->stratum.get_job(); - if(!j) { - if(!c->stratum.connected()) { - c->miner->clear_job(); - } + + if (solo_mining) { + std::cout << "info: " << "Starting solo mining..." << std::endl; + + c->collab_thread = std::thread([c]() { + while (c->miner->state() != miner::Miner::Running) {} + + std::cout << "Miner is Running and ready to start getting job and then mine it" << std::endl; + + // TODO: fix this when implementing server support for solo mining + c->stratum.stop(); // disconnect from server + + while (c->miner->running()) + try { +// auto j = c->stratum.get_solo_job(path_to_meritd); + +// std::cout << "After getting the job" << std::endl; +// if (!j) { +// if (!c->stratum.connected()) { +// c->miner->clear_job(); +// } +// std::this_thread::sleep_for(50ms); +// continue; +// } +// +// c->miner->submit_job(*j); + + // get block + + // mine it + + // if good cycle, then submit block + + // again... + + } catch (std::exception &e) { + std::cerr << "error: " << "error getting job: " << e.what() << std::endl; std::this_thread::sleep_for(50ms); - continue; } + }); + } else { + c->collab_thread = std::thread([c]() { + while (c->miner->state() != miner::Miner::Running) {} + while (c->miner->running()) + try { + auto j = c->stratum.get_job(); + if (!j) { + if (!c->stratum.connected()) { + c->miner->clear_job(); + } + std::this_thread::sleep_for(50ms); + continue; + } - c->miner->submit_job(*j); + c->miner->submit_job(*j); - } catch(std::exception& e) { - std::cerr << "error: " << "error getting job: " << e.what()<< std::endl; - std::this_thread::sleep_for(50ms); - } - }); - return true; + } catch (std::exception &e) { + std::cerr << "error: " << "error getting job: " << e.what() << std::endl; + std::this_thread::sleep_for(50ms); + } + }); + return true; + } } - catch(std::exception& e) - { - std::cerr << "error: " << "error starting miners: " << e.what()<< std::endl; + catch (std::exception &e) { + std::cerr << "error: " << "error starting miners: " << e.what() << std::endl; return false; } - void stop_miner(Context* c) - { + void stop_miner(Context *c) { assert(c); - if(!c->miner) { + if (!c->miner) { return; } c->miner->stop(); } - bool is_stratum_running(Context* c) - { + bool is_stratum_running(Context *c) { assert(c); return c->stratum.running(); } - bool is_miner_running(Context* c) - { + bool is_miner_running(Context *c) { assert(c); return c->miner && c->miner->running(); } - bool is_stratum_stopping(Context* c) - { + bool is_stratum_stopping(Context *c) { assert(c); return c->stratum.stopping(); } - bool is_miner_stopping(Context* c) - { + bool is_miner_stopping(Context *c) { assert(c); - return c->miner && c->miner->stopping(); + return c->miner && c->miner->stopping(); } - int number_of_cores() - { + int number_of_cores() { return std::thread::hardware_concurrency(); } - int number_of_gpus() - { + int number_of_gpus() { return miner::GpuDevices(); } - size_t free_memory_on_gpu(int device){ + size_t free_memory_on_gpu(int device) { return miner::CudaGetFreeMemory(device); }; - MinerStat to_public_stat(const miner::Stat& s) - { + MinerStat to_public_stat(const miner::Stat &s) { return { - s.start.time_since_epoch().count(), - s.end.time_since_epoch().count(), - s.seconds(), - s.attempts_per_second(), - s.cycles_per_second(), - s.shares_per_second(), - s.attempts, - s.cycles, - s.shares + s.start.time_since_epoch().count(), + s.end.time_since_epoch().count(), + s.seconds(), + s.attempts_per_second(), + s.cycles_per_second(), + s.shares_per_second(), + s.attempts, + s.cycles, + s.shares }; } - MinerStats get_miner_stats(Context* c) - { + MinerStats get_miner_stats(Context *c) { assert(c); - if(!c->miner) return {}; + if (!c->miner) return {}; auto total = c->miner->total_stats(); auto history = c->miner->stats(); @@ -315,7 +348,7 @@ namespace merit return s; } - std::vector gpus_info(){ + std::vector gpus_info() { return miner::GPUInfo(); }; diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 8a098f6..d987e7f 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -578,6 +578,11 @@ namespace merit return _job; } + MaybeJob Client::get_solo_job(const std::string& path_to_meritd) + { + + } + void Client::submit_work(const util::Work& w) { std::string xnonce2_hex; From 4a9f8feb201a27a1dd71c601275eaf413f005c34 Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 6 Aug 2018 16:56:42 +0300 Subject: [PATCH 03/22] getblocktemplate call --- include/merit/stratum/stratum.hpp | 2 +- src/minerd.cpp | 4 +++- src/public.cpp | 30 +++++++++++++++++++++++------- src/stratum/stratum.cpp | 22 +++++++++++++++++++++- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index ef6cdbd..fd41da1 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -95,7 +95,7 @@ namespace merit bool stopping() const; MaybeJob get_job(); - MaybeJob get_solo_job(const std::string& path_to_meritd); + MaybeJob get_solo_job(); void submit_work(const util::Work&); diff --git a/src/minerd.cpp b/src/minerd.cpp index 813d476..598832d 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -64,7 +64,7 @@ int main(int argc, char** argv) "The stratum pool url") ("address", po::value(&address), "The address to send mining rewards to.") ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") - ("soloaddress", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), + ("solourl", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), "Solo mining stratum server url") ("gpu", po::value>(&gpu_devices)->multitoken(), "Index of GPU device to use in mining(can use multiple times). For more info check --infogpu") @@ -123,6 +123,8 @@ int main(int argc, char** argv) std::cerr << "Error connecting" << std::endl; return 1; } + + merit::run_stratum(c.get()); } merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining); diff --git a/src/public.cpp b/src/public.cpp index ad31a43..8122e15 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -107,15 +107,28 @@ namespace merit { const char *user, const char *pass) { - assert(c); + try { + assert(c); - std::cerr << "info: " << "connecting to: " << url << " with user = " << user << " pass = " << pass << std::endl; - if (!c->stratum.connect(url, user, pass)) { - std::cerr << "error: " << "error connecting to stratum server: " << url << std::endl; + std::cerr << "info: " << "connecting to: " << url << " with user = " << user << " pass = " << pass + << std::endl; + if (!c->stratum.connect(url, user, pass)) { + std::cerr << "error: " << "error connecting to stratum server: " << url << std::endl; + return false; + } + +// c->submit_work_func = [c](const util::Work &w) { +// c->stratum.submit_work(w); +// }; + + std::cerr << "info: " << "connected to: " << url << std::endl; + + return true; + } catch (std::exception &e) { + std::cerr << "error: " << "error connecting to stratum server: " << e.what() << std::endl; + c->stratum.disconnect(); return false; } - - return true; } void disconnect_stratum(Context *c) { @@ -216,8 +229,11 @@ namespace merit { while (c->miner->running()) try { -// auto j = c->stratum.get_solo_job(path_to_meritd); + auto j = c->stratum.get_solo_job(); + if(j) { + break; + } // std::cout << "After getting the job" << std::endl; // if (!j) { // if (!c->stratum.connected()) { diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index d987e7f..33246ad 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -194,11 +194,13 @@ namespace merit boost::asio::connect(_socket, endpoints, e); if(e) { + std::cout << "Error: " << e << std::endl; disconnect(); return false; } if(!set_socket_opts(_socket)) { + std::cout << "Error while setting socket options" << std::endl; return false; } @@ -458,6 +460,7 @@ namespace merit _state = Authorizing; std::stringstream req; req << "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"" << _user << "\", \"" << _pass << "\"]}"; + std::cout << "=== Authorizing: " << req.str() << std::endl; if (!send(req.str())) { std::cerr << "error: " << "error sending authorize request" << std::endl; @@ -578,9 +581,26 @@ namespace merit return _job; } - MaybeJob Client::get_solo_job(const std::string& path_to_meritd) + MaybeJob Client::get_solo_job() { + std::stringstream req; + req << "POST / HTTP/1.1\n" << + "Content-Type: text/plain\n" << + "Authorization: Basic bWVyaXRycGM6TERwaWtWYkRpM2VYX042UHdQZy1OVVk3Q0RCSGtMOG11Z0pjX0JYNTdnVT0=\n" << + "Accept: */*\n" << + "Content-Length: " << 79 + _user.size() << "\n\n" << + "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{}, \""<< _user <<"\"], \"id\": \"9\"}"; + + std::cout << "=== req: " << req.str() << std::endl; + + if(!send(req.str())) { + std::cerr << "error: " << "Error getting blocktemplate for mining: " << req.str() << std::endl; + disconnect(); + } else { + std::cout << "info: " << "blocktemplate: " << req.str() << std::endl; + } + return _job; } void Client::submit_work(const util::Work& w) From 608d950e2c7ba528091cc05a7091eea06bc3c16e Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 13 Aug 2018 11:05:52 +0300 Subject: [PATCH 04/22] Getting blocktemplate --- include/merit/miner.hpp | 2 +- include/merit/stratum/stratum.hpp | 2 +- src/minerd.cpp | 6 +++--- src/public.cpp | 6 +++--- src/stratum/stratum.cpp | 16 +++++++++++++++- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/merit/miner.hpp b/include/merit/miner.hpp index b87bd04..073951e 100644 --- a/include/merit/miner.hpp +++ b/include/merit/miner.hpp @@ -33,7 +33,7 @@ namespace merit bool is_stratum_connected(Context* c); void init(); - bool run_stratum(Context*); + bool run_stratum(Context*, bool solo_mining); void stop_stratum(Context*); struct GPUInfo { diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index fd41da1..e7e7a01 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -88,7 +88,7 @@ namespace merit void disconnect(); bool subscribe(); bool authorize(); - bool run(); + bool run(bool solo_mining); void stop(); bool connected() const; bool running() const; diff --git a/src/minerd.cpp b/src/minerd.cpp index 598832d..dda16c6 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -92,7 +92,7 @@ int main(int argc, char** argv) std::cout << "Memory util: " << item.memory_util << std::endl; std::cout << "Fan speed: " << item.fan_speed << std::endl << std::endl; } - + return 1; } @@ -117,14 +117,14 @@ int main(int argc, char** argv) std::cerr << "Error connecting" << std::endl; return 1; } - merit::run_stratum(c.get()); + merit::run_stratum(c.get(), solo_mining); } else { if (!merit::connect_solo_stratum(c.get(), solo_url.c_str(), address.c_str(), "")) { std::cerr << "Error connecting" << std::endl; return 1; } - merit::run_stratum(c.get()); + merit::run_stratum(c.get(), solo_mining); } merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining); diff --git a/src/public.cpp b/src/public.cpp index 8122e15..7865c66 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -145,7 +145,7 @@ namespace merit { ::SetupKernelBuffers(); } - bool run_stratum(Context *c) { + bool run_stratum(Context *c, bool solo_mining) { assert(c); if (c->stratum.running()) { stop_stratum(c); @@ -156,9 +156,9 @@ namespace merit { c->stratum_thread.join(); } - c->stratum_thread = std::thread([c]() { + c->stratum_thread = std::thread([c, solo_mining]() { try { - c->stratum.run(); + c->stratum.run(solo_mining); } catch (std::exception &e) { std::cerr << "error: " << "error running stratum: " << e.what() << std::endl; } diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 33246ad..e8be0fe 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -508,7 +508,7 @@ namespace merit return true; } - bool Client::run() + bool Client::run(bool solo_mining) { _run_state = Running; while (_run_state == Running) @@ -523,6 +523,12 @@ namespace merit throw std::runtime_error("disconnected."); } + // skip 5 lines of HTTP headers + // TODO: refactor this + if(solo_mining){ + recv(res); recv(res); recv(res); recv(res); recv(res); + } + pt::ptree val; if(!parse_json(res, val)) { _sockbuf.clear(); @@ -530,6 +536,14 @@ namespace merit continue; } + if(solo_mining){ + val.put("method", val.get("id")); + } + + std::ostringstream oss; + pt::write_json(oss, val); + std::cout << "JSON: " << oss.str() << std::endl; + if(!handle_command(val, res)) { continue; } From 88166f1dca2a9d43fca83b6442be7eb7bfd5012c Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 20 Aug 2018 18:30:36 +0300 Subject: [PATCH 05/22] Add method for getting raw(with headers) http response --- include/merit/stratum/stratum.hpp | 1 + src/stratum/stratum.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index e7e7a01..e81258d 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -103,6 +103,7 @@ namespace merit bool reconnect(); bool send(const std::string&); bool recv(std::string&); + bool recv_with_headers(std::string&); void cleanup(); bool subscribe_resp(); bool handle_command(const pt::ptree&, const std::string& res); diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index e8be0fe..69952a4 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -514,7 +514,7 @@ namespace merit while (_run_state == Running) try { std::string res; - if(!recv(res)) { + if((solo_mining && !recv_with_headers(res)) || (!solo_mining && !recv(res))) { std::cerr << "error: " << "error receiving" << std::endl; throw std::runtime_error("error receiving"); } @@ -523,12 +523,6 @@ namespace merit throw std::runtime_error("disconnected."); } - // skip 5 lines of HTTP headers - // TODO: refactor this - if(solo_mining){ - recv(res); recv(res); recv(res); recv(res); recv(res); - } - pt::ptree val; if(!parse_json(res, val)) { _sockbuf.clear(); @@ -537,7 +531,7 @@ namespace merit } if(solo_mining){ - val.put("method", val.get("id")); + val.put("method", val.get("id")); } std::ostringstream oss; @@ -802,6 +796,14 @@ namespace merit return true; } + bool Client::recv_with_headers(std::string& res) + { + // Skip 4 lines with HTTP headers + blank line + recv(res); recv(res); recv(res); recv(res); recv(res); + + return recv(res); + } + void diff_to_target(std::array& target, double diff) { int k; From f8687003a74d4e0b36538234c2478e55b2a9c3dd Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 20 Aug 2018 18:44:24 +0300 Subject: [PATCH 06/22] Add RPC token for solo mining --- include/merit/miner.hpp | 3 ++- include/merit/stratum/stratum.hpp | 2 +- src/minerd.cpp | 5 ++++- src/public.cpp | 9 +++++---- src/stratum/stratum.cpp | 4 ++-- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/merit/miner.hpp b/include/merit/miner.hpp index 073951e..0246029 100644 --- a/include/merit/miner.hpp +++ b/include/merit/miner.hpp @@ -46,7 +46,8 @@ namespace merit int fan_speed; }; - bool run_miner(Context*, int workers, int threads_per_worker, const std::vector& gpu_devices, bool solo_mining); + bool run_miner(Context*, int workers, int threads_per_worker, const std::vector& gpu_devices, + bool solo_mining, const std::string& auth_token); void stop_miner(Context*); bool is_stratum_running(Context*); bool is_miner_running(Context*); diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index e81258d..d0786ee 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -95,7 +95,7 @@ namespace merit bool stopping() const; MaybeJob get_job(); - MaybeJob get_solo_job(); + MaybeJob get_solo_job(const std::string& auth_token); void submit_work(const util::Work&); diff --git a/src/minerd.cpp b/src/minerd.cpp index dda16c6..aa39f91 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -57,6 +57,7 @@ int main(int argc, char** argv) std::string address; bool solo_mining; std::string solo_url; + std::string auth_token; desc.add_options() ("help", "show the help message") ("infogpu", "show the info about GPU in your system") @@ -64,6 +65,8 @@ int main(int argc, char** argv) "The stratum pool url") ("address", po::value(&address), "The address to send mining rewards to.") ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") + ("token", po::value(&auth_token)->default_value("bWVyaXRycGM6TERwaWtWYkRpM2VYX042UHdQZy1OVVk3Q0RCSGtMOG11Z0pjX0JYNTdnVT0="), + "RPC token for solo-mining") ("solourl", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), "Solo mining stratum server url") ("gpu", po::value>(&gpu_devices)->multitoken(), @@ -127,7 +130,7 @@ int main(int argc, char** argv) merit::run_stratum(c.get(), solo_mining); } - merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining); + merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining, auth_token); int prev_graphs = 0; while (true) { diff --git a/src/public.cpp b/src/public.cpp index 7865c66..69c0083 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -176,7 +176,8 @@ namespace merit { } bool run_miner(Context *c, int workers, int threads_per_worker, - const std::vector &gpu_devices, bool solo_mining) + const std::vector &gpu_devices, bool solo_mining, + const std::string& auth_token) try { assert(c); using namespace std::chrono_literals; @@ -229,11 +230,11 @@ namespace merit { while (c->miner->running()) try { - auto j = c->stratum.get_solo_job(); + auto j = c->stratum.get_solo_job(auth_token); - if(j) { + if(j) break; - } + // std::cout << "After getting the job" << std::endl; // if (!j) { // if (!c->stratum.connected()) { diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 69952a4..8439a95 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -589,12 +589,12 @@ namespace merit return _job; } - MaybeJob Client::get_solo_job() + MaybeJob Client::get_solo_job(const std::string& auth_token) { std::stringstream req; req << "POST / HTTP/1.1\n" << "Content-Type: text/plain\n" << - "Authorization: Basic bWVyaXRycGM6TERwaWtWYkRpM2VYX042UHdQZy1OVVk3Q0RCSGtMOG11Z0pjX0JYNTdnVT0=\n" << + "Authorization: Basic "<< auth_token << "\n" << "Accept: */*\n" << "Content-Length: " << 79 + _user.size() << "\n\n" << "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{}, \""<< _user <<"\"], \"id\": \"9\"}"; From ee6bcd494f29774f3cd914a8af17d9e09091b941 Mon Sep 17 00:00:00 2001 From: retsediv Date: Tue, 21 Aug 2018 18:03:41 +0300 Subject: [PATCH 07/22] Fix text description --- src/minerd.cpp | 2 +- src/stratum/stratum.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/minerd.cpp b/src/minerd.cpp index aa39f91..4c38d62 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) ("address", po::value(&address), "The address to send mining rewards to.") ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") ("token", po::value(&auth_token)->default_value("bWVyaXRycGM6TERwaWtWYkRpM2VYX042UHdQZy1OVVk3Q0RCSGtMOG11Z0pjX0JYNTdnVT0="), - "RPC token for solo-mining") + "RPC token for solo-mining. You can set it in the merit.conf") ("solourl", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), "Solo mining stratum server url") ("gpu", po::value>(&gpu_devices)->multitoken(), diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 8439a95..60431e1 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -605,7 +605,7 @@ namespace merit std::cerr << "error: " << "Error getting blocktemplate for mining: " << req.str() << std::endl; disconnect(); } else { - std::cout << "info: " << "blocktemplate: " << req.str() << std::endl; + std::cout << "info: " << "getting blocktemplate for " << _user << std::endl; } return _job; From ad3e7ffa3575dd72168bf54018ec377833e17c44 Mon Sep 17 00:00:00 2001 From: retsediv Date: Thu, 23 Aug 2018 17:10:42 +0300 Subject: [PATCH 08/22] Minor commit --- include/merit/stratum/stratum.hpp | 1 + src/miner/miner.cpp | 6 ++ src/public.cpp | 26 ++++--- src/stratum/stratum.cpp | 112 +++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 16 deletions(-) diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index d0786ee..4f4fe46 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -109,6 +109,7 @@ namespace merit bool handle_command(const pt::ptree&, const std::string& res); bool mining_notify(const pt::ptree& params); bool mining_difficulty(const pt::ptree& params); + bool mining_set_solo_job(const pt::ptree& params); bool client_reconnect(const pt::ptree& params); bool client_get_version(const pt::ptree& params); bool client_show_message(const pt::ptree& params, const pt::ptree& id); diff --git a/src/miner/miner.cpp b/src/miner/miner.cpp index f38328e..8011825 100644 --- a/src/miner/miner.cpp +++ b/src/miner/miner.cpp @@ -193,6 +193,8 @@ namespace merit void Miner::submit_job(const stratum::Job& j) { + std::cout << "submit_job" << std::endl; + auto w = stratum::work_from_job(j); util::MaybeWork prev_work; { @@ -384,9 +386,11 @@ namespace merit _state = Running; while(_miner.state() == Miner::Running) { + std::cout << "in miner cycle" << std::endl; auto work = _miner.next_work(); if(!work) { + std::cout << "There is no work!" << std::endl; std::this_thread::sleep_for(10ms); continue; } @@ -469,6 +473,8 @@ namespace merit stat.attempts++; if(found) { + std::cout << "CYCLE FOUND" << std::endl; + stat.cycles+=cycles.size(); int idx = 0; diff --git a/src/public.cpp b/src/public.cpp index 69c0083..6e45447 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -220,7 +220,7 @@ namespace merit { if (solo_mining) { std::cout << "info: " << "Starting solo mining..." << std::endl; - c->collab_thread = std::thread([c]() { + c->collab_thread = std::thread([c, auth_token]() { while (c->miner->state() != miner::Miner::Running) {} std::cout << "Miner is Running and ready to start getting job and then mine it" << std::endl; @@ -232,19 +232,17 @@ namespace merit { try { auto j = c->stratum.get_solo_job(auth_token); - if(j) - break; - -// std::cout << "After getting the job" << std::endl; -// if (!j) { -// if (!c->stratum.connected()) { -// c->miner->clear_job(); -// } -// std::this_thread::sleep_for(50ms); -// continue; -// } -// -// c->miner->submit_job(*j); + if (!j) { + std::cout << "== NO JOB! ==" << std::endl; + c->miner->clear_job(); + std::this_thread::sleep_for(50ms); + continue; + } + + + std::cout << "After getting the job" << std::endl; + + c->miner->submit_job(*j); // get block diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 60431e1..009fa11 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT #include @@ -272,6 +273,7 @@ namespace merit auto job_id = v->second.get_value_optional(); v++; if(!job_id) { return false; } + std::cout << "job_id: " << typeid(job_id).name() << std::endl; auto prevhash = v->second.get_value_optional(); v++; if(!prevhash) { return false; } @@ -360,6 +362,98 @@ namespace merit return true; } + bool Client::mining_set_solo_job(const pt::ptree& params) + { +// auto v = params.begin(); + +// auto job_id = params.get_optional(); + auto job_id = "a"; // TODO: fix this +// if(!job_id) { return false; } + + auto prevhash = params.get("result.previousblockhash"); +// if(!prevhash) { return false; } + + std::string coinbase1 = "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"; +// auto coinbase1 = params.get(); +// if(!coinbase1) { return false; } + + std::string coinbase2 = "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"; +// auto coinbase2 = params.get(); +// if(!coinbase2) { return false; } + + auto merkle_array = std::vector{}; + + std::string version = "12311111"; +// auto version = params.get("result.version"); +// if(!version) { return false; } + + auto nbits = params.get("result.bits"); +// if(!nbits) { return false; } + + auto edgebits = params.get("result.edgebits"); +// auto edgebits = params.get_value_optional("result.edgebits"); +// if(!edgebits) { return false; } + + std::string time = "12312312"; +// auto time = params.get("result.curtime"); +// if(!time) { return false; } + + auto is_clean = true; +// if(!is_clean) { return false; } + + + if(prevhash.size() != 64) { return false; } + if(version.size() != 8) { return false; } + if(nbits.size() != 8) { return false; } + std::cout << "== HERE ==" << std::endl; + if(time.size() != 8) { return false; } + + + + std::lock_guard guard{_job_mutex}; + Job j; + + if(!util::parse_hex(prevhash, j.prevhash)) { return false;} + if(!util::parse_hex(version, j.version)) { return false;} + if(!util::parse_hex(nbits, j.nbits)) { return false;} + if(!util::parse_hex(time, j.time)) { return false;} + + j.nedgebits = edgebits; + + j.coinbase1_size = coinbase1.size()/2; + + if(!util::parse_hex(coinbase1, j.coinbase)) { return false; } + j.coinbase.insert(j.coinbase.end(), _xnonce1.begin(), _xnonce1.end()); + + j.xnonce2_start = j.coinbase.size(); + j.xnonce2_size = _xnonce2_size; + + j.coinbase.insert(j.coinbase.end(), _xnonce2_size, 0); + if(!util::parse_hex(coinbase2, j.coinbase)) { return false; } + + j.id = *job_id; + +// for(const auto& hex : merkle_array) { +// std::string s = hex.second.get_value(); +// util::ubytes bin; +// if(!util::parse_hex(s, bin)) { +// return false; +// } +// +// j.merkle.push_back(bin); +// } + + j.diff = _next_diff; + j.clean = is_clean; + _new_job = true; + std::cerr << "info: " << "new solo job: " << j.id << " time: " << time << " nbits: " << nbits << " edgebits: " << j.nedgebits << " prevhash: " << prevhash << std::endl; + + _job = j; + + return true; + + } + bool Client::client_reconnect(const pt::ptree& params) { auto v = params.begin(); @@ -415,6 +509,15 @@ namespace merit return true; } + if(*method == "mining.get_solo_job"){ + if(!mining_set_solo_job(val)){ + std::cerr << "error: " << "unable to set mining.set_solo_job" << std::endl; + return false; + } + + return true; + } + auto params = val.get_child_optional("params"); if(!params) { std::cerr << "error: " << "unable to get params from response" << std::endl; @@ -596,8 +699,8 @@ namespace merit "Content-Type: text/plain\n" << "Authorization: Basic "<< auth_token << "\n" << "Accept: */*\n" << - "Content-Length: " << 79 + _user.size() << "\n\n" << - "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{}, \""<< _user <<"\"], \"id\": \"9\"}"; + "Content-Length: " << 97 + _user.size() << "\n\n" << + "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{}, \""<< _user <<"\"], \"id\": \"mining.get_solo_job\"}"; std::cout << "=== req: " << req.str() << std::endl; @@ -680,6 +783,8 @@ namespace merit return false; } + std::cout << "=== Another response(subscribe_resp): " << resp_line << std::endl; + pt::ptree resp; if(!parse_json(resp_line, resp)) { std::cerr << "error: " << "error parsing response: " << resp_line << std::endl; @@ -744,6 +849,7 @@ namespace merit { auto message_with_nl = message + "\n"; std::lock_guard guard{_sock_mutex}; + std::cout << "=== message to send: " << message_with_nl << std::endl; boost::system::error_code error; asio::write(_socket, boost::asio::buffer(message_with_nl), error); return !error; @@ -786,6 +892,8 @@ namespace merit message.resize(size); std::copy(_sockbuf.begin(), nl, message.begin()); + std::cout << "=== receive message: " << message << " ===" << std::endl; + if (_sockbuf.size() > size + 1) { std::copy(_sockbuf.begin() + size + 1, _sockbuf.end(), _sockbuf.begin()); _sockbuf.resize(_sockbuf.size() - size - 1); From 1a457857d95c8127fa86e10da56b03785501d326 Mon Sep 17 00:00:00 2001 From: retsediv Date: Fri, 24 Aug 2018 17:00:22 +0300 Subject: [PATCH 09/22] Start converting getblochtemplate result to usable data --- include/merit/stratum/stratum.hpp | 5 ++ include/merit/util/util.hpp | 18 +++++ src/public.cpp | 16 +++-- src/stratum/stratum.cpp | 106 ++++++++++++++++++------------ 4 files changed, 98 insertions(+), 47 deletions(-) diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index 4f4fe46..28ff7c9 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -97,6 +97,8 @@ namespace merit MaybeJob get_job(); MaybeJob get_solo_job(const std::string& auth_token); + unsigned int get_solo_job_id(); + void submit_work(const util::Work&); private: @@ -110,6 +112,7 @@ namespace merit bool mining_notify(const pt::ptree& params); bool mining_difficulty(const pt::ptree& params); bool mining_set_solo_job(const pt::ptree& params); + pt::ptree convert_blocktemplate(const pt::ptree& params); bool client_reconnect(const pt::ptree& params); bool client_get_version(const pt::ptree& params); bool client_show_message(const pt::ptree& params, const pt::ptree& id); @@ -142,6 +145,8 @@ namespace merit std::string _port; util::bytes _sockbuf; + unsigned int static _solo_job_id; + std::atomic _next_diff; mutable std::mutex _sock_mutex; mutable std::mutex _job_mutex; diff --git a/include/merit/util/util.hpp b/include/merit/util/util.hpp index fd46257..ee76808 100644 --- a/include/merit/util/util.hpp +++ b/include/merit/util/util.hpp @@ -166,6 +166,24 @@ namespace merit boost::algorithm::hex_lower(begin, end, std::back_inserter(res)); } + bool reverse_hex_string(const std::string& str, std::string& res) + { + std::string tmp; + + try + { + util::parse_hex(str, tmp); + tmp.reserve(); + util::to_hex(tmp, res); + + return true; + } + catch (...) + { + return false; + } + } + void double_sha256( unsigned char* digest, const unsigned char* data, diff --git a/src/public.cpp b/src/public.cpp index 6e45447..823da26 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -232,17 +232,21 @@ namespace merit { try { auto j = c->stratum.get_solo_job(auth_token); - if (!j) { - std::cout << "== NO JOB! ==" << std::endl; - c->miner->clear_job(); - std::this_thread::sleep_for(50ms); - continue; + if(j){ + std::this_thread::sleep_for(5s); + break; } +// if (!j) { +// std::cout << "== NO JOB! ==" << std::endl; +// c->miner->clear_job(); +// std::this_thread::sleep_for(50ms); +// continue; +// } std::cout << "After getting the job" << std::endl; - c->miner->submit_job(*j); +// c->miner->submit_job(*j); // get block diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 009fa11..5fe878a 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -78,6 +78,8 @@ namespace merit { } + unsigned int Client::_solo_job_id = 0; + Client::~Client() { disconnect(); @@ -364,51 +366,23 @@ namespace merit bool Client::mining_set_solo_job(const pt::ptree& params) { -// auto v = params.begin(); - -// auto job_id = params.get_optional(); - auto job_id = "a"; // TODO: fix this -// if(!job_id) { return false; } - - auto prevhash = params.get("result.previousblockhash"); -// if(!prevhash) { return false; } - - std::string coinbase1 = "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"; -// auto coinbase1 = params.get(); -// if(!coinbase1) { return false; } - - std::string coinbase2 = "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"; -// auto coinbase2 = params.get(); -// if(!coinbase2) { return false; } + auto res = convert_blocktemplate(params); + auto job_id = res.get("id"); + auto prevhash = res.get("prevhash"); + auto coinbase1 = res.get("coinbase1"); + auto coinbase2 = res.get("coinbase2"); auto merkle_array = std::vector{}; - - std::string version = "12311111"; -// auto version = params.get("result.version"); -// if(!version) { return false; } - - auto nbits = params.get("result.bits"); -// if(!nbits) { return false; } - - auto edgebits = params.get("result.edgebits"); -// auto edgebits = params.get_value_optional("result.edgebits"); -// if(!edgebits) { return false; } - - std::string time = "12312312"; -// auto time = params.get("result.curtime"); -// if(!time) { return false; } - - auto is_clean = true; -// if(!is_clean) { return false; } - + auto version = res.get("version"); + auto nbits = res.get("bits"); + auto edgebits = res.get("edgebits"); + auto time = res.get("time"); + auto is_clean = res.get("is_clean"); if(prevhash.size() != 64) { return false; } - if(version.size() != 8) { return false; } + if(version.size() != 8) { return false; } // problem if(nbits.size() != 8) { return false; } - std::cout << "== HERE ==" << std::endl; - if(time.size() != 8) { return false; } - - + if(time.size() != 8) { return false; } // problem std::lock_guard guard{_job_mutex}; Job j; @@ -431,7 +405,7 @@ namespace merit j.coinbase.insert(j.coinbase.end(), _xnonce2_size, 0); if(!util::parse_hex(coinbase2, j.coinbase)) { return false; } - j.id = *job_id; + j.id = job_id; // for(const auto& hex : merkle_array) { // std::string s = hex.second.get_value(); @@ -454,6 +428,48 @@ namespace merit } + pt::ptree Client::convert_blocktemplate(const pt::ptree& params) + { + pt::ptree res{}; + std::string tmp; + std::stringstream stream; + + res.add("id", get_solo_job_id()); + + std::string prevhash; + util::to_hex(params.get("result.previousblockhash"), prevhash); + res.add("prevhash", prevhash); + + // TODO: fix this + res.add("coinbase1", "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"); + res.add("coinbase2", "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"); + + + // TODO: looks like it's wrong + uint32_t version = static_cast(atoi(params.get("result.version").c_str())); // get, convert to BigEndian, then to HexString + stream << std::hex << version; + res.add("version", version); + stream.clear(); + + res.add("bits", params.get("result.bits")); + + res.add("edgebits", params.get("result.edgebits")); + + uint32_t time = static_cast(atoi(params.get("result.curtime").c_str())); + stream << std::hex << time; + res.add("time", std::string(stream.str())); + stream.clear(); + + res.add("is_clean", true); + + std::cout << "=== CONVERTING BLOCKTEMPLATE ===" << std::endl; + std::ostringstream oss; + pt::write_json(oss, res); + std::cout << oss.str() << std::endl; + + return res; + } + bool Client::client_reconnect(const pt::ptree& params) { auto v = params.begin(); @@ -912,6 +928,14 @@ namespace merit return recv(res); } + unsigned int Client::get_solo_job_id() + { + // return and increment(so all ids will be different) + return _solo_job_id++; + } + + + void diff_to_target(std::array& target, double diff) { int k; From 02c5202d6f3957e41c8751b6efa9f7787ffcb993 Mon Sep 17 00:00:00 2001 From: retsediv Date: Wed, 29 Aug 2018 14:20:22 +0300 Subject: [PATCH 10/22] Correctly transform version and time parameters for solo job --- src/stratum/stratum.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 5fe878a..8e057ba 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT #include @@ -436,6 +437,7 @@ namespace merit res.add("id", get_solo_job_id()); + // TODO: probably we do not need hex it here std::string prevhash; util::to_hex(params.get("result.previousblockhash"), prevhash); res.add("prevhash", prevhash); @@ -445,20 +447,25 @@ namespace merit res.add("coinbase2", "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"); - // TODO: looks like it's wrong - uint32_t version = static_cast(atoi(params.get("result.version").c_str())); // get, convert to BigEndian, then to HexString - stream << std::hex << version; - res.add("version", version); - stream.clear(); + auto block_version = boost::lexical_cast(params.get("result.version")); // get version parameter + + // divide into bytes and take hex of each of them + // e.g. 671088640 -> 2800000000 + std::bitset<32> version_bits(block_version); + stream << std::hex << version_bits.to_ulong(); + + res.add("version", stream.str()); + stream.clear(); stream.str(""); res.add("bits", params.get("result.bits")); res.add("edgebits", params.get("result.edgebits")); uint32_t time = static_cast(atoi(params.get("result.curtime").c_str())); - stream << std::hex << time; - res.add("time", std::string(stream.str())); - stream.clear(); + std::bitset<32> time_bits(time); + stream << std::hex << time_bits.to_ulong(); + res.add("time", stream.str()); + stream.clear(); stream.str(""); res.add("is_clean", true); @@ -715,8 +722,8 @@ namespace merit "Content-Type: text/plain\n" << "Authorization: Basic "<< auth_token << "\n" << "Accept: */*\n" << - "Content-Length: " << 97 + _user.size() << "\n\n" << - "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{}, \""<< _user <<"\"], \"id\": \"mining.get_solo_job\"}"; + "Content-Length: " << 157 + _user.size() << "\n\n" << + "{\"method\": \"getblocktemplate\", \"jsonrpc\": \"2.0\", \"params\": [{\"capabilities\": [\"coinbasetxn\", \"workid\", \"coinbase/append\"]}, \""<< _user <<"\"], \"id\": \"mining.get_solo_job\"}"; std::cout << "=== req: " << req.str() << std::endl; From be8c1b2739f498ea70377937db5024035094de83 Mon Sep 17 00:00:00 2001 From: retsediv Date: Wed, 29 Aug 2018 18:47:06 +0300 Subject: [PATCH 11/22] Fix prev_hash when getting solo job --- src/stratum/stratum.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 8e057ba..b6f58d7 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -437,16 +437,12 @@ namespace merit res.add("id", get_solo_job_id()); - // TODO: probably we do not need hex it here - std::string prevhash; - util::to_hex(params.get("result.previousblockhash"), prevhash); - res.add("prevhash", prevhash); + res.add("prevhash", params.get("result.previousblockhash")); // TODO: fix this res.add("coinbase1", "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"); res.add("coinbase2", "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"); - auto block_version = boost::lexical_cast(params.get("result.version")); // get version parameter // divide into bytes and take hex of each of them From d3369a670fb21009bac807709a1bc54073b5bca0 Mon Sep 17 00:00:00 2001 From: retsediv Date: Wed, 29 Aug 2018 19:57:55 +0300 Subject: [PATCH 12/22] Add basic interface for merkle tree implementation --- CMakeLists.txt | 9 ++- include/merit/merkle/merkle.h | 129 ++++++++++++++++++++++++++++++++++ src/merkle/merkle.cpp | 42 +++++++++++ 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 include/merit/merkle/merkle.h create mode 100644 src/merkle/merkle.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aa8c7a..8d3f8d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,9 @@ if(CUDA_FOUND) src/stratum/stratum.cpp src/miner/miner.cpp src/util/util.cpp - src/nvml/nvml.cpp) + src/nvml/nvml.cpp + src/merkle/merkle.cpp) + else() set(COMBINE_LIBS $ @@ -68,7 +70,8 @@ else() src/blake2/blake2b-ref.c src/stratum/stratum.cpp src/miner/miner.cpp - src/util/util.cpp) + src/util/util.cpp + src/merkle/merkle.cpp) endif() if(CMAKE_HOST_WIN32) @@ -117,6 +120,7 @@ file(GLOB H_PICO include/merit/PicoSHA2/*.h) file(GLOB H_STRATUM include/merit/stratum/*.hpp) file(GLOB H_UTIL include/merit/util/*.hpp) file(GLOB H_NVML include/merit/nvml/*.h) +file(GLOB H_MERKLE include/merit/merkle/*.h) install(FILES ${H_PUB} DESTINATION include/merit) install(FILES ${H_BLAKE} DESTINATION include/merit/blake) install(FILES ${H_CRYPTO} DESTINATION include/merit/crypto) @@ -127,5 +131,6 @@ install(FILES ${H_PICO} DESTINATION include/merit/PicoSHA2) install(FILES ${H_STRATUM} DESTINATION include/merit/stratum) install(FILES ${H_UTIL} DESTINATION include/merit/util) install(FILES ${H_NVML} DESTINATION include/merit/nvml) +install(FILES ${H_MERKLE} DESTINATION include/merit/merkle) include(CPack) diff --git a/include/merit/merkle/merkle.h b/include/merit/merkle/merkle.h new file mode 100644 index 0000000..711b160 --- /dev/null +++ b/include/merit/merkle/merkle.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 The Merit Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either vedit_refsion 3 of the License, or + * (at your option) any later vedit_refsion. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * Botan library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects for + * all of the code used other than Botan. If you modify file(s) with + * this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + */ + +#ifndef MERIT_MERKLE_H +#define MERIT_MERKLE_H + +#include +#include +#include +#include +#include + +namespace merit { + + namespace merkle { + + template + class MerkleNode { + protected: + + std::unique_ptr left_, right_; + const char *hash_; + const std::shared_ptr value_; + + /** + * Computes the hash of the children nodes' respective hashes. + * In other words, given a node N, with children (N1, N2), whose hash values are, + * respectively, H1 and H2, computes: + * + * H = hash(H1 || H2) + * + * where `||` represents the concatenation operation. + * If the `right_` descendant is missing, it will simply duplicate the `left_` node's hash. + * + * For a "leaf" node (both descendants missing), it will use the `hash_func()` to compute the + * hash of the stored `value_`. + */ + virtual const char *computeHash() const = 0; + + public: + + /** + * Builds a "leaf" node, with no descendants and a `value` that will be copied and stored. + * We also compute the hash (`hash_func()`) of the value and store it in this node. + * + * We assume ownership of the pointer returned by the `hash_func()` which we assume has been + * freshly allocated, and will be released upon destruction of this node. + */ + MerkleNode(const T &value) : value_(new T(value)), left_(nullptr), right_(nullptr) { + hash_ = hash_func(value); + } + + /** + * Creates an intermediate node, storing the descendants as well as computing the compound hash. + */ + MerkleNode(const MerkleNode *left, + const MerkleNode *right) : + left_(left), right_(right), value_(nullptr) { + } + + /** + * Deletes the memory pointed to by the `hash_` pointer: if your `hash_func()` and/or the + * `computeHash()` method implementation do not allocate this memory (or you do not wish to + * free the allocated memory) remember to override this destructor's behavior too. + */ + virtual ~MerkleNode() { + if (hash_) delete[](hash_); + } + + /** + * Recursively validate the subtree rooted in this node: if executed at the root of the tree, + * it will validate the entire tree. + */ + virtual bool validate() const; + + /** + * The length of the hash, also part of the template instantiation (`hash_len`). + * + * @see hash_len + */ + size_t len() const { return hash_len; } + + /** + * Returns the buffer containing the hash value, of `len()` bytes length. + * + * @see len() + */ + const char *hash() const { return hash_; } + + bool hasChildren() const { + return left_ || right_; + } + + const MerkleNode *left() const { return left_.get(); } + + const MerkleNode *right() const { return right_.get(); } + }; + } +} + +#endif //MERIT_MERKLE_H diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp new file mode 100644 index 0000000..4a32655 --- /dev/null +++ b/src/merkle/merkle.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 The Merit Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either vedit_refsion 3 of the License, or + * (at your option) any later vedit_refsion. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * Botan library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects for + * all of the code used other than Botan. If you modify file(s) with + * this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + */ + +#include "merit/merkle/merkle.h" + + +namespace merit { + + namespace merkle { + + + } +} + From 535775c052865eb98828d3d8b1e8cd4167860e8e Mon Sep 17 00:00:00 2001 From: retsediv Date: Thu, 30 Aug 2018 10:49:10 +0300 Subject: [PATCH 13/22] Add merkle tree implementation --- CMakeLists.txt | 2 +- include/merit/merkle/{merkle.h => merkle.hpp} | 20 +++++++ include/merit/stratum/stratum.hpp | 1 + src/merkle/merkle.cpp | 60 ++++++++++++++++++- src/stratum/stratum.cpp | 17 ++++++ 5 files changed, 96 insertions(+), 4 deletions(-) rename include/merit/merkle/{merkle.h => merkle.hpp} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d3f8d1..fda6f55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,7 +120,7 @@ file(GLOB H_PICO include/merit/PicoSHA2/*.h) file(GLOB H_STRATUM include/merit/stratum/*.hpp) file(GLOB H_UTIL include/merit/util/*.hpp) file(GLOB H_NVML include/merit/nvml/*.h) -file(GLOB H_MERKLE include/merit/merkle/*.h) +file(GLOB H_MERKLE include/merit/merkle/*.hpp) install(FILES ${H_PUB} DESTINATION include/merit) install(FILES ${H_BLAKE} DESTINATION include/merit/blake) install(FILES ${H_CRYPTO} DESTINATION include/merit/crypto) diff --git a/include/merit/merkle/merkle.h b/include/merit/merkle/merkle.hpp similarity index 84% rename from include/merit/merkle/merkle.h rename to include/merit/merkle/merkle.hpp index 711b160..ac4bf5d 100644 --- a/include/merit/merkle/merkle.h +++ b/include/merit/merkle/merkle.hpp @@ -33,10 +33,15 @@ #define MERIT_MERKLE_H #include +#include #include #include #include #include +#include + +#include "merit/PicoSHA2/picosha2.h" +#include "merit/util/util.hpp" namespace merit { @@ -123,6 +128,21 @@ namespace merit { const MerkleNode *right() const { return right_.get(); } }; + + char* double_hash(const std::string& str); + + class DoubleSHA256StringMerkleNode : public MerkleNode { + public: + DoubleSHA256StringMerkleNode(const std::string &value): MerkleNode(value) {} + DoubleSHA256StringMerkleNode(const DoubleSHA256StringMerkleNode *left, const DoubleSHA256StringMerkleNode *right): MerkleNode(left, right) {} + protected: + const char *computeHash() const override; + }; + + template const NodeType* build_(NodeType *nodes[], size_t len); + template const NodeType* build(const std::list &values); + template const NodeType* build(const std::vector &values); + } } diff --git a/include/merit/stratum/stratum.hpp b/include/merit/stratum/stratum.hpp index 28ff7c9..5bb91fd 100644 --- a/include/merit/stratum/stratum.hpp +++ b/include/merit/stratum/stratum.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp index 4a32655..79b75dd 100644 --- a/src/merkle/merkle.cpp +++ b/src/merkle/merkle.cpp @@ -29,14 +29,68 @@ * also delete it here. */ -#include "merit/merkle/merkle.h" - +#include "merit/merkle/merkle.hpp" namespace merit { namespace merkle { - + template + bool MerkleNode::validate() const { + // If either child is not valid, the entire subtree is invalid too. + if (left_ && !left_->validate()) { + return false; + } + if (right_ && !right_->validate()) { + return false; + } + + std::unique_ptr computedHash(hasChildren() ? computeHash() : hash_func(*value_)); + return memcmp(hash_, computedHash.get(), len()) == 0; + } + + const char *DoubleSHA256StringMerkleNode::computeHash() const { + if(!right_) + return left_.get()->hash(); + + return (std::string(left_.get()->hash()) + std::string(right_.get()->hash())).c_str(); + } + + char* double_hash(const std::string& str){ + auto *result = new unsigned char[str.size()]; + merit::util::double_sha256(result, reinterpret_cast(str.c_str()), str.size()); + return reinterpret_cast(result); + } + + // Recursive implementation of the build algorithm. + template + const NodeType *build_(NodeType *nodes[], size_t len) { + + if (len == 1) return new NodeType(nodes[0], nullptr); + if (len == 2) return new NodeType(nodes[0], nodes[1]); + + size_t half = len % 2 == 0 ? len / 2 : len / 2 + 1; + return new NodeType(build_(nodes, half), build_(nodes + half, len - half)); + } + + template + const NodeType *build(const std::list &values) { + + NodeType *leaves[values.size()]; + int i = 0; + for (auto value : values) { + leaves[i++] = new NodeType(value); + } + + return build_(leaves, values.size()); + }; + + template + const NodeType *build(const std::vector &values) { + std::list lst(values.begin(), values.end()); + + return build(lst); + }; } } diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index b6f58d7..83c8080 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -29,6 +29,7 @@ * also delete it here. */ #include "merit/stratum/stratum.hpp" +#include "merit/merkle/merkle.hpp" #include #include @@ -443,6 +444,22 @@ namespace merit res.add("coinbase1", "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"); res.add("coinbase2", "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"); + // Merkle array of transactions, invites and referrals + std::cout << std::endl << "MERKLE ARRAY WORK" << std::endl; + std::vector hashes{}; + BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("transactions")){ + std::cout << "first : " << v.first << std::endl; + std::cout << "second.data : " << v.second.get("data") << std::endl; + std::cout << "second.txid : " << v.second.get("txid") << std::endl; + hashes.push_back(v.second.get("txid")); + } + // 2... for refs + // 3... for invites + + auto merkle_tree_root = merit::merkle::build(hashes); + + // push merkle branches to the result + auto block_version = boost::lexical_cast(params.get("result.version")); // get version parameter // divide into bytes and take hex of each of them From 05c2e508909a734bc62a716f1de5a0df839e1ba8 Mon Sep 17 00:00:00 2001 From: retsediv Date: Thu, 30 Aug 2018 10:56:58 +0300 Subject: [PATCH 14/22] Add README for merkle tree --- src/merkle/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/merkle/README.md diff --git a/src/merkle/README.md b/src/merkle/README.md new file mode 100644 index 0000000..85a6b32 --- /dev/null +++ b/src/merkle/README.md @@ -0,0 +1,7 @@ +# Merkle tree + +Contains an implementation of the [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) data structure. + +| Files | Description | +|:---------------------------------------|:-----------------------------------------| +| [merkle.hpp](merkle.hpp) | Interface to the merkle tree | From 8f64993d7145301dcbd45ccfe37fde4e95791735 Mon Sep 17 00:00:00 2001 From: retsediv Date: Mon, 3 Sep 2018 17:58:05 +0300 Subject: [PATCH 15/22] minor changes --- include/merit/merkle/merkle.hpp | 292 +++++++++++++++++++++++--------- include/merit/util/util.hpp | 43 +++-- src/merkle/merkle.cpp | 75 +++----- src/miner/miner.cpp | 4 +- src/minerd.cpp | 2 +- src/public.cpp | 7 +- src/stratum/stratum.cpp | 105 ++++++++++-- src/util/util.cpp | 56 ++++++ 8 files changed, 413 insertions(+), 171 deletions(-) diff --git a/include/merit/merkle/merkle.hpp b/include/merit/merkle/merkle.hpp index ac4bf5d..43d8e6b 100644 --- a/include/merit/merkle/merkle.hpp +++ b/include/merit/merkle/merkle.hpp @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include "merit/PicoSHA2/picosha2.h" #include "merit/util/util.hpp" @@ -47,101 +49,229 @@ namespace merit { namespace merkle { - template - class MerkleNode { - protected: - - std::unique_ptr left_, right_; - const char *hash_; - const std::shared_ptr value_; - - /** - * Computes the hash of the children nodes' respective hashes. - * In other words, given a node N, with children (N1, N2), whose hash values are, - * respectively, H1 and H2, computes: - * - * H = hash(H1 || H2) - * - * where `||` represents the concatenation operation. - * If the `right_` descendant is missing, it will simply duplicate the `left_` node's hash. - * - * For a "leaf" node (both descendants missing), it will use the `hash_func()` to compute the - * hash of the stored `value_`. - */ - virtual const char *computeHash() const = 0; +// template +// class MerkleNode { +// protected: +// +// std::unique_ptr left_, right_; +// const char *hash_; +// const std::shared_ptr value_; +// +// /** +// * Computes the hash of the children nodes' respective hashes. +// * In other words, given a node N, with children (N1, N2), whose hash values are, +// * respectively, H1 and H2, computes: +// * +// * H = hash(H1 || H2) +// * +// * where `||` represents the concatenation operation. +// * If the `right_` descendant is missing, it will simply duplicate the `left_` node's hash. +// * +// * For a "leaf" node (both descendants missing), it will use the `hash_func()` to compute the +// * hash of the stored `value_`. +// */ +// virtual const char *computeHash() const = 0; +// +// public: +// +// /** +// * Builds a "leaf" node, with no descendants and a `value` that will be copied and stored. +// * We also compute the hash (`hash_func()`) of the value and store it in this node. +// * +// * We assume ownership of the pointer returned by the `hash_func()` which we assume has been +// * freshly allocated, and will be released upon destruction of this node. +// */ +// MerkleNode(const T &value) : value_(new T(value)), left_(nullptr), right_(nullptr) { +// hash_ = hash_func(value); +// } +// +// /** +// * Creates an intermediate node, storing the descendants as well as computing the compound hash. +// */ +// MerkleNode(const MerkleNode *left, +// const MerkleNode *right) : +// left_(left), right_(right), value_(nullptr) { +// } +// +// /** +// * Deletes the memory pointed to by the `hash_` pointer: if your `hash_func()` and/or the +// * `computeHash()` method implementation do not allocate this memory (or you do not wish to +// * free the allocated memory) remember to override this destructor's behavior too. +// */ +// virtual ~MerkleNode() { +// if (hash_) delete[](hash_); +// } +// +// /** +// * Recursively validate the subtree rooted in this node: if executed at the root of the tree, +// * it will validate the entire tree. +// */ +// virtual bool validate() const; +// +// /** +// * The length of the hash, also part of the template instantiation (`hash_len`). +// * +// * @see hash_len +// */ +// size_t len() const { return hash_len; } +// +// /** +// * Returns the buffer containing the hash value, of `len()` bytes length. +// * +// * @see len() +// */ +// const char *hash() const { return hash_; } +// +// bool hasChildren() const { +// return left_ || right_; +// } +// +// const MerkleNode *left() const { return left_.get(); } +// +// const MerkleNode *right() const { return right_.get(); } +// }; + template + class MerkleTree { public: - - /** - * Builds a "leaf" node, with no descendants and a `value` that will be copied and stored. - * We also compute the hash (`hash_func()`) of the value and store it in this node. - * - * We assume ownership of the pointer returned by the `hash_func()` which we assume has been - * freshly allocated, and will be released upon destruction of this node. - */ - MerkleNode(const T &value) : value_(new T(value)), left_(nullptr), right_(nullptr) { - hash_ = hash_func(value); + explicit MerkleTree(const std::vector &hashes_list) { + steps = calculateSteps(hashes_list); } - /** - * Creates an intermediate node, storing the descendants as well as computing the compound hash. - */ - MerkleNode(const MerkleNode *left, - const MerkleNode *right) : - left_(left), right_(right), value_(nullptr) { - } + std::vector branches() { + std::cout << "=== Trying to get branches..." << std::endl; + + std::vector branches; + std::string tmp_hash; + std::stringstream stream; + + std::cout << "before foreach loop" << std::endl; + + for (const auto &step: steps) { + std::cout << "looping..." << std::endl; + std::string tmp{step}; + std::cout << "Step: " << step << " : " << tmp << std::endl; + std::string step_hex; + + merit::util::to_hex(tmp.begin(), tmp.end(), step_hex); + + std::cout << "Step HEX: " << step_hex << std::endl; + +// std::bitset version_bits(step_binary); +// stream << std::hex << version_bits.to_ullong(); +// branches.push_back(stream.str()); stream.str(""); + branches.push_back(step_hex); + } - /** - * Deletes the memory pointed to by the `hash_` pointer: if your `hash_func()` and/or the - * `computeHash()` method implementation do not allocate this memory (or you do not wish to - * free the allocated memory) remember to override this destructor's behavior too. - */ - virtual ~MerkleNode() { - if (hash_) delete[](hash_); + std::cout << "End loop and function stuff ===" << std::endl; + + + return branches; } - /** - * Recursively validate the subtree rooted in this node: if executed at the root of the tree, - * it will validate the entire tree. - */ - virtual bool validate() const; - - /** - * The length of the hash, also part of the template instantiation (`hash_len`). - * - * @see hash_len - */ - size_t len() const { return hash_len; } - - /** - * Returns the buffer containing the hash value, of `len()` bytes length. - * - * @see len() - */ - const char *hash() const { return hash_; } - - bool hasChildren() const { - return left_ || right_; + private: + std::vector steps; + + std::vector calculateSteps(const std::vector &hashes_list) { + std::cout << "=== calculateSteps()" << std::endl; + + std::vector steps{}; + std::vector L{nullptr}; + for (const auto &el: hashes_list) { + L.push_back(el.c_str()); + } + + int startL = 2; + unsigned long Ll = L.size(); + + if (Ll > 1) + { + std::cout << "Calculating steps.." << std::endl; + while (true) + { + std::cout << " while loop..." << std::endl; + + if(Ll == 1) + break; + + steps.push_back(L[1]); + + if(Ll % 2 == 1) + L.push_back(L[L.size() - 1]); + + std::vector Ld; + + for (int i = startL; i < Ll; i += 2) { + Ld.push_back(merkleJoin(L[i], L[i+1])); + } + + L.clear(); L.push_back(nullptr); + for(const auto& el: Ld) + L.push_back(el); + + Ll = L.size(); + + std::cout << " end of while loop" << std::endl; + + } + } + + std::cout << " end of Calculating steps function ===" << std::endl; + + return steps; } - const MerkleNode *left() const { return left_.get(); } + const char* merkleJoin(const char* h1, const char* h2){ + std::string joined = h1; + joined.append(h2); - const MerkleNode *right() const { return right_.get(); } + return hash_func(joined); + } }; - char* double_hash(const std::string& str); + const char *double_hash(const std::string &str); - class DoubleSHA256StringMerkleNode : public MerkleNode { - public: - DoubleSHA256StringMerkleNode(const std::string &value): MerkleNode(value) {} - DoubleSHA256StringMerkleNode(const DoubleSHA256StringMerkleNode *left, const DoubleSHA256StringMerkleNode *right): MerkleNode(left, right) {} - protected: - const char *computeHash() const override; - }; +// class DoubleSHA256StringMerkleNode : public MerkleNode { +// public: +// DoubleSHA256StringMerkleNode(const std::string &value) : MerkleNode(value) {} +// +// DoubleSHA256StringMerkleNode(const DoubleSHA256StringMerkleNode *left, +// const DoubleSHA256StringMerkleNode *right) : MerkleNode(left, right) {} +// +// protected: +// const char *computeHash() const override; +// }; + + // Recursive implementation of the build algorithm. +// template +// const NodeType *build_(NodeType *nodes[], size_t len) { +// +// if (len == 1) return new NodeType(nodes[0], nullptr); +// if (len == 2) return new NodeType(nodes[0], nodes[1]); +// +// size_t half = len % 2 == 0 ? len / 2 : len / 2 + 1; +// return new NodeType(build_(nodes, half), build_(nodes + half, len - half)); +// } +// +// template +// const NodeType *build(const std::list &values) { +// +// NodeType *leaves[values.size()]; +// int i = 0; +// for (auto value : values) { +// leaves[i++] = new NodeType(value); +// } +// +// return build_(leaves, values.size()); +// }; +// +// template +// const NodeType *build(const std::vector &values) { +// std::list lst(values.begin(), values.end()); +// +// return build(lst); +// }; - template const NodeType* build_(NodeType *nodes[], size_t len); - template const NodeType* build(const std::list &values); - template const NodeType* build(const std::vector &values); } } diff --git a/include/merit/util/util.hpp b/include/merit/util/util.hpp index ee76808..d82d6b6 100644 --- a/include/merit/util/util.hpp +++ b/include/merit/util/util.hpp @@ -85,6 +85,9 @@ static inline void le32enc(void *pp, uint32_t x) #if defined(__linux__) // Linux #include // for htole32/64 +#include +#include +#include #elif defined(__APPLE__) // macOS @@ -166,23 +169,29 @@ namespace merit boost::algorithm::hex_lower(begin, end, std::back_inserter(res)); } - bool reverse_hex_string(const std::string& str, std::string& res) - { - std::string tmp; - - try - { - util::parse_hex(str, tmp); - tmp.reserve(); - util::to_hex(tmp, res); - - return true; - } - catch (...) - { - return false; - } - } +// bool reverse_hex_string(const std::string& str, std::string& res) +// { +// std::string tmp; +// +// try +// { +// util::parse_hex(str, tmp); +// tmp.reserve(); +// util::to_hex(tmp, res); +// +// return true; +// } +// catch (...) +// { +// return false; +// } +// } + + std::string HexCharToBin(char c); + std::string HexStrToBin(const std::string & hs); + std::vector ReverseByteOrder(const std::string& binary); + + void double_sha256( unsigned char* digest, diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp index 79b75dd..6d0657f 100644 --- a/src/merkle/merkle.cpp +++ b/src/merkle/merkle.cpp @@ -35,62 +35,33 @@ namespace merit { namespace merkle { - template - bool MerkleNode::validate() const { - // If either child is not valid, the entire subtree is invalid too. - if (left_ && !left_->validate()) { - return false; - } - if (right_ && !right_->validate()) { - return false; - } - - std::unique_ptr computedHash(hasChildren() ? computeHash() : hash_func(*value_)); - return memcmp(hash_, computedHash.get(), len()) == 0; - } - - const char *DoubleSHA256StringMerkleNode::computeHash() const { - if(!right_) - return left_.get()->hash(); - - return (std::string(left_.get()->hash()) + std::string(right_.get()->hash())).c_str(); - } - - char* double_hash(const std::string& str){ +// template +// bool MerkleNode::validate() const { +// // If either child is not valid, the entire subtree is invalid too. +// if (left_ && !left_->validate()) { +// return false; +// } +// if (right_ && !right_->validate()) { +// return false; +// } +// +// std::unique_ptr computedHash(hasChildren() ? computeHash() : hash_func(*value_)); +// return memcmp(hash_, computedHash.get(), len()) == 0; +// } +// +// const char *DoubleSHA256StringMerkleNode::computeHash() const { +// if(!right_) +// return left_.get()->hash(); +// +// return (std::string(left_.get()->hash()) + std::string(right_.get()->hash())).c_str(); +// } + + const char* double_hash(const std::string& str){ auto *result = new unsigned char[str.size()]; merit::util::double_sha256(result, reinterpret_cast(str.c_str()), str.size()); - return reinterpret_cast(result); - } - - // Recursive implementation of the build algorithm. - template - const NodeType *build_(NodeType *nodes[], size_t len) { - - if (len == 1) return new NodeType(nodes[0], nullptr); - if (len == 2) return new NodeType(nodes[0], nodes[1]); - - size_t half = len % 2 == 0 ? len / 2 : len / 2 + 1; - return new NodeType(build_(nodes, half), build_(nodes + half, len - half)); + return reinterpret_cast(result); } - template - const NodeType *build(const std::list &values) { - - NodeType *leaves[values.size()]; - int i = 0; - for (auto value : values) { - leaves[i++] = new NodeType(value); - } - - return build_(leaves, values.size()); - }; - - template - const NodeType *build(const std::vector &values) { - std::list lst(values.begin(), values.end()); - - return build(lst); - }; } } diff --git a/src/miner/miner.cpp b/src/miner/miner.cpp index 8011825..d91d10d 100644 --- a/src/miner/miner.cpp +++ b/src/miner/miner.cpp @@ -386,11 +386,11 @@ namespace merit _state = Running; while(_miner.state() == Miner::Running) { - std::cout << "in miner cycle" << std::endl; +// std::cout << "in miner cycle" << std::endl; auto work = _miner.next_work(); if(!work) { - std::cout << "There is no work!" << std::endl; +// std::cout << "There is no work!" << std::endl; std::this_thread::sleep_for(10ms); continue; } diff --git a/src/minerd.cpp b/src/minerd.cpp index 4c38d62..ca14f04 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -67,7 +67,7 @@ int main(int argc, char** argv) ("solo", po::value(&solo_mining)->default_value(false), "Enable solo-mining or not?") ("token", po::value(&auth_token)->default_value("bWVyaXRycGM6TERwaWtWYkRpM2VYX042UHdQZy1OVVk3Q0RCSGtMOG11Z0pjX0JYNTdnVT0="), "RPC token for solo-mining. You can set it in the merit.conf") - ("solourl", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:18332"), + ("solourl", po::value(&solo_url)->default_value("=stratum+tcp://127.0.0.1:8332"), // 18332 -> testnet, 8332 -> livenet "Solo mining stratum server url") ("gpu", po::value>(&gpu_devices)->multitoken(), "Index of GPU device to use in mining(can use multiple times). For more info check --infogpu") diff --git a/src/public.cpp b/src/public.cpp index 823da26..45784c1 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -226,15 +226,18 @@ namespace merit { std::cout << "Miner is Running and ready to start getting job and then mine it" << std::endl; // TODO: fix this when implementing server support for solo mining - c->stratum.stop(); // disconnect from server +// c->stratum.stop(); // disconnect from server while (c->miner->running()) try { auto j = c->stratum.get_solo_job(auth_token); + std::this_thread::sleep_for(20s); + if(j){ + std::cout << "There is a job!!!" << std::endl; std::this_thread::sleep_for(5s); - break; +// break; } // if (!j) { // std::cout << "== NO JOB! ==" << std::endl; diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 83c8080..89df536 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -37,6 +37,7 @@ #include +#include #include #include #include @@ -277,7 +278,6 @@ namespace merit auto job_id = v->second.get_value_optional(); v++; if(!job_id) { return false; } - std::cout << "job_id: " << typeid(job_id).name() << std::endl; auto prevhash = v->second.get_value_optional(); v++; if(!prevhash) { return false; } @@ -432,33 +432,100 @@ namespace merit pt::ptree Client::convert_blocktemplate(const pt::ptree& params) { + + std::cout << "converting blocktemplate" << std::endl; + pt::ptree res{}; std::string tmp; std::stringstream stream; res.add("id", get_solo_job_id()); - res.add("prevhash", params.get("result.previousblockhash")); + std::cout << "0" << std::endl; + + try { + auto prev = params.get("result.previousblockhash"); + prev = "353fac2931e2d8f6d3474fa66ccafe4c9de02d845b4f68b82f6816137ec57b7b"; + std::cout << "prev: " << prev << " : " << prev.size() << std::endl; + +// std::string prev_unhex; +// merit::util::parse_hex(prev, prev_unhex); +// std::cout << "prev_unhex: " << prev_unhex << " : " << prev_unhex.size() << std::endl; + +// prev = "0123456789abcdef"; +// unsigned long long prev_hex_num; +// std::istringstream ost(prev); +// ost >> std::hex >> prev_hex_num; + + +// std::cout << "prev_unhex reversed: " << prev_unhex << " : " << prev_unhex.size() << std::endl; + + auto bin_prev = merit::util::HexStrToBin(prev); + std::cout << "bin_prev: " << bin_prev << std::endl; + std::cout << "bin_prev: " << bin_prev << std::endl; + + auto bin_prev_reverse = merit::util::ReverseByteOrder(bin_prev); + + + std::cout << "CONVERTING TO HEX" << std::endl; + for(const auto& el: bin_prev_reverse){ + std::bitset<8> tmp(el); + std::cout << " el: " << tmp.to_string() << " : " << std::hex << tmp.to_ulong() << std::endl; + } + +// stream << std::hex << prevhash_bits.to_ulong(); +// std::cout << "2" << std::endl; +// +// std::string prevhash = stream.str(); +// std::cout << "3" << std::endl; +// +// std::reverse(prevhash.begin(), prevhash.end()); + + res.add("prevhash", stream.str()); + stream.clear(); stream.str(""); + + } catch (std::exception &e){ + std::cout << " !!! === Exception === : " << e.what() << std::endl; + } // TODO: fix this res.add("coinbase1", "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"); res.add("coinbase2", "0b2f4d65726974506f6f6c2fffffffff160aca9a3b000000001976a9144bfac9c3a88aab06ae1dcdf59a22eef6dbab361b88acd2665703000000001976a91429b3b93cf44ffa4f14415ca00e4b7cd0a44e0b2988ac07c36003000000001976a9145cdcaad0a61feeff8c474d50daf79885bd08694188acc8d3ef02000000001976a914c5d1ce565e99547c2bf056c996b5b8409356b27d88acca231603000000001976a9144904ee33f9345b6532ade7e043f6f61e8c69e3b388acafc79703000000001976a9142c930dff417ce135d133a0d6b4bd91b27885390788acc1916f03000000001976a914d7552b88da89bce65f8e8f6825391413e03d7b7488acfeb95b03000000001976a914a6080afe276ac0f5ae29926cf3fd67539dd0dbd888ac28bf5103000000001976a9145aeb58b3a35dc7282e15ff71a6b21ee1c21021c088ac03ac3d03000000001976a9145fab2bf7f998f84bf085e44a7edb61868361a1cf88acf50e4203000000001976a91401a2071430bdd5f5264bf9970ec0cc2649cbe88988ac0e4c6a02000000001976a914dbc5297edb42d494a7de6d6e126306b83f3b805288ac397f8302000000001976a91470e932c20dc49f72eb669a6a3ad7fe026175708988aca64e3603000000001976a9149b1b860efdb47e2dd0f9504326d5217beedbba5488ac6842ad02000000001976a914efe006f514be4e91118c835966909ddabd5a633a88ac98155c02000000001976a914e5f369d2151e8591766912d406a8f884d7690cd188ac6018b702000000001976a914a5f97cb5333d20ac335431dba391d2e8b09cc33e88ac8eb6b702000000001976a91492f32bed913273f7a11dc26a21ad3c3675732d0e88ac79626502000000001976a914c82be3807dfb9f02a2996bc6ad0b5ca29297fca888ace2f38802000000001976a9143fd2058fb6faeb7090798692d1f51ad44e46960b88acc7831d03000000001976a914ee34a60e8fe4223c0ad57600b7d70713c73c216e88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf900000000"); // Merkle array of transactions, invites and referrals - std::cout << std::endl << "MERKLE ARRAY WORK" << std::endl; std::vector hashes{}; - BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("transactions")){ - std::cout << "first : " << v.first << std::endl; - std::cout << "second.data : " << v.second.get("data") << std::endl; - std::cout << "second.txid : " << v.second.get("txid") << std::endl; - hashes.push_back(v.second.get("txid")); + int i = 0; + BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("result.transactions")){ + if (i != 0) + hashes.push_back(v.second.get("txid")); + + i++; } // 2... for refs + BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("result.referrals")){ + hashes.push_back(v.second.get("hash")); + } + // 3... for invites + BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("result.invites")){ + hashes.push_back(v.second.get("hash")); + } + + std::cout << "MERKLE HASHES SIZE = " << hashes.size() << std::endl; + + try { + auto merkle_tree = merit::merkle::MerkleTree(hashes); + auto branches = merkle_tree.branches(); +// std::cout << "Branches: " << branches.size() << std::endl; +// for(const auto& branch: branches){ +// std::cout << branch << std::endl; +// } - auto merkle_tree_root = merit::merkle::build(hashes); + // push merkle branches to the result - // push merkle branches to the result + } catch (std::exception &e) { + std::cout << "||| Error ||| = " << e.what() << std::endl; + } auto block_version = boost::lexical_cast(params.get("result.version")); // get version parameter @@ -612,6 +679,8 @@ namespace merit bool Client::reconnect() { + + std::cout << std::endl << " !!! === RECONNECTING === !!! " << std::endl << std::endl; using namespace std::chrono_literals; disconnect(); bool connected = false; @@ -663,6 +732,8 @@ namespace merit } pt::ptree val; + + std::cout << "RES: " << res << std::endl; if(!parse_json(res, val)) { _sockbuf.clear(); std::cerr << "error parsing stratum response: " << res << std::endl; @@ -682,11 +753,13 @@ namespace merit } } catch(std::exception& e) { - if(!reconnect()) { - std::cerr << "error: " << "failed to reconnect" << std::endl; - return false; - } else if(_run_state == Running) { - std::cerr << "info: reconnected!" << std::endl; + if(!solo_mining){ // TODO: remove this if statement later + if(!reconnect()) { + std::cerr << "error: " << "failed to reconnect" << std::endl; + return false; + } else if(_run_state == Running) { + std::cerr << "info: reconnected!" << std::endl; + } } } @@ -928,7 +1001,7 @@ namespace merit message.resize(size); std::copy(_sockbuf.begin(), nl, message.begin()); - std::cout << "=== receive message: " << message << " ===" << std::endl; +// std::cout << "=== receive message: " << message << " ===" << std::endl; if (_sockbuf.size() > size + 1) { std::copy(_sockbuf.begin() + size + 1, _sockbuf.end(), _sockbuf.begin()); diff --git a/src/util/util.cpp b/src/util/util.cpp index 2594543..28fe4a0 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -48,5 +48,61 @@ namespace merit picosha2::hash256(data, data+len, d.begin(), d.end()); picosha2::hash256(d.begin(), d.end(), digest, digest+picosha2::k_digest_size); } + + std::string HexCharToBin( char c ) { + switch( c ) { + case '0' : return "0000"; + case '1' : return "0001"; + case '2' : return "0010"; + case '3' : return "0011"; + case '4' : return "0100"; + case '5' : return "0101"; + case '6' : return "0110"; + case '7' : return "0111"; + case '8' : return "1000"; + case '9' : return "1001"; + case 'A' : return "1010"; + case 'a' : return "1010"; + case 'B' : return "1011"; + case 'b' : return "1011"; + case 'C' : return "1100"; + case 'c' : return "1100"; + case 'D' : return "1101"; + case 'd' : return "1101"; + case 'E' : return "1110"; + case 'e' : return "1110"; + case 'F' : return "1111"; + case 'f' : return "1111"; + } + } + + + std::string HexStrToBin(const std::string & hs) { + std::string bin; + for(auto c : hs) { + bin += HexCharToBin(c); + } + return bin; + } + + std::vector ReverseByteOrder(const std::string& binary){ + std::vector result; + + for (unsigned int i = 0; i < 8; ++i) { // binary.size() / 32 + std::bitset<32> tmp_32{binary.substr(i*32, (i+1) * 32)}; + auto endian_32 = htonl(static_cast(tmp_32.to_ulong())); + + std::bitset<32> tmp_32_{endian_32}; + std::cout << " ||| function: " << tmp_32_.to_string() << std::endl; + + for (int j = 0; j < 4; j++) + result.push_back(static_cast(endian_32 >> (j * 8))); + } + +// std::reverse(result.begin(), result.end()); + + return result; + } + } } From bbd8ca6dd4cddccd4a5f9e46d2aa6db0f48cfae2 Mon Sep 17 00:00:00 2001 From: retsediv Date: Tue, 4 Sep 2018 17:52:52 +0300 Subject: [PATCH 16/22] Fix prevhash --- src/stratum/stratum.cpp | 51 ++++++++--------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 89df536..aa386e1 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -432,7 +432,6 @@ namespace merit pt::ptree Client::convert_blocktemplate(const pt::ptree& params) { - std::cout << "converting blocktemplate" << std::endl; pt::ptree res{}; @@ -443,50 +442,20 @@ namespace merit std::cout << "0" << std::endl; - try { - auto prev = params.get("result.previousblockhash"); - prev = "353fac2931e2d8f6d3474fa66ccafe4c9de02d845b4f68b82f6816137ec57b7b"; - std::cout << "prev: " << prev << " : " << prev.size() << std::endl; - -// std::string prev_unhex; -// merit::util::parse_hex(prev, prev_unhex); -// std::cout << "prev_unhex: " << prev_unhex << " : " << prev_unhex.size() << std::endl; - -// prev = "0123456789abcdef"; -// unsigned long long prev_hex_num; -// std::istringstream ost(prev); -// ost >> std::hex >> prev_hex_num; + auto prev = params.get("result.previousblockhash"); + // then divide to the 8 sybmols parts, reverse array of this parts and join them together + std::string reversed_prevblockhash; + std::vector parts_of_hash; + for (int i = 0; i < 8; ++i) + parts_of_hash.push_back(prev.substr(8 * i, 8)); -// std::cout << "prev_unhex reversed: " << prev_unhex << " : " << prev_unhex.size() << std::endl; + std::reverse(parts_of_hash.begin(), parts_of_hash.end()); - auto bin_prev = merit::util::HexStrToBin(prev); - std::cout << "bin_prev: " << bin_prev << std::endl; - std::cout << "bin_prev: " << bin_prev << std::endl; + for(const auto& part: parts_of_hash) + reversed_prevblockhash += part; - auto bin_prev_reverse = merit::util::ReverseByteOrder(bin_prev); - - - std::cout << "CONVERTING TO HEX" << std::endl; - for(const auto& el: bin_prev_reverse){ - std::bitset<8> tmp(el); - std::cout << " el: " << tmp.to_string() << " : " << std::hex << tmp.to_ulong() << std::endl; - } - -// stream << std::hex << prevhash_bits.to_ulong(); -// std::cout << "2" << std::endl; -// -// std::string prevhash = stream.str(); -// std::cout << "3" << std::endl; -// -// std::reverse(prevhash.begin(), prevhash.end()); - - res.add("prevhash", stream.str()); - stream.clear(); stream.str(""); - - } catch (std::exception &e){ - std::cout << " !!! === Exception === : " << e.what() << std::endl; - } + res.add("prevhash", reversed_prevblockhash); // TODO: fix this res.add("coinbase1", "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1d03693e0503366c1708"); From e2f74938a6682852321e8a0ee12a5e12b7768f30 Mon Sep 17 00:00:00 2001 From: retsediv Date: Wed, 5 Sep 2018 15:10:13 +0300 Subject: [PATCH 17/22] Cleanup --- include/merit/merkle/merkle.hpp | 213 +------------------------------- include/merit/util/util.hpp | 3 - src/merkle/merkle.cpp | 115 ++++++++++++++--- src/stratum/stratum.cpp | 11 +- src/util/util.cpp | 19 --- 5 files changed, 108 insertions(+), 253 deletions(-) diff --git a/include/merit/merkle/merkle.hpp b/include/merit/merkle/merkle.hpp index 43d8e6b..e772836 100644 --- a/include/merit/merkle/merkle.hpp +++ b/include/merit/merkle/merkle.hpp @@ -49,230 +49,23 @@ namespace merit { namespace merkle { -// template -// class MerkleNode { -// protected: -// -// std::unique_ptr left_, right_; -// const char *hash_; -// const std::shared_ptr value_; -// -// /** -// * Computes the hash of the children nodes' respective hashes. -// * In other words, given a node N, with children (N1, N2), whose hash values are, -// * respectively, H1 and H2, computes: -// * -// * H = hash(H1 || H2) -// * -// * where `||` represents the concatenation operation. -// * If the `right_` descendant is missing, it will simply duplicate the `left_` node's hash. -// * -// * For a "leaf" node (both descendants missing), it will use the `hash_func()` to compute the -// * hash of the stored `value_`. -// */ -// virtual const char *computeHash() const = 0; -// -// public: -// -// /** -// * Builds a "leaf" node, with no descendants and a `value` that will be copied and stored. -// * We also compute the hash (`hash_func()`) of the value and store it in this node. -// * -// * We assume ownership of the pointer returned by the `hash_func()` which we assume has been -// * freshly allocated, and will be released upon destruction of this node. -// */ -// MerkleNode(const T &value) : value_(new T(value)), left_(nullptr), right_(nullptr) { -// hash_ = hash_func(value); -// } -// -// /** -// * Creates an intermediate node, storing the descendants as well as computing the compound hash. -// */ -// MerkleNode(const MerkleNode *left, -// const MerkleNode *right) : -// left_(left), right_(right), value_(nullptr) { -// } -// -// /** -// * Deletes the memory pointed to by the `hash_` pointer: if your `hash_func()` and/or the -// * `computeHash()` method implementation do not allocate this memory (or you do not wish to -// * free the allocated memory) remember to override this destructor's behavior too. -// */ -// virtual ~MerkleNode() { -// if (hash_) delete[](hash_); -// } -// -// /** -// * Recursively validate the subtree rooted in this node: if executed at the root of the tree, -// * it will validate the entire tree. -// */ -// virtual bool validate() const; -// -// /** -// * The length of the hash, also part of the template instantiation (`hash_len`). -// * -// * @see hash_len -// */ -// size_t len() const { return hash_len; } -// -// /** -// * Returns the buffer containing the hash value, of `len()` bytes length. -// * -// * @see len() -// */ -// const char *hash() const { return hash_; } -// -// bool hasChildren() const { -// return left_ || right_; -// } -// -// const MerkleNode *left() const { return left_.get(); } -// -// const MerkleNode *right() const { return right_.get(); } -// }; - - template class MerkleTree { public: explicit MerkleTree(const std::vector &hashes_list) { steps = calculateSteps(hashes_list); } - std::vector branches() { - std::cout << "=== Trying to get branches..." << std::endl; - - std::vector branches; - std::string tmp_hash; - std::stringstream stream; - - std::cout << "before foreach loop" << std::endl; - - for (const auto &step: steps) { - std::cout << "looping..." << std::endl; - std::string tmp{step}; - std::cout << "Step: " << step << " : " << tmp << std::endl; - std::string step_hex; - - merit::util::to_hex(tmp.begin(), tmp.end(), step_hex); - - std::cout << "Step HEX: " << step_hex << std::endl; - -// std::bitset version_bits(step_binary); -// stream << std::hex << version_bits.to_ullong(); -// branches.push_back(stream.str()); stream.str(""); - branches.push_back(step_hex); - } - - std::cout << "End loop and function stuff ===" << std::endl; - - - return branches; - } + std::vector branches(); private: std::vector steps; - std::vector calculateSteps(const std::vector &hashes_list) { - std::cout << "=== calculateSteps()" << std::endl; - - std::vector steps{}; - std::vector L{nullptr}; - for (const auto &el: hashes_list) { - L.push_back(el.c_str()); - } - - int startL = 2; - unsigned long Ll = L.size(); - - if (Ll > 1) - { - std::cout << "Calculating steps.." << std::endl; - while (true) - { - std::cout << " while loop..." << std::endl; - - if(Ll == 1) - break; - - steps.push_back(L[1]); - - if(Ll % 2 == 1) - L.push_back(L[L.size() - 1]); - - std::vector Ld; - - for (int i = startL; i < Ll; i += 2) { - Ld.push_back(merkleJoin(L[i], L[i+1])); - } - - L.clear(); L.push_back(nullptr); - for(const auto& el: Ld) - L.push_back(el); - - Ll = L.size(); - - std::cout << " end of while loop" << std::endl; - - } - } - - std::cout << " end of Calculating steps function ===" << std::endl; - - return steps; - } - - const char* merkleJoin(const char* h1, const char* h2){ - std::string joined = h1; - joined.append(h2); - - return hash_func(joined); - } + std::vector calculateSteps(const std::vector &hashes_list); + const char* merkleJoin(const char* h1, const char* h2); }; const char *double_hash(const std::string &str); -// class DoubleSHA256StringMerkleNode : public MerkleNode { -// public: -// DoubleSHA256StringMerkleNode(const std::string &value) : MerkleNode(value) {} -// -// DoubleSHA256StringMerkleNode(const DoubleSHA256StringMerkleNode *left, -// const DoubleSHA256StringMerkleNode *right) : MerkleNode(left, right) {} -// -// protected: -// const char *computeHash() const override; -// }; - - // Recursive implementation of the build algorithm. -// template -// const NodeType *build_(NodeType *nodes[], size_t len) { -// -// if (len == 1) return new NodeType(nodes[0], nullptr); -// if (len == 2) return new NodeType(nodes[0], nodes[1]); -// -// size_t half = len % 2 == 0 ? len / 2 : len / 2 + 1; -// return new NodeType(build_(nodes, half), build_(nodes + half, len - half)); -// } -// -// template -// const NodeType *build(const std::list &values) { -// -// NodeType *leaves[values.size()]; -// int i = 0; -// for (auto value : values) { -// leaves[i++] = new NodeType(value); -// } -// -// return build_(leaves, values.size()); -// }; -// -// template -// const NodeType *build(const std::vector &values) { -// std::list lst(values.begin(), values.end()); -// -// return build(lst); -// }; - - } } diff --git a/include/merit/util/util.hpp b/include/merit/util/util.hpp index d82d6b6..dcc0d39 100644 --- a/include/merit/util/util.hpp +++ b/include/merit/util/util.hpp @@ -189,9 +189,6 @@ namespace merit std::string HexCharToBin(char c); std::string HexStrToBin(const std::string & hs); - std::vector ReverseByteOrder(const std::string& binary); - - void double_sha256( unsigned char* digest, diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp index 6d0657f..e4d2faa 100644 --- a/src/merkle/merkle.cpp +++ b/src/merkle/merkle.cpp @@ -29,32 +29,107 @@ * also delete it here. */ +#include + #include "merit/merkle/merkle.hpp" namespace merit { namespace merkle { -// template -// bool MerkleNode::validate() const { -// // If either child is not valid, the entire subtree is invalid too. -// if (left_ && !left_->validate()) { -// return false; -// } -// if (right_ && !right_->validate()) { -// return false; -// } -// -// std::unique_ptr computedHash(hasChildren() ? computeHash() : hash_func(*value_)); -// return memcmp(hash_, computedHash.get(), len()) == 0; -// } -// -// const char *DoubleSHA256StringMerkleNode::computeHash() const { -// if(!right_) -// return left_.get()->hash(); -// -// return (std::string(left_.get()->hash()) + std::string(right_.get()->hash())).c_str(); -// } + std::vector MerkleTree::branches() { + std::cout << "=== Trying to get branches... === " << std::endl; + + std::cout << " == Before hexing: " << std::endl; + for(const auto& s: steps){ + std::cout << "step: " << s << std::endl; + } + std::cout << " That's all ==" << std::endl << std::endl; + + + std::vector branches; + std::string tmp_hash; + std::stringstream stream; + + std::cout << "before foreach loop" << std::endl; + + for (const auto &step: steps) { + std::cout << "looping..." << std::endl; + std::string tmp{step}; + std::cout << "Step: " << step << " : " << tmp << std::endl; + std::string step_hex; + + merit::util::to_hex(tmp.begin(), tmp.end(), step_hex); + + std::cout << "Step HEX: " << step_hex << std::endl; + +// std::bitset version_bits(step_binary); +// stream << std::hex << version_bits.to_ullong(); +// branches.push_back(stream.str()); stream.str(""); + branches.push_back(step_hex); + } + + std::cout << "End loop and function stuff ===" << std::endl; + + + return branches; + } + + std::vector MerkleTree::calculateSteps(const std::vector &hashes_list) { + std::cout << "=== calculateSteps()" << std::endl; + + std::vector steps{}; + std::vector L{nullptr}; + for (const auto &el: hashes_list) { + L.push_back(el.c_str()); + } + + int startL = 2; + unsigned long Ll = L.size(); + + if (Ll > 1) + { + std::cout << "Calculating steps.." << std::endl; + while (true) + { + std::cout << " while loop..." << std::endl; + + if(Ll == 1) + break; + + steps.push_back(L[1]); + + if(Ll % 2 == 1) + L.push_back(L[L.size() - 1]); + + std::vector Ld; + + for (int i = startL; i < Ll; i += 2) { + Ld.push_back(merkleJoin(L[i], L[i+1])); + } + + L.clear(); L.push_back(nullptr); + for(const auto& el: Ld) + L.push_back(el); + + Ll = L.size(); + + std::cout << " end of while loop" << std::endl; + + } + } + + std::cout << " end of Calculating steps function ===" << std::endl; + + return steps; + } + + const char *MerkleTree::merkleJoin(const char *h1, const char *h2){ + std::string joined = h1; + joined.append(h2); + + return double_hash(joined); + } const char* double_hash(const std::string& str){ auto *result = new unsigned char[str.size()]; diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index aa386e1..b702b2b 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -481,9 +481,18 @@ namespace merit } std::cout << "MERKLE HASHES SIZE = " << hashes.size() << std::endl; + for(const auto& hash: hashes) + std::cout << "Hash: " << hash << std::endl; + std::cout << std::endl << std::endl; + // Input: + // 1. af5269712e2ccf2d2ff9c3022f03b2b2d252bccc4c01eab5c687f655ba0834cc + + // Result: + // 1. cc3408ba55f687c6b5ea014cccbc52d2b2b2032f02c3f92f2dcf2c2e716952af + try { - auto merkle_tree = merit::merkle::MerkleTree(hashes); + auto merkle_tree = merit::merkle::MerkleTree(hashes); auto branches = merkle_tree.branches(); // std::cout << "Branches: " << branches.size() << std::endl; // for(const auto& branch: branches){ diff --git a/src/util/util.cpp b/src/util/util.cpp index 28fe4a0..db842e8 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -85,24 +85,5 @@ namespace merit return bin; } - std::vector ReverseByteOrder(const std::string& binary){ - std::vector result; - - for (unsigned int i = 0; i < 8; ++i) { // binary.size() / 32 - std::bitset<32> tmp_32{binary.substr(i*32, (i+1) * 32)}; - auto endian_32 = htonl(static_cast(tmp_32.to_ulong())); - - std::bitset<32> tmp_32_{endian_32}; - std::cout << " ||| function: " << tmp_32_.to_string() << std::endl; - - for (int j = 0; j < 4; j++) - result.push_back(static_cast(endian_32 >> (j * 8))); - } - -// std::reverse(result.begin(), result.end()); - - return result; - } - } } From f3279b22df88a0b73bb1d693696b468dbde2356d Mon Sep 17 00:00:00 2001 From: retsediv Date: Thu, 6 Sep 2018 21:27:27 +0300 Subject: [PATCH 18/22] Minor commit, finish merkle tree computations. Need a huge cleanup --- include/merit/merkle/merkle.hpp | 13 +++++-- include/merit/util/util.hpp | 24 ++---------- src/merkle/merkle.cpp | 68 ++++++++++++++++++++++----------- src/stratum/stratum.cpp | 58 ++++++++++++++++++++++------ src/util/util.cpp | 48 +++++++++-------------- 5 files changed, 120 insertions(+), 91 deletions(-) diff --git a/include/merit/merkle/merkle.hpp b/include/merit/merkle/merkle.hpp index e772836..c7c1a85 100644 --- a/include/merit/merkle/merkle.hpp +++ b/include/merit/merkle/merkle.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -51,7 +52,7 @@ namespace merit { class MerkleTree { public: - explicit MerkleTree(const std::vector &hashes_list) { + explicit MerkleTree(const std::vector &hashes_list) { steps = calculateSteps(hashes_list); } @@ -60,11 +61,15 @@ namespace merit { private: std::vector steps; - std::vector calculateSteps(const std::vector &hashes_list); - const char* merkleJoin(const char* h1, const char* h2); + /** + * As input takes array of bytes + * So, before use this function you have to convert hex string into byte array(const char*) + */ + std::vector calculateSteps(const std::vector &hashes_list); + void merkleJoin(const char* h1, const char* h2, char* dest); }; - const char *double_hash(const std::string &str); + const unsigned char *double_hash(const unsigned char* str, unsigned int size); } } diff --git a/include/merit/util/util.hpp b/include/merit/util/util.hpp index dcc0d39..71f3226 100644 --- a/include/merit/util/util.hpp +++ b/include/merit/util/util.hpp @@ -169,31 +169,13 @@ namespace merit boost::algorithm::hex_lower(begin, end, std::back_inserter(res)); } -// bool reverse_hex_string(const std::string& str, std::string& res) -// { -// std::string tmp; -// -// try -// { -// util::parse_hex(str, tmp); -// tmp.reserve(); -// util::to_hex(tmp, res); -// -// return true; -// } -// catch (...) -// { -// return false; -// } -// } - - std::string HexCharToBin(char c); - std::string HexStrToBin(const std::string & hs); - void double_sha256( unsigned char* digest, const unsigned char* data, size_t len); + + int char2int(char input); + void hex2bin(const char* src, char* target); } } #endif diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp index e4d2faa..3dc258d 100644 --- a/src/merkle/merkle.cpp +++ b/src/merkle/merkle.cpp @@ -51,37 +51,26 @@ namespace merit { std::string tmp_hash; std::stringstream stream; - std::cout << "before foreach loop" << std::endl; - for (const auto &step: steps) { - std::cout << "looping..." << std::endl; std::string tmp{step}; - std::cout << "Step: " << step << " : " << tmp << std::endl; std::string step_hex; merit::util::to_hex(tmp.begin(), tmp.end(), step_hex); - - std::cout << "Step HEX: " << step_hex << std::endl; - -// std::bitset version_bits(step_binary); -// stream << std::hex << version_bits.to_ullong(); -// branches.push_back(stream.str()); stream.str(""); branches.push_back(step_hex); } - std::cout << "End loop and function stuff ===" << std::endl; - +// std::cout << "End loop and function stuff ===" << std::endl; return branches; } - std::vector MerkleTree::calculateSteps(const std::vector &hashes_list) { + std::vector MerkleTree::calculateSteps(const std::vector &hashes_list) { std::cout << "=== calculateSteps()" << std::endl; std::vector steps{}; std::vector L{nullptr}; for (const auto &el: hashes_list) { - L.push_back(el.c_str()); + L.push_back(el); } int startL = 2; @@ -105,7 +94,10 @@ namespace merit { std::vector Ld; for (int i = startL; i < Ll; i += 2) { - Ld.push_back(merkleJoin(L[i], L[i+1])); + char *join_res = new char[picosha2::k_digest_size]; + merkleJoin(L[i], L[i+1], join_res); + std::cout << "!========= RESULT OF MERKLE JOIN: " << join_res << std::endl; + Ld.push_back(join_res); } L.clear(); L.push_back(nullptr); @@ -124,17 +116,47 @@ namespace merit { return steps; } - const char *MerkleTree::merkleJoin(const char *h1, const char *h2){ - std::string joined = h1; - joined.append(h2); + void MerkleTree::merkleJoin(const char *h1, const char *h2, char* dest){ + std::cout << " == merkleJoin == " << std::endl; + std::cout << " h1= " << h1 << std::endl; + std::cout << " h2= " << h2 << std::endl; + + std::string joined{h1}; + joined += h2; + + unsigned char buf[joined.size()]; // array to hold the result. + std::copy(joined.begin(), joined.end(), buf); + +// std::cout << " joined= " << joined << " | size= " << joined.size() << std::endl; +// std::cout << " buf= " << buf << std::endl; +// +// for (int i = 0; i < 64; ++i) { +// std::bitset<8> bitset{buf[i]}; +// std::cout << i << " := " << bitset << std::endl; +// } + +// std::cout << "=== before hashing ==="<< std::endl; + + auto res = double_hash(buf, joined.size()); + +// std::cout << "=== after hashing ==="<< std::endl; +// std::cout << " res=" << res << std::endl; +// +// // cast from unsigned to the ordinary + std::string final{reinterpret_cast(res), 32}; + +// std::cout << " final=" << final << " with size=" << final.size() << std::endl; +// std::cout << " final.c_str() =" << final.c_str()<< std::endl; - return double_hash(joined); + std::copy(final.begin(), final.end(), dest); } - const char* double_hash(const std::string& str){ - auto *result = new unsigned char[str.size()]; - merit::util::double_sha256(result, reinterpret_cast(str.c_str()), str.size()); - return reinterpret_cast(result); + const unsigned char* double_hash(const unsigned char* str, unsigned int size){ + auto *result = new unsigned char[picosha2::k_digest_size]; + std::cout << "!!!double_hash!!!" << std::endl; + merit::util::double_sha256(result, str, size); + std::cout << " result=" << result << std::endl; + return result; } } diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index b702b2b..234c7ae 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -440,8 +440,6 @@ namespace merit res.add("id", get_solo_job_id()); - std::cout << "0" << std::endl; - auto prev = params.get("result.previousblockhash"); // then divide to the 8 sybmols parts, reverse array of this parts and join them together @@ -463,6 +461,7 @@ namespace merit // Merkle array of transactions, invites and referrals std::vector hashes{}; + std::vector bin_hashes{}; int i = 0; BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("result.transactions")){ if (i != 0) @@ -480,24 +479,59 @@ namespace merit hashes.push_back(v.second.get("hash")); } + // TODO: it's just for testing, remove then + hashes = {"46f6d6e43c5ee19e2ec0eb63bdf33793b4d7e4a2999b208aa0346cc887da26a2", "ac344a8fd86d70e0193219b8f968c29361f79ac7a908741096d3a31cae9809e2"}; + // 310956155a2ac7809c6c67cd5b60402c0a5698a5b6122b563004dcd2204aa6fd + + // prepare hashes + // to do it: divide it by 2 bytes and reverse(similar as with prevblockhash) + // not sure why should we do that, but pool code doing the same thing + std::string reversed_hash{}; + std::vector parts_of_merkle_hash{}; + + for (int i = 0; i < hashes.size(); ++i) { + // 1. divive by 2 bytes(chars) + for (unsigned long offset = 0; offset < hashes[i].size(); offset += 2) + parts_of_merkle_hash.push_back(hashes[i].substr(offset, 2)); + + // 2. reverse + std::reverse(parts_of_merkle_hash.begin(), parts_of_merkle_hash.end()); + + // 3. join + for(const auto& part: parts_of_merkle_hash) + reversed_hash += part; + + hashes[i] = reversed_hash; + parts_of_merkle_hash.clear(); reversed_hash = ""; + } + std::cout << "MERKLE HASHES SIZE = " << hashes.size() << std::endl; for(const auto& hash: hashes) std::cout << "Hash: " << hash << std::endl; + + // unhex hashes: hex to byte array + for(unsigned int i = 0; i < hashes.size(); ++i){ + std::cout << "Transforming hex to byte array" << std::endl; + std::cout << "char array size: " << hashes[i].size() / 2 << std::endl; + char* target = new char[hashes[i].size() / 2 + 1]; + merit::util::hex2bin(hashes[i].c_str(), target); + target[hashes[i].size() / 2] = '\0'; + bin_hashes.push_back(target); + } + + std::cout << "MERKLE HASHES IN BINARY = " << bin_hashes.size() << std::endl; + for(const auto& hash: bin_hashes) + std::cout << "Hash_Bin: " << hash << std::endl; std::cout << std::endl << std::endl; - // Input: - // 1. af5269712e2ccf2d2ff9c3022f03b2b2d252bccc4c01eab5c687f655ba0834cc - // Result: - // 1. cc3408ba55f687c6b5ea014cccbc52d2b2b2032f02c3f92f2dcf2c2e716952af - try { - auto merkle_tree = merit::merkle::MerkleTree(hashes); + auto merkle_tree = merit::merkle::MerkleTree(bin_hashes); auto branches = merkle_tree.branches(); -// std::cout << "Branches: " << branches.size() << std::endl; -// for(const auto& branch: branches){ -// std::cout << branch << std::endl; -// } + std::cout << "Branches: " << branches.size() << std::endl; + for(const auto& branch: branches){ + std::cout << branch << std::endl; + } // push merkle branches to the result diff --git a/src/util/util.cpp b/src/util/util.cpp index db842e8..d734192 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -49,40 +49,26 @@ namespace merit picosha2::hash256(d.begin(), d.end(), digest, digest+picosha2::k_digest_size); } - std::string HexCharToBin( char c ) { - switch( c ) { - case '0' : return "0000"; - case '1' : return "0001"; - case '2' : return "0010"; - case '3' : return "0011"; - case '4' : return "0100"; - case '5' : return "0101"; - case '6' : return "0110"; - case '7' : return "0111"; - case '8' : return "1000"; - case '9' : return "1001"; - case 'A' : return "1010"; - case 'a' : return "1010"; - case 'B' : return "1011"; - case 'b' : return "1011"; - case 'C' : return "1100"; - case 'c' : return "1100"; - case 'D' : return "1101"; - case 'd' : return "1101"; - case 'E' : return "1110"; - case 'e' : return "1110"; - case 'F' : return "1111"; - case 'f' : return "1111"; - } + int char2int(char input) + { + if(input >= '0' && input <= '9') + return input - '0'; + if(input >= 'A' && input <= 'F') + return input - 'A' + 10; + if(input >= 'a' && input <= 'f') + return input - 'a' + 10; + throw std::invalid_argument("Invalid input string"); } - - std::string HexStrToBin(const std::string & hs) { - std::string bin; - for(auto c : hs) { - bin += HexCharToBin(c); + // This function assumes src to be a zero terminated sanitized string with + // an even number of [0-9a-f] characters, and target to be sufficiently large + void hex2bin(const char* src, char* target) + { + while(*src && src[1]) + { + *(target++) = char2int(*src)*16 + char2int(src[1]); + src += 2; } - return bin; } } From 9d4547afe9e7727bd67d188f4116cf43e111b6f4 Mon Sep 17 00:00:00 2001 From: retsediv Date: Fri, 7 Sep 2018 11:10:26 +0300 Subject: [PATCH 19/22] Cleanup --- src/merkle/merkle.cpp | 53 ++++------------------------------------- src/stratum/stratum.cpp | 17 ++----------- 2 files changed, 7 insertions(+), 63 deletions(-) diff --git a/src/merkle/merkle.cpp b/src/merkle/merkle.cpp index 3dc258d..5eea7a0 100644 --- a/src/merkle/merkle.cpp +++ b/src/merkle/merkle.cpp @@ -38,35 +38,23 @@ namespace merit { namespace merkle { std::vector MerkleTree::branches() { - std::cout << "=== Trying to get branches... === " << std::endl; - - std::cout << " == Before hexing: " << std::endl; - for(const auto& s: steps){ - std::cout << "step: " << s << std::endl; - } - std::cout << " That's all ==" << std::endl << std::endl; - - std::vector branches; std::string tmp_hash; std::stringstream stream; for (const auto &step: steps) { - std::string tmp{step}; + std::string tmp{step, picosha2::k_digest_size}; std::string step_hex; merit::util::to_hex(tmp.begin(), tmp.end(), step_hex); + branches.push_back(step_hex); } -// std::cout << "End loop and function stuff ===" << std::endl; - return branches; } std::vector MerkleTree::calculateSteps(const std::vector &hashes_list) { - std::cout << "=== calculateSteps()" << std::endl; - std::vector steps{}; std::vector L{nullptr}; for (const auto &el: hashes_list) { @@ -76,12 +64,8 @@ namespace merit { int startL = 2; unsigned long Ll = L.size(); - if (Ll > 1) - { - std::cout << "Calculating steps.." << std::endl; - while (true) - { - std::cout << " while loop..." << std::endl; + if (Ll > 1) { + while (true) { if(Ll == 1) break; @@ -96,7 +80,6 @@ namespace merit { for (int i = startL; i < Ll; i += 2) { char *join_res = new char[picosha2::k_digest_size]; merkleJoin(L[i], L[i+1], join_res); - std::cout << "!========= RESULT OF MERKLE JOIN: " << join_res << std::endl; Ld.push_back(join_res); } @@ -106,56 +89,30 @@ namespace merit { Ll = L.size(); - std::cout << " end of while loop" << std::endl; - } } - std::cout << " end of Calculating steps function ===" << std::endl; - return steps; } void MerkleTree::merkleJoin(const char *h1, const char *h2, char* dest){ - std::cout << " == merkleJoin == " << std::endl; - std::cout << " h1= " << h1 << std::endl; - std::cout << " h2= " << h2 << std::endl; - std::string joined{h1}; joined += h2; unsigned char buf[joined.size()]; // array to hold the result. std::copy(joined.begin(), joined.end(), buf); -// std::cout << " joined= " << joined << " | size= " << joined.size() << std::endl; -// std::cout << " buf= " << buf << std::endl; -// -// for (int i = 0; i < 64; ++i) { -// std::bitset<8> bitset{buf[i]}; -// std::cout << i << " := " << bitset << std::endl; -// } - -// std::cout << "=== before hashing ==="<< std::endl; - auto res = double_hash(buf, joined.size()); -// std::cout << "=== after hashing ==="<< std::endl; -// std::cout << " res=" << res << std::endl; -// -// // cast from unsigned to the ordinary + // cast from unsigned to the ordinary std::string final{reinterpret_cast(res), 32}; -// std::cout << " final=" << final << " with size=" << final.size() << std::endl; -// std::cout << " final.c_str() =" << final.c_str()<< std::endl; - std::copy(final.begin(), final.end(), dest); } const unsigned char* double_hash(const unsigned char* str, unsigned int size){ auto *result = new unsigned char[picosha2::k_digest_size]; - std::cout << "!!!double_hash!!!" << std::endl; merit::util::double_sha256(result, str, size); - std::cout << " result=" << result << std::endl; return result; } diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 234c7ae..ee24c3e 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -479,10 +479,6 @@ namespace merit hashes.push_back(v.second.get("hash")); } - // TODO: it's just for testing, remove then - hashes = {"46f6d6e43c5ee19e2ec0eb63bdf33793b4d7e4a2999b208aa0346cc887da26a2", "ac344a8fd86d70e0193219b8f968c29361f79ac7a908741096d3a31cae9809e2"}; - // 310956155a2ac7809c6c67cd5b60402c0a5698a5b6122b563004dcd2204aa6fd - // prepare hashes // to do it: divide it by 2 bytes and reverse(similar as with prevblockhash) // not sure why should we do that, but pool code doing the same thing @@ -505,35 +501,26 @@ namespace merit parts_of_merkle_hash.clear(); reversed_hash = ""; } - std::cout << "MERKLE HASHES SIZE = " << hashes.size() << std::endl; - for(const auto& hash: hashes) - std::cout << "Hash: " << hash << std::endl; - // unhex hashes: hex to byte array for(unsigned int i = 0; i < hashes.size(); ++i){ - std::cout << "Transforming hex to byte array" << std::endl; - std::cout << "char array size: " << hashes[i].size() / 2 << std::endl; char* target = new char[hashes[i].size() / 2 + 1]; merit::util::hex2bin(hashes[i].c_str(), target); target[hashes[i].size() / 2] = '\0'; bin_hashes.push_back(target); } - std::cout << "MERKLE HASHES IN BINARY = " << bin_hashes.size() << std::endl; - for(const auto& hash: bin_hashes) - std::cout << "Hash_Bin: " << hash << std::endl; - std::cout << std::endl << std::endl; - try { auto merkle_tree = merit::merkle::MerkleTree(bin_hashes); auto branches = merkle_tree.branches(); + std::cout << "Branches: " << branches.size() << std::endl; for(const auto& branch: branches){ std::cout << branch << std::endl; } // push merkle branches to the result + // ... } catch (std::exception &e) { std::cout << "||| Error ||| = " << e.what() << std::endl; From 1601efb9cc7b6b2e6904bfbb4bcd221de352cdd6 Mon Sep 17 00:00:00 2001 From: retsediv Date: Fri, 7 Sep 2018 11:17:43 +0300 Subject: [PATCH 20/22] Return merkle branches in the resulting json(ptree) object --- src/stratum/stratum.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index ee24c3e..238cd46 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -514,16 +514,17 @@ namespace merit auto merkle_tree = merit::merkle::MerkleTree(bin_hashes); auto branches = merkle_tree.branches(); - std::cout << "Branches: " << branches.size() << std::endl; + // push merkle branches to the result + pt::ptree children; for(const auto& branch: branches){ - std::cout << branch << std::endl; + pt::ptree child; + child.put("", branch); + children.push_back(std::make_pair("", child)); } - // push merkle branches to the result - // ... - + res.add_child("merkle_braches", children); } catch (std::exception &e) { - std::cout << "||| Error ||| = " << e.what() << std::endl; + std::cout << "An error occurred during 'Merkle Tree' computations = " << e.what() << std::endl; } auto block_version = boost::lexical_cast(params.get("result.version")); // get version parameter From c77b3fe0926dbc83ba1cdbdf05e2c73d2290b6f2 Mon Sep 17 00:00:00 2001 From: retsediv Date: Fri, 7 Sep 2018 11:27:41 +0300 Subject: [PATCH 21/22] Fix typo --- src/stratum/stratum.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index 238cd46..ccbd9a4 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -464,6 +464,7 @@ namespace merit std::vector bin_hashes{}; int i = 0; BOOST_FOREACH(const pt::ptree::value_type &v, params.get_child("result.transactions")){ + // to skip the first transaction if (i != 0) hashes.push_back(v.second.get("txid")); @@ -522,7 +523,7 @@ namespace merit children.push_back(std::make_pair("", child)); } - res.add_child("merkle_braches", children); + res.add_child("merkle_branches", children); } catch (std::exception &e) { std::cout << "An error occurred during 'Merkle Tree' computations = " << e.what() << std::endl; } From 169dce52a7634ff1b561a8bfd49ab16fdd2ea251 Mon Sep 17 00:00:00 2001 From: retsediv Date: Wed, 12 Sep 2018 16:04:59 +0300 Subject: [PATCH 22/22] Properly get solo block and start mine it --- src/minerd.cpp | 5 ++--- src/public.cpp | 33 ++++++++++++--------------------- src/stratum/stratum.cpp | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/minerd.cpp b/src/minerd.cpp index ca14f04..5f1d319 100644 --- a/src/minerd.cpp +++ b/src/minerd.cpp @@ -120,16 +120,15 @@ int main(int argc, char** argv) std::cerr << "Error connecting" << std::endl; return 1; } - merit::run_stratum(c.get(), solo_mining); } else { if (!merit::connect_solo_stratum(c.get(), solo_url.c_str(), address.c_str(), "")) { std::cerr << "Error connecting" << std::endl; return 1; } - - merit::run_stratum(c.get(), solo_mining); } + merit::run_stratum(c.get(), solo_mining); + merit::run_miner(c.get(), utilization.first, utilization.second, gpu_devices, solo_mining, auth_token); int prev_graphs = 0; diff --git a/src/public.cpp b/src/public.cpp index 45784c1..2bc2379 100644 --- a/src/public.cpp +++ b/src/public.cpp @@ -230,37 +230,28 @@ namespace merit { while (c->miner->running()) try { - auto j = c->stratum.get_solo_job(auth_token); + c->stratum.get_solo_job(auth_token); - std::this_thread::sleep_for(20s); - - if(j){ - std::cout << "There is a job!!!" << std::endl; - std::this_thread::sleep_for(5s); -// break; + // get block + auto j = c->stratum.get_job(); + while(!j.is_initialized()){ + std::this_thread::sleep_for(1s); + j = c->stratum.get_job(); } -// if (!j) { -// std::cout << "== NO JOB! ==" << std::endl; -// c->miner->clear_job(); -// std::this_thread::sleep_for(50ms); -// continue; -// } - - - std::cout << "After getting the job" << std::endl; -// c->miner->submit_job(*j); - - // get block + // submit and then finding cycles starts + c->miner->submit_job(*j); - // mine it + std::this_thread::sleep_for(10s); // just for testing // if good cycle, then submit block // again... +// std::cout << "Clearing the job" << std::endl; +// c->miner->clear_job(); } catch (std::exception &e) { - std::cerr << "error: " << "error getting job: " << e.what() << std::endl; + std::cerr << "error: " << "error getting job for solo mining: " << e.what() << std::endl; std::this_thread::sleep_for(50ms); } }); diff --git a/src/stratum/stratum.cpp b/src/stratum/stratum.cpp index ccbd9a4..d37cf58 100644 --- a/src/stratum/stratum.cpp +++ b/src/stratum/stratum.cpp @@ -374,7 +374,7 @@ namespace merit auto prevhash = res.get("prevhash"); auto coinbase1 = res.get("coinbase1"); auto coinbase2 = res.get("coinbase2"); - auto merkle_array = std::vector{}; + auto merkle_array = res.get_child("merkle_branches"); auto version = res.get("version"); auto nbits = res.get("bits"); auto edgebits = res.get("edgebits"); @@ -382,9 +382,9 @@ namespace merit auto is_clean = res.get("is_clean"); if(prevhash.size() != 64) { return false; } - if(version.size() != 8) { return false; } // problem + if(version.size() != 8) { return false; } if(nbits.size() != 8) { return false; } - if(time.size() != 8) { return false; } // problem + if(time.size() != 8) { return false; } std::lock_guard guard{_job_mutex}; Job j; @@ -409,15 +409,15 @@ namespace merit j.id = job_id; -// for(const auto& hex : merkle_array) { -// std::string s = hex.second.get_value(); -// util::ubytes bin; -// if(!util::parse_hex(s, bin)) { -// return false; -// } -// -// j.merkle.push_back(bin); -// } + for(const auto& hex : merkle_array) { + std::string s = hex.second.get_value(); + util::ubytes bin; + if(!util::parse_hex(s, bin)) { + return false; + } + + j.merkle.push_back(bin); + } j.diff = _next_diff; j.clean = is_clean;