partial bitcoin#20196: fix GetListenPort() to derive the proper port

excludes:
- 0cfc0cd32239d3c08d2121e028b297022450b320
- 7d64ea4a01920bb55bc6de0de6766712ec792a11
This commit is contained in:
Kittywhiskers Van Gogh 2021-01-18 14:27:00 +01:00
parent 7f7200986b
commit 24205d94fe
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
6 changed files with 55 additions and 18 deletions

View File

@ -4268,7 +4268,11 @@ void CConnman::UnregisterEvents(CNode *pnode)
} }
#endif #endif
} }
void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Span<const unsigned char>& data, bool is_incoming)
void CaptureMessageToFile(const CAddress& addr,
const std::string& msg_type,
Span<const unsigned char> data,
bool is_incoming)
{ {
// Note: This function captures the message at the time of processing, // Note: This function captures the message at the time of processing,
// not at socket receive/send time. // not at socket receive/send time.
@ -4295,3 +4299,9 @@ void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Spa
ser_writedata32(f, size); ser_writedata32(f, size);
f.write(AsBytes(data)); f.write(AsBytes(data));
} }
std::function<void(const CAddress& addr,
const std::string& msg_type,
Span<const unsigned char> data,
bool is_incoming)>
CaptureMessage = CaptureMessageToFile;

View File

@ -36,6 +36,7 @@
#include <condition_variable> #include <condition_variable>
#include <cstdint> #include <cstdint>
#include <deque> #include <deque>
#include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
#include <thread> #include <thread>
@ -1528,7 +1529,17 @@ private:
std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval); std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval);
/** Dump binary message to file, with timestamp */ /** Dump binary message to file, with timestamp */
void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Span<const unsigned char>& data, bool is_incoming); void CaptureMessageToFile(const CAddress& addr,
const std::string& msg_type,
Span<const unsigned char> data,
bool is_incoming);
/** Defaults to `CaptureMessageToFile()`, but can be overridden by unit tests. */
extern std::function<void(const CAddress& addr,
const std::string& msg_type,
Span<const unsigned char> data,
bool is_incoming)>
CaptureMessage;
struct NodeEvictionCandidate struct NodeEvictionCandidate
{ {

View File

@ -96,9 +96,10 @@ BOOST_AUTO_TEST_CASE(addtimedata)
// not to fix this because it prevents possible attacks. See the comment in AddTimeData() or issue #4521 // not to fix this because it prevents possible attacks. See the comment in AddTimeData() or issue #4521
// for a more detailed explanation. // for a more detailed explanation.
MultiAddTimeData(2, 100); // filter median is 100 now, but nTimeOffset will not change MultiAddTimeData(2, 100); // filter median is 100 now, but nTimeOffset will not change
// We want this test to end with nTimeOffset==0, otherwise subsequent tests of the suite will fail.
BOOST_CHECK_EQUAL(GetTimeOffset(), 0); BOOST_CHECK_EQUAL(GetTimeOffset(), 0);
// We want this test to end with nTimeOffset==0, otherwise subsequent tests of the suite will fail. TestOnlyResetTimeData();
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -39,29 +39,31 @@ int64_t GetAdjustedTime()
#define BITCOIN_TIMEDATA_MAX_SAMPLES 200 #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
static std::set<CNetAddr> g_sources;
static CMedianFilter<int64_t> g_time_offsets{BITCOIN_TIMEDATA_MAX_SAMPLES, 0};
static bool g_warning_emitted;
void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
{ {
LOCK(g_timeoffset_mutex); LOCK(g_timeoffset_mutex);
// Ignore duplicates // Ignore duplicates
static std::set<CNetAddr> setKnown; if (g_sources.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
return; return;
if (!setKnown.insert(ip).second) if (!g_sources.insert(ip).second)
return; return;
// Add data // Add data
static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0); g_time_offsets.input(nOffsetSample);
vTimeOffsets.input(nOffsetSample); LogPrint(BCLog::NET, "added time data, samples %d, offset %+d (%+d minutes)\n", g_time_offsets.size(), nOffsetSample, nOffsetSample / 60);
LogPrint(BCLog::NET, "added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample / 60);
// There is a known issue here (see issue #4521): // There is a known issue here (see issue #4521):
// //
// - The structure vTimeOffsets contains up to 200 elements, after which // - The structure g_time_offsets contains up to 200 elements, after which
// any new element added to it will not increase its size, replacing the // any new element added to it will not increase its size, replacing the
// oldest element. // oldest element.
// //
// - The condition to update nTimeOffset includes checking whether the // - The condition to update nTimeOffset includes checking whether the
// number of elements in vTimeOffsets is odd, which will never happen after // number of elements in g_time_offsets is odd, which will never happen after
// there are 200 elements. // there are 200 elements.
// //
// But in this case the 'bug' is protective against some attacks, and may // But in this case the 'bug' is protective against some attacks, and may
@ -71,9 +73,9 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
// So we should hold off on fixing this and clean it up as part of // 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. // a timing cleanup that strengthens it in a number of other ways.
// //
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { if (g_time_offsets.size() >= 5 && g_time_offsets.size() % 2 == 1) {
int64_t nMedian = vTimeOffsets.median(); int64_t nMedian = g_time_offsets.median();
std::vector<int64_t> vSorted = vTimeOffsets.sorted(); std::vector<int64_t> vSorted = g_time_offsets.sorted();
// Only let other nodes change our time by so much // Only let other nodes change our time by so much
int64_t max_adjustment = std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)); int64_t max_adjustment = std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT));
if (nMedian >= -max_adjustment && nMedian <= max_adjustment) { if (nMedian >= -max_adjustment && nMedian <= max_adjustment) {
@ -81,8 +83,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
} else { } else {
nTimeOffset = 0; nTimeOffset = 0;
static bool fDone; if (!g_warning_emitted) {
if (!fDone) {
// If nobody has a time different than ours but within 5 minutes of ours, give a warning // If nobody has a time different than ours but within 5 minutes of ours, give a warning
bool fMatch = false; bool fMatch = false;
for (const int64_t nOffset : vSorted) { for (const int64_t nOffset : vSorted) {
@ -90,7 +91,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
} }
if (!fMatch) { if (!fMatch) {
fDone = true; g_warning_emitted = true;
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); 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); SetMiscWarning(strMessage);
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
@ -108,3 +109,12 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
} }
} }
} }
void TestOnlyResetTimeData()
{
LOCK(g_timeoffset_mutex);
nTimeOffset = 0;
g_sources.clear();
g_time_offsets = CMedianFilter<int64_t>{BITCOIN_TIMEDATA_MAX_SAMPLES, 0};
g_warning_emitted = false;
}

View File

@ -75,4 +75,9 @@ int64_t GetTimeOffset();
int64_t GetAdjustedTime(); int64_t GetAdjustedTime();
void AddTimeData(const CNetAddr& ip, int64_t nTime); void AddTimeData(const CNetAddr& ip, int64_t nTime);
/**
* Reset the internal state of GetTimeOffset(), GetAdjustedTime() and AddTimeData().
*/
void TestOnlyResetTimeData();
#endif // BITCOIN_TIMEDATA_H #endif // BITCOIN_TIMEDATA_H

View File

@ -20,7 +20,7 @@ LENGTH_SIZE = 4
MSGTYPE_SIZE = 12 MSGTYPE_SIZE = 12
def mini_parser(dat_file): def mini_parser(dat_file):
"""Parse a data file created by CaptureMessage. """Parse a data file created by CaptureMessageToFile.
From the data file we'll only check the structure. From the data file we'll only check the structure.