1
0
Fork 0
forked from lthn/blockchain

implemented target_calculation optimisation

This commit is contained in:
crypro.zoidberg 2019-04-18 23:29:38 +02:00
parent d846d26bf4
commit cfbe5d2bbc
7 changed files with 67 additions and 117 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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()

View file

@ -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);