Skip to content

Commit bcee94d

Browse files
committed
Merge bitcoin/bitcoin#26359: p2p: Erlay support signaling follow-ups
46339d2 test, refactor: Reorder sendtxrcncl tests for better readability (Gleb Naumenko) 14263c1 p2p, refactor: Extend logs for unexpected sendtxrcncl (Gleb Naumenko) 87493e1 p2p, test, refactor: Minor code improvements (Gleb Naumenko) 00c5dec p2p: Clarify sendtxrcncl policies (Gleb Naumenko) ac6ee5b test: Expand unit and functional tests for txreconciliation (Gleb Naumenko) bc84e24 p2p, refactor: Switch to enum class for ReconciliationRegisterResult (Gleb Naumenko) a60f729 p2p: Drop roles from sendtxrcncl (Gleb Naumenko) 6772cbf tests: stabilize sendtxrcncl test (Gleb Naumenko) Pull request description: Non-trivial changes include: - Getting rid of roles in `sendtxrcncl` message (summarized in the [BIP PR](bitcoin/bips#1376)); - Disconnect the peer if it send `sendtxrcncl` although we are in `blocksonly` and notified the peer with `fRelay=0`; - Don't send `sendtxrcncl` to feeler connections. ACKs for top commit: vasild: ACK 46339d2 ariard: ACK 46339d2 mzumsande: Code Review ACK 46339d2 Tree-SHA512: b5cc6934b4670c12b7dbb3189e739ef747ee542ec56678bf4e4355bfb481b746d32363c173635685b71969b3fe4bd52b1c8ebd3ea3b35c82044bba69220f6417
2 parents 3be2106 + 46339d2 commit bcee94d

File tree

8 files changed

+169
-166
lines changed

8 files changed

+169
-166
lines changed

src/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ void SetupServerArgs(ArgsManager& argsman)
477477
argsman.AddArg("-onlynet=<net>", "Make automatic outbound connections only to network <net> (" + Join(GetNetworkNames(), ", ") + "). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
478478
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
479479
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
480+
argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
480481
// TODO: remove the sentence "Nodes not using ... incoming connections." once the changes from
481482
// https://github.com/bitcoin/bitcoin/pull/23542 have become widespread.
482483
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, signet: %u, regtest: %u) are unlikely to get incoming connections. Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
@@ -485,7 +486,6 @@ void SetupServerArgs(ArgsManager& argsman)
485486
argsman.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
486487
argsman.AddArg("-networkactive", "Enable all P2P network activity (default: 1). Can be changed by the setnetworkactive RPC command", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
487488
argsman.AddArg("-timeout=<n>", strprintf("Specify socket connection timeout in milliseconds. If an initial attempt to connect is unsuccessful after this amount of time, drop it (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
488-
argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
489489
argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
490490
argsman.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
491491
argsman.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);

src/net_processing.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,17 +3273,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32733273

32743274
if (greatest_common_version >= WTXID_RELAY_VERSION && m_txreconciliation) {
32753275
// Per BIP-330, we announce txreconciliation support if:
3276-
// - protocol version per the VERSION message supports WTXID_RELAY;
3277-
// - we intended to exchange transactions over this connection while establishing it
3278-
// and the peer indicated support for transaction relay in the VERSION message;
3276+
// - protocol version per the peer's VERSION message supports WTXID_RELAY;
3277+
// - transaction relay is supported per the peer's VERSION message (see m_relays_txs);
3278+
// - this is not a block-relay-only connection and not a feeler (see m_relays_txs);
3279+
// - this is not an addr fetch connection;
32793280
// - we are not in -blocksonly mode.
3280-
if (pfrom.m_relays_txs && !m_ignore_incoming_txs) {
3281+
if (pfrom.m_relays_txs && !pfrom.IsAddrFetchConn() && !m_ignore_incoming_txs) {
32813282
const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.GetId());
3282-
// We suggest our txreconciliation role (initiator/responder) based on
3283-
// the connection direction.
32843283
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDTXRCNCL,
3285-
!pfrom.IsInboundConn(),
3286-
pfrom.IsInboundConn(),
32873284
TXRECONCILIATION_VERSION, recon_salt));
32883285
}
32893286
}
@@ -3500,41 +3497,44 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
35003497
}
35013498

35023499
if (pfrom.fSuccessfullyConnected) {
3503-
// Disconnect peers that send a SENDTXRCNCL message after VERACK.
35043500
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl received after verack from peer=%d; disconnecting\n", pfrom.GetId());
35053501
pfrom.fDisconnect = true;
35063502
return;
35073503
}
35083504

3509-
if (!peer->GetTxRelay()) {
3510-
// Disconnect peers that send a SENDTXRCNCL message even though we indicated we don't
3511-
// support transaction relay.
3505+
// Peer must not offer us reconciliations if we specified no tx relay support in VERSION.
3506+
if (RejectIncomingTxs(pfrom)) {
35123507
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl received from peer=%d to which we indicated no tx relay; disconnecting\n", pfrom.GetId());
35133508
pfrom.fDisconnect = true;
35143509
return;
35153510
}
35163511

3517-
bool is_peer_initiator, is_peer_responder;
3512+
// Peer must not offer us reconciliations if they specified no tx relay support in VERSION.
3513+
// This flag might also be false in other cases, but the RejectIncomingTxs check above
3514+
// eliminates them, so that this flag fully represents what we are looking for.
3515+
if (!pfrom.m_relays_txs) {
3516+
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl received from peer=%d which indicated no tx relay to us; disconnecting\n", pfrom.GetId());
3517+
pfrom.fDisconnect = true;
3518+
return;
3519+
}
3520+
35183521
uint32_t peer_txreconcl_version;
35193522
uint64_t remote_salt;
3520-
vRecv >> is_peer_initiator >> is_peer_responder >> peer_txreconcl_version >> remote_salt;
3523+
vRecv >> peer_txreconcl_version >> remote_salt;
35213524

3522-
if (m_txreconciliation->IsPeerRegistered(pfrom.GetId())) {
3523-
// A peer is already registered, meaning we already received SENDTXRCNCL from them.
3525+
const ReconciliationRegisterResult result = m_txreconciliation->RegisterPeer(pfrom.GetId(), pfrom.IsInboundConn(),
3526+
peer_txreconcl_version, remote_salt);
3527+
switch (result) {
3528+
case ReconciliationRegisterResult::NOT_FOUND:
3529+
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "Ignore unexpected txreconciliation signal from peer=%d\n", pfrom.GetId());
3530+
break;
3531+
case ReconciliationRegisterResult::SUCCESS:
3532+
break;
3533+
case ReconciliationRegisterResult::ALREADY_REGISTERED:
35243534
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "txreconciliation protocol violation from peer=%d (sendtxrcncl received from already registered peer); disconnecting\n", pfrom.GetId());
35253535
pfrom.fDisconnect = true;
35263536
return;
3527-
}
3528-
3529-
const ReconciliationRegisterResult result = m_txreconciliation->RegisterPeer(pfrom.GetId(), pfrom.IsInboundConn(),
3530-
is_peer_initiator, is_peer_responder,
3531-
peer_txreconcl_version,
3532-
remote_salt);
3533-
3534-
// If it's a protocol violation, disconnect.
3535-
// If the peer was not found (but something unexpected happened) or it was registered,
3536-
// nothing to be done.
3537-
if (result == ReconciliationRegisterResult::PROTOCOL_VIOLATION) {
3537+
case ReconciliationRegisterResult::PROTOCOL_VIOLATION:
35383538
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "txreconciliation protocol violation from peer=%d; disconnecting\n", pfrom.GetId());
35393539
pfrom.fDisconnect = true;
35403540
return;

src/node/txreconciliation.cpp

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class TxReconciliationState
3939
* the following commits.
4040
*
4141
* Reconciliation protocol assumes using one role consistently: either a reconciliation
42-
* initiator (requesting sketches), or responder (sending sketches). This defines our role.
42+
* initiator (requesting sketches), or responder (sending sketches). This defines our role,
43+
* based on the direction of the p2p connection.
4344
*
4445
*/
4546
bool m_we_initiate;
@@ -81,31 +82,30 @@ class TxReconciliationTracker::Impl
8182
{
8283
AssertLockNotHeld(m_txreconciliation_mutex);
8384
LOCK(m_txreconciliation_mutex);
84-
// We do not support txreconciliation salt/version updates.
85-
assert(m_states.find(peer_id) == m_states.end());
8685

8786
LogPrintLevel(BCLog::TXRECONCILIATION, BCLog::Level::Debug, "Pre-register peer=%d\n", peer_id);
8887
const uint64_t local_salt{GetRand(UINT64_MAX)};
8988

9089
// We do this exactly once per peer (which are unique by NodeId, see GetNewNodeId) so it's
9190
// safe to assume we don't have this record yet.
92-
Assert(m_states.emplace(peer_id, local_salt).second);
91+
Assume(m_states.emplace(peer_id, local_salt).second);
9392
return local_salt;
9493
}
9594

96-
ReconciliationRegisterResult RegisterPeer(NodeId peer_id, bool is_peer_inbound, bool is_peer_recon_initiator,
97-
bool is_peer_recon_responder, uint32_t peer_recon_version,
98-
uint64_t remote_salt) EXCLUSIVE_LOCKS_REQUIRED(!m_txreconciliation_mutex)
95+
ReconciliationRegisterResult RegisterPeer(NodeId peer_id, bool is_peer_inbound, uint32_t peer_recon_version,
96+
uint64_t remote_salt) EXCLUSIVE_LOCKS_REQUIRED(!m_txreconciliation_mutex)
9997
{
10098
AssertLockNotHeld(m_txreconciliation_mutex);
10199
LOCK(m_txreconciliation_mutex);
102100
auto recon_state = m_states.find(peer_id);
103101

104-
// A peer should be in the pre-registered state to proceed here.
105-
if (recon_state == m_states.end()) return NOT_FOUND;
106-
uint64_t* local_salt = std::get_if<uint64_t>(&recon_state->second);
107-
// A peer is already registered. This should be checked by the caller.
108-
Assume(local_salt);
102+
if (recon_state == m_states.end()) return ReconciliationRegisterResult::NOT_FOUND;
103+
104+
if (std::holds_alternative<TxReconciliationState>(recon_state->second)) {
105+
return ReconciliationRegisterResult::ALREADY_REGISTERED;
106+
}
107+
108+
uint64_t local_salt = *std::get_if<uint64_t>(&recon_state->second);
109109

110110
// If the peer supports the version which is lower than ours, we downgrade to the version
111111
// it supports. For now, this only guarantees that nodes with future reconciliation
@@ -114,27 +114,14 @@ class TxReconciliationTracker::Impl
114114
// satisfactory (e.g. too low).
115115
const uint32_t recon_version{std::min(peer_recon_version, m_recon_version)};
116116
// v1 is the lowest version, so suggesting something below must be a protocol violation.
117-
if (recon_version < 1) return PROTOCOL_VIOLATION;
118-
119-
// Must match SENDTXRCNCL logic.
120-
const bool they_initiate = is_peer_recon_initiator && is_peer_inbound;
121-
const bool we_initiate = !is_peer_inbound && is_peer_recon_responder;
122-
123-
// If we ever announce support for both requesting and responding, this will need
124-
// tie-breaking. For now, this is mutually exclusive because both are based on the
125-
// inbound flag.
126-
assert(!(they_initiate && we_initiate));
127-
128-
// The peer set both flags to false, we treat it as a protocol violation.
129-
if (!(they_initiate || we_initiate)) return PROTOCOL_VIOLATION;
117+
if (recon_version < 1) return ReconciliationRegisterResult::PROTOCOL_VIOLATION;
130118

131-
LogPrintLevel(BCLog::TXRECONCILIATION, BCLog::Level::Debug, "Register peer=%d with the following params: " /* Continued */
132-
"we_initiate=%i, they_initiate=%i.\n",
133-
peer_id, we_initiate, they_initiate);
119+
LogPrintLevel(BCLog::TXRECONCILIATION, BCLog::Level::Debug, "Register peer=%d (inbound=%i)\n",
120+
peer_id, is_peer_inbound);
134121

135-
const uint256 full_salt{ComputeSalt(*local_salt, remote_salt)};
136-
recon_state->second = TxReconciliationState(we_initiate, full_salt.GetUint64(0), full_salt.GetUint64(1));
137-
return SUCCESS;
122+
const uint256 full_salt{ComputeSalt(local_salt, remote_salt)};
123+
recon_state->second = TxReconciliationState(!is_peer_inbound, full_salt.GetUint64(0), full_salt.GetUint64(1));
124+
return ReconciliationRegisterResult::SUCCESS;
138125
}
139126

140127
void ForgetPeer(NodeId peer_id) EXCLUSIVE_LOCKS_REQUIRED(!m_txreconciliation_mutex)
@@ -166,11 +153,9 @@ uint64_t TxReconciliationTracker::PreRegisterPeer(NodeId peer_id)
166153
}
167154

168155
ReconciliationRegisterResult TxReconciliationTracker::RegisterPeer(NodeId peer_id, bool is_peer_inbound,
169-
bool is_peer_recon_initiator, bool is_peer_recon_responder,
170156
uint32_t peer_recon_version, uint64_t remote_salt)
171157
{
172-
return m_impl->RegisterPeer(peer_id, is_peer_inbound, is_peer_recon_initiator, is_peer_recon_responder,
173-
peer_recon_version, remote_salt);
158+
return m_impl->RegisterPeer(peer_id, is_peer_inbound, peer_recon_version, remote_salt);
174159
}
175160

176161
void TxReconciliationTracker::ForgetPeer(NodeId peer_id)

src/node/txreconciliation.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ static constexpr bool DEFAULT_TXRECONCILIATION_ENABLE{false};
1616
/** Supported transaction reconciliation protocol version */
1717
static constexpr uint32_t TXRECONCILIATION_VERSION{1};
1818

19-
enum ReconciliationRegisterResult {
20-
NOT_FOUND = 0,
21-
SUCCESS = 1,
22-
PROTOCOL_VIOLATION = 2,
19+
enum class ReconciliationRegisterResult {
20+
NOT_FOUND,
21+
SUCCESS,
22+
ALREADY_REGISTERED,
23+
PROTOCOL_VIOLATION,
2324
};
2425

2526
/**
@@ -72,8 +73,8 @@ class TxReconciliationTracker
7273
* Step 0. Once the peer agreed to reconcile txs with us, generate the state required to track
7374
* ongoing reconciliations. Must be called only after pre-registering the peer and only once.
7475
*/
75-
ReconciliationRegisterResult RegisterPeer(NodeId peer_id, bool is_peer_inbound, bool is_peer_recon_initiator,
76-
bool is_peer_recon_responder, uint32_t peer_recon_version, uint64_t remote_salt);
76+
ReconciliationRegisterResult RegisterPeer(NodeId peer_id, bool is_peer_inbound,
77+
uint32_t peer_recon_version, uint64_t remote_salt);
7778

7879
/**
7980
* Attempts to forget txreconciliation-related state of the peer (if we previously stored any).

src/protocol.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,7 @@ extern const char* CFCHECKPT;
259259
*/
260260
extern const char* WTXIDRELAY;
261261
/**
262-
* Contains 2 1-byte bools, a 4-byte version number and an 8-byte salt.
263-
* The 2 booleans indicate that a node is willing to participate in transaction
264-
* reconciliation, respectively as an initiator or as a receiver.
262+
* Contains a 4-byte version number and an 8-byte salt.
265263
* The salt is used to compute short txids needed for efficient
266264
* txreconciliation, as described by BIP 330.
267265
*/

0 commit comments

Comments
 (0)