Merge pull request #62 from moneroexamples/emission_rate_thread

Emission rate thread
This commit is contained in:
moneroexamples 2017-05-24 12:55:40 +08:00 committed by GitHub
commit 41e2e22cde
17 changed files with 697 additions and 61 deletions

View file

@ -113,6 +113,7 @@ set(LIBRARIES
unbound unbound
curl curl
crypto crypto
atomic
ssl) ssl)
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32) if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32)

View file

@ -146,10 +146,10 @@ Go to your browser: http://127.0.0.1:8081
``` ```
./xmrblocks -h ./xmrblocks -h
xmrblocks, start Onion Monero Blockchain Explorer: xmrblocks, Onion Monero Blockchain Explorer:
-h [ --help ] [=arg(=1)] (=0) produce help message -h [ --help ] [=arg(=1)] (=0) produce help message
-t [ --testnet ] [=arg(=1)] (=0) use testnet blockchain -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 [=arg(=1)] (=0)
enable mixin details for key images, enable mixin details for key images,
e.g., timescale, mixin of mixins, in tx e.g., timescale, mixin of mixins, in tx
@ -158,44 +158,79 @@ xmrblocks, start Onion Monero Blockchain Explorer:
enable key images file checker enable key images file checker
--enable-output-key-checker [=arg(=1)] (=0) --enable-output-key-checker [=arg(=1)] (=0)
enable outputs key file checker 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-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 --show-cache-times [=arg(=1)] (=0) show times of getting data from cache
vs no cache vs no cache
--enable-block-cache [=arg(=1)] (=0) enable caching of block details --enable-block-cache [=arg(=1)] (=0) enable caching of block details
--enable-autorefresh-option [=arg(=1)] (=0) --enable-autorefresh-option [=arg(=1)] (=0)
enable users to have the index page on enable users to have the index page on
autorefresh autorefresh
-p [ --port ] arg (=8081) default port --enable-emission-monitor [=arg(=1)] (=0)
--testnet-url arg you can specifiy testnet url, if you enable Monero total emission monitoring
run it on mainet. link will show on thread
front page to testnet explorer -p [ --port ] arg (=8081) default explorer port
--mainnet-url arg you can specifiy mainnet url, if you --testnet-url arg you can specify testnet url, if you run
run it on testnet. link will show on it on mainnet. link will show on front
front page to mainnet explorer 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 --no-blocks-on-index arg (=10) number of last blocks to be shown on
index page index page
-b [ --bc-path ] arg path to lmdb blockchain -b [ --bc-path ] arg path to lmdb folder of the blockchain,
--ssl-crt-file arg A path to crt file for ssl (https) e.g., ~/.bitmonero/lmdb
--ssl-crt-file arg path to crt file for ssl (https)
functionality 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 functionality
-d [ --deamon-url ] arg (=http:://127.0.0.1:18081) -d [ --deamon-url ] arg (=http:://127.0.0.1:18081)
monero address string Monero deamon url
``` ```
Example usage, defined as bash aliases. Example usage, defined as bash aliases.
```bash ```bash
# for mainnet explorer # 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 # 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) ## Enable SSL (https)
@ -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/<block_number|block_hash> #### api/rawblock/<block_number|block_hash>

View file

@ -17,7 +17,8 @@ namespace myxmr
{ {
struct jsonresponse: crow::response 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-Origin", "*");
add_header("Access-Control-Allow-Headers", "Content-Type"); 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 // get command line options
xmreg::CmdLineOptions opts {ac, av}; xmreg::CmdLineOptions opts {ac, av};
@ -60,6 +60,8 @@ int main(int ac, const char* av[]) {
auto enable_tx_cache_opt = opts.get_option<bool>("enable-tx-cache"); auto enable_tx_cache_opt = opts.get_option<bool>("enable-tx-cache");
auto enable_block_cache_opt = opts.get_option<bool>("enable-block-cache"); auto enable_block_cache_opt = opts.get_option<bool>("enable-block-cache");
auto show_cache_times_opt = opts.get_option<bool>("show-cache-times"); auto show_cache_times_opt = opts.get_option<bool>("show-cache-times");
auto enable_emission_monitor_opt = opts.get_option<bool>("enable-emission-monitor");
bool testnet {*testnet_opt}; bool testnet {*testnet_opt};
bool enable_pusher {*enable_pusher_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_json_api {*enable_json_api_opt};
bool enable_tx_cache {*enable_tx_cache_opt}; bool enable_tx_cache {*enable_tx_cache_opt};
bool enable_block_cache {*enable_block_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}; bool show_cache_times {*show_cache_times_opt};
@ -128,6 +131,7 @@ int main(int ac, const char* av[]) {
cout << blockchain_path << endl; cout << blockchain_path << endl;
// create instance of our MicroCore // create instance of our MicroCore
// and make pointer to the Blockchain // and make pointer to the Blockchain
xmreg::MicroCore mcore; xmreg::MicroCore mcore;
@ -144,7 +148,41 @@ int main(int ac, const char* av[]) {
string deamon_url {*deamon_url_opt}; string deamon_url {*deamon_url_opt};
if (testnet && deamon_url == "http:://127.0.0.1:18081") if (testnet && deamon_url == "http:://127.0.0.1:18081")
{
deamon_url = "http:://127.0.0.1:28081"; 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
// <blockchain_path>/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 // create instance of page class which
// contains logic for the website // contains logic for the website
@ -434,6 +472,14 @@ int main(int ac, const char* av[]) {
return r; 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) CROW_ROUTE(app, "/api/outputs").methods("GET"_method)
([&](const crow::request &req) { ([&](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; return EXIT_SUCCESS;
} }

View file

@ -6,7 +6,7 @@ set(SOURCE_HEADERS
MicroCore.h MicroCore.h
tools.h tools.h
monero_headers.h monero_headers.h
) CurrentBlockchainStatus.h)
set(SOURCE_FILES set(SOURCE_FILES
MicroCore.cpp MicroCore.cpp
@ -14,7 +14,7 @@ set(SOURCE_FILES
CmdLineOptions.cpp CmdLineOptions.cpp
page.h page.h
rpccalls.cpp rpccalls.h rpccalls.cpp rpccalls.h
version.h.in) version.h.in CurrentBlockchainStatus.cpp)
# make static library called libmyxrm # make static library called libmyxrm
# that we are going to link to # that we are going to link to

View file

@ -18,7 +18,7 @@ namespace xmreg
p.add("txhash", -1); p.add("txhash", -1);
options_description desc( options_description desc(
"xmrblocks, start Onion Monero Blockchain Explorer"); "xmrblocks, Onion Monero Blockchain Explorer");
desc.add_options() desc.add_options()
("help,h", value<bool>()->default_value(false)->implicit_value(true), ("help,h", value<bool>()->default_value(false)->implicit_value(true),
@ -26,7 +26,7 @@ namespace xmreg
("testnet,t", value<bool>()->default_value(false)->implicit_value(true), ("testnet,t", value<bool>()->default_value(false)->implicit_value(true),
"use testnet blockchain") "use testnet blockchain")
("enable-pusher", value<bool>()->default_value(false)->implicit_value(true), ("enable-pusher", value<bool>()->default_value(false)->implicit_value(true),
"enable pushing signed tx") "enable signed transaction pusher")
("enable-mixin-details", value<bool>()->default_value(false)->implicit_value(true), ("enable-mixin-details", value<bool>()->default_value(false)->implicit_value(true),
"enable mixin details for key images, e.g., timescale, mixin of mixins, in tx context") "enable mixin details for key images, e.g., timescale, mixin of mixins, in tx context")
("enable-key-image-checker", value<bool>()->default_value(false)->implicit_value(true), ("enable-key-image-checker", value<bool>()->default_value(false)->implicit_value(true),
@ -34,33 +34,35 @@ namespace xmreg
("enable-output-key-checker", value<bool>()->default_value(false)->implicit_value(true), ("enable-output-key-checker", value<bool>()->default_value(false)->implicit_value(true),
"enable outputs key file checker") "enable outputs key file checker")
("enable-mempool-cache", value<bool>()->default_value(true), ("enable-mempool-cache", value<bool>()->default_value(true),
"enable caching txs in the mempool") "enable caching of transactions from the mempool")
("enable-json-api", value<bool>()->default_value(true), ("enable-json-api", value<bool>()->default_value(true),
"enable JSON REST api") "enable JSON REST api")
("enable-tx-cache", value<bool>()->default_value(false)->implicit_value(true), ("enable-tx-cache", value<bool>()->default_value(false)->implicit_value(true),
"enable caching of tx details") "enable caching of transaction details")
("show-cache-times", value<bool>()->default_value(false)->implicit_value(true), ("show-cache-times", value<bool>()->default_value(false)->implicit_value(true),
"show times of getting data from cache vs no cache") "show times of getting data from cache vs no cache")
("enable-block-cache", value<bool>()->default_value(false)->implicit_value(true), ("enable-block-cache", value<bool>()->default_value(false)->implicit_value(true),
"enable caching of block details") "enable caching of block details")
("enable-autorefresh-option", value<bool>()->default_value(false)->implicit_value(true), ("enable-autorefresh-option", value<bool>()->default_value(false)->implicit_value(true),
"enable users to have the index page on autorefresh") "enable users to have the index page on autorefresh")
("enable-emission-monitor", value<bool>()->default_value(false)->implicit_value(true),
"enable Monero total emission monitoring thread")
("port,p", value<string>()->default_value("8081"), ("port,p", value<string>()->default_value("8081"),
"default port") "default explorer port")
("testnet-url", value<string>()->default_value(""), ("testnet-url", value<string>()->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<string>()->default_value(""), ("mainnet-url", value<string>()->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<string>()->default_value("10"), ("no-blocks-on-index", value<string>()->default_value("10"),
"number of last blocks to be shown on index page") "number of last blocks to be shown on index page")
("bc-path,b", value<string>(), ("bc-path,b", value<string>(),
"path to lmdb blockchain") "path to lmdb folder of the blockchain, e.g., ~/.bitmonero/lmdb")
("ssl-crt-file", value<string>(), ("ssl-crt-file", value<string>(),
"A path to crt file for ssl (https) functionality") "path to crt file for ssl (https) functionality")
("ssl-key-file", value<string>(), ("ssl-key-file", value<string>(),
"A path to key file for ssl (https) functionality") "path to key file for ssl (https) functionality")
("deamon-url,d", value<string>()->default_value("http:://127.0.0.1:18081"), ("deamon-url,d", value<string>()->default_value("http:://127.0.0.1:18081"),
"monero address string"); "Monero deamon url");
store(command_line_parser(acc, avv) store(command_line_parser(acc, avv)

View file

@ -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<transaction> txs;
std::list<crypto::hash> 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<string> 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<uint64_t>(strs.at(0));
emission_loaded.coinbase = boost::lexical_cast<uint64_t>(strs.at(1));
emission_loaded.fee = boost::lexical_cast<uint64_t>(strs.at(2));
read_check_sum = boost::lexical_cast<uint64_t>(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<uint64_t> CurrentBlockchainStatus::current_height {0};
atomic<CurrentBlockchainStatus::Emission> CurrentBlockchainStatus::total_emission_atomic;
boost::thread CurrentBlockchainStatus::m_thread;
atomic<bool> CurrentBlockchainStatus::is_running {false};
Blockchain* CurrentBlockchainStatus::core_storage {nullptr};
xmreg::MicroCore* CurrentBlockchainStatus::mcore {nullptr};
}

View file

@ -0,0 +1,114 @@
//
// Created by mwo on 16/05/17.
//
#ifndef XMRBLOCKS_CURRENTBLOCKCHAINSTATUS_H
#define XMRBLOCKS_CURRENTBLOCKCHAINSTATUS_H
#include "MicroCore.h"
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
#include <atomic>
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<uint64_t> current_height;
static atomic<Emission> total_emission_atomic;
static boost::thread m_thread;
static atomic<bool> 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

View file

@ -327,6 +327,7 @@ MicroCore::get_blk_timestamp(uint64_t blk_height)
*/ */
MicroCore::~MicroCore() MicroCore::~MicroCore()
{ {
m_blockchain_storage.get_db().close();
delete &m_blockchain_storage.get_db(); delete &m_blockchain_storage.get_db();
} }

View file

@ -17,6 +17,8 @@
#include "tools.h" #include "tools.h"
#include "rpccalls.h" #include "rpccalls.h"
#include "CurrentBlockchainStatus.h"
#include "../ext/crow/http_request.h" #include "../ext/crow/http_request.h"
#include "../ext/vpetrigocaches/cache.hpp" #include "../ext/vpetrigocaches/cache.hpp"
@ -149,7 +151,7 @@ namespace xmreg
if (!input_key_imgs.empty()) 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_str = fmt::format("{:0.6f}", xmr_amount);
fee_short_str = fmt::format("{:0.3f}", xmr_amount); fee_short_str = fmt::format("{:0.3f}", xmr_amount);
} }
@ -454,6 +456,16 @@ namespace xmreg
{"show_cache_times" , show_cache_times} {"show_cache_times" , show_cache_times}
}; };
// std::list<block> 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 context.emplace("txs", mstch::array()); // will keep tx to show
// get reference to txs mstch map to be field below // get reference to txs mstch map to be field below
@ -746,9 +758,10 @@ namespace xmreg
} }
context["network_info"] = mstch::map { context["network_info"] = mstch::map {
{"difficulty", j_network_info["difficulty"].get<uint64_t>()}, {"difficulty" , j_network_info["difficulty"].get<uint64_t>()},
{"hash_rate" , difficulty}, {"hash_rate" , difficulty},
{"fee_per_kb", xmreg::xmr_amount_to_str(j_network_info["fee_per_kb"], "{:0.12f}")} {"fee_per_kb" , print_money(j_network_info["fee_per_kb"])},
{"alt_blocks_no" , j_network_info["alt_blocks_count"].get<uint64_t>()}
}; };
} }
} }
@ -757,6 +770,27 @@ namespace xmreg
cerr << "network_info future not ready yet, skipping." << endl; 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 // get memory pool rendered template
string mempool_html = mempool(false, no_of_mempool_tx_of_frontpage); string mempool_html = mempool(false, no_of_mempool_tx_of_frontpage);
@ -978,7 +1012,7 @@ namespace xmreg
{"no_inputs" , no_inputs}, {"no_inputs" , no_inputs},
{"no_outputs" , no_outputs}, {"no_outputs" , no_outputs},
{"no_nonrct_inputs", num_nonrct_inputs}, {"no_nonrct_inputs", num_nonrct_inputs},
{"mixin" , mixin_no}, {"mixin" , mixin_no+1},
{"txsize" , txsize} {"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: private:
json json
@ -5623,3 +5701,4 @@ namespace xmreg
#endif //CROWXMR_PAGE_H #endif //CROWXMR_PAGE_H

View file

@ -60,7 +60,7 @@
<td>hash</td> <td>hash</td>
<td>outputs</td> <td>outputs</td>
<td>fee</td> <td>fee</td>
<td>mixin</td> <td>ring size</td>
<td>in/out</td> <td>in/out</td>
<td>size [kB]</td> <td>size [kB]</td>
<td>version</td> <td>version</td>

View file

@ -36,8 +36,8 @@
</h5> </h5>
<h3> <h3>
Inputs' mixins time scale (from {{min_mix_time}} till {{max_mix_time}}; Inputs' ring size time scale (from {{min_mix_time}} till {{max_mix_time}};
resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real mixin {{/have_raw_tx}}) resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real ring member {{/have_raw_tx}})
</h3> </h3>
<div class="center"> <div class="center">
<ul class="center"> <ul class="center">

View file

@ -32,7 +32,7 @@
<td>txs</td> <td>txs</td>
<td>fees</td> <td>fees</td>
<td>outputs</td> <td>outputs</td>
<td>mixins</td> <td>ring size</td>
<td>size [kB]</td> <td>size [kB]</td>
</tr> </tr>
{{#blocks}} {{#blocks}}

View file

@ -35,14 +35,20 @@
{{#network_info}} {{#network_info}}
<h3 style="font-size: 12px; margin-top: 5px; margin-bottom: 3">
<h3 style="font-size: 12px; margin-top: 10px">
Network difficulty: {{difficulty}} Network difficulty: {{difficulty}}
| Hash rate: {{hash_rate}} | Hash rate: {{hash_rate}}
| Fee per kb: {{fee_per_kb}} | Fee per kb: {{fee_per_kb}}
| Alt blocks: {{alt_blocks_no}}
</h3> </h3>
{{/network_info}} {{/network_info}}
{{#emission}}
<h3 style="font-size: 12px; margin-top: 2px">
Monero emission (fees) is {{amount}} ({{fee_amount}}) as of {{blk_no}} block
</h3>
{{/emission}}
</div> </div>
@ -70,7 +76,7 @@
<td>fees</td> <td>fees</td>
<td>outputs</td> <td>outputs</td>
<td>in(nonrct)/out</td> <td>in(nonrct)/out</td>
<td>mixin</td> <td>ring size</td>
<td>tx size [kB]</td> <td>tx size [kB]</td>
</tr> </tr>
{{#txs}} {{#txs}}

View file

@ -11,7 +11,7 @@
<td>fee</td> <td>fee</td>
<td>outputs</td> <td>outputs</td>
<td>in(nonrct)/out</td> <td>in(nonrct)/out</td>
<td>mixin</td> <td>ring size</td>
<td>tx size [kB]</td> <td>tx size [kB]</td>
</tr> </tr>
{{#mempooltxs}} {{#mempooltxs}}

View file

@ -91,7 +91,7 @@
<table class="center"> <table class="center">
<tr> <tr>
<td style="text-align: center;"> <td style="text-align: center;">
Mixin {{mixin_pub_key}} might use your outputs Ring member {{mixin_pub_key}} might use your outputs
<br/> <br/>
from tx of hash: <a href="/tx/{{mix_tx_hash}}">{{mix_tx_hash}}</a> from tx of hash: <a href="/tx/{{mix_tx_hash}}">{{mix_tx_hash}}</a>
<br/>(tx public key: {{mix_tx_pub_key}}) <br/>(tx public key: {{mix_tx_pub_key}})
@ -133,7 +133,7 @@
</div> </div>
<h3> <h3>
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}}
<br/> <br/>
<span style="font-size: 16px"> Possible spending is: <span style="font-size: 16px"> Possible spending is:
{{possible_spending}} (tx fee included) {{possible_spending}} (tx fee included)

View file

@ -125,8 +125,8 @@
{{#has_inputs}} {{#has_inputs}}
{{#enable_mixins_details}} {{#enable_mixins_details}}
<h3>Inputs' mixins time scale (from {{min_mix_time}} till {{max_mix_time}}; <h3>Inputs' ring size time scale (from {{min_mix_time}} till {{max_mix_time}};
resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real mixin {{/have_raw_tx}}) resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real ring member {{/have_raw_tx}})
</h3> </h3>
<div class="center"> <div class="center">
<ul class="center"> <ul class="center">
@ -180,12 +180,12 @@
{{#enable_mixins_details}} {{#enable_mixins_details}}
<table style="width:100%; margin-bottom:20px"> <table style="width:100%; margin-bottom:20px">
<tr> <tr>
<td>Mixin stealth address</td> <td>ring members</td>
{{#have_raw_tx}} {{#have_raw_tx}}
<td>Is it real?</td> <td>Is it real?</td>
{{/have_raw_tx}} {{/have_raw_tx}}
<td>blk</td> <td>blk</td>
<td>mixin</td> <td>ring size</td>
<td>in/out</td> <td>in/out</td>
<td>timestamp</td> <td>timestamp</td>
<td>age [y:d:h:m:s]</td> <td>age [y:d:h:m:s]</td>
@ -214,7 +214,7 @@
{{^enable_mixins_details}} {{^enable_mixins_details}}
<table style="width:100%; margin-bottom:20px"> <table style="width:100%; margin-bottom:20px">
<tr> <tr>
<td>Mixin stealth address</td> <td>ring members</td>
{{#have_raw_tx}} {{#have_raw_tx}}
<td>Is it real?</td> <td>Is it real?</td>
{{/have_raw_tx}} {{/have_raw_tx}}

View file

@ -3,7 +3,7 @@
<td>tx hash</td> <td>tx hash</td>
<td>outputs</td> <td>outputs</td>
<td>fee</td> <td>fee</td>
<td>mixin</td> <td>ring size</td>
<td>in/out</td> <td>in/out</td>
<td>size [kB]</td> <td>size [kB]</td>
</tr> </tr>