1
0
Fork 0
forked from lthn/blockchain

implemented workaround for rear case when an old node is stuck in an altchain right after the hardfork

This commit is contained in:
sowle 2025-03-20 20:33:34 +03:00
parent 6be32747c7
commit 2e57faf822
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
3 changed files with 57 additions and 2 deletions

View file

@ -67,6 +67,7 @@ using namespace currency;
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION 3 //DON'T CHANGE THIS, if you need to resync db change BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION 4 //mismatch here means some reinitializations
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_MAJOR_FAILURE 5 //if not blocks should ever be added with this condition
#define BLOCKCHAIN_STORAGE_OPTIONS_ID_MOST_RECENT_HARDFORK_ID 6
#define TARGETDATA_CACHE_SIZE DIFFICULTY_WINDOW + 10
@ -95,6 +96,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m
m_db_storage_major_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION, m_db_solo_options),
m_db_storage_minor_compatibility_version(BLOCKCHAIN_STORAGE_OPTIONS_ID_STORAGE_MINOR_COMPATIBILITY_VERSION, m_db_solo_options),
m_db_major_failure(BLOCKCHAIN_STORAGE_OPTIONS_ID_MAJOR_FAILURE, m_db_solo_options),
m_db_most_recent_hardfork_id(BLOCKCHAIN_STORAGE_OPTIONS_ID_MOST_RECENT_HARDFORK_ID, m_db_solo_options),
m_db_per_block_gindex_incs(m_db),
m_tx_pool(tx_pool),
m_is_in_checkpoint_zone(false),
@ -116,6 +118,7 @@ blockchain_storage::blockchain_storage(tx_memory_pool& tx_pool) :m_db(nullptr, m
m_services_mgr.set_core_runtime_config(m_core_runtime_config);
m_performance_data.epic_failure_happend = false;
}
blockchain_storage::~blockchain_storage()
{
if (!m_deinit_is_done)
@ -451,7 +454,47 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
m_db.commit_transaction();
LOG_PRINT_MAGENTA("migration of m_db_per_block_gindex_incs completed successfully", LOG_LEVEL_0);
}
}
#ifndef TESTNET
// MAINNET ONLY
if (m_db_most_recent_hardfork_id == 0)
{
// HF5 and the first time use: we need to check
// to handle this case we manually check hash for the block, right after HF5 activation, and if it doesn't match -- truncate the blockchain
block blk{};
if (get_block_by_height(ZANO_HARDFORK_05_AFTER_HEIGHT + 1, blk))
{
crypto::hash b3076401_id = epee::string_tools::hex_to_pod<crypto::hash>("8d93e0a7ab93b367dea44862f27ee9ca044649db84a9f44bf095d2eebc133b2d");
crypto::hash h = get_block_hash(blk);
if (h != b3076401_id)
{
LOG_PRINT_L0("In the blockchain hash for the block 3076401 is " << h << " while it is expected to be " << b3076401_id <<
". Most likely recent blocks are alternative and invalid for the current hardfork, thus we truncate the blockchain, so that block 3076400 becomes new top block...");
truncate_blockchain(ZANO_HARDFORK_05_AFTER_HEIGHT + 1);
}
}
else
{
need_reinit = true;
LOG_ERROR("get_block_by_height(" << ZANO_HARDFORK_05_AFTER_HEIGHT + 1 << ") returned false, which is unexpected. Reinit the blockchain.");
}
}
else
{
size_t current_hardfork_id = m_core_runtime_config.hard_forks.get_the_most_recent_hardfork_id_for_height(get_top_block_height());
if (m_db_most_recent_hardfork_id < current_hardfork_id)
{
// most likely we have blocks that don't meet new hardfork criteria, so we need to remove last N blocks till the hardfork and try to resync them again
uint64_t height_right_before_hardfork_activation = m_core_runtime_config.hard_forks.get_height_the_hardfork_active_after(current_hardfork_id);
LOG_PRINT_L0("The most recent hardfork id in the DB is " << m_db_most_recent_hardfork_id << " while according to the code, the top block must belong to the hardfork " <<
current_hardfork_id << ". Most likely recent blocks are alternative and invalid for the current hardfork, thus we truncate the blockchain, so that block " <<
height_right_before_hardfork_activation << " becomes new top block...");
truncate_blockchain(height_right_before_hardfork_activation + 1);
}
}
#endif
} // if (m_db_blocks.size() != 0)
if (need_reinit)
{
@ -505,9 +548,10 @@ bool blockchain_storage::init(const std::string& config_folder, const boost::pro
set_lost_tx_unmixable();
m_db.commit_transaction();
LOG_PRINT_GREEN("Blockchain initialized, ver: " << m_db_storage_major_compatibility_version << "." << m_db_storage_minor_compatibility_version << ", last block: " << m_db_blocks.size() - 1 << ENDL
LOG_PRINT_GREEN("Blockchain initialized, ver: " << m_db_storage_major_compatibility_version << "." << m_db_storage_minor_compatibility_version << ENDL
<< " genesis: " << get_block_hash(m_db_blocks[0]->bl) << ENDL
<< " last block: " << m_db_blocks.size() - 1 << ", " << misc_utils::get_time_interval_string(timestamp_diff) << " ago" << ENDL
<< " last hardfork id: " << m_db_most_recent_hardfork_id << ENDL
<< " current pos difficulty: " << get_next_diff_conditional(true) << ENDL
<< " current pow difficulty: " << get_next_diff_conditional(false) << ENDL
<< " total transactions: " << m_db_transactions.size() << ENDL
@ -579,6 +623,7 @@ void blockchain_storage::store_db_solo_options_values()
m_db_storage_major_compatibility_version = BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION;
m_db_storage_minor_compatibility_version = BLOCKCHAIN_STORAGE_MINOR_COMPATIBILITY_VERSION;
m_db_last_worked_version = std::string(PROJECT_VERSION_LONG);
m_db_most_recent_hardfork_id = m_core_runtime_config.hard_forks.get_the_most_recent_hardfork_id_for_height(get_top_block_height());
m_db.commit_transaction();
}
//------------------------------------------------------------------
@ -5380,6 +5425,13 @@ void blockchain_storage::do_full_db_warm_up() const
}
}
//------------------------------------------------------------------
void blockchain_storage::on_hardfork_activated(size_t hardfork_id)
{
m_db.begin_transaction();
m_db_most_recent_hardfork_id = hardfork_id;
m_db.commit_transaction();
}
//------------------------------------------------------------------
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
{
CRITICAL_REGION_LOCAL(m_read_lock);

View file

@ -513,6 +513,7 @@ namespace currency
void set_db_l2_cache_size(uint64_t ceched_elements) const;
//experimental
void do_full_db_warm_up() const;
void on_hardfork_activated(size_t hardfork_id);
private:
@ -566,6 +567,7 @@ namespace currency
tools::db::solo_db_value<uint64_t, uint64_t, solo_options_container> m_db_storage_major_compatibility_version;
tools::db::solo_db_value<uint64_t, uint64_t, solo_options_container> m_db_storage_minor_compatibility_version;
tools::db::solo_db_value<uint64_t, bool, solo_options_container> m_db_major_failure; //safety fuse
tools::db::solo_db_value<uint64_t, uint64_t, solo_options_container> m_db_most_recent_hardfork_id;
outputs_container m_db_outputs;
multisig_outs_container m_db_multisig_outs;

View file

@ -566,6 +566,7 @@ namespace currency
if (hardfork_id_for_prev_block != hardfork_id_for_curr_block)
{
LOG_PRINT_GREEN("Hardfork " << hardfork_id_for_curr_block << " has been activated after the block at height " << h, LOG_LEVEL_0);
m_blockchain_storage.on_hardfork_activated(hardfork_id_for_curr_block);
m_pprotocol->on_hardfork_activated(hardfork_id_for_curr_block);
}
}