Skip to content

Commit

Permalink
Add -trustlocalclock option to trust local clock source
Browse files Browse the repository at this point in the history
If set then the local clock is taken as authorative. If false then old
logics of adjusting time with median of first 199 seen nodes are preserved.

This also changes logics on time notification somewhat, alerting if median
network time and local time drifts apart more than 15 minutes. The warning
is also repeated in the log on each new connection while the error persists.
The UI popup is still only shown once.

This addresses some concerns raised in issue bitcoin#4521
  • Loading branch information
Henrik Nordström committed Jul 29, 2015
1 parent 1dac192 commit 1f4d197
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 43 deletions.
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"));
#endif
strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0));
strUsage += HelpMessageOpt("-trustlocalclock", strprintf(_("Trust local clock source, for example if configured by NTP or the like (default: %u)"), 0));

strUsage += HelpMessageGroup(_("Connection options:"));
strUsage += HelpMessageOpt("-addnode=<ip>", _("Add a node to connect to and attempt to keep the connection open"));
Expand Down
73 changes: 30 additions & 43 deletions src/timedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,53 +63,40 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
vTimeOffsets.input(nOffsetSample);
LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);

// 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.
//
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
if (vTimeOffsets.size() >= 5) {
int64_t nMedian = vTimeOffsets.median();
std::vector<int64_t> vSorted = vTimeOffsets.sorted();
// Only let other nodes change our time by so much
if (abs64(nMedian) < 70 * 60)
{
nTimeOffset = nMedian;
}
else
{
// Only let other nodes change our time by so much, and only if local clock no trusted
if (abs64(nMedian) < 70 * 60 && !GetBoolArg("-trustlocalclock", false)) {
// Preserve old "bug" of only adjusting network time on data from first 199 nodes
// as this may explain why we've never seen attacks which manipulate the clock
// offset. (see issue #4521).
// Note: This limits network time adjustments to detect static clock offset
// errors at startup, and do not compensate for runtime clock drift.
if (vTimeOffsets.size() < medianRange)
nTimeOffset = nMedian;
} else {
nTimeOffset = 0;
}

static bool fDone;
if (!fDone)
{
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false;
BOOST_FOREACH(int64_t nOffset, vSorted)
if (nOffset != 0 && abs64(nOffset) < 5 * 60)
fMatch = true;
// If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false;
std::vector<int64_t> vSorted = vTimeOffsets.sorted();
BOOST_FOREACH(int64_t nOffset, vSorted)
if (nOffset != 0 && abs64(nOffset) < 5 * 60)
fMatch = true;

// If median time too far off, give a warning
if (abs64(nMedian) > 15 * 60)
fMatch = false;

if (!fMatch)
{
fDone = true;
string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly.");
strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
}
if (!fMatch) {
string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly.");
strMiscWarning = strMessage;
LogPrintf("*** %s\n", strMessage);
static bool fDone;
if (!fDone) {
fDone = true;
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
}
}
if (fDebug) {
Expand Down

0 comments on commit 1f4d197

Please sign in to comment.