Update CMakeLists.txt - play with openssl
[novacoin.git] / src / timedata.cpp
1 #include "timedata.h"
2 #include "netbase.h"
3 #include "sync.h"
4 #include "interface.h"
5
6
7 static CCriticalSection cs_nTimeOffset;
8 static uint32_t NOVACOIN_TIMEDATA_MAX_SAMPLES = 200;
9
10 // Trusted NTP offset or median of NTP samples.
11 extern int64_t nNtpOffset;
12
13 // Median of time samples given by other nodes.
14 static int64_t nNodesOffset = std::numeric_limits<int64_t>::max();
15
16 //
17 // "Never go to sea with two chronometers; take one or three."
18 // Our three time sources are:
19 //  - System clock
20 //  - Median of other nodes clocks
21 //  - The user (asking the user to fix the system clock if the first two disagree)
22 //
23
24 // Select time offset:
25 int64_t GetTimeOffset()
26 {
27     LOCK(cs_nTimeOffset);
28     // If NTP and system clock are in agreement within 40 minutes, then use NTP.
29     if (std::abs(nNtpOffset) < 40 * 60)
30         return nNtpOffset;
31
32     // If not, then choose between median peer time and system clock.
33     if (std::abs(nNodesOffset) < 70 * 60)
34         return nNodesOffset;
35
36     return 0;
37 }
38
39 int64_t GetNodesOffset()
40 {
41         return nNodesOffset;
42 }
43
44 int64_t GetAdjustedTime()
45 {
46     return GetTime() + GetTimeOffset();
47 }
48
49 void AddTimeData(const CNetAddr& ip, int64_t nTime)
50 {
51     int64_t nOffsetSample = nTime - GetTime();
52
53     LOCK(cs_nTimeOffset);
54     // Ignore duplicates
55     static std::set<CNetAddr> setKnown;
56     if (setKnown.size() == NOVACOIN_TIMEDATA_MAX_SAMPLES)
57         return;
58     if (!setKnown.insert(ip).second)
59         return;
60
61     // Add data
62     static CMedianFilter<int64_t> vTimeOffsets(NOVACOIN_TIMEDATA_MAX_SAMPLES,0);
63     vTimeOffsets.input(nOffsetSample);
64     printf("Added time data, samples %d, offset %+" PRId64 " (%+" PRId64 " minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
65     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
66     {
67         int64_t nMedian = vTimeOffsets.median();
68         std::vector<int64_t> vSorted = vTimeOffsets.sorted();
69         // Only let other nodes change our time by so much
70         if (std::abs(nMedian) < 70 * 60)
71         {
72             nNodesOffset = nMedian;
73         }
74         else
75         {
76             nNodesOffset = std::numeric_limits<int64_t>::max();
77
78             static bool fDone;
79             if (!fDone)
80             {
81                 bool fMatch = false;
82
83                 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
84                 for (int64_t nOffset : vSorted)
85                     if (nOffset != 0 && std::abs(nOffset) < 5 * 60)
86                         fMatch = true;
87
88                 if (!fMatch)
89                 {
90                     fDone = true;
91                     std::string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong NovaCoin will not work properly.");
92                     strMiscWarning = strMessage;
93                     printf("*** %s\n", strMessage.c_str());
94                     uiInterface.ThreadSafeMessageBox(strMessage+" ", std::string("NovaCoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION);
95                 }
96             }
97         }
98         if (fDebug) {
99             for (int64_t n : vSorted)
100                 printf("%+" PRId64 "  ", n);
101             printf("|  ");
102         }
103         if (nNodesOffset != std::numeric_limits<int64_t>::max())
104             printf("nNodesOffset = %+" PRId64 "  (%+" PRId64 " minutes)\n", nNodesOffset, nNodesOffset/60);
105     }
106 }