2023-04-25 13:51:26 +02:00
// Copyright (c) 2014-2020 The Bitcoin Core developers
2014-10-31 01:43:19 +01:00
// Distributed under the MIT software license, see the accompanying
2014-06-19 15:08:37 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2016-02-04 13:41:58 +01:00
# if defined(HAVE_CONFIG_H)
2022-08-02 18:34:58 +02:00
# include <config/bitcoin-config.h>
2016-02-04 13:41:58 +01:00
# endif
2020-03-19 23:46:56 +01:00
# include <timedata.h>
2014-06-19 15:08:37 +02:00
2020-03-19 23:46:56 +01:00
# include <netaddress.h>
# include <sync.h>
# include <ui_interface.h>
2021-06-27 08:33:13 +02:00
# include <util/system.h>
2022-03-24 05:13:51 +01:00
# include <util/translation.h>
2020-03-19 23:46:56 +01:00
# include <warnings.h>
2014-06-19 15:08:37 +02:00
2020-06-08 13:03:36 +02:00
static Mutex g_timeoffset_mutex ;
static int64_t nTimeOffset GUARDED_BY ( g_timeoffset_mutex ) = 0 ;
2014-06-19 15:08:37 +02:00
2014-10-31 01:43:19 +01:00
/**
* " Never go to sea with two chronometers; take one or three. "
* Our three time sources are :
* - System clock
* - Median of other nodes clocks
* - The user ( asking the user to fix the system clock if the first two disagree )
*/
2014-06-19 15:08:37 +02:00
int64_t GetTimeOffset ( )
{
2020-06-08 13:03:36 +02:00
LOCK ( g_timeoffset_mutex ) ;
2014-06-19 15:08:37 +02:00
return nTimeOffset ;
}
int64_t GetAdjustedTime ( )
{
return GetTime ( ) + GetTimeOffset ( ) ;
}
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
static int64_t abs64 ( int64_t n )
{
return ( n > = 0 ? n : - n ) ;
}
2015-08-11 15:57:52 +02:00
# define BITCOIN_TIMEDATA_MAX_SAMPLES 200
2014-06-19 15:08:37 +02:00
2014-12-15 11:06:15 +01:00
void AddTimeData ( const CNetAddr & ip , int64_t nOffsetSample )
2014-06-19 15:08:37 +02:00
{
2020-06-08 13:03:36 +02:00
LOCK ( g_timeoffset_mutex ) ;
2014-06-19 15:08:37 +02:00
// Ignore duplicates
2017-01-30 13:13:07 +01:00
static std : : set < CNetAddr > setKnown ;
2015-08-11 15:57:52 +02:00
if ( setKnown . size ( ) = = BITCOIN_TIMEDATA_MAX_SAMPLES )
return ;
2014-06-19 15:08:37 +02:00
if ( ! setKnown . insert ( ip ) . second )
return ;
// Add data
2015-08-11 15:57:52 +02:00
static CMedianFilter < int64_t > vTimeOffsets ( BITCOIN_TIMEDATA_MAX_SAMPLES , 0 ) ;
2014-06-19 15:08:37 +02:00
vTimeOffsets . input ( nOffsetSample ) ;
2020-06-08 13:03:36 +02:00
LogPrint ( BCLog : : NET , " added time data, samples %d, offset %+d (%+d minutes) \n " , vTimeOffsets . size ( ) , nOffsetSample , nOffsetSample / 60 ) ;
2014-07-24 19:00:24 +02:00
// There is a known issue here (see issue #4521):
//
// - The structure vTimeOffsets contains up to 200 elements, after which
// any new element added to it will not increase its size, replacing the
// oldest element.
//
// - The condition to update nTimeOffset includes checking whether the
// number of elements in vTimeOffsets is odd, which will never happen after
// there are 200 elements.
//
// But in this case the 'bug' is protective against some attacks, and may
// actually explain why we've never seen attacks which manipulate the
// clock offset.
//
// 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.
//
2020-06-08 13:03:36 +02:00
if ( vTimeOffsets . size ( ) > = 5 & & vTimeOffsets . size ( ) % 2 = = 1 ) {
2014-06-19 15:08:37 +02:00
int64_t nMedian = vTimeOffsets . median ( ) ;
std : : vector < int64_t > vSorted = vTimeOffsets . sorted ( ) ;
// Only let other nodes change our time by so much
2020-06-08 13:03:36 +02:00
if ( abs64 ( nMedian ) < = std : : max < int64_t > ( 0 , gArgs . GetArg ( " -maxtimeadjustment " , DEFAULT_MAX_TIME_ADJUSTMENT ) ) ) {
2014-06-19 15:08:37 +02:00
nTimeOffset = nMedian ;
2020-06-08 13:03:36 +02:00
} else {
2014-06-19 15:08:37 +02:00
nTimeOffset = 0 ;
static bool fDone ;
2020-06-08 13:03:36 +02:00
if ( ! fDone ) {
2014-06-19 15:08:37 +02:00
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false ;
2020-06-08 13:03:36 +02:00
for ( const int64_t nOffset : vSorted ) {
if ( nOffset ! = 0 & & abs64 ( nOffset ) < 5 * 60 ) fMatch = true ;
}
2014-06-19 15:08:37 +02:00
2020-06-08 13:03:36 +02:00
if ( ! fMatch ) {
2014-06-19 15:08:37 +02:00
fDone = true ;
2020-05-08 18:17:47 +02:00
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 . translated ) ;
2014-06-19 15:08:37 +02:00
uiInterface . ThreadSafeMessageBox ( strMessage , " " , CClientUIInterface : : MSG_WARNING ) ;
}
}
}
2019-05-22 23:51:39 +02:00
if ( LogAcceptCategory ( BCLog : : NET ) ) {
2018-09-04 15:36:09 +02:00
for ( const int64_t n : vSorted ) {
2018-05-02 15:56:30 +02:00
LogPrint ( BCLog : : NET , " %+d " , n ) ; /* Continued */
2019-05-22 23:51:39 +02:00
}
2018-05-02 15:56:30 +02:00
LogPrint ( BCLog : : NET , " | " ) ; /* Continued */
2020-06-08 13:03:36 +02:00
LogPrint ( BCLog : : NET , " nTimeOffset = %+d (%+d minutes) \n " , nTimeOffset , nTimeOffset / 60 ) ;
2019-05-22 23:51:39 +02:00
}
2014-06-19 15:08:37 +02:00
}
}