Skip to content

Commit

Permalink
[p2p]: BIP324 transport version placeholder messages
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruv committed Feb 15, 2022
1 parent f92d0eb commit b8be16d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 21 deletions.
45 changes: 30 additions & 15 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -942,14 +942,26 @@ CNetMessage V2TransportDeserializer::GetMessage(const std::chrono::microseconds
msg.m_time = time;

Reset();

// The first message we receive is the BIP324 transport version placeholder message.
// Discard it for v2.0 clients.
if (!m_processed_version_placeholder) {
reject_message = true;
m_processed_version_placeholder = true;
}
return msg;
}

bool V2TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header)
{
size_t serialized_command_size = 1; // short-IDs are 1 byte
std::optional<uint8_t> cmd_short_id = GetShortIDFromMessageType(msg.m_type);
if (!cmd_short_id) {

if (msg.m_type.empty() && msg.data.size() == 0) {
// This condition is only true for the transport version placeholder message.
// We don't need to serialize the command in this case.
serialized_command_size = 0;
} else if (!cmd_short_id) {
// message command without an assigned short-ID
assert(msg.m_type.size() <= NET_P2P_V2_CMD_MAX_CHARS_SIZE);
// encode as varstr, max 12 chars
Expand All @@ -960,7 +972,7 @@ bool V2TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vec
uint32_t packet_length = serialized_command_size + msg.data.size();

// prepare the packet length & message command and reserve 4 bytes (3bytes AAD + 1byte short-ID)
std::vector<unsigned char> serialized_header(CHACHA20_POLY1305_AEAD_AAD_LEN + 1);
std::vector<unsigned char> serialized_header(CHACHA20_POLY1305_AEAD_AAD_LEN + serialized_command_size);
// LE serialize the 24bits length
// we do "manually" encode this since there is no helper for 24bit serialization
packet_length = htole32(packet_length);
Expand All @@ -971,7 +983,7 @@ bool V2TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vec
if (cmd_short_id) {
// append the single byte short ID...
vector_writer << cmd_short_id.value();
} else {
} else if (!msg.m_type.empty()) {
// or the ASCII command string
vector_writer << msg.m_type;
}
Expand Down Expand Up @@ -1805,20 +1817,19 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
{
// typical socket buffer is 8K-64K
uint8_t pchBuf[0x10000];
int nBytes = 0;
size_t nBytes = 0;
{
LOCK(pnode->m_sock_mutex);
if (!pnode->m_sock) {
continue;
}
nBytes = pnode->m_sock->Recv(pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
}
if (nBytes > 0)
{
if (nBytes > 0) {
bool notify = false;
if (!pnode->m_deserializer ||
!pnode->ReceiveMsgBytes({pchBuf, (size_t)nBytes}, notify)) {
if (!pnode->tried_v2_handshake && nBytes == ELLSQ_ENCODED_SIZE) {
if (!pnode->tried_v2_handshake && nBytes >= ELLSQ_ENCODED_SIZE) {
pnode->EnsureInitV2Key(!pnode->IsInboundConn());
EllSqPubKey peer_ellsq;
std::copy(pchBuf, pchBuf + ELLSQ_ENCODED_SIZE, peer_ellsq.data());
Expand All @@ -1828,20 +1839,27 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,

if (pnode->IsInboundConn()) {
// We are the responder
initiator_hdata = Span(pchBuf, nBytes);
initiator_hdata = Span(pchBuf, ELLSQ_ENCODED_SIZE);
responder_hdata = pnode->hdata_ellsq_pubkey;
} else {
initiator_hdata = pnode->hdata_ellsq_pubkey;
responder_hdata = Span(pchBuf, nBytes);
responder_hdata = Span(pchBuf, ELLSQ_ENCODED_SIZE);
}

pnode->InitV2P2P(v2_peer_pubkey, initiator_hdata, responder_hdata, !pnode->IsInboundConn());
if (pnode->IsInboundConn()) {
PushV2EllSqPubkey(pnode);
}

// Send empty message for transport version placeholder
CSerializedNetMsg msg;
PushMessage(pnode, std::move(msg));

pnode->tried_v2_handshake = true;
m_msgproc->InitializeNode(pnode);
if (nBytes > ELLSQ_ENCODED_SIZE && !pnode->ReceiveMsgBytes({pchBuf + ELLSQ_ENCODED_SIZE, (size_t)(nBytes - ELLSQ_ENCODED_SIZE)}, notify)) {
pnode->CloseSocketDisconnect();
}
} else {
pnode->CloseSocketDisconnect();
}
Expand All @@ -1863,17 +1881,13 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
}
WakeMessageHandler();
}
}
else if (nBytes == 0)
{
} else if (nBytes == 0) {
// socket closed gracefully
if (!pnode->fDisconnect) {
LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
}
pnode->CloseSocketDisconnect();
}
else if (nBytes < 0)
{
} else if (nBytes < 0) {
// error
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
Expand Down Expand Up @@ -2520,6 +2534,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
if (grantOutbound)
grantOutbound->MoveTo(pnode->grantOutbound);

// Only the outbound peer knows that both sides support BIP324 transport
if (pnode->PreferV2Conn()) {
PushV2EllSqPubkey(pnode);
} else {
Expand Down
13 changes: 7 additions & 6 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,13 @@ class V2TransportDeserializer final : public TransportDeserializer
{
private:
std::unique_ptr<ChaCha20Poly1305AEAD> m_aead;
const NodeId m_node_id; // Only for logging
bool m_in_data = false; // parsing header (false) or data (true)
size_t m_message_size = 0; // expected message size
CDataStream vRecv; // received message data (encrypted length, payload ciphertext, MAC tag)
size_t m_hdr_pos = 0; // read pos in header
size_t m_data_pos = 0; // read pos in data
const NodeId m_node_id; // Only for logging
bool m_in_data = false; // parsing header (false) or data (true)
size_t m_message_size = 0; // expected message size
CDataStream vRecv; // received message data (encrypted length, payload ciphertext, MAC tag)
size_t m_hdr_pos = 0; // read pos in header
size_t m_data_pos = 0; // read pos in data
bool m_processed_version_placeholder; // BIP324 version message has been received

public:
V2TransportDeserializer(const NodeId node_id, CPrivKey& k1, CPrivKey& k2) : m_aead(new ChaCha20Poly1305AEAD(Span<unsigned char>(k1.data(), k1.size()), Span<unsigned char>(k2.data(), k2.size()))), m_node_id(node_id), vRecv(SER_NETWORK, INIT_PROTO_VERSION)
Expand Down

0 comments on commit b8be16d

Please sign in to comment.