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/README.md b/README.md index d73fadf..3cb014b 100644 --- a/README.md +++ b/README.md @@ -146,10 +146,10 @@ Go to your browser: http://127.0.0.1:8081 ``` ./xmrblocks -h -xmrblocks, start Onion Monero Blockchain Explorer: +xmrblocks, Onion Monero Blockchain Explorer: -h [ --help ] [=arg(=1)] (=0) produce help message -t [ --testnet ] [=arg(=1)] (=0) use testnet blockchain - --enable-pusher [=arg(=1)] (=0) enable pushing signed tx + --enable-pusher [=arg(=1)] (=0) enable signed transaction pusher --enable-mixin-details [=arg(=1)] (=0) enable mixin details for key images, e.g., timescale, mixin of mixins, in tx @@ -158,45 +158,80 @@ xmrblocks, start Onion Monero Blockchain Explorer: enable key images file checker --enable-output-key-checker [=arg(=1)] (=0) enable outputs key file checker - --enable-mempool-cache arg (=1) enable caching txs in the mempool + --enable-mempool-cache arg (=1) enable caching of transactions from the + mempool --enable-json-api arg (=1) enable JSON REST api - --enable-tx-cache [=arg(=1)] (=0) enable caching of tx details + --enable-tx-cache [=arg(=1)] (=0) enable caching of transaction details --show-cache-times [=arg(=1)] (=0) show times of getting data from cache vs no cache --enable-block-cache [=arg(=1)] (=0) enable caching of block details --enable-autorefresh-option [=arg(=1)] (=0) enable users to have the index page on autorefresh - -p [ --port ] arg (=8081) default port - --testnet-url arg you can specifiy testnet url, if you - run it on mainet. link will show on - front page to testnet explorer - --mainnet-url arg you can specifiy mainnet url, if you - run it on testnet. link will show on - front page to mainnet explorer + --enable-emission-monitor [=arg(=1)] (=0) + enable Monero total emission monitoring + thread + -p [ --port ] arg (=8081) default explorer port + --testnet-url arg you can specify testnet url, if you run + it on mainnet. link will show on front + page to testnet explorer + --mainnet-url arg you can specify mainnet url, if you run + it on testnet. link will show on front + page to mainnet explorer --no-blocks-on-index arg (=10) number of last blocks to be shown on index page - -b [ --bc-path ] arg path to lmdb blockchain - --ssl-crt-file arg A path to crt file for ssl (https) + -b [ --bc-path ] arg path to lmdb folder of the blockchain, + e.g., ~/.bitmonero/lmdb + --ssl-crt-file arg path to crt file for ssl (https) functionality - --ssl-key-file arg A path to key file for ssl (https) + --ssl-key-file arg path to key file for ssl (https) functionality -d [ --deamon-url ] arg (=http:://127.0.0.1:18081) - monero address string + Monero deamon url ``` Example usage, defined as bash aliases. ```bash # for mainnet explorer -alias xmrblocksmainnet='~/onion-monero-blockchain-explorer/build/xmrblocks --port 8081 --no-blocks-on-index 49 --testnet-url "http://139.162.32.245:8082" --enable-block-cache=1 --enable-tx-cache=1 --enable-mempool-cache=1 --show-cache-times=1 --enable-pusher' +alias xmrblocksmainnet='~/onion-monero-blockchain-explorer/build/xmrblocks --port 8081 --no-blocks-on-index 24 --testnet-url "http://139.162.32.245:8082" --enable-pusher --enable-emission-monitor' # for testnet explorer -alias xmrblockstestnet='~/onion-monero-blockchain-explorer/build/xmrblocks -t --port 8082 --no-blocks-on-index 24 --mainnet-url "http://139.162.32.245:8081" --enable-block-cache=1 --enable-tx-cache=1 --enable-mempool-cache=1 --show-cache-times=1 --enable-pusher' +alias xmrblockstestnet='~/onion-monero-blockchain-explorer/build/xmrblocks -t --port 8082 --no-blocks-on-index 24 --mainnet-url "http://139.162.32.245:8081" --enable-pusher --enable-emission-monitor' ``` -These are explorer commands used for http://139.162.32.245:8081/ and http://139.162.32.245:8082/, respectively. +These are aliases similar to those used for http://139.162.32.245:8081/ and http://139.162.32.245:8082/, respectively. +## Enable Monero emission + +Obtaining current Monero emission amount is not straight forward. Thus, by default it is +disabled. To enable it use `--enable-emission-monitor` flag, e.g., + + +```bash +xmrblocks --enable-emission-monitor +``` + +This flag will enable emission monitoring thread. When started, the thread + will initially scan the entire blockchain, and calculate the cumulative emission based on each block. +Since it is a separate thread, the explorer will work as usual during this time. +Every 10000 blocks, the thread will save current emission in a file, by default, + in `~/.bitmonero/lmdb/emission_amount.txt`. This file is used so that we don't + need to rescan entire blockchain whenever the explorer is restarted. When the + explorer restarts, the thread will first check if `~/.bitmonero/lmdb/emission_amount.txt` + is present, read its values, and continue from there if possible. Subsequently, only the initial + use of the tread is time consuming. Once the thread scans the entire blockchain, it updates + the emission amount using new blocks as they come. + + When the emission monitor is enabled, information about current emission of coinbase and fees is + displayed on the front page, e.g., : + +``` +Monero emission (fees) is 14485540.430 (52545.373) as of 1313448 block +``` + +To disable the monitor, simply restart the explorer without `--enable-emission-monitor` flag. + ## Enable SSL (https) By default, the explorer does not use ssl. But it has such a functionality. @@ -589,6 +624,25 @@ curl -w "\n" -X GET "http://139.162.32.245:8081/api/networkinfo" } ``` +#### api/emission + +```bash +curl -w "\n" -X GET "http://139.162.32.245:8081/api/emission" +``` + +```json +{ + "data": { + "blk_no": 1313969, + "coinbase": 14489473877253413000, + "fee": 52601974988641130 + }, + "status": "success" +} +``` + +Emission only works when the emission monitoring thread is enabled. + #### api/rawblock/ diff --git a/main.cpp b/main.cpp index 8c1827d..b3bee81 100644 --- a/main.cpp +++ b/main.cpp @@ -17,7 +17,8 @@ namespace myxmr { struct jsonresponse: crow::response { - jsonresponse(const nlohmann::json& _body) : crow::response {_body.dump()} + jsonresponse(const nlohmann::json& _body) + : crow::response {_body.dump()} { add_header("Access-Control-Allow-Origin", "*"); add_header("Access-Control-Allow-Headers", "Content-Type"); @@ -26,10 +27,9 @@ struct jsonresponse: crow::response }; } - - -int main(int ac, const char* av[]) { - +int +main(int ac, const char* av[]) +{ // get command line options xmreg::CmdLineOptions opts {ac, av}; @@ -60,6 +60,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 +73,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}; @@ -128,6 +131,7 @@ int main(int ac, const char* av[]) { cout << blockchain_path << endl; + // create instance of our MicroCore // and make pointer to the Blockchain xmreg::MicroCore mcore; @@ -144,7 +148,41 @@ int main(int ac, const char* av[]) { string deamon_url {*deamon_url_opt}; if (testnet && deamon_url == "http:://127.0.0.1:18081") + { deamon_url = "http:://127.0.0.1:28081"; + } + + + if (enable_emission_monitor == true) + { + // This starts new thread, which aim is + // to calculate, store and monitor + // current total Monero emission amount. + + // 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; + xmreg::CurrentBlockchainStatus::testnet + = testnet; + xmreg::CurrentBlockchainStatus::deamon_url + = deamon_url; + xmreg::CurrentBlockchainStatus::set_blockchain_variables( + &mcore, core_storage); + + // 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 @@ -434,6 +472,14 @@ int main(int ac, const char* av[]) { return r; }); + CROW_ROUTE(app, "/api/emission") + ([&](const crow::request &req) { + + myxmr::jsonresponse r{xmrblocks.json_emission()}; + + return r; + }); + CROW_ROUTE(app, "/api/outputs").methods("GET"_method) ([&](const crow::request &req) { @@ -490,5 +536,16 @@ int main(int ac, const char* av[]) { } + if (enable_emission_monitor == true) + { + // finish Emission monitoring thread in a cotrolled manner. + xmreg::CurrentBlockchainStatus::m_thread.interrupt(); + xmreg::CurrentBlockchainStatus::m_thread.join(); + + cout << "Emission monitoring thread joined." << endl; + } + + cout << "The explorer is terminating." << endl; + return EXIT_SUCCESS; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a15dc01..d4f476c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ set(SOURCE_HEADERS MicroCore.h tools.h monero_headers.h - ) + CurrentBlockchainStatus.h) set(SOURCE_FILES MicroCore.cpp @@ -14,7 +14,7 @@ set(SOURCE_FILES CmdLineOptions.cpp page.h rpccalls.cpp rpccalls.h - version.h.in) + version.h.in CurrentBlockchainStatus.cpp) # make static library called libmyxrm # that we are going to link to diff --git a/src/CmdLineOptions.cpp b/src/CmdLineOptions.cpp index 2a2830a..1ae6493 100644 --- a/src/CmdLineOptions.cpp +++ b/src/CmdLineOptions.cpp @@ -18,7 +18,7 @@ namespace xmreg p.add("txhash", -1); options_description desc( - "xmrblocks, start Onion Monero Blockchain Explorer"); + "xmrblocks, Onion Monero Blockchain Explorer"); desc.add_options() ("help,h", value()->default_value(false)->implicit_value(true), @@ -26,7 +26,7 @@ namespace xmreg ("testnet,t", value()->default_value(false)->implicit_value(true), "use testnet blockchain") ("enable-pusher", value()->default_value(false)->implicit_value(true), - "enable pushing signed tx") + "enable signed transaction pusher") ("enable-mixin-details", value()->default_value(false)->implicit_value(true), "enable mixin details for key images, e.g., timescale, mixin of mixins, in tx context") ("enable-key-image-checker", value()->default_value(false)->implicit_value(true), @@ -34,33 +34,35 @@ namespace xmreg ("enable-output-key-checker", value()->default_value(false)->implicit_value(true), "enable outputs key file checker") ("enable-mempool-cache", value()->default_value(true), - "enable caching txs in the mempool") + "enable caching of transactions from the mempool") ("enable-json-api", value()->default_value(true), "enable JSON REST api") ("enable-tx-cache", value()->default_value(false)->implicit_value(true), - "enable caching of tx details") + "enable caching of transaction details") ("show-cache-times", value()->default_value(false)->implicit_value(true), "show times of getting data from cache vs no cache") ("enable-block-cache", value()->default_value(false)->implicit_value(true), "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") + "default explorer port") ("testnet-url", value()->default_value(""), - "you can specifiy testnet url, if you run it on mainet. link will show on front page to testnet explorer") + "you can specify testnet url, if you run it on mainnet. link will show on front page to testnet explorer") ("mainnet-url", value()->default_value(""), - "you can specifiy mainnet url, if you run it on testnet. link will show on front page to mainnet explorer") + "you can specify mainnet url, if you run it on testnet. link will show on front page to mainnet explorer") ("no-blocks-on-index", value()->default_value("10"), "number of last blocks to be shown on index page") ("bc-path,b", value(), - "path to lmdb blockchain") + "path to lmdb folder of the blockchain, e.g., ~/.bitmonero/lmdb") ("ssl-crt-file", value(), - "A path to crt file for ssl (https) functionality") + "path to crt file for ssl (https) functionality") ("ssl-key-file", value(), - "A path to key file for ssl (https) functionality") + "path to key file for ssl (https) functionality") ("deamon-url,d", value()->default_value("http:://127.0.0.1:18081"), - "monero address string"); + "Monero deamon url"); store(command_line_parser(acc, avv) diff --git a/src/CurrentBlockchainStatus.cpp b/src/CurrentBlockchainStatus.cpp new file mode 100644 index 0000000..8750700 --- /dev/null +++ b/src/CurrentBlockchainStatus.cpp @@ -0,0 +1,322 @@ +// +// Created by mwo on 16/05/17. +// + +#include "CurrentBlockchainStatus.h" + +namespace xmreg +{ + +using namespace std; + + + +void +CurrentBlockchainStatus::set_blockchain_variables(MicroCore* _mcore, + Blockchain* _core_storage) +{ + mcore = _mcore; + core_storage =_core_storage; +} + + +void +CurrentBlockchainStatus::start_monitor_blockchain_thread() +{ + total_emission_atomic = Emission {0, 0, 0}; + + string emmision_saved_file = get_output_file_path().string(); + + // read stored emission data if possible + if (boost::filesystem::exists(emmision_saved_file)) + { + if (!load_current_emission_amount()) + { + cerr << "Emission file cant be read, got corrupted or has incorrect format:\n " << emmision_saved_file + << "\nEmission monitoring thread is not started.\nDelete the file and" + << " restart the explorer or disable emission monitoring." + << endl; + + cerr << "Press ENTER to continue without emission monitoring or Ctr+C to exit" << endl; + + cin.get(); + + return; + } + } + + if (!is_running) + { + m_thread = boost::thread{[]() + { + try + { + while (true) + { + Emission current_emission = total_emission_atomic; + + current_height = core_storage->get_current_blockchain_height(); + + // scan 10000 blocks for emissiom or if we are at the top of + // the blockchain, only few top blocks + update_current_emission_amount(); + + cout << "current emission: " << string(current_emission) << endl; + + save_current_emission_amount(); + + if (current_emission.blk_no < current_height - blockchain_chunk_size) + { + // while we scan the blockchain from scrach, every 10000 + // blocks take 1 second break + boost::this_thread::sleep_for(boost::chrono::seconds(1)); + } + else + { + // when we reach top of the blockchain, update + // the emission amount every minute. + boost::this_thread::sleep_for(boost::chrono::seconds(60)); + } + + } // while (true) + } + catch (boost::thread_interrupted&) + { + cout << "Emission monitoring thread interrupted." << endl; + return; + } + + }}; // m_thread = boost::thread{[]() + + is_running = true; + + } // if (!is_running) +} + + +void +CurrentBlockchainStatus::update_current_emission_amount() +{ + + Emission current_emission = total_emission_atomic; + + uint64_t blk_no = current_emission.blk_no; + + uint64_t end_block = blk_no + blockchain_chunk_size; + + uint64_t current_blockchain_height = current_height; + + // blockchain_chunk_gap is used so that we + // never read and store few top blocks + // the emission in the top few blocks will be calcalted + // later + end_block = end_block > current_blockchain_height + ? current_blockchain_height - blockchain_chunk_gap + : end_block; + + Emission emission_calculated = calculate_emission_in_blocks(blk_no, end_block); + + current_emission.coinbase += emission_calculated.coinbase; + current_emission.fee += emission_calculated.fee; + current_emission.blk_no = emission_calculated.blk_no; + + total_emission_atomic = current_emission; +} + +CurrentBlockchainStatus::Emission +CurrentBlockchainStatus::calculate_emission_in_blocks( + uint64_t start_blk, uint64_t end_blk) +{ + Emission emission_calculated {0, 0, 0}; + + while (start_blk < end_blk) + { + block blk; + + mcore->get_block_by_height(start_blk, blk); + + uint64_t coinbase_amount = get_outs_money_amount(blk.miner_tx); + + std::list txs; + std::list missed_txs; + + uint64_t tx_fee_amount = 0; + + core_storage->get_transactions(blk.tx_hashes, txs, missed_txs); + + for(const auto& tx: txs) + { + tx_fee_amount += get_tx_fee(tx); + } + + (void) missed_txs; + + emission_calculated.coinbase += coinbase_amount - tx_fee_amount; + emission_calculated.fee += tx_fee_amount; + + ++start_blk; + } + + emission_calculated.blk_no = start_blk; + + return emission_calculated; +} + + +bool +CurrentBlockchainStatus::save_current_emission_amount() +{ + + string emmision_saved_file = get_output_file_path().string(); + + ofstream out(emmision_saved_file); + + if( !out ) + { + cerr << "Couldn't open file." << endl; + return false; + } + + Emission current_emission = total_emission_atomic; + + out << string(current_emission) << flush; + + return true; +} + + +bool +CurrentBlockchainStatus::load_current_emission_amount() +{ + string emmision_saved_file = get_output_file_path().string(); + + string last_saved_emmision = xmreg::read(emmision_saved_file); + + if (last_saved_emmision.empty()) + { + cerr << "Couldn't open file." << endl; + return false; + } + + last_saved_emmision.erase(last_saved_emmision.find_last_not_of(" \n\r\t")+1); + + vector strs; + boost::split(strs, last_saved_emmision, boost::is_any_of(",")); + + if (strs.empty()) + { + cerr << "Problem spliting string values form emission_amount." << endl; + return false; + } + + Emission emission_loaded {0, 0, 0}; + + uint64_t read_check_sum {0}; + + try + { + 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) + { + cerr << "Cant parse to number date from string: " << last_saved_emmision << endl; + return false; + } + + if (read_check_sum != emission_loaded.checksum()) + { + cerr << "read_check_sum != check_sum: " + << read_check_sum << " != " << emission_loaded.checksum() + << endl; + + return false; + } + + total_emission_atomic = emission_loaded; + + return true; + +} + +bf::path +CurrentBlockchainStatus::get_output_file_path() +{ + return blockchain_path / output_file; +} + + +CurrentBlockchainStatus::Emission +CurrentBlockchainStatus::get_emission() +{ + // get current emission + Emission current_emission = total_emission_atomic; + + // this emission will be few blocks behind current blockchain + // height. By default 3 blocks. So we need to calcualate here + // the emission from the top missing blocks, to have complete + // emission data. + + uint64_t current_blockchain_height = current_height; + + uint64_t start_blk = current_emission.blk_no; + + // this should be at current hight or above + // as we calculate missing blocks only for top blockchain + // height + uint64_t end_block = start_blk + blockchain_chunk_gap; + + if (end_block >= current_blockchain_height + && start_blk < current_blockchain_height) + { + // make sure we are not over the blockchain height + end_block = end_block > current_blockchain_height + ? current_blockchain_height : end_block; + + // calculated emission for missing blocks + Emission gap_emission_calculated + = calculate_emission_in_blocks(start_blk, end_block); + + //cout << "gap_emission_calculated: " << std::string(gap_emission_calculated) << endl; + + current_emission.coinbase += gap_emission_calculated.coinbase; + current_emission.fee += gap_emission_calculated.fee; + current_emission.blk_no = gap_emission_calculated.blk_no > 0 + ? gap_emission_calculated.blk_no + : current_emission.blk_no; + } + + return current_emission; +} + +bool +CurrentBlockchainStatus::is_thread_running() +{ + return is_running; +} + +bf::path CurrentBlockchainStatus::blockchain_path {"/home/mwo/.bitmonero/lmdb"}; + +bool CurrentBlockchainStatus::testnet {false}; + +string CurrentBlockchainStatus::output_file {"emission_amount.txt"}; + +string CurrentBlockchainStatus::deamon_url {"http:://127.0.0.1:18081"}; + +uint64_t CurrentBlockchainStatus::blockchain_chunk_size {10000}; + +uint64_t CurrentBlockchainStatus::blockchain_chunk_gap {3}; + +atomic CurrentBlockchainStatus::current_height {0}; + +atomic CurrentBlockchainStatus::total_emission_atomic; + +boost::thread CurrentBlockchainStatus::m_thread; + +atomic CurrentBlockchainStatus::is_running {false}; + +Blockchain* CurrentBlockchainStatus::core_storage {nullptr}; +xmreg::MicroCore* CurrentBlockchainStatus::mcore {nullptr}; +} diff --git a/src/CurrentBlockchainStatus.h b/src/CurrentBlockchainStatus.h new file mode 100644 index 0000000..d213894 --- /dev/null +++ b/src/CurrentBlockchainStatus.h @@ -0,0 +1,114 @@ +// +// Created by mwo on 16/05/17. +// + +#ifndef XMRBLOCKS_CURRENTBLOCKCHAINSTATUS_H +#define XMRBLOCKS_CURRENTBLOCKCHAINSTATUS_H + +#include "MicroCore.h" + +#include + +#include +#include +#include +#include +#include + +namespace xmreg +{ + +using namespace std; + +namespace bf = boost::filesystem; + +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 bf::path blockchain_path; + + static bool testnet; + + static string output_file; + + static string deamon_url; + + // how many blocks to read before thread goes to sleep + static uint64_t blockchain_chunk_size; + + // gap from what we store total_emission_atomic and + // current blockchain height. We dont want to store + // what is on, e.g., top block, as this can get messy + // if the block gets orphaned or blockchain reorganization + // occurs. So the top 3 blocks (default number) will always + // be calculated in flight and added to what we have so far. + static uint64_t blockchain_chunk_gap; + + // current blockchain height and + // hash of top block + static atomic current_height; + + + static atomic total_emission_atomic; + + + static boost::thread m_thread; + + static atomic is_running; + + // make object for accessing the blockchain here + static MicroCore* mcore; + static Blockchain* core_storage; + + static void + start_monitor_blockchain_thread(); + + static void + set_blockchain_variables(MicroCore* _mcore, + Blockchain* _core_storage); + + static void + update_current_emission_amount(); + + static Emission + calculate_emission_in_blocks(uint64_t start_blk, uint64_t end_blk); + + static bool + save_current_emission_amount(); + + static bool + load_current_emission_amount(); + + static Emission + get_emission(); + + static bf::path + get_output_file_path(); + + static bool + is_thread_running(); +}; + +} + +#endif //XMRBLOCKS_CURRENTBLOCKCHAINSTATUS_H diff --git a/src/MicroCore.cpp b/src/MicroCore.cpp index a75f24a..03feee4 100644 --- a/src/MicroCore.cpp +++ b/src/MicroCore.cpp @@ -327,6 +327,7 @@ MicroCore::get_blk_timestamp(uint64_t blk_height) */ MicroCore::~MicroCore() { + m_blockchain_storage.get_db().close(); delete &m_blockchain_storage.get_db(); } diff --git a/src/page.h b/src/page.h index fe2b864..2c8d72e 100644 --- a/src/page.h +++ b/src/page.h @@ -17,6 +17,8 @@ #include "tools.h" #include "rpccalls.h" +#include "CurrentBlockchainStatus.h" + #include "../ext/crow/http_request.h" #include "../ext/vpetrigocaches/cache.hpp" @@ -149,7 +151,7 @@ namespace xmreg if (!input_key_imgs.empty()) { - mixin_str = std::to_string(mixin_no - 1); + mixin_str = std::to_string(mixin_no); fee_str = fmt::format("{:0.6f}", xmr_amount); fee_short_str = fmt::format("{:0.3f}", xmr_amount); } @@ -454,6 +456,16 @@ namespace xmreg {"show_cache_times" , show_cache_times} }; +// std::list atl_blks; +// +// if (core_storage->get_alternative_blocks(atl_blks)) +// { +// for (const block& alt_blk: atl_blks) +// { +// //cout << "alt_blk: " << get_block_height(alt_blk) << endl; +// } +// } + context.emplace("txs", mstch::array()); // will keep tx to show // get reference to txs mstch map to be field below @@ -746,9 +758,10 @@ namespace xmreg } context["network_info"] = mstch::map { - {"difficulty", j_network_info["difficulty"].get()}, - {"hash_rate" , difficulty}, - {"fee_per_kb", xmreg::xmr_amount_to_str(j_network_info["fee_per_kb"], "{:0.12f}")} + {"difficulty" , j_network_info["difficulty"].get()}, + {"hash_rate" , difficulty}, + {"fee_per_kb" , print_money(j_network_info["fee_per_kb"])}, + {"alt_blocks_no" , j_network_info["alt_blocks_count"].get()} }; } } @@ -757,6 +770,27 @@ namespace xmreg cerr << "network_info future not ready yet, skipping." << endl; } + if (CurrentBlockchainStatus::is_thread_running()) + { + CurrentBlockchainStatus::Emission current_values + = CurrentBlockchainStatus::get_emission(); + + string emission_blk_no = std::to_string(current_values.blk_no - 1); + 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_coinbase}, + {"fee_amount", emission_fee} + }; + } + else + { + cerr << "emission thread not running, skipping." << endl; + } + + // get memory pool rendered template string mempool_html = mempool(false, no_of_mempool_tx_of_frontpage); @@ -978,7 +1012,7 @@ namespace xmreg {"no_inputs" , no_inputs}, {"no_outputs" , no_outputs}, {"no_nonrct_inputs", num_nonrct_inputs}, - {"mixin" , mixin_no}, + {"mixin" , mixin_no+1}, {"txsize" , txsize} }); @@ -4768,6 +4802,50 @@ namespace xmreg } + /* + * Lets use this json api convention for success and error + * https://labs.omniti.com/labs/jsend + */ + json + json_emission() + { + json j_response { + {"status", "fail"}, + {"data", json {}} + }; + + json& j_data = j_response["data"]; + + json j_info; + + // get basic network info + if (!CurrentBlockchainStatus::is_thread_running()) + { + j_data["title"] = "Emission monitoring thread not enabled."; + return j_response; + } + else + { + CurrentBlockchainStatus::Emission current_values + = CurrentBlockchainStatus::get_emission(); + + string emission_blk_no = std::to_string(current_values.blk_no - 1); + string emission_coinbase = xmr_amount_to_str(current_values.coinbase, "{:0.3f}"); + string emission_fee = xmr_amount_to_str(current_values.fee, "{:0.3f}"); + + j_data = json { + {"blk_no" , current_values.blk_no - 1}, + {"coinbase", current_values.coinbase}, + {"fee" , current_values.fee}, + }; + } + + j_response["status"] = "success"; + + return j_response; + } + + private: json @@ -5623,3 +5701,4 @@ namespace xmreg #endif //CROWXMR_PAGE_H + diff --git a/src/templates/block.html b/src/templates/block.html index 117a4f9..c299f91 100644 --- a/src/templates/block.html +++ b/src/templates/block.html @@ -60,7 +60,7 @@ hash outputs fee - mixin + ring size in/out size [kB] version diff --git a/src/templates/checkrawtx.html b/src/templates/checkrawtx.html index 37772b6..85c8ee3 100644 --- a/src/templates/checkrawtx.html +++ b/src/templates/checkrawtx.html @@ -36,8 +36,8 @@

- Inputs' mixins time scale (from {{min_mix_time}} till {{max_mix_time}}; - resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real mixin {{/have_raw_tx}}) + Inputs' ring size time scale (from {{min_mix_time}} till {{max_mix_time}}; + resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real ring member {{/have_raw_tx}})

    @@ -111,4 +111,4 @@

- \ No newline at end of file + diff --git a/src/templates/index.html b/src/templates/index.html index 46b0272..41bcd93 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -32,7 +32,7 @@ txs fees outputs - mixins + ring size size [kB] {{#blocks}} diff --git a/src/templates/index2.html b/src/templates/index2.html index 94ac810..a675b57 100644 --- a/src/templates/index2.html +++ b/src/templates/index2.html @@ -35,13 +35,19 @@ {{#network_info}} - -

+

Network difficulty: {{difficulty}} | Hash rate: {{hash_rate}} | Fee per kb: {{fee_per_kb}} + | Alt blocks: {{alt_blocks_no}}

- {{/network_info}} + {{/network_info}} + + {{#emission}} +

+ Monero emission (fees) is {{amount}} ({{fee_amount}}) as of {{blk_no}} block +

+ {{/emission}} @@ -70,7 +76,7 @@ fees outputs in(nonrct)/out - mixin + ring size tx size [kB] {{#txs}} @@ -109,4 +115,4 @@ and {{construction_time_non_cached}} s from non cache ({{cache_misses}} misses) -{{/show_cache_times}} \ No newline at end of file +{{/show_cache_times}} diff --git a/src/templates/mempool.html b/src/templates/mempool.html index 1f00920..b7e4c18 100644 --- a/src/templates/mempool.html +++ b/src/templates/mempool.html @@ -11,7 +11,7 @@ fee outputs in(nonrct)/out - mixin + ring size tx size [kB] {{#mempooltxs}} diff --git a/src/templates/my_outputs.html b/src/templates/my_outputs.html index f744cbf..69040a1 100644 --- a/src/templates/my_outputs.html +++ b/src/templates/my_outputs.html @@ -91,7 +91,7 @@
- Mixin {{mixin_pub_key}} might use your outputs + Ring member {{mixin_pub_key}} might use your outputs
from tx of hash: {{mix_tx_hash}}
(tx public key: {{mix_tx_pub_key}}) @@ -133,7 +133,7 @@

- Sum XMR from matched and marked by * mixin's outputs: {{sum_mixin_xmr}} + Sum XMR from matched and marked by * ring member's outputs: {{sum_mixin_xmr}}
Possible spending is: {{possible_spending}} (tx fee included) @@ -150,4 +150,4 @@ -
\ No newline at end of file +
diff --git a/src/templates/partials/tx_details.html b/src/templates/partials/tx_details.html index 91deb2d..8260d3c 100644 --- a/src/templates/partials/tx_details.html +++ b/src/templates/partials/tx_details.html @@ -125,8 +125,8 @@ {{#has_inputs}} {{#enable_mixins_details}} -

Inputs' mixins time scale (from {{min_mix_time}} till {{max_mix_time}}; - resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real mixin {{/have_raw_tx}}) +

Inputs' ring size time scale (from {{min_mix_time}} till {{max_mix_time}}; + resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real ring member {{/have_raw_tx}})

    @@ -180,12 +180,12 @@ {{#enable_mixins_details}} - + {{#have_raw_tx}} {{/have_raw_tx}} - + @@ -214,7 +214,7 @@ {{^enable_mixins_details}}
    Mixin stealth addressring membersIs it real?blkmixinring size in/out timestamp age [y:d:h:m:s]
    - + {{#have_raw_tx}} {{/have_raw_tx}} diff --git a/src/templates/partials/tx_table_header.html b/src/templates/partials/tx_table_header.html index 123d214..3de6ef2 100644 --- a/src/templates/partials/tx_table_header.html +++ b/src/templates/partials/tx_table_header.html @@ -3,7 +3,7 @@ - +
    Mixin stealth addressring membersIs it real?tx hash outputs feemixinring size in/out size [kB]