@ -1185,7 +1185,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
}
if ( base_reward + fee < money_in_use )
{
MERROR_VER ( " coinbase transaction spend too much money ( " < < print_money ( money_in_use ) < < " ). Block reward is " < < print_money ( base_reward + fee ) < < " ( " < < print_money ( base_reward ) < < " + " < < print_money ( fee ) < < " ) " ) ;
MERROR_VER ( " coinbase transaction spend too much money ( " < < print_money ( money_in_use ) < < " ). Block reward is " < < print_money ( base_reward + fee ) < < " ( " < < print_money ( base_reward ) < < " + " < < print_money ( fee ) < < " ) , cumulative_block_weight " < < cumulative_block_weight ) ;
return false ;
}
// From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
@ -1863,8 +1863,9 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
std : : vector < std : : pair < cryptonote : : blobdata , block > > blocks ;
get_blocks ( arg . blocks , blocks , rsp . missed_ids ) ;
for ( auto & bl : blocks )
for ( size_t i = 0 ; i < blocks . size ( ) ; + + i )
{
auto & bl = blocks [ i ] ;
std : : vector < crypto : : hash > missed_tx_ids ;
rsp . blocks . push_back ( block_complete_entry ( ) ) ;
@ -1872,8 +1873,8 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
// FIXME: s/rsp.missed_ids/missed_tx_id/ ? Seems like rsp.missed_ids
// is for missed blocks, not missed transactions as well.
get_transactions_blobs( bl . second . tx_hashes , e . txs , missed_tx_ids ) ;
e. pruned = arg . prune ;
get_transactions_blobs ( bl . second . tx_hashes , e . txs , missed_tx_ids , arg . prune ) ;
if ( missed_tx_ids . size ( ) ! = 0 )
{
// do not display an error if the peer asked for an unpruned block which we are not meant to have
@ -1894,6 +1895,9 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NO
//pack block
e . block = std : : move ( bl . first ) ;
e . block_weight = 0 ;
if ( arg . prune & & m_db - > block_exists ( arg . blocks [ i ] ) )
e . block_weight = m_db - > get_block_weight ( m_db - > get_block_height ( arg . blocks [ i ] ) ) ;
}
return true ;
@ -2172,23 +2176,95 @@ bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container
return true ;
}
//------------------------------------------------------------------
static bool fill ( BlockchainDB * db , const crypto : : hash & tx_hash , cryptonote : : blobdata & tx , bool pruned )
{
if ( pruned )
{
if ( ! db - > get_pruned_tx_blob ( tx_hash , tx ) )
{
MDEBUG ( " Pruned transaction blob not found for " < < tx_hash ) ;
return false ;
}
}
else
{
if ( ! db - > get_tx_blob ( tx_hash , tx ) )
{
MDEBUG ( " Transaction blob not found for " < < tx_hash ) ;
return false ;
}
}
return true ;
}
//------------------------------------------------------------------
static bool fill ( BlockchainDB * db , const crypto : : hash & tx_hash , tx_blob_entry & tx , bool pruned )
{
if ( ! fill ( db , tx_hash , tx . blob , pruned ) )
return false ;
if ( pruned )
{
if ( is_v1_tx ( tx . blob ) )
{
// v1 txes aren't pruned, so fetch the whole thing
cryptonote : : blobdata prunable_blob ;
if ( ! db - > get_prunable_tx_blob ( tx_hash , prunable_blob ) )
{
MDEBUG ( " Prunable transaction blob not found for " < < tx_hash ) ;
return false ;
}
tx . blob . append ( prunable_blob ) ;
tx . prunable_hash = crypto : : null_hash ;
}
else
{
if ( ! db - > get_prunable_tx_hash ( tx_hash , tx . prunable_hash ) )
{
MDEBUG ( " Prunable transaction data hash not found for " < < tx_hash ) ;
return false ;
}
}
}
return true ;
}
//------------------------------------------------------------------
//TODO: return type should be void, throw on exception
// alternatively, return true only if no transactions missed
template < class t_ids_container , class t_tx_container , class t_missed_container >
bool Blockchain : : get_transactions_blobs ( const t_ids_container & txs_ids , t_tx_container & txs , t_missed_container & missed_txs , bool pruned ) const
bool Blockchain : : get_transactions_blobs ( const std : : vector < crypto : : hash > & txs_ids , std : : vector < cryptonote : : blobdata > & txs , std : : vector < crypto : : hash > & missed_txs , bool pruned ) const
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
reserve_container ( txs , txs_ids . size ( ) ) ;
txs. reserve( txs_ids . size ( ) ) ;
for ( const auto & tx_hash : txs_ids )
{
try
{
cryptonote : : blobdata tx ;
if ( pruned & & m_db - > get_pruned_tx_blob ( tx_hash , tx ) )
if ( fill( m_db , tx_hash , tx , pruned ) )
txs . push_back ( std : : move ( tx ) ) ;
else if ( ! pruned & & m_db - > get_tx_blob ( tx_hash , tx ) )
else
missed_txs . push_back ( tx_hash ) ;
}
catch ( const std : : exception & e )
{
return false ;
}
}
return true ;
}
//------------------------------------------------------------------
bool Blockchain : : get_transactions_blobs ( const std : : vector < crypto : : hash > & txs_ids , std : : vector < tx_blob_entry > & txs , std : : vector < crypto : : hash > & missed_txs , bool pruned ) const
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
txs . reserve ( txs_ids . size ( ) ) ;
for ( const auto & tx_hash : txs_ids )
{
try
{
tx_blob_entry tx ;
if ( fill ( m_db , tx_hash , tx , pruned ) )
txs . push_back ( std : : move ( tx ) ) ;
else
missed_txs . push_back ( tx_hash ) ;
@ -2281,7 +2357,7 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container
// Find the split point between us and foreign blockchain and return
// (by reference) the most recent common block hash along with up to
// BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.
bool Blockchain : : find_blockchain_supplement ( const std : : list < crypto : : hash > & qblock_ids , std : : vector < crypto : : hash > & hashes , uint64_t & start_height , uint64_t & current_height , bool clip_pruned ) const
bool Blockchain : : find_blockchain_supplement ( const std : : list < crypto : : hash > & qblock_ids , std : : vector < crypto : : hash > & hashes , std : : vector < uint64_t > * weights , uint64_t & start_height , uint64_t & current_height , bool clip_pruned ) const
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
@ -2298,25 +2374,34 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
if ( clip_pruned )
{
const uint32_t pruning_seed = get_blockchain_pruning_seed ( ) ;
start_height = tools : : get_next_unpruned_block_height ( start_height , current_height , pruning_seed ) ;
if ( start_height < tools : : get_next_unpruned_block_height ( start_height , current_height , pruning_seed ) )
{
MDEBUG ( " We only have a pruned version of the common ancestor " ) ;
return false ;
}
stop_height = tools : : get_next_pruned_block_height ( start_height , current_height , pruning_seed ) ;
}
size_t count = 0 ;
hashes . reserve ( std : : min ( ( size_t ) ( stop_height - start_height ) , ( size_t ) BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT ) ) ;
const size_t reserve = std : : min ( ( size_t ) ( stop_height - start_height ) , ( size_t ) BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT ) ;
hashes . reserve ( reserve ) ;
if ( weights )
weights - > reserve ( reserve ) ;
for ( size_t i = start_height ; i < stop_height & & count < BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT ; i + + , count + + )
{
hashes . push_back ( m_db - > get_block_hash_from_height ( i ) ) ;
if ( weights )
weights - > push_back ( m_db - > get_block_weight ( i ) ) ;
}
return true ;
}
bool Blockchain : : find_blockchain_supplement ( const std : : list < crypto : : hash > & qblock_ids , NOTIFY_RESPONSE_CHAIN_ENTRY : : request & resp ) const
bool Blockchain : : find_blockchain_supplement ( const std : : list < crypto : : hash > & qblock_ids , bool clip_pruned , NOTIFY_RESPONSE_CHAIN_ENTRY : : request & resp ) const
{
LOG_PRINT_L3 ( " Blockchain:: " < < __func__ ) ;
CRITICAL_REGION_LOCAL ( m_blockchain_lock ) ;
bool result = find_blockchain_supplement ( qblock_ids , resp . m_block_ids , resp . start_height , resp . total_height , true ) ;
bool result = find_blockchain_supplement ( qblock_ids , resp . m_block_ids , & resp . m_block_weights , resp . start_height , resp . total_height , clip_pruned ) ;
if ( result )
{
cryptonote : : difficulty_type wide_cumulative_difficulty = m_db - > get_block_cumulative_difficulty ( resp . total_height - 1 ) ;
@ -2755,18 +2840,24 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
// II
if ( rv . type = = rct : : RCTTypeFull )
{
rv . p . MGs . resize ( 1 ) ;
rv . p . MGs [ 0 ] . II . resize ( tx . vin . size ( ) ) ;
for ( size_t n = 0 ; n < tx . vin . size ( ) ; + + n )
rv . p . MGs [ 0 ] . II [ n ] = rct : : ki2rct ( boost : : get < txin_to_key > ( tx . vin [ n ] ) . k_image ) ;
if ( ! tx . pruned )
{
rv . p . MGs . resize ( 1 ) ;
rv . p . MGs [ 0 ] . II . resize ( tx . vin . size ( ) ) ;
for ( size_t n = 0 ; n < tx . vin . size ( ) ; + + n )
rv . p . MGs [ 0 ] . II [ n ] = rct : : ki2rct ( boost : : get < txin_to_key > ( tx . vin [ n ] ) . k_image ) ;
}
}
else if ( rv . type = = rct : : RCTTypeSimple | | rv . type = = rct : : RCTTypeBulletproof | | rv . type = = rct : : RCTTypeBulletproof2 )
{
CHECK_AND_ASSERT_MES ( rv . p . MGs . size ( ) = = tx . vin . size ( ) , false , " Bad MGs size " ) ;
for ( size_t n = 0 ; n < tx . vin . size ( ) ; + + n )
if ( ! tx . pruned )
{
rv . p . MGs [ n ] . II . resize ( 1 ) ;
rv . p . MGs [ n ] . II [ 0 ] = rct : : ki2rct ( boost : : get < txin_to_key > ( tx . vin [ n ] ) . k_image ) ;
CHECK_AND_ASSERT_MES ( rv . p . MGs . size ( ) = = tx . vin . size ( ) , false , " Bad MGs size " ) ;
for ( size_t n = 0 ; n < tx . vin . size ( ) ; + + n )
{
rv . p . MGs [ n ] . II . resize ( 1 ) ;
rv . p . MGs [ n ] . II [ 0 ] = rct : : ki2rct ( boost : : get < txin_to_key > ( tx . vin [ n ] ) . k_image ) ;
}
}
}
else
@ -2792,6 +2883,10 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
if ( pmax_used_block_height )
* pmax_used_block_height = 0 ;
// pruned txes are skipped, as they're only allowed in sync-pruned-blocks mode, which is within the builtin hashes
if ( tx . pruned )
return true ;
crypto : : hash tx_prefix_hash = get_transaction_prefix_hash ( tx ) ;
const uint8_t hf_version = m_hardfork - > get_current_version ( ) ;
@ -3520,9 +3615,9 @@ bool Blockchain::flush_txes_from_pool(const std::vector<crypto::hash> &txids)
cryptonote : : blobdata txblob ;
size_t tx_weight ;
uint64_t fee ;
bool relayed , do_not_relay , double_spend_seen ;
bool relayed , do_not_relay , double_spend_seen , pruned ;
MINFO ( " Removing txid " < < txid < < " from the pool " ) ;
if ( m_tx_pool . have_tx ( txid ) & & ! m_tx_pool . take_tx ( txid , tx , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen ))
if ( m_tx_pool . have_tx ( txid ) & & ! m_tx_pool . take_tx ( txid , tx , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen , pruned ))
{
MERROR ( " Failed to remove txid " < < txid < < " from the pool " ) ;
res = false ;
@ -3621,7 +3716,7 @@ leave:
# if defined(PER_BLOCK_CHECKPOINT)
if ( blockchain_height < m_blocks_hash_check . size ( ) )
{
const auto & expected_hash = m_blocks_hash_check [ blockchain_height ] ;
const auto & expected_hash = m_blocks_hash_check [ blockchain_height ] .first ;
if ( expected_hash ! = crypto : : null_hash )
{
if ( memcmp ( & id , & expected_hash , sizeof ( hash ) ) ! = 0 )
@ -3695,6 +3790,7 @@ leave:
uint64_t t_exists = 0 ;
uint64_t t_pool = 0 ;
uint64_t t_dblspnd = 0 ;
uint64_t n_pruned = 0 ;
TIME_MEASURE_FINISH ( t3 ) ;
// XXX old code adds miner tx here
@ -3710,7 +3806,7 @@ leave:
blobdata txblob ;
size_t tx_weight = 0 ;
uint64_t fee = 0 ;
bool relayed = false , do_not_relay = false , double_spend_seen = false ;
bool relayed = false , do_not_relay = false , double_spend_seen = false , pruned = false ;
TIME_MEASURE_START ( aa ) ;
// XXX old code does not check whether tx exists
@ -3727,13 +3823,15 @@ leave:
TIME_MEASURE_START ( bb ) ;
// get transaction with hash <tx_id> from tx_pool
if ( ! m_tx_pool . take_tx ( tx_id , tx_tmp , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen ))
if ( ! m_tx_pool . take_tx ( tx_id , tx_tmp , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen , pruned ))
{
MERROR_VER ( " Block with id: " < < id < < " has at least one unknown transaction with id: " < < tx_id ) ;
bvc . m_verifivation_failed = true ;
return_tx_to_pool ( txs ) ;
goto leave ;
}
if ( pruned )
+ + n_pruned ;
TIME_MEASURE_FINISH ( bb ) ;
t_pool + = bb ;
@ -3804,6 +3902,17 @@ leave:
cumulative_block_weight + = tx_weight ;
}
// if we were syncing pruned blocks
if ( n_pruned > 0 )
{
if ( blockchain_height > = m_blocks_hash_check . size ( ) | | m_blocks_hash_check [ blockchain_height ] . second = = 0 )
{
MERROR ( " Block at " < < blockchain_height < < " is pruned, but we do not have a weight for it " ) ;
goto leave ;
}
cumulative_block_weight = m_blocks_hash_check [ blockchain_height ] . second ;
}
m_blocks_txs_check . clear ( ) ;
TIME_MEASURE_START ( vmt ) ;
@ -4244,11 +4353,13 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uin
}
}
uint64_t Blockchain : : prevalidate_block_hashes ( uint64_t height , const std : : vector < crypto : : hash > & hashes )
uint64_t Blockchain : : prevalidate_block_hashes ( uint64_t height , const std : : vector < crypto : : hash > & hashes , const std : : vector < uint64_t > & weights )
{
// new: . . . . . X X X X X . . . . . .
// pre: A A A A B B B B C C C C D D D D
CHECK_AND_ASSERT_MES ( weights . empty ( ) | | weights . size ( ) = = hashes . size ( ) , 0 , " Unexpected weights size " ) ;
// easy case: height >= hashes
if ( height > = m_blocks_hash_of_hashes . size ( ) * HASH_OF_HASHES_STEP )
return hashes . size ( ) ;
@ -4267,8 +4378,11 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
return hashes . size ( ) ;
// build hashes vector to hash hashes together
std : : vector < crypto : : hash > data ;
data . reserve ( hashes . size ( ) + HASH_OF_HASHES_STEP - 1 ) ; // may be a bit too much
std : : vector < crypto : : hash > data_hashes ;
std : : vector < uint64_t > data_weights ;
data_hashes . reserve ( hashes . size ( ) + HASH_OF_HASHES_STEP - 1 ) ; // may be a bit too much
if ( ! weights . empty ( ) )
data_weights . reserve ( data_hashes . size ( ) ) ;
// we expect height to be either equal or a bit below db height
bool disconnected = ( height > m_db - > height ( ) ) ;
@ -4283,18 +4397,24 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
// we might need some already in the chain for the first part of the first hash
for ( uint64_t h = first_index * HASH_OF_HASHES_STEP ; h < height ; + + h )
{
data . push_back ( m_db - > get_block_hash_from_height ( h ) ) ;
data_hashes . push_back ( m_db - > get_block_hash_from_height ( h ) ) ;
if ( ! weights . empty ( ) )
data_weights . push_back ( m_db - > get_block_weight ( h ) ) ;
}
pop = 0 ;
}
// push the data to check
for ( const auto & h : hashes )
for ( size_t i = 0 ; i < hashes . size ( ) ; + + i )
{
if ( pop )
- - pop ;
else
data . push_back ( h ) ;
{
data_hashes . push_back ( hashes [ i ] ) ;
if ( ! weights . empty ( ) )
data_weights . push_back ( weights [ i ] ) ;
}
}
// hash and check
@ -4304,12 +4424,17 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
if ( n < m_blocks_hash_of_hashes . size ( ) )
{
// if the last index isn't fully filled, we can't tell if valid
if ( data . size ( ) < ( n - first_index ) * HASH_OF_HASHES_STEP + HASH_OF_HASHES_STEP )
if ( data _hashes . size ( ) < ( n - first_index ) * HASH_OF_HASHES_STEP + HASH_OF_HASHES_STEP )
break ;
crypto : : hash hash ;
cn_fast_hash ( data . data ( ) + ( n - first_index ) * HASH_OF_HASHES_STEP , HASH_OF_HASHES_STEP * sizeof ( crypto : : hash ) , hash ) ;
bool valid = hash = = m_blocks_hash_of_hashes [ n ] ;
cn_fast_hash ( data_hashes . data ( ) + ( n - first_index ) * HASH_OF_HASHES_STEP , HASH_OF_HASHES_STEP * sizeof ( crypto : : hash ) , hash ) ;
bool valid = hash = = m_blocks_hash_of_hashes [ n ] . first ;
if ( valid & & ! weights . empty ( ) )
{
cn_fast_hash ( data_weights . data ( ) + ( n - first_index ) * HASH_OF_HASHES_STEP , HASH_OF_HASHES_STEP * sizeof ( uint64_t ) , hash ) ;
valid & = hash = = m_blocks_hash_of_hashes [ n ] . second ;
}
// add to the known hashes array
if ( ! valid )
@ -4321,9 +4446,15 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
size_t end = n * HASH_OF_HASHES_STEP + HASH_OF_HASHES_STEP ;
for ( size_t i = n * HASH_OF_HASHES_STEP ; i < end ; + + i )
{
CHECK_AND_ASSERT_MES ( m_blocks_hash_check [ i ] = = crypto : : null_hash | | m_blocks_hash_check [ i ] = = data [ i - first_index * HASH_OF_HASHES_STEP ] ,
CHECK_AND_ASSERT_MES ( m_blocks_hash_check [ i ] . first = = crypto : : null_hash | | m_blocks_hash_check [ i ] . first = = data _hashes [ i - first_index * HASH_OF_HASHES_STEP ] ,
0 , " Consistency failure in m_blocks_hash_check construction " ) ;
m_blocks_hash_check [ i ] = data [ i - first_index * HASH_OF_HASHES_STEP ] ;
m_blocks_hash_check [ i ] . first = data_hashes [ i - first_index * HASH_OF_HASHES_STEP ] ;
if ( ! weights . empty ( ) )
{
CHECK_AND_ASSERT_MES ( m_blocks_hash_check [ i ] . second = = 0 | | m_blocks_hash_check [ i ] . second = = data_weights [ i - first_index * HASH_OF_HASHES_STEP ] ,
0 , " Consistency failure in m_blocks_hash_check construction " ) ;
m_blocks_hash_check [ i ] . second = data_weights [ i - first_index * HASH_OF_HASHES_STEP ] ;
}
}
usable + = HASH_OF_HASHES_STEP ;
}
@ -4340,6 +4471,18 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector
return usable ;
}
bool Blockchain : : has_block_weights ( uint64_t height , uint64_t nblocks ) const
{
CHECK_AND_ASSERT_MES ( nblocks > 0 , false , " nblocks is 0 " ) ;
uint64_t last_block_height = height + nblocks - 1 ;
if ( last_block_height > = m_blocks_hash_check . size ( ) )
return false ;
for ( uint64_t h = height ; h < = last_block_height ; + + h )
if ( m_blocks_hash_check [ h ] . second = = 0 )
return false ;
return true ;
}
//------------------------------------------------------------------
// ND: Speedups:
// 1. Thread long_hash computations if possible (m_max_prepare_blocks_threads = nthreads, default = 4)
@ -4381,7 +4524,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
bytes + = entry . block . size ( ) ;
for ( const auto & tx_blob : entry . txs )
{
bytes + = tx_blob . size( ) ;
bytes + = tx_blob . blob. size( ) ;
}
total_txs + = entry . txs . size ( ) ;
}
@ -4541,7 +4684,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
crypto : : hash & tx_prefix_hash = txes [ tx_index ] . second ;
+ + tx_index ;
if ( ! parse_and_validate_tx_base_from_blob ( tx_blob , tx ) )
if ( ! parse_and_validate_tx_base_from_blob ( tx_blob .blob , tx ) )
SCAN_TABLE_QUIT ( " Could not parse tx from incoming blocks. " ) ;
cryptonote : : get_transaction_prefix_hash ( tx , tx_prefix_hash ) ;
@ -4840,7 +4983,7 @@ void Blockchain::cancel()
}
# if defined(PER_BLOCK_CHECKPOINT)
static const char expected_block_hashes_hash [ ] = " 7dafb40b414a0e59bfced6682ef519f0b416bc914dd3d622b72e0dd1a47117c2 " ;
static const char expected_block_hashes_hash [ ] = " 95e60612c1a16f4cd992c335b66daabd98e2d351c2b02b66e43ced0296848d33 " ;
void Blockchain : : load_compiled_in_block_hashes ( const GetCheckpointsCallback & get_checkpoints )
{
if ( get_checkpoints = = nullptr | | ! m_fast_sync )
@ -4884,19 +5027,21 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get
MERROR ( " Block hash data is too large " ) ;
return ;
}
const size_t size_needed = 4 + nblocks * sizeof ( crypto : : hash ) ;
const size_t size_needed = 4 + nblocks * ( sizeof ( crypto : : hash ) * 2 ) ;
if ( nblocks > 0 & & nblocks > ( m_db - > height ( ) + HASH_OF_HASHES_STEP - 1 ) / HASH_OF_HASHES_STEP & & checkpoints . size ( ) > = size_needed )
{
p + = sizeof ( uint32_t ) ;
m_blocks_hash_of_hashes . reserve ( nblocks ) ;
for ( uint32_t i = 0 ; i < nblocks ; i + + )
{
crypto : : hash hash ;
memcpy ( hash . data , p , sizeof ( hash . data ) ) ;
p + = sizeof ( hash . data ) ;
m_blocks_hash_of_hashes . push_back ( hash ) ;
crypto : : hash hash_hashes , hash_weights ;
memcpy ( hash_hashes . data , p , sizeof ( hash_hashes . data ) ) ;
p + = sizeof ( hash_hashes . data ) ;
memcpy ( hash_weights . data , p , sizeof ( hash_weights . data ) ) ;
p + = sizeof ( hash_weights . data ) ;
m_blocks_hash_of_hashes . push_back ( std : : make_pair ( hash_hashes , hash_weights ) ) ;
}
m_blocks_hash_check . resize ( m_blocks_hash_of_hashes . size ( ) * HASH_OF_HASHES_STEP , crypto : : null_hash ) ;
m_blocks_hash_check . resize ( m_blocks_hash_of_hashes . size ( ) * HASH_OF_HASHES_STEP , std: : make_pair ( crypto: : null_hash , 0 ) ) ;
MINFO ( nblocks < < " block hashes loaded " ) ;
// FIXME: clear tx_pool because the process might have been
@ -4911,13 +5056,13 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get
size_t tx_weight ;
uint64_t fee ;
bool relayed , do_not_relay , double_spend_seen ;
bool relayed , do_not_relay , double_spend_seen , pruned ;
transaction pool_tx ;
blobdata txblob ;
for ( const transaction & tx : txs )
{
crypto : : hash tx_hash = get_transaction_hash ( tx ) ;
m_tx_pool . take_tx ( tx_hash , pool_tx , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen );
m_tx_pool . take_tx ( tx_hash , pool_tx , txblob , tx_weight , fee , relayed , do_not_relay , double_spend_seen , pruned );
}
}
}
@ -4990,6 +5135,5 @@ void Blockchain::cache_block_template(const block &b, const cryptonote::account_
namespace cryptonote {
template bool Blockchain : : get_transactions ( const std : : vector < crypto : : hash > & , std : : vector < transaction > & , std : : vector < crypto : : hash > & ) const ;
template bool Blockchain : : get_transactions_blobs ( const std : : vector < crypto : : hash > & , std : : vector < cryptonote : : blobdata > & , std : : vector < crypto : : hash > & , bool ) const ;
template bool Blockchain : : get_split_transactions_blobs ( const std : : vector < crypto : : hash > & , std : : vector < std : : tuple < crypto : : hash , cryptonote : : blobdata , crypto : : hash , cryptonote : : blobdata > > & , std : : vector < crypto : : hash > & ) const ;
}