diff --git a/CMakeLists.txt b/CMakeLists.txt index 75e18f7..de22f5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ set(LIBRARIES unbound curl crypto + atomic ssl) if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32) diff --git a/main.cpp b/main.cpp index 2b38b74..a809719 100644 --- a/main.cpp +++ b/main.cpp @@ -26,7 +26,18 @@ struct jsonresponse: crow::response }; } +class ExitHandler +{ +public: + void exit() { exitHandler(0); } + static void exitHandler(int) { s_shouldExit = true; } + bool shouldExit() const { return s_shouldExit; } +private: + static bool s_shouldExit; +}; + +bool ExitHandler::s_shouldExit = false; int main(int ac, const char* av[]) { @@ -60,6 +71,8 @@ int main(int ac, const char* av[]) { auto enable_tx_cache_opt = opts.get_option("enable-tx-cache"); auto enable_block_cache_opt = opts.get_option("enable-block-cache"); auto show_cache_times_opt = opts.get_option("show-cache-times"); + auto enable_emission_monitor_opt = opts.get_option("enable-emission-monitor"); + bool testnet {*testnet_opt}; bool enable_pusher {*enable_pusher_opt}; @@ -71,6 +84,7 @@ int main(int ac, const char* av[]) { bool enable_json_api {*enable_json_api_opt}; bool enable_tx_cache {*enable_tx_cache_opt}; bool enable_block_cache {*enable_block_cache_opt}; + bool enable_emission_monitor {*enable_emission_monitor_opt}; bool show_cache_times {*show_cache_times_opt}; @@ -149,24 +163,41 @@ int main(int ac, const char* av[]) { deamon_url = "http:://127.0.0.1:28081"; } - xmreg::CurrentBlockchainStatus::blockchain_path - = blockchain_path.string(); - xmreg::CurrentBlockchainStatus::testnet - = testnet; - xmreg::CurrentBlockchainStatus::deamon_url - = deamon_url; - if (!xmreg::CurrentBlockchainStatus::init_monero_blockchain()) + if (enable_emission_monitor == true) { - cerr << "Error accessing blockchain from CurrentBlockchainStatus." << endl; - return EXIT_FAILURE; - } + // This starts new thread, which aim is + // to calculate, store and monitor + // current total Monero emission amount. - // launch the status monitoring thread so that it keeps track of blockchain - // info, e.g., current height. Information from this thread is used - // by tx searching threads that are launched for each user independently, - // when they log back or create new account. - xmreg::CurrentBlockchainStatus::start_monitor_blockchain_thread(); + // This thread stores the current emission + // which it has caluclated in + // /emission_amount.txt file, + // e.g., ~/.bitmonero/lmdb/emission_amount.txt. + // So instead of calcualting the emission + // from scrach whenever the explorer is started, + // the thread is initalized with the values + // found in emission_amount.txt file. + + xmreg::CurrentBlockchainStatus::blockchain_path + = blockchain_path.string(); + xmreg::CurrentBlockchainStatus::testnet + = testnet; + xmreg::CurrentBlockchainStatus::deamon_url + = deamon_url; + + if (!xmreg::CurrentBlockchainStatus::init_monero_blockchain()) + { + cerr << "Error accessing blockchain from CurrentBlockchainStatus." << endl; + return EXIT_FAILURE; + } + + // launch the status monitoring thread so that it keeps track of blockchain + // info, e.g., current height. Information from this thread is used + // by tx searching threads that are launched for each user independently, + // when they log back or create new account. + xmreg::CurrentBlockchainStatus::start_monitor_blockchain_thread(); + } // create instance of page class which // contains logic for the website diff --git a/src/CmdLineOptions.cpp b/src/CmdLineOptions.cpp index 2a2830a..e93bdec 100644 --- a/src/CmdLineOptions.cpp +++ b/src/CmdLineOptions.cpp @@ -45,6 +45,8 @@ namespace xmreg "enable caching of block details") ("enable-autorefresh-option", value()->default_value(false)->implicit_value(true), "enable users to have the index page on autorefresh") + ("enable-emission-monitor", value()->default_value(false)->implicit_value(true), + "enable Monero total emission monitoring thread") ("port,p", value()->default_value("8081"), "default port") ("testnet-url", value()->default_value(""), diff --git a/src/CurrentBlockchainStatus.cpp b/src/CurrentBlockchainStatus.cpp index c25ad99..2327e8e 100644 --- a/src/CurrentBlockchainStatus.cpp +++ b/src/CurrentBlockchainStatus.cpp @@ -38,6 +38,7 @@ CurrentBlockchainStatus::init_monero_blockchain() void CurrentBlockchainStatus::start_monitor_blockchain_thread() { + total_emission_atomic = Emission {0, 0, 0}; string emmision_saved_file = get_output_file_path(); @@ -64,13 +65,15 @@ CurrentBlockchainStatus::start_monitor_blockchain_thread() { while (true) { + Emission current_emission = total_emission_atomic; + current_height = core_storage->get_current_blockchain_height(); update_current_emission_amount(); save_current_emission_amount(); - if (searched_blk_no < current_height - blockchain_chunk_size) + if (current_emission.blk_no < current_height - blockchain_chunk_size) { std::this_thread::sleep_for(std::chrono::seconds(1)); } @@ -90,9 +93,9 @@ void CurrentBlockchainStatus::update_current_emission_amount() { - cout << "updating emission rate: " << current_height << endl; + Emission current_emission = total_emission_atomic; - uint64_t blk_no = searched_blk_no; + uint64_t blk_no = current_emission.blk_no; uint64_t end_block = blk_no + blockchain_chunk_size; @@ -100,8 +103,8 @@ CurrentBlockchainStatus::update_current_emission_amount() end_block = end_block > current_blockchain_height ? current_blockchain_height : end_block; - uint64_t current_emission_amount {0}; - uint64_t current_fee_amount {0}; + uint64_t temp_emission_amount {0}; + uint64_t temp_fee_amount {0}; while (blk_no < end_block) { @@ -124,20 +127,19 @@ CurrentBlockchainStatus::update_current_emission_amount() tx_fee_amount += get_tx_fee(tx); } - current_emission_amount += coinbase_amount - tx_fee_amount; - current_fee_amount += tx_fee_amount; + temp_emission_amount += coinbase_amount - tx_fee_amount; + temp_fee_amount += tx_fee_amount; ++blk_no; } - searched_blk_no = blk_no; - total_emission_amount += current_emission_amount; - total_fee_amount += current_fee_amount; + current_emission.coinbase += temp_emission_amount; + current_emission.fee += temp_fee_amount; + current_emission.blk_no = blk_no; - cout << "blk: " << blk_no - << " total_emission_amount: " << xmr_amount_to_str(uint64_t(total_emission_amount)) - << " total_fee_amount: " << xmr_amount_to_str(uint64_t(total_fee_amount)) - << endl; + total_emission_atomic = current_emission; + + cout << "total emission: " << string(current_emission) << endl; } @@ -156,16 +158,9 @@ CurrentBlockchainStatus::save_current_emission_amount() return false; } - uint64_t check_sum = uint64_t(searched_blk_no) - + uint64_t(total_emission_amount) - + uint64_t(total_fee_amount); + Emission current_emission = total_emission_atomic; - string out_line = to_string(searched_blk_no) - + "," + to_string(total_emission_amount) - + "," + to_string(total_fee_amount) - + "," + to_string(check_sum); - - out << out_line << flush; + out << string(current_emission) << flush; return true; } @@ -195,14 +190,16 @@ CurrentBlockchainStatus::load_current_emission_amount() return false; } - uint64_t read_check_sum{0}; + Emission emission_loaded {0, 0, 0}; + + uint64_t read_check_sum {0}; try { - searched_blk_no = boost::lexical_cast(strs.at(0)); - total_emission_amount = boost::lexical_cast(strs.at(1)); - total_fee_amount = boost::lexical_cast(strs.at(2)); - read_check_sum = boost::lexical_cast(strs.at(3)); + emission_loaded.blk_no = boost::lexical_cast(strs.at(0)); + emission_loaded.coinbase = boost::lexical_cast(strs.at(1)); + emission_loaded.fee = boost::lexical_cast(strs.at(2)); + read_check_sum = boost::lexical_cast(strs.at(3)); } catch (boost::bad_lexical_cast &e) { @@ -210,19 +207,17 @@ CurrentBlockchainStatus::load_current_emission_amount() return false; } - uint64_t check_sum = uint64_t(searched_blk_no) - + uint64_t(total_emission_amount) - + uint64_t(total_fee_amount); - - if (read_check_sum != check_sum) + if (read_check_sum != emission_loaded.checksum()) { cerr << "read_check_sum != check_sum: " - << read_check_sum << " != " << check_sum + << read_check_sum << " != " << emission_loaded.checksum() << endl; return false; } + total_emission_atomic = emission_loaded; + return true; } @@ -236,16 +231,10 @@ CurrentBlockchainStatus::get_output_file_path() } -vector -CurrentBlockchainStatus::get_emission_amount() +CurrentBlockchainStatus::Emission +CurrentBlockchainStatus::get_emission() { - - uint64_t searched_block = searched_blk_no; - uint64_t emission_amount = total_emission_amount; - uint64_t fee_amount = total_fee_amount; - - return {searched_block, emission_amount, fee_amount}; - + return total_emission_atomic.load(); } bool @@ -266,11 +255,7 @@ uint64_t CurrentBlockchainStatus::blockchain_chunk_size {10000}; atomic CurrentBlockchainStatus::current_height {0}; -atomic CurrentBlockchainStatus::total_emission_amount {0} ; - -atomic CurrentBlockchainStatus::total_fee_amount {0} ; - -atomic CurrentBlockchainStatus::searched_blk_no {0}; +atomic CurrentBlockchainStatus::total_emission_atomic; std::thread CurrentBlockchainStatus::m_thread; diff --git a/src/CurrentBlockchainStatus.h b/src/CurrentBlockchainStatus.h index 983c0fc..57e2010 100644 --- a/src/CurrentBlockchainStatus.h +++ b/src/CurrentBlockchainStatus.h @@ -23,6 +23,26 @@ using namespace std; struct CurrentBlockchainStatus { + struct Emission + { + uint64_t coinbase; + uint64_t fee; + uint64_t blk_no; + + inline uint64_t + checksum() const + { + return coinbase + fee + blk_no; + } + + operator + std::string() const + { + return to_string(blk_no) + "," + to_string(coinbase) + + "," + to_string(fee) + "," + to_string(checksum()); + } + }; + static string blockchain_path; static bool testnet; @@ -35,11 +55,7 @@ struct CurrentBlockchainStatus static atomic current_height; - static atomic total_emission_amount; - - static atomic total_fee_amount; - - static atomic searched_blk_no; + static atomic total_emission_atomic; static std::thread m_thread; @@ -65,8 +81,8 @@ struct CurrentBlockchainStatus static bool load_current_emission_amount(); - static vector - get_emission_amount(); + static Emission + get_emission(); static string get_output_file_path(); diff --git a/src/page.h b/src/page.h index fb6a1ea..374d948 100644 --- a/src/page.h +++ b/src/page.h @@ -761,17 +761,17 @@ namespace xmreg if (CurrentBlockchainStatus::is_thread_running()) { - vector emission_values - = CurrentBlockchainStatus::get_emission_amount(); + CurrentBlockchainStatus::Emission current_values + = CurrentBlockchainStatus::get_emission(); - string emission_blk_no = std::to_string(emission_values.at(0) - 1); - string emission_amount = xmr_amount_to_str(emission_values.at(1), "{:0.3f}"); - string emission_fee_amount = xmr_amount_to_str(emission_values.at(2), "{:0.3f}"); + string emission_blk_no = std::to_string(current_values.blk_no); + string emission_coinbase = xmr_amount_to_str(current_values.coinbase, "{:0.3f}"); + string emission_fee = xmr_amount_to_str(current_values.fee, "{:0.3f}"); context["emission"] = mstch::map { {"blk_no" , emission_blk_no}, - {"amount" , emission_amount}, - {"fee_amount", emission_fee_amount} + {"amount" , emission_coinbase}, + {"fee_amount", emission_fee} }; } else