forked from lthn/blockchain
implemented target_calculation optimisation
This commit is contained in:
parent
d846d26bf4
commit
cfbe5d2bbc
7 changed files with 67 additions and 117 deletions
|
|
@ -61,6 +61,7 @@ using namespace currency;
|
|||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 3 //mismatch here means full resync
|
||||
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION 4 //mismatch here means some reinitializations
|
||||
|
||||
#define TARGETDATA_CACHE_SIZE DIFFICULTY_WINDOW + 10
|
||||
|
||||
|
||||
DISABLE_VS_WARNINGS(4267)
|
||||
|
|
@ -447,6 +448,8 @@ bool blockchain_storage::clear()
|
|||
m_db_aliases.clear();
|
||||
m_db_addr_to_alias.clear();
|
||||
m_db_per_block_gindex_incs.clear();
|
||||
m_pos_targetdata_cache.clear();
|
||||
m_pow_targetdata_cache.clear();
|
||||
|
||||
m_db.commit_transaction();
|
||||
|
||||
|
|
@ -889,62 +892,21 @@ wide_difficulty_type blockchain_storage::get_next_diff_conditional(bool pos) con
|
|||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<wide_difficulty_type> commulative_difficulties;
|
||||
size_t count = 0;
|
||||
if (!m_db_blocks.size())
|
||||
return DIFFICULTY_STARTER;
|
||||
//skip genesis timestamp
|
||||
uint64_t stop_ind = 0;
|
||||
uint64_t blocks_size = m_db_blocks.size();
|
||||
TIME_MEASURE_START_PD(target_calculating_enum_blocks);
|
||||
std::list<std::pair<wide_difficulty_type, uint64_t>>& targetdata_cache = pos ? m_pos_targetdata_cache : m_pow_targetdata_cache;
|
||||
if (targetdata_cache.empty())
|
||||
load_targetdata_cache(pos);
|
||||
|
||||
//@#@
|
||||
// #define PRINT_PERFORMANCE_DATA_NATIVE(var_name) << #var_name": " << m_db_blocks.get_performance_data_native().var_name.get_avg() << "(" << m_db_blocks.get_performance_data_native().var_name.get_count()<< ")" << ENDL
|
||||
// #define PRINT_PERFORMANCE_DATA_GLOBAL(var_name) << #var_name": " << m_db_blocks.get_performance_data_global().var_name.get_avg() << "(" << m_db_blocks.get_performance_data_global().var_name.get_count()<< ")" << ENDL
|
||||
// #define PRINT_PERFORMANCE_DATA(var_name) << #var_name": " << m_db_blocks.get_performance_data().var_name.get_avg() << "(" << m_db_blocks.get_performance_data().var_name.get_count()<< ")" << ENDL
|
||||
//
|
||||
// #define RESET_PERFORMANCE_DATA_NATIVE(var_name) m_db_blocks.get_performance_data_native().var_name.reset();
|
||||
// #define RESET_PERFORMANCE_DATA_GLOBAL(var_name) m_db_blocks.get_performance_data_global().var_name.reset();
|
||||
// #define RESET_PERFORMANCE_DATA(var_name) m_db_blocks.get_performance_data().var_name.reset();
|
||||
//
|
||||
//
|
||||
// RESET_PERFORMANCE_DATA_GLOBAL(backend_get_pod_time);
|
||||
// RESET_PERFORMANCE_DATA_GLOBAL(backend_get_t_time);
|
||||
// RESET_PERFORMANCE_DATA_GLOBAL(get_serialize_t_time);
|
||||
// RESET_PERFORMANCE_DATA(hit_percent);
|
||||
// RESET_PERFORMANCE_DATA(read_cache_microsec);
|
||||
// RESET_PERFORMANCE_DATA(read_db_microsec);
|
||||
// RESET_PERFORMANCE_DATA(update_cache_microsec);
|
||||
// RESET_PERFORMANCE_DATA(write_to_cache_microsec);
|
||||
for (uint64_t cur_ind = blocks_size - 1; cur_ind != stop_ind && count < DIFFICULTY_WINDOW; cur_ind--)
|
||||
size_t count = 0;
|
||||
for (auto it = targetdata_cache.rbegin(); it != targetdata_cache.rend() && count < DIFFICULTY_WINDOW; it++)
|
||||
{
|
||||
auto beiptr = m_db_blocks[cur_ind];
|
||||
|
||||
bool is_pos_bl = is_pos_block(beiptr->bl);
|
||||
if (pos != is_pos_bl)
|
||||
continue;
|
||||
timestamps.push_back(beiptr->bl.timestamp);
|
||||
commulative_difficulties.push_back(beiptr->cumulative_diff_precise);
|
||||
timestamps.push_back(it->second);
|
||||
commulative_difficulties.push_back(it->first);
|
||||
++count;
|
||||
}
|
||||
//@#@
|
||||
|
||||
|
||||
|
||||
// LOG_PRINT_MAGENTA("[GET_NEXT_DIFF_CONDITIONAL][DB STAT]: count: " << count << ENDL
|
||||
// PRINT_PERFORMANCE_DATA_NATIVE(backend_set_pod_time)
|
||||
// PRINT_PERFORMANCE_DATA_NATIVE(backend_set_t_time)
|
||||
// PRINT_PERFORMANCE_DATA_NATIVE(set_serialize_t_time)
|
||||
// PRINT_PERFORMANCE_DATA_GLOBAL(backend_get_pod_time)
|
||||
// PRINT_PERFORMANCE_DATA_GLOBAL(backend_get_t_time)
|
||||
// PRINT_PERFORMANCE_DATA_GLOBAL(get_serialize_t_time)
|
||||
// PRINT_PERFORMANCE_DATA(hit_percent)
|
||||
// PRINT_PERFORMANCE_DATA(read_cache_microsec)
|
||||
// PRINT_PERFORMANCE_DATA(read_db_microsec)
|
||||
// PRINT_PERFORMANCE_DATA(update_cache_microsec)
|
||||
// PRINT_PERFORMANCE_DATA(write_to_cache_microsec)
|
||||
// //PRINT_PERFORMANCE_DATA(write_to_db_microsec)
|
||||
// , LOG_LEVEL_0);
|
||||
//!@#@
|
||||
|
||||
wide_difficulty_type& dif = pos ? m_cached_next_pos_difficulty : m_cached_next_pow_difficulty;
|
||||
TIME_MEASURE_FINISH_PD(target_calculating_enum_blocks);
|
||||
|
|
@ -4600,23 +4562,67 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
bvc.m_added_to_main_chain = true;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::on_block_added(const block_extended_info& bei, const crypto::hash& id)
|
||||
{
|
||||
update_next_comulative_size_limit();
|
||||
m_timestamps_median_cache.clear();
|
||||
m_tx_pool.on_blockchain_inc(bei.height, id);
|
||||
|
||||
update_targetdata_cache_on_block_added(bei);
|
||||
|
||||
TIME_MEASURE_START_PD(raise_block_core_event);
|
||||
rise_core_event(CORE_EVENT_BLOCK_ADDED, void_struct());
|
||||
TIME_MEASURE_FINISH_PD(raise_block_core_event);
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::on_block_removed(const block_extended_info& bei)
|
||||
{
|
||||
m_tx_pool.on_blockchain_dec(m_db_blocks.size() - 1, get_top_block_id());
|
||||
m_timestamps_median_cache.clear();
|
||||
update_targetdata_cache_on_block_removed(bei);
|
||||
LOG_PRINT_L2("block at height " << bei.height << " was removed from the blockchain");
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::update_targetdata_cache_on_block_added(const block_extended_info& bei)
|
||||
{
|
||||
if (bei.height == 0)
|
||||
return; //skip genesis
|
||||
std::list<std::pair<wide_difficulty_type, uint64_t>>& targetdata_cache = is_pos_block(bei.bl) ? m_pos_targetdata_cache : m_pow_targetdata_cache;
|
||||
targetdata_cache.push_back(std::pair<wide_difficulty_type, uint64_t>(bei.cumulative_diff_precise, bei.bl.timestamp));
|
||||
while (targetdata_cache.size() > TARGETDATA_CACHE_SIZE)
|
||||
targetdata_cache.pop_front();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::update_targetdata_cache_on_block_removed(const block_extended_info& bei)
|
||||
{
|
||||
std::list<std::pair<wide_difficulty_type, uint64_t>>& targetdata_cache = is_pos_block(bei.bl) ? m_pos_targetdata_cache : m_pow_targetdata_cache;
|
||||
if (targetdata_cache.size())
|
||||
targetdata_cache.pop_back();
|
||||
if (targetdata_cache.size() < DIFFICULTY_WINDOW)
|
||||
targetdata_cache.clear();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::load_targetdata_cache(bool is_pos)const
|
||||
{
|
||||
std::list<std::pair<wide_difficulty_type, uint64_t>>& targetdata_cache = is_pos? m_pos_targetdata_cache: m_pow_targetdata_cache;
|
||||
targetdata_cache.clear();
|
||||
uint64_t stop_ind = 0;
|
||||
uint64_t blocks_size = m_db_blocks.size();
|
||||
size_t count = 0;
|
||||
for (uint64_t cur_ind = blocks_size - 1; cur_ind != stop_ind && count < DIFFICULTY_WINDOW + 5; cur_ind--)
|
||||
{
|
||||
auto beiptr = m_db_blocks[cur_ind];
|
||||
|
||||
bool is_pos_bl = is_pos_block(beiptr->bl);
|
||||
if (is_pos != is_pos_bl)
|
||||
continue;
|
||||
targetdata_cache.push_front(std::pair<wide_difficulty_type, uint64_t>(beiptr->cumulative_diff_precise, beiptr->bl.timestamp));
|
||||
++count;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::on_abort_transaction()
|
||||
{
|
||||
if (m_event_handler) m_event_handler->on_clear_events();
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ namespace currency
|
|||
mutable core_runtime_config m_core_runtime_config;
|
||||
mutable i_core_event_handler* m_event_handler;
|
||||
mutable i_core_event_handler m_event_handler_stub;
|
||||
|
||||
|
||||
//tools::median_db_cache<uint64_t, uint64_t> m_tx_fee_median;
|
||||
mutable std::unordered_map<size_t, uint64_t> m_timestamps_median_cache;
|
||||
mutable performnce_data m_performance_data;
|
||||
|
|
@ -510,7 +510,10 @@ namespace currency
|
|||
//just informational
|
||||
mutable wide_difficulty_type m_cached_next_pow_difficulty;
|
||||
mutable wide_difficulty_type m_cached_next_pos_difficulty;
|
||||
//work like a cache to avoid
|
||||
|
||||
mutable std::list <std::pair<wide_difficulty_type, uint64_t>> m_pos_targetdata_cache;
|
||||
mutable std::list <std::pair<wide_difficulty_type, uint64_t>> m_pow_targetdata_cache;
|
||||
//work like a cache to avoid recalculation on read operations
|
||||
mutable uint64_t m_current_fee_median;
|
||||
mutable uint64_t m_current_fee_median_effective_index;
|
||||
bool m_is_reorganize_in_process;
|
||||
|
|
@ -560,9 +563,12 @@ namespace currency
|
|||
const std::vector<txin_etc_details_v>& get_txin_etc_options(const txin_v& in)const;
|
||||
void on_block_added(const block_extended_info& bei, const crypto::hash& id);
|
||||
void on_block_removed(const block_extended_info& bei);
|
||||
void update_targetdata_cache_on_block_added(const block_extended_info& bei);
|
||||
void update_targetdata_cache_on_block_removed(const block_extended_info& bei);
|
||||
uint64_t tx_fee_median_for_height(uint64_t h) const;
|
||||
uint64_t get_tx_fee_median_effective_index(uint64_t h) const;
|
||||
void on_abort_transaction();
|
||||
void load_targetdata_cache(bool is_pos) const;
|
||||
|
||||
|
||||
uint64_t get_adjusted_time()const;
|
||||
|
|
|
|||
|
|
@ -55,23 +55,7 @@ namespace currency {
|
|||
return a + b < a || (c && a + b == (uint64_t)-1);
|
||||
}
|
||||
|
||||
bool check_hash_old(const crypto::hash &hash, difficulty_type difficulty) {
|
||||
uint64_t low, high, top, cur;
|
||||
// First check the highest word, this will most likely fail for a random hash.
|
||||
mul(swap64le(((const uint64_t *)&hash)[3]), difficulty, top, high);
|
||||
if (high != 0) {
|
||||
return false;
|
||||
}
|
||||
mul(swap64le(((const uint64_t *)&hash)[0]), difficulty, low, cur);
|
||||
mul(swap64le(((const uint64_t *)&hash)[1]), difficulty, low, high);
|
||||
bool carry = cadd(cur, low);
|
||||
cur = high;
|
||||
mul(swap64le(((const uint64_t *)&hash)[2]), difficulty, low, high);
|
||||
carry = cadc(cur, low, carry);
|
||||
carry = cadc(high, top, carry);
|
||||
return !carry;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#ifdef max
|
||||
#undef max
|
||||
|
|
@ -143,48 +127,6 @@ namespace currency {
|
|||
}
|
||||
}
|
||||
|
||||
difficulty_type next_difficulty_old(vector<uint64_t> timestamps, vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
||||
//cutoff DIFFICULTY_LAG
|
||||
if (timestamps.size() > DIFFICULTY_WINDOW)
|
||||
{
|
||||
timestamps.resize(DIFFICULTY_WINDOW);
|
||||
cumulative_difficulties.resize(DIFFICULTY_WINDOW);
|
||||
}
|
||||
|
||||
|
||||
size_t length = timestamps.size();
|
||||
assert(length == cumulative_difficulties.size());
|
||||
if (length <= 1) {
|
||||
return DIFFICULTY_STARTER;
|
||||
}
|
||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
||||
assert(length <= DIFFICULTY_WINDOW);
|
||||
sort(timestamps.begin(), timestamps.end());
|
||||
size_t cut_begin, cut_end;
|
||||
static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large");
|
||||
if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) {
|
||||
cut_begin = 0;
|
||||
cut_end = length;
|
||||
}
|
||||
else {
|
||||
cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2;
|
||||
cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT);
|
||||
}
|
||||
assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length);
|
||||
uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin];
|
||||
if (time_span == 0) {
|
||||
time_span = 1;
|
||||
}
|
||||
difficulty_type total_work = cumulative_difficulties[cut_end - 1] - cumulative_difficulties[cut_begin];
|
||||
assert(total_work > 0);
|
||||
uint64_t low, high;
|
||||
mul(total_work, target_seconds, low, high);
|
||||
if (high != 0 || low + time_span - 1 < low) {
|
||||
return 0;
|
||||
}
|
||||
return (low + time_span - 1) / time_span;
|
||||
}
|
||||
|
||||
void get_cut_location_from_len(size_t length, size_t& cut_begin, size_t& cut_end, size_t REDEF_DIFFICULTY_WINDOW, size_t REDEF_DIFFICULTY_CUT_OLD, size_t REDEF_DIFFICULTY_CUT_LAST)
|
||||
{
|
||||
if (length <= REDEF_DIFFICULTY_WINDOW)
|
||||
|
|
|
|||
|
|
@ -15,13 +15,9 @@
|
|||
|
||||
namespace currency
|
||||
{
|
||||
typedef std::uint64_t difficulty_type;
|
||||
|
||||
typedef boost::multiprecision::uint128_t wide_difficulty_type;
|
||||
|
||||
bool check_hash_old(const crypto::hash &hash, difficulty_type difficulty);
|
||||
difficulty_type next_difficulty_old(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties);
|
||||
difficulty_type next_difficulty_old(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
|
||||
bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty);
|
||||
wide_difficulty_type next_difficulty(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds);
|
||||
uint64_t difficulty_to_boundary(wide_difficulty_type difficulty);
|
||||
|
|
|
|||
|
|
@ -893,7 +893,7 @@ namespace currency
|
|||
response.height = get_block_height(blk);
|
||||
response.depth = m_core.get_current_blockchain_size() - response.height - 1;
|
||||
response.hash = string_tools::pod_to_hex(get_block_hash(blk));
|
||||
response.difficulty = m_core.get_blockchain_storage().block_difficulty(response.height).convert_to<uint64_t>();
|
||||
response.difficulty = m_core.get_blockchain_storage().block_difficulty(response.height).convert_to<std::string>();
|
||||
response.reward = get_block_reward(blk);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -834,7 +834,7 @@ namespace currency
|
|||
uint64_t height;
|
||||
uint64_t depth;
|
||||
std::string hash;
|
||||
difficulty_type difficulty;
|
||||
std::string difficulty;
|
||||
uint64_t reward;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ bool gen_chain_switch_pow_pos::generate(std::vector<test_event_entry>& events) c
|
|||
for(size_t i = 0; i < CURRENCY_MINED_MONEY_UNLOCK_WINDOW; ++i)
|
||||
{
|
||||
block blk = AUTO_VAL_INIT(blk);
|
||||
uint64_t ts = blk_0r.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN / 3; // to increase main chain difficulty
|
||||
uint64_t ts = blk_0r.timestamp + DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN / 2; // to increase main chain difficulty
|
||||
bool r = generator.construct_block_manually(blk, blk_0r, miner_acc,test_generator::bf_timestamp, 0, 0, ts);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_block_manually failed");
|
||||
events.push_back(blk);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue