Skip to content

Commit 3bf1a2c

Browse files
committed
Add handshake handling of peer timestamp deviation.
1 parent d84157a commit 3bf1a2c

File tree

6 files changed

+42
-1
lines changed

6 files changed

+42
-1
lines changed

include/bitcoin/network/error.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ enum error_t : uint8_t
7575
peer_disconnect,
7676
peer_unsupported,
7777
peer_insufficient,
78+
peer_timestamp,
7879
protocol_violation,
7980
channel_overflow,
8081
channel_underflow,

include/bitcoin/network/protocols/protocol_version_31402.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ class BCT_API protocol_version_31402
7878
const uint64_t invalid_services_;
7979

8080
private:
81+
static bool is_disallowed_deviation(uint64_t timestamp) NOEXCEPT;
82+
8183
// These are protected by strand.
8284
bool sent_version_{};
8385
bool received_version_{};

src/error.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error)
5151
{ peer_disconnect, "peer disconnect" },
5252
{ peer_unsupported, "peer unsupported" },
5353
{ peer_insufficient, "peer insufficient" },
54+
{ peer_timestamp, "peer timestamp" },
5455
{ protocol_violation, "protocol violation" },
5556
{ channel_overflow, "channel overflow" },
5657
{ channel_underflow, "channel underflow" },

src/protocols/protocol_version_31402.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ using namespace system;
4040
using namespace messages;
4141
using namespace std::placeholders;
4242

43+
// Drop peer it its clock deviates more than 2 hours from own clock.
44+
constexpr auto allowed_timestamp_deviation = hours{ 2 };
45+
4346
// Require the configured minimum protocol and services by default.
4447
protocol_version_31402::protocol_version_31402(const session::ptr& session,
4548
const channel::ptr& channel) NOEXCEPT
@@ -273,6 +276,16 @@ bool protocol_version_31402::handle_receive_acknowledge(const code& ec,
273276
// Incoming [receive_version => send_acknowledge].
274277
// ----------------------------------------------------------------------------
275278

279+
// private
280+
bool protocol_version_31402::is_disallowed_deviation(
281+
uint64_t timestamp) NOEXCEPT
282+
{
283+
const auto now = wall_clock::now();
284+
const auto time = wall_clock::from_time_t(timestamp);
285+
return time < (now - allowed_timestamp_deviation)
286+
|| time > (now + allowed_timestamp_deviation);
287+
}
288+
276289
bool protocol_version_31402::handle_receive_version(const code& ec,
277290
const version::cptr& message) NOEXCEPT
278291
{
@@ -320,6 +333,15 @@ bool protocol_version_31402::handle_receive_version(const code& ec,
320333
return false;
321334
}
322335

336+
if (is_disallowed_deviation(message->timestamp))
337+
{
338+
LOGP("Timestamp out of range (" << message->value << ") "
339+
"for [" << authority() << "].");
340+
341+
rejection(error::peer_timestamp);
342+
return false;
343+
}
344+
323345
const auto version = std::min(message->value, maximum_version_);
324346
set_negotiated_version(version);
325347
set_peer_version(message);

src/protocols/protocol_version_70002.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,20 @@ void protocol_version_70002::rejection(const code& ec) NOEXCEPT
8484
}
8585
else if (ec == error::peer_unsupported)
8686
{
87-
SEND((reject{ version::command, reject::reason_code::nonstandard }),
87+
SEND((reject{ version::command, reject::reason_code::undefined,
88+
"services" }),
8889
handle_send, _1);
8990
}
9091
else if (ec == error::protocol_violation)
9192
{
9293
SEND((reject{ version::command, reject::reason_code::duplicate }),
9394
handle_send, _1);
9495
}
96+
else if (ec == error::peer_timestamp)
97+
{
98+
SEND((reject{ version::command, reject::reason_code::undefined,
99+
"timestamp" }), handle_send, _1);
100+
}
95101

96102
return protocol_version_70001::rejection(ec);
97103
}

test/error.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ BOOST_AUTO_TEST_CASE(error_t__code__peer_insufficient__true_exected_message)
182182
BOOST_REQUIRE_EQUAL(ec.message(), "peer insufficient");
183183
}
184184

185+
BOOST_AUTO_TEST_CASE(error_t__code__peer_timestamp__true_exected_message)
186+
{
187+
constexpr auto value = error::peer_timestamp;
188+
const auto ec = code(value);
189+
BOOST_REQUIRE(ec);
190+
BOOST_REQUIRE(ec == value);
191+
BOOST_REQUIRE_EQUAL(ec.message(), "peer timestamp");
192+
}
193+
185194
BOOST_AUTO_TEST_CASE(error_t__code__protocol_violation__true_exected_message)
186195
{
187196
constexpr auto value = error::protocol_violation;

0 commit comments

Comments
 (0)