@ -1471,6 +1471,7 @@ namespace cryptonote
m_txpool_auto_relayer . do_call ( boost : : bind ( & core : : relay_txpool_transactions , this ) ) ;
m_txpool_auto_relayer . do_call ( boost : : bind ( & core : : relay_txpool_transactions , this ) ) ;
m_check_updates_interval . do_call ( boost : : bind ( & core : : check_updates , this ) ) ;
m_check_updates_interval . do_call ( boost : : bind ( & core : : check_updates , this ) ) ;
m_check_disk_space_interval . do_call ( boost : : bind ( & core : : check_disk_space , this ) ) ;
m_check_disk_space_interval . do_call ( boost : : bind ( & core : : check_disk_space , this ) ) ;
m_block_rate_interval . do_call ( boost : : bind ( & core : : check_block_rate , this ) ) ;
m_miner . on_idle ( ) ;
m_miner . on_idle ( ) ;
m_mempool . on_idle ( ) ;
m_mempool . on_idle ( ) ;
return true ;
return true ;
@ -1655,6 +1656,52 @@ namespace cryptonote
return true ;
return true ;
}
}
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
double factorial ( unsigned int n )
{
if ( n < = 1 )
return 1.0 ;
double f = n ;
while ( n - - > 1 )
f * = n ;
return f ;
}
//-----------------------------------------------------------------------------------------------
static double probability ( unsigned int blocks , unsigned int expected )
{
// https://www.umass.edu/wsp/resources/poisson/#computing
return pow ( expected , blocks ) / ( factorial ( blocks ) * exp ( expected ) ) ;
}
//-----------------------------------------------------------------------------------------------
bool core : : check_block_rate ( )
{
if ( m_offline | | m_target_blockchain_height > get_current_blockchain_height ( ) )
{
MDEBUG ( " Not checking block rate, offline or syncing " ) ;
return true ;
}
static constexpr double threshold = 1. / ( 864000 / DIFFICULTY_TARGET_V2 ) ; // one false positive every 10 days
const time_t now = time ( NULL ) ;
const std : : vector < time_t > timestamps = m_blockchain_storage . get_last_block_timestamps ( 60 ) ;
static const unsigned int seconds [ ] = { 5400 , 1800 , 600 } ;
for ( size_t n = 0 ; n < sizeof ( seconds ) / sizeof ( seconds [ 0 ] ) ; + + n )
{
unsigned int b = 0 ;
for ( time_t ts : timestamps ) b + = ts > = now - seconds [ n ] ;
const double p = probability ( b , seconds [ n ] / DIFFICULTY_TARGET_V2 ) ;
MDEBUG ( " blocks in the last " < < seconds [ n ] / 60 < < " minutes: " < < b < < " (probability " < < p < < " ) " ) ;
if ( p < threshold )
{
MWARNING ( " There were " < < b < < " blocks in the last " < < seconds [ n ] / 60 < < " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Monero network or under attack. Or it could be just sheer bad luck. " ) ;
break ; // no need to look further
}
}
return true ;
}
//-----------------------------------------------------------------------------------------------
void core : : set_target_blockchain_height ( uint64_t target_blockchain_height )
void core : : set_target_blockchain_height ( uint64_t target_blockchain_height )
{
{
m_target_blockchain_height = target_blockchain_height ;
m_target_blockchain_height = target_blockchain_height ;