LCOV - code coverage report
Current view: top level - src - timedata.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 16 34 47.1 %
Date: 2015-10-12 22:39:14 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2014 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "timedata.h"
       6             : 
       7             : #include "netbase.h"
       8             : #include "sync.h"
       9             : #include "ui_interface.h"
      10             : #include "util.h"
      11             : #include "utilstrencodings.h"
      12             : 
      13             : #include <boost/foreach.hpp>
      14             : 
      15             : using namespace std;
      16             : 
      17          96 : static CCriticalSection cs_nTimeOffset;
      18             : static int64_t nTimeOffset = 0;
      19             : 
      20             : /**
      21             :  * "Never go to sea with two chronometers; take one or three."
      22             :  * Our three time sources are:
      23             :  *  - System clock
      24             :  *  - Median of other nodes clocks
      25             :  *  - The user (asking the user to fix the system clock if the first two disagree)
      26             :  */
      27       99888 : int64_t GetTimeOffset()
      28             : {
      29       99888 :     LOCK(cs_nTimeOffset);
      30      199776 :     return nTimeOffset;
      31             : }
      32             : 
      33       99884 : int64_t GetAdjustedTime()
      34             : {
      35       99884 :     return GetTime() + GetTimeOffset();
      36             : }
      37             : 
      38             : static int64_t abs64(int64_t n)
      39             : {
      40           0 :     return (n >= 0 ? n : -n);
      41             : }
      42             : 
      43             : #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
      44             : 
      45         250 : void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
      46             : {
      47         250 :     LOCK(cs_nTimeOffset);
      48             :     // Ignore duplicates
      49         335 :     static set<CNetAddr> setKnown;
      50         250 :     if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
      51             :         return;
      52         250 :     if (!setKnown.insert(ip).second)
      53             :         return;
      54             : 
      55             :     // Add data
      56          85 :     static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
      57          85 :     vTimeOffsets.input(nOffsetSample);
      58         170 :     LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
      59             : 
      60             :     // There is a known issue here (see issue #4521):
      61             :     //
      62             :     // - The structure vTimeOffsets contains up to 200 elements, after which
      63             :     // any new element added to it will not increase its size, replacing the
      64             :     // oldest element.
      65             :     //
      66             :     // - The condition to update nTimeOffset includes checking whether the
      67             :     // number of elements in vTimeOffsets is odd, which will never happen after
      68             :     // there are 200 elements.
      69             :     //
      70             :     // But in this case the 'bug' is protective against some attacks, and may
      71             :     // actually explain why we've never seen attacks which manipulate the
      72             :     // clock offset.
      73             :     //
      74             :     // So we should hold off on fixing this and clean it up as part of
      75             :     // a timing cleanup that strengthens it in a number of other ways.
      76             :     //
      77          85 :     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
      78             :     {
      79           0 :         int64_t nMedian = vTimeOffsets.median();
      80             :         std::vector<int64_t> vSorted = vTimeOffsets.sorted();
      81             :         // Only let other nodes change our time by so much
      82           0 :         if (abs64(nMedian) < 70 * 60)
      83             :         {
      84           0 :             nTimeOffset = nMedian;
      85             :         }
      86             :         else
      87             :         {
      88           0 :             nTimeOffset = 0;
      89             : 
      90             :             static bool fDone;
      91           0 :             if (!fDone)
      92             :             {
      93             :                 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
      94           0 :                 bool fMatch = false;
      95           0 :                 BOOST_FOREACH(int64_t nOffset, vSorted)
      96           0 :                     if (nOffset != 0 && abs64(nOffset) < 5 * 60)
      97             :                         fMatch = true;
      98             : 
      99           0 :                 if (!fMatch)
     100             :                 {
     101           0 :                     fDone = true;
     102           0 :                     string strMessage = _("Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly.");
     103             :                     strMiscWarning = strMessage;
     104           0 :                     uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
     105             :                 }
     106             :             }
     107             :         }
     108           0 :         if (fDebug) {
     109           0 :             BOOST_FOREACH(int64_t n, vSorted)
     110           0 :                 LogPrintf("%+d  ", n);
     111           0 :             LogPrintf("|  ");
     112             :         }
     113           0 :         LogPrintf("nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
     114             :     }
     115         288 : }

Generated by: LCOV version 1.11