@ -731,9 +731,9 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
m_timestamps_and_difficulties_height = 0 ;
m_alternative_chains . clear ( ) ;
invalidate_block_template_cache ( ) ;
m_db - > reset ( ) ;
m_db - > drop_alt_blocks ( ) ;
m_hardfork - > init ( ) ;
db_wtxn_guard wtxn_guard ( m_db ) ;
@ -858,10 +858,15 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph
// try to find block in alternative chain
catch ( const BLOCK_DNE & e )
{
blocks_ext_by_hash : : const_iterator it_alt = m_alternative_chains . find ( h ) ;
if ( m_alternative_chains . end ( ) ! = it_alt )
alt_block_data_t data ;
cryptonote : : blobdata blob ;
if ( m_db - > get_alt_block ( h , & data , & blob ) )
{
blk = it_alt - > second . bl ;
if ( ! cryptonote : : parse_and_validate_block_from_blob ( blob , blk ) )
{
MERROR ( " Found block " < < h < < " in alt chain, but failed to parse it " ) ;
throw std : : runtime_error ( " Found block in alt chain, but failed to parse it " ) ;
}
if ( orphan )
* orphan = true ;
return true ;
@ -1019,7 +1024,7 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
//------------------------------------------------------------------
// This function attempts to switch to an alternate chain, returning
// boolean based on success therein.
bool Blockchain : : switch_to_alternative_blockchain ( std : : list < block s_ext_by_hash: : const_iterator > & alt_chain , bool discard_disconnected_chain )
bool Blockchain : : switch_to_alternative_blockchain ( std : : list < block _extended_info > & alt_chain , bool discard_disconnected_chain )
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
@ -1030,7 +1035,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
CHECK_AND_ASSERT_MES ( alt_chain . size ( ) , false , " switch_to_alternative_blockchain: empty chain passed " ) ;
// verify that main chain has front of alt chain's parent block
if ( ! m_db - > block_exists ( alt_chain . front ( ) - > second . bl . prev_id ) )
if ( ! m_db - > block_exists ( alt_chain . front ( ) . bl . prev_id ) )
{
LOG_ERROR ( " Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain! " ) ;
return false ;
@ -1039,7 +1044,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
// pop blocks from the blockchain until the top block is the parent
// of the front block of the alt chain.
std : : list < block > disconnected_chain ;
while ( m_db - > top_block_hash ( ) ! = alt_chain . front ( ) - > second . bl . prev_id )
while ( m_db - > top_block_hash ( ) ! = alt_chain . front ( ) . bl . prev_id )
{
block b = pop_block_from_blockchain ( ) ;
disconnected_chain . push_front ( b ) ;
@ -1050,11 +1055,11 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
//connecting new alternative chain
for ( auto alt_ch_iter = alt_chain . begin ( ) ; alt_ch_iter ! = alt_chain . end ( ) ; alt_ch_iter + + )
{
auto ch_ent = * alt_ch_iter ;
const auto & bei = * alt_ch_iter ;
block_verification_context bvc = boost : : value_initialized < block_verification_context > ( ) ;
// add block to main chain
bool r = handle_block_to_main_chain ( ch_ent- > second . bl , bvc ) ;
bool r = handle_block_to_main_chain ( bei . bl , bvc ) ;
// if adding block to main chain failed, rollback to previous state and
// return false
@ -1070,14 +1075,18 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
// FIXME: Why do we keep invalid blocks around? Possibly in case we hear
// about them again so we can immediately dismiss them, but needs some
// looking into.
add_block_as_invalid ( ch_ent - > second , get_block_hash ( ch_ent - > second . bl ) ) ;
MERROR ( " The block was inserted as invalid while connecting new alternative chain, block_id: " < < get_block_hash ( ch_ent - > second . bl ) ) ;
m_alternative_chains . erase ( * alt_ch_iter + + ) ;
const crypto : : hash blkid = cryptonote : : get_block_hash ( bei . bl ) ;
add_block_as_invalid ( bei , blkid ) ;
MERROR ( " The block was inserted as invalid while connecting new alternative chain, block_id: " < < blkid ) ;
m_db - > remove_alt_block ( blkid ) ;
alt_ch_iter + + ;
for ( auto alt_ch_to_orph_iter = alt_ch_iter ; alt_ch_to_orph_iter ! = alt_chain . end ( ) ; )
{
add_block_as_invalid ( ( * alt_ch_to_orph_iter ) - > second , ( * alt_ch_to_orph_iter ) - > first ) ;
m_alternative_chains . erase ( * alt_ch_to_orph_iter + + ) ;
const auto & bei = * alt_ch_to_orph_iter + + ;
const crypto : : hash blkid = cryptonote : : get_block_hash ( bei . bl ) ;
add_block_as_invalid ( bei , blkid ) ;
m_db - > remove_alt_block ( blkid ) ;
}
return false ;
}
@ -1102,9 +1111,9 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
}
//removing alt_chain entries from alternative chains container
for ( auto ch_ent : alt_chain )
for ( const auto & bei : alt_chain )
{
m_ alternative_chains. erase ( ch_ent ) ;
m_ db- > remove_alt_block ( cryptonote : : get_block_hash ( bei . bl ) ) ;
}
m_hardfork - > reorganize_from_chain_height ( split_height ) ;
@ -1120,7 +1129,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
//------------------------------------------------------------------
// This function calculates the difficulty target for the block being added to
// an alternate chain.
difficulty_type Blockchain : : get_next_difficulty_for_alternative_chain ( const std : : list < block s_ext_by_hash: : const_iterator > & alt_chain , block_extended_info & bei ) const
difficulty_type Blockchain : : get_next_difficulty_for_alternative_chain ( const std : : list < block _extended_info > & alt_chain , block_extended_info & bei ) const
{
if ( m_fixed_difficulty )
{
@ -1138,7 +1147,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
// Figure out start and stop offsets for main chain blocks
size_t main_chain_stop_offset = alt_chain . size ( ) ? alt_chain . front ( ) - > second . height : bei . height ;
size_t main_chain_stop_offset = alt_chain . size ( ) ? alt_chain . front ( ) . height : bei . height ;
size_t main_chain_count = DIFFICULTY_BLOCKS_COUNT - std : : min ( static_cast < size_t > ( DIFFICULTY_BLOCKS_COUNT ) , alt_chain . size ( ) ) ;
main_chain_count = std : : min ( main_chain_count , main_chain_stop_offset ) ;
size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count ;
@ -1156,10 +1165,10 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// make sure we haven't accidentally grabbed too many blocks...maybe don't need this check?
CHECK_AND_ASSERT_MES ( ( alt_chain . size ( ) + timestamps . size ( ) ) < = DIFFICULTY_BLOCKS_COUNT , false , " Internal error, alt_chain.size()[ " < < alt_chain . size ( ) < < " ] + vtimestampsec.size()[ " < < timestamps . size ( ) < < " ] NOT <= DIFFICULTY_WINDOW[] " < < DIFFICULTY_BLOCKS_COUNT ) ;
for ( auto it : alt_chain )
for ( const auto & be i : alt_chain )
{
timestamps . push_back ( it- > second . bl . timestamp ) ;
cumulative_difficulties . push_back ( it- > second . cumulative_difficulty ) ;
timestamps . push_back ( be i. bl . timestamp ) ;
cumulative_difficulties . push_back ( be i. cumulative_difficulty ) ;
}
}
// if the alt chain is long enough for the difficulty calc, grab difficulties
@ -1171,10 +1180,10 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
size_t count = 0 ;
size_t max_i = timestamps . size ( ) - 1 ;
// get difficulties and timestamps from most recent blocks in alt chain
for ( auto it : boost : : adaptors : : reverse ( alt_chain ) )
for ( const auto be i: boost : : adaptors : : reverse ( alt_chain ) )
{
timestamps [ max_i - count ] = it- > second . bl . timestamp ;
cumulative_difficulties [ max_i - count ] = it- > second . cumulative_difficulty ;
timestamps [ max_i - count ] = be i. bl . timestamp ;
cumulative_difficulties [ max_i - count ] = be i. cumulative_difficulty ;
count + + ;
if ( count > = DIFFICULTY_BLOCKS_COUNT )
break ;
@ -1393,16 +1402,17 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
//build alternative subchain, front -> mainchain, back -> alternative head
//block is not related with head of main chain
//first of all - look in alternative chains container
auto it_prev = m_alternative_chains . find ( * from_block ) ;
alt_block_data_t prev_data ;
bool parent_in_alt = m_db - > get_alt_block ( * from_block , & prev_data , NULL ) ;
bool parent_in_main = m_db - > block_exists ( * from_block ) ;
if ( it_prev = = m_alternative_chains . end ( ) & & ! parent_in_main )
if ( ! parent_in_alt & & ! parent_in_main )
{
MERROR ( " Unknown from block " ) ;
return false ;
}
//we have new block in alternative chain
std : : list < block s_ext_by_hash: : const_iterator > alt_chain ;
std : : list < block _extended_info > alt_chain ;
block_verification_context bvc = boost : : value_initialized < block_verification_context > ( ) ;
std : : vector < uint64_t > timestamps ;
if ( ! build_alt_chain ( * from_block , alt_chain , timestamps , bvc ) )
@ -1417,7 +1427,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
}
else
{
height = alt_chain . back ( ) - > second . height + 1 ;
height = alt_chain . back ( ) . height + 1 ;
}
b . major_version = m_hardfork - > get_ideal_version ( height ) ;
b . minor_version = m_hardfork - > get_ideal_version ( ) ;
@ -1432,14 +1442,14 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
}
else
{
median_weight = it_prev- > second . block_cumulative_weight - it_prev - > second . block_ cumulative_weight / 20 ;
already_generated_coins = alt_chain . back ( ) - > second . already_generated_coins ;
median_weight = prev_data. cumulative_weight - prev_data . cumulative_weight / 20 ;
already_generated_coins = alt_chain . back ( ) . already_generated_coins ;
}
// FIXME: consider moving away from block_extended_info at some point
block_extended_info bei = boost : : value_initialized < block_extended_info > ( ) ;
bei . bl = b ;
bei . height = alt_chain . size ( ) ? it_prev- > second . height + 1 : m_db - > get_block_height ( * from_block ) + 1 ;
bei . height = alt_chain . size ( ) ? prev_data . height + 1 : m_db - > get_block_height ( * from_block ) + 1 ;
diffic = get_next_difficulty_for_alternative_chain ( alt_chain , bei ) ;
}
@ -1618,16 +1628,25 @@ bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vect
return true ;
}
//------------------------------------------------------------------
bool Blockchain : : build_alt_chain ( const crypto : : hash & prev_id , std : : list < block s_ext_by_hash: : const_iterator > & alt_chain , std : : vector < uint64_t > & timestamps , block_verification_context & bvc ) const
bool Blockchain : : build_alt_chain ( const crypto : : hash & prev_id , std : : list < block _extended_info > & alt_chain , std : : vector < uint64_t > & timestamps , block_verification_context & bvc ) const
{
//build alternative subchain, front -> mainchain, back -> alternative head
blocks_ext_by_hash : : const_iterator alt_it = m_alternative_chains . find ( prev_id ) ;
cryptonote : : alt_block_data_t data ;
cryptonote : : blobdata blob ;
bool found = m_db - > get_alt_block ( prev_id , & data , & blob ) ;
timestamps . clear ( ) ;
while ( alt_it ! = m_alternative_chains . end ( ) )
while ( found )
{
alt_chain . push_front ( alt_it ) ;
timestamps . push_back ( alt_it - > second . bl . timestamp ) ;
alt_it = m_alternative_chains . find ( alt_it - > second . bl . prev_id ) ;
block_extended_info bei ;
CHECK_AND_ASSERT_MES ( cryptonote : : parse_and_validate_block_from_blob ( blob , bei . bl ) , false , " Failed to parse alt block " ) ;
bei . height = data . height ;
bei . block_cumulative_weight = data . cumulative_weight ;
bei . cumulative_difficulty = data . cumulative_difficulty_high ;
bei . cumulative_difficulty = ( bei . cumulative_difficulty < < 64 ) + data . cumulative_difficulty_low ;
bei . already_generated_coins = data . already_generated_coins ;
timestamps . push_back ( bei . bl . timestamp ) ;
alt_chain . push_front ( std : : move ( bei ) ) ;
found = m_db - > get_alt_block ( bei . bl . prev_id , & data , & blob ) ;
}
// if block to be added connects to known blocks that aren't part of the
@ -1635,20 +1654,20 @@ bool Blockchain::build_alt_chain(const crypto::hash &prev_id, std::list<blocks_e
if ( ! alt_chain . empty ( ) )
{
// make sure alt chain doesn't somehow start past the end of the main chain
CHECK_AND_ASSERT_MES ( m_db - > height ( ) > alt_chain . front ( ) - > second . height , false , " main blockchain wrong height " ) ;
CHECK_AND_ASSERT_MES ( m_db - > height ( ) > alt_chain . front ( ) . height , false , " main blockchain wrong height " ) ;
// make sure that the blockchain contains the block that should connect
// this alternate chain with it.
if ( ! m_db - > block_exists ( alt_chain . front ( ) - > second . bl . prev_id ) )
if ( ! m_db - > block_exists ( alt_chain . front ( ) . bl . prev_id ) )
{
MERROR ( " alternate chain does not appear to connect to main chain... " ) ;
return false ;
}
// make sure block connects correctly to the main chain
auto h = m_db - > get_block_hash_from_height ( alt_chain . front ( ) - > second . height - 1 ) ;
CHECK_AND_ASSERT_MES ( h = = alt_chain . front ( ) - > second . bl . prev_id , false , " alternative chain has wrong connection to main chain " ) ;
complete_timestamps_vector ( m_db - > get_block_height ( alt_chain . front ( ) - > second . bl . prev_id ) , timestamps ) ;
auto h = m_db - > get_block_hash_from_height ( alt_chain . front ( ) . height - 1 ) ;
CHECK_AND_ASSERT_MES ( h = = alt_chain . front ( ) . bl . prev_id , false , " alternative chain has wrong connection to main chain " ) ;
complete_timestamps_vector ( m_db - > get_block_height ( alt_chain . front ( ) . bl . prev_id ) , timestamps ) ;
}
// if block not associated with known alternate chain
else
@ -1703,12 +1722,13 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
//block is not related with head of main chain
//first of all - look in alternative chains container
auto it_prev = m_alternative_chains . find ( b . prev_id ) ;
alt_block_data_t prev_data ;
bool parent_in_alt = m_db - > get_alt_block ( b . prev_id , & prev_data , NULL ) ;
bool parent_in_main = m_db - > block_exists ( b . prev_id ) ;
if ( it_prev ! = m_alternative_chains . end ( ) | | parent_in_main )
if ( parent_in_alt | | parent_in_main )
{
//we have new block in alternative chain
std : : list < block s_ext_by_hash: : const_iterator > alt_chain ;
std : : list < block _extended_info > alt_chain ;
std : : vector < uint64_t > timestamps ;
if ( ! build_alt_chain ( b . prev_id , alt_chain , timestamps , bvc ) )
return false ;
@ -1716,10 +1736,10 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
// FIXME: consider moving away from block_extended_info at some point
block_extended_info bei = boost : : value_initialized < block_extended_info > ( ) ;
bei . bl = b ;
const uint64_t prev_height = alt_chain . size ( ) ? it_prev- > second . height : m_db - > get_block_height ( b . prev_id ) ;
const uint64_t prev_height = alt_chain . size ( ) ? prev_data . height : m_db - > get_block_height ( b . prev_id ) ;
bei . height = prev_height + 1 ;
uint64_t block_reward = get_outs_money_amount ( b . miner_tx ) ;
bei . already_generated_coins = block_reward + ( alt_chain . size ( ) ? it_prev- > second . already_generated_coins : m_db - > get_block_already_generated_coins ( prev_height ) ) ;
bei . already_generated_coins = block_reward + ( alt_chain . size ( ) ? prev_data . already_generated_coins : m_db - > get_block_already_generated_coins ( prev_height ) ) ;
// verify that the block's timestamp is within the acceptable range
// (not earlier than the median of the last X blocks)
@ -1763,7 +1783,8 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
difficulty_type main_chain_cumulative_difficulty = m_db - > get_block_cumulative_difficulty ( m_db - > height ( ) - 1 ) ;
if ( alt_chain . size ( ) )
{
bei . cumulative_difficulty = it_prev - > second . cumulative_difficulty ;
bei . cumulative_difficulty = prev_data . cumulative_difficulty_high ;
bei . cumulative_difficulty = ( bei . cumulative_difficulty < < 64 ) + prev_data . cumulative_difficulty_low ;
}
else
{
@ -1774,15 +1795,21 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
// add block to alternate blocks storage,
// as well as the current "alt chain" container
auto i_res = m_alternative_chains . insert ( blocks_ext_by_hash : : value_type ( id , bei ) ) ;
CHECK_AND_ASSERT_MES ( i_res . second , false , " insertion of new alternative block returned as it already exist " ) ;
alt_chain . push_back ( i_res . first ) ;
CHECK_AND_ASSERT_MES ( ! m_db - > get_alt_block ( id , NULL , NULL ) , false , " insertion of new alternative block returned as it already exists " ) ;
cryptonote : : alt_block_data_t data ;
data . height = bei . height ;
data . cumulative_weight = bei . block_cumulative_weight ;
data . cumulative_difficulty_low = ( bei . cumulative_difficulty & 0xffffffffffffffff ) . convert_to < uint64_t > ( ) ;
data . cumulative_difficulty_high = ( ( bei . cumulative_difficulty > > 64 ) & 0xffffffffffffffff ) . convert_to < uint64_t > ( ) ;
data . already_generated_coins = bei . already_generated_coins ;
m_db - > add_alt_block ( id , data , cryptonote : : block_to_blob ( bei . bl ) ) ;
alt_chain . push_back ( bei ) ;
// FIXME: is it even possible for a checkpoint to show up not on the main chain?
if ( is_a_checkpoint )
{
//do reorganize!
MGINFO_GREEN ( " ###### REORGANIZE on height: " < < alt_chain . front ( ) - > second . height < < " of " < < m_db - > height ( ) - 1 < < " , checkpoint is found in alternative chain on height " < < bei . height ) ;
MGINFO_GREEN ( " ###### REORGANIZE on height: " < < alt_chain . front ( ) . height < < " of " < < m_db - > height ( ) - 1 < < " , checkpoint is found in alternative chain on height " < < bei . height ) ;
bool r = switch_to_alternative_blockchain ( alt_chain , true ) ;
@ -1794,7 +1821,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
else if ( main_chain_cumulative_difficulty < bei . cumulative_difficulty ) //check if difficulty bigger then in main chain
{
//do reorganize!
MGINFO_GREEN ( " ###### REORGANIZE on height: " < < alt_chain . front ( ) - > second . height < < " of " < < m_db - > height ( ) - 1 < < " with cum_difficulty " < < m_db - > get_block_cumulative_difficulty ( m_db - > height ( ) - 1 ) < < std : : endl < < " alternative blockchain size: " < < alt_chain . size ( ) < < " with cum_difficulty " < < bei . cumulative_difficulty ) ;
MGINFO_GREEN ( " ###### REORGANIZE on height: " < < alt_chain . front ( ) . height < < " of " < < m_db - > height ( ) - 1 < < " with cum_difficulty " < < m_db - > get_block_cumulative_difficulty ( m_db - > height ( ) - 1 ) < < std : : endl < < " alternative blockchain size: " < < alt_chain . size ( ) < < " with cum_difficulty " < < bei . cumulative_difficulty ) ;
bool r = switch_to_alternative_blockchain ( alt_chain , false ) ;
if ( r )
@ -1814,7 +1841,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
//block orphaned
bvc . m_marked_as_orphaned = true ;
MERROR_VER ( " Block recognized as orphaned and rejected, id = " < < id < < " , height " < < block_height
< < " , parent in alt " < < ( it_prev ! = m_alternative_chains . end ( ) ) < < " , parent in main " < < parent_in_main
< < " , parent in alt " < < parent_in_alt < < " , parent in main " < < parent_in_main
< < " (parent " < < b . prev_id < < " , current top " < < get_tail_id ( ) < < " , chain height " < < get_current_blockchain_height ( ) < < " ) " ) ;
}
@ -1923,11 +1950,20 @@ bool Blockchain::get_alternative_blocks(std::vector<block>& blocks) const
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
blocks . reserve ( m_alternative_chains . size ( ) ) ;
for ( const auto & alt_bl : m_alternative_chains )
{
blocks . push_back ( alt_bl . second . bl ) ;
}
blocks . reserve ( m_db - > get_alt_block_count ( ) ) ;
m_db - > for_all_alt_blocks ( [ & blocks ] ( const crypto : : hash & blkid , const cryptonote : : alt_block_data_t & data , const cryptonote : : blobdata * blob ) {
if ( ! blob )
{
MERROR ( " No blob, but blobs were requested " ) ;
return false ;
}
cryptonote : : block bl ;
if ( cryptonote : : parse_and_validate_block_from_blob ( * blob , bl ) )
blocks . push_back ( std : : move ( bl ) ) ;
else
MERROR ( " Failed to parse block from blob " ) ;
return true ;
} , true ) ;
return true ;
}
//------------------------------------------------------------------
@ -1935,7 +1971,7 @@ size_t Blockchain::get_alternative_blocks_count() const
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
return m_ alternative_chains. size ( ) ;
return m_ db- > get_alt_block_count ( ) ;
}
//------------------------------------------------------------------
// This function adds the output specified by <amount, i> to the result_outs container
@ -2422,9 +2458,9 @@ bool Blockchain::have_block(const crypto::hash& id) const
return true ;
}
if ( m_ alternative_chains. count ( id ) )
if ( m_ db- > get_alt_block ( id , NULL , NULL ) )
{
LOG_PRINT_L2 ( " block " < < id < < " found in m_alternative_ chains" ) ;
LOG_PRINT_L2 ( " block " < < id < < " found in alternative chains" ) ;
return true ;
}
@ -4810,11 +4846,35 @@ std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>>
{
std : : list < std : : pair < Blockchain : : block_extended_info , std : : vector < crypto : : hash > > > chains ;
for ( const auto & i : m_alternative_chains )
blocks_ext_by_hash alt_blocks ;
alt_blocks . reserve ( m_db - > get_alt_block_count ( ) ) ;
m_db - > for_all_alt_blocks ( [ & alt_blocks ] ( const crypto : : hash & blkid , const cryptonote : : alt_block_data_t & data , const cryptonote : : blobdata * blob ) {
if ( ! blob )
{
MERROR ( " No blob, but blobs were requested " ) ;
return false ;
}
cryptonote : : block bl ;
block_extended_info bei ;
if ( cryptonote : : parse_and_validate_block_from_blob ( * blob , bei . bl ) )
{
bei . height = data . height ;
bei . block_cumulative_weight = data . cumulative_weight ;
bei . cumulative_difficulty = data . cumulative_difficulty_high ;
bei . cumulative_difficulty = ( bei . cumulative_difficulty < < 64 ) + data . cumulative_difficulty_low ;
bei . already_generated_coins = data . already_generated_coins ;
alt_blocks . insert ( std : : make_pair ( cryptonote : : get_block_hash ( bei . bl ) , std : : move ( bei ) ) ) ;
}
else
MERROR ( " Failed to parse block from blob " ) ;
return true ;
} , true ) ;
for ( const auto & i : alt_blocks )
{
const crypto : : hash & top = i . first ;
const crypto : : hash top = cryptonote : : get_block_hash ( i . second . bl ) ;
bool found = false ;
for ( const auto & j : m_alternative_chains )
for ( const auto & j : alt_block s)
{
if ( j . second . bl . prev_id = = top )
{
@ -4828,7 +4888,7 @@ std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>>
auto h = i . second . bl . prev_id ;
chain . push_back ( top ) ;
blocks_ext_by_hash : : const_iterator prev ;
while ( ( prev = m_alternative_chains. find ( h ) ) ! = m_alternative_chain s. end ( ) )
while ( ( prev = alt_blocks. find ( h ) ) ! = alt_block s. end ( ) )
{
chain . push_back ( h ) ;
h = prev - > second . bl . prev_id ;