]> Git Repo - VerusCoin.git/blob - src/timedata.cpp
PBaaS refund fix to fund refund transactions with gateway deposits
[VerusCoin.git] / src / timedata.cpp
1 // Copyright (c) 2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://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 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 int64_t GetTimeOffset()
28 {
29     LOCK(cs_nTimeOffset);
30     return nTimeOffset;
31 }
32
33 int64_t GetAdjustedTime()
34 {
35     return GetTime() + GetTimeOffset();
36 }
37
38 static int64_t abs64(int64_t n)
39 {
40     return (n >= 0 ? n : -n);
41 }
42
43 #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
44
45 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
46 {
47     LOCK(cs_nTimeOffset);
48     // Ignore duplicates
49     static set<CNetAddr> setKnown;
50     if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
51         return;
52     if (!setKnown.insert(ip).second)
53         return;
54
55     // Add data
56     static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
57     vTimeOffsets.input(nOffsetSample);
58     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     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
78     {
79         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         if (abs64(nMedian) < 70 * 60)
83         {
84             nTimeOffset = nMedian;
85         }
86         else
87         {
88             nTimeOffset = 0;
89
90             static bool fDone;
91             if (!fDone)
92             {
93                 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
94                 bool fMatch = false;
95                 BOOST_FOREACH(int64_t nOffset, vSorted)
96                     if (nOffset != 0 && abs64(nOffset) < 5 * 60)
97                         fMatch = true;
98
99                 if (!fMatch)
100                 {
101                     fDone = true;
102                     string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Zcash will not work properly.");
103                     strMiscWarning = strMessage;
104                     LogPrintf("*** %s\n", strMessage);
105                     uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
106                 }
107             }
108         }
109         if (fDebug) {
110             BOOST_FOREACH(int64_t n, vSorted)
111                 LogPrintf("%+d  ", n);
112             LogPrintf("|  ");
113         }
114         LogPrintf("nTimeOffset = %+d  (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
115     }
116 }
This page took 0.030095 seconds and 4 git commands to generate.