@ -39,31 +39,31 @@ int64_t GetAdjustedTime()
# define BITCOIN_TIMEDATA_MAX_SAMPLES 200
# define BITCOIN_TIMEDATA_MAX_SAMPLES 200
static std : : set < CNetAddr > setKnown ;
static std : : set < CNetAddr > g_sources ;
static CMedianFilter < int64_t > vTimeOffsets( BITCOIN_TIMEDATA_MAX_SAMPLES , 0 ) ;
static CMedianFilter < int64_t > g_time_offsets{ BITCOIN_TIMEDATA_MAX_SAMPLES , 0 } ;
static bool fDone ;
static bool g_warning_emitted ;
void AddTimeData ( const CNetAddr & ip , int64_t nOffsetSample )
void AddTimeData ( const CNetAddr & ip , int64_t nOffsetSample )
{
{
LOCK ( g_timeoffset_mutex ) ;
LOCK ( g_timeoffset_mutex ) ;
// Ignore duplicates
// Ignore duplicates
if ( setKnown . size ( ) = = BITCOIN_TIMEDATA_MAX_SAMPLES )
if ( g_sources . size ( ) = = BITCOIN_TIMEDATA_MAX_SAMPLES )
return ;
return ;
if ( ! setKnown . insert ( ip ) . second )
if ( ! g_sources . insert ( ip ) . second )
return ;
return ;
// Add data
// Add data
vTimeO ffsets. input ( nOffsetSample ) ;
g_time_o ffsets. input ( nOffsetSample ) ;
LogPrint ( BCLog : : NET , " added time data, samples %d, offset %+d (%+d minutes) \n " , vTimeO ffsets. size ( ) , nOffsetSample , nOffsetSample / 60 ) ;
LogPrint ( BCLog : : NET , " added time data, samples %d, offset %+d (%+d minutes) \n " , g_time_o ffsets. size ( ) , nOffsetSample , nOffsetSample / 60 ) ;
// There is a known issue here (see issue #4521):
// There is a known issue here (see issue #4521):
//
//
// - The structure vTimeO ffsets contains up to 200 elements, after which
// - The structure g_time_o ffsets contains up to 200 elements, after which
// any new element added to it will not increase its size, replacing the
// any new element added to it will not increase its size, replacing the
// oldest element.
// oldest element.
//
//
// - The condition to update nTimeOffset includes checking whether the
// - The condition to update nTimeOffset includes checking whether the
// number of elements in vTimeO ffsets is odd, which will never happen after
// number of elements in g_time_o ffsets is odd, which will never happen after
// there are 200 elements.
// there are 200 elements.
//
//
// But in this case the 'bug' is protective against some attacks, and may
// But in this case the 'bug' is protective against some attacks, and may
@ -73,9 +73,9 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
// So we should hold off on fixing this and clean it up as part of
// So we should hold off on fixing this and clean it up as part of
// a timing cleanup that strengthens it in a number of other ways.
// a timing cleanup that strengthens it in a number of other ways.
//
//
if ( vTimeO ffsets. size ( ) > = 5 & & vTimeO ffsets. size ( ) % 2 = = 1 ) {
if ( g_time_o ffsets. size ( ) > = 5 & & g_time_o ffsets. size ( ) % 2 = = 1 ) {
int64_t nMedian = vTimeO ffsets. median ( ) ;
int64_t nMedian = g_time_o ffsets. median ( ) ;
std : : vector < int64_t > vSorted = vTimeO ffsets. sorted ( ) ;
std : : vector < int64_t > vSorted = g_time_o ffsets. sorted ( ) ;
// Only let other nodes change our time by so much
// Only let other nodes change our time by so much
int64_t max_adjustment = std : : max < int64_t > ( 0 , gArgs . GetIntArg ( " -maxtimeadjustment " , DEFAULT_MAX_TIME_ADJUSTMENT ) ) ;
int64_t max_adjustment = std : : max < int64_t > ( 0 , gArgs . GetIntArg ( " -maxtimeadjustment " , DEFAULT_MAX_TIME_ADJUSTMENT ) ) ;
if ( nMedian > = - max_adjustment & & nMedian < = max_adjustment ) {
if ( nMedian > = - max_adjustment & & nMedian < = max_adjustment ) {
@ -83,7 +83,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
} else {
} else {
nTimeOffset = 0 ;
nTimeOffset = 0 ;
if ( ! fDone ) {
if ( ! g_warning_emitted ) {
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false ;
bool fMatch = false ;
for ( const int64_t nOffset : vSorted ) {
for ( const int64_t nOffset : vSorted ) {
@ -91,7 +91,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
}
}
if ( ! fMatch ) {
if ( ! fMatch ) {
fDone = true ;
g_warning_emitted = true ;
bilingual_str strMessage = strprintf ( _ ( " Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. " ) , PACKAGE_NAME ) ;
bilingual_str strMessage = strprintf ( _ ( " Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly. " ) , PACKAGE_NAME ) ;
SetMiscWarning ( strMessage ) ;
SetMiscWarning ( strMessage ) ;
uiInterface . ThreadSafeMessageBox ( strMessage , " " , CClientUIInterface : : MSG_WARNING ) ;
uiInterface . ThreadSafeMessageBox ( strMessage , " " , CClientUIInterface : : MSG_WARNING ) ;
@ -114,7 +114,7 @@ void TestOnlyResetTimeData()
{
{
LOCK ( g_timeoffset_mutex ) ;
LOCK ( g_timeoffset_mutex ) ;
nTimeOffset = 0 ;
nTimeOffset = 0 ;
setKnown . clear ( ) ;
g_sources . clear ( ) ;
vTimeOffsets = CMedianFilter < int64_t > ( BITCOIN_TIMEDATA_MAX_SAMPLES , 0 ) ;
g_time_offsets = CMedianFilter < int64_t > { BITCOIN_TIMEDATA_MAX_SAMPLES , 0 } ;
fDone = false ;
g_warning_emitted = false ;
}
}