From 3fcf87bdfc867bfa019b62d58933401a9c5a9b6a Mon Sep 17 00:00:00 2001 From: moneroexamples Date: Fri, 19 May 2017 10:22:11 +0800 Subject: [PATCH] total_emission_gap added --- src/CurrentBlockchainStatus.cpp | 125 +++++++++++++++++++++++++++----- src/CurrentBlockchainStatus.h | 16 ++++ src/page.h | 2 +- 3 files changed, 125 insertions(+), 18 deletions(-) diff --git a/src/CurrentBlockchainStatus.cpp b/src/CurrentBlockchainStatus.cpp index 90af54c..05957b2 100644 --- a/src/CurrentBlockchainStatus.cpp +++ b/src/CurrentBlockchainStatus.cpp @@ -42,6 +42,7 @@ CurrentBlockchainStatus::start_monitor_blockchain_thread() 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()) @@ -101,17 +102,36 @@ CurrentBlockchainStatus::update_current_emission_amount() uint64_t current_blockchain_height = current_height; - end_block = end_block > current_blockchain_height ? current_blockchain_height : end_block; + // 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; - uint64_t temp_emission_amount {0}; - uint64_t temp_fee_amount {0}; + Emission emission_calculated = calculate_emission_in_blocks(blk_no, end_block); - while (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; + + cout << "total emission: " << string(current_emission) << endl; +} +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(blk_no, blk); + mcore->get_block_by_height(start_blk, blk); uint64_t coinbase_amount = get_outs_money_amount(blk.miner_tx); @@ -127,23 +147,20 @@ CurrentBlockchainStatus::update_current_emission_amount() tx_fee_amount += get_tx_fee(tx); } - temp_emission_amount += coinbase_amount - tx_fee_amount; - temp_fee_amount += tx_fee_amount; + (void) missed_txs; - ++blk_no; - } + emission_calculated.coinbase += coinbase_amount - tx_fee_amount; + emission_calculated.fee += tx_fee_amount; - current_emission.coinbase += temp_emission_amount; - current_emission.fee += temp_fee_amount; - current_emission.blk_no = blk_no; + ++start_blk; + } - total_emission_atomic = current_emission; + emission_calculated.blk_no = start_blk; - cout << "total emission: " << string(current_emission) << endl; + return emission_calculated; } - bool CurrentBlockchainStatus::save_current_emission_amount() { @@ -232,7 +249,79 @@ CurrentBlockchainStatus::get_output_file_path() CurrentBlockchainStatus::Emission CurrentBlockchainStatus::get_emission() { - return total_emission_atomic.load(); + // we store gap emission from last few blocks + // we use it together with last_block_hash, so that + // we can reuse gap emission if hash is same between + // requests. no need to always keep recalucalting + // it, if top block hash is same as last time. + static Emission total_emission_gap {0, 0, 0}; + static crypto::hash last_block_hash {null_hash}; + + + // 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. + + Emission gap_emission_calculated {0, 0, 0}; + + crypto::hash top_block_id = core_storage->get_tail_id(); + + if (last_block_hash == top_block_id) + { + // if we already calclated gap for the same few blocks + // just reuse the emission calcualted for the gap. + + //cout << "reusing total_emission_gap" << endl; + + gap_emission_calculated = total_emission_gap; + } + else + { + // if top height has change for whatever reason, e.g, new block + // was added, blockchain reoraganization happened, then + // recaulate the gap emission + + //cout << "recalculate total_emission_gap" << endl; + + 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 + gap_emission_calculated = calculate_emission_in_blocks(start_blk, end_block); + } + + // store calcualted gap emission for future use + total_emission_gap = gap_emission_calculated; + + // update stored top block hash + last_block_hash = top_block_id; + } + + //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 @@ -251,6 +340,8 @@ 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; diff --git a/src/CurrentBlockchainStatus.h b/src/CurrentBlockchainStatus.h index 5c8fa3a..036eb0c 100644 --- a/src/CurrentBlockchainStatus.h +++ b/src/CurrentBlockchainStatus.h @@ -53,12 +53,25 @@ struct CurrentBlockchainStatus 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 std::thread m_thread; static atomic is_running; @@ -77,6 +90,9 @@ struct CurrentBlockchainStatus 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(); diff --git a/src/page.h b/src/page.h index 5bc79cd..1b9543c 100644 --- a/src/page.h +++ b/src/page.h @@ -775,7 +775,7 @@ namespace xmreg CurrentBlockchainStatus::Emission current_values = CurrentBlockchainStatus::get_emission(); - string emission_blk_no = std::to_string(current_values.blk_no); + 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}");