[net processing] [refactor] Move m_next_send_feefilter and m_fee_filter_sent

Move m_next_send_feefilter and m_fee_filter_sent out of the `TxRelay`
data structure. All of the other members of `TxRelay` are related to
sending transactions _to_ the peer, whereas m_fee_filter_sent and
m_next_send_feefilter are both related to receiving transactions _from_
the peer. A node's tx relay behaviour is not always symmetrical (eg a
blocksonly node will ignore incoming transactions, but may still send
out its own transactions), so it doesn't make sense to group the
feefilter sending data with the TxRelay data in a single structure.

This does not change behaviour, since IsBlockOnlyConn() is always equal
to !peer.m_tx_relay. We still don't send feefilter messages to outbound
block-relay-only peers (tested in p2p_feefilter.py).
This commit is contained in:
John Newbery 2022-04-26 11:50:54 +01:00
parent b74a6dde8c
commit 42e3250497

View File

@ -237,6 +237,13 @@ struct Peer {
/** Whether this peer relays txs via wtxid */ /** Whether this peer relays txs via wtxid */
std::atomic<bool> m_wtxid_relay{false}; std::atomic<bool> m_wtxid_relay{false};
/** The feerate in the most recent BIP133 `feefilter` message sent to the peer.
* It is *not* a p2p protocol violation for the peer to send us
* transactions with a lower fee rate than this. See BIP133. */
CAmount m_fee_filter_sent{0};
/** Timestamp after which we will send the next BIP133 `feefilter` message
* to the peer. */
std::chrono::microseconds m_next_send_feefilter{0};
struct TxRelay { struct TxRelay {
mutable RecursiveMutex m_bloom_filter_mutex; mutable RecursiveMutex m_bloom_filter_mutex;
@ -260,8 +267,6 @@ struct Peer {
/** Minimum fee rate with which to filter inv's to this node */ /** Minimum fee rate with which to filter inv's to this node */
std::atomic<CAmount> m_fee_filter_received{0}; std::atomic<CAmount> m_fee_filter_received{0};
CAmount m_fee_filter_sent{0};
std::chrono::microseconds m_next_send_feefilter{0};
}; };
/** Transaction relay data. Will be a nullptr if we're not relaying /** Transaction relay data. Will be a nullptr if we're not relaying
@ -4565,10 +4570,12 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::microseconds current_time) void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::microseconds current_time)
{ {
if (m_ignore_incoming_txs) return; if (m_ignore_incoming_txs) return;
if (!peer.m_tx_relay) return;
if (pto.GetCommonVersion() < FEEFILTER_VERSION) return; if (pto.GetCommonVersion() < FEEFILTER_VERSION) return;
// peers with the forcerelay permission should not filter txs to us // peers with the forcerelay permission should not filter txs to us
if (pto.HasPermission(NetPermissionFlags::ForceRelay)) return; if (pto.HasPermission(NetPermissionFlags::ForceRelay)) return;
// Don't send feefilter messages to outbound block-relay-only peers since they should never announce
// transactions to us, regardless of feefilter state.
if (pto.IsBlockOnlyConn()) return;
CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
static FeeFilterRounder g_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}}; static FeeFilterRounder g_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}};
@ -4579,27 +4586,27 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
currentFilter = MAX_MONEY; currentFilter = MAX_MONEY;
} else { } else {
static const CAmount MAX_FILTER{g_filter_rounder.round(MAX_MONEY)}; static const CAmount MAX_FILTER{g_filter_rounder.round(MAX_MONEY)};
if (peer.m_tx_relay->m_fee_filter_sent == MAX_FILTER) { if (peer.m_fee_filter_sent == MAX_FILTER) {
// Send the current filter if we sent MAX_FILTER previously // Send the current filter if we sent MAX_FILTER previously
// and made it out of IBD. // and made it out of IBD.
peer.m_tx_relay->m_next_send_feefilter = 0us; peer.m_next_send_feefilter = 0us;
} }
} }
if (current_time > peer.m_tx_relay->m_next_send_feefilter) { if (current_time > peer.m_next_send_feefilter) {
CAmount filterToSend = g_filter_rounder.round(currentFilter); CAmount filterToSend = g_filter_rounder.round(currentFilter);
// We always have a fee filter of at least minRelayTxFee // We always have a fee filter of at least minRelayTxFee
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK()); filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
if (filterToSend != peer.m_tx_relay->m_fee_filter_sent) { if (filterToSend != peer.m_fee_filter_sent) {
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend)); m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
peer.m_tx_relay->m_fee_filter_sent = filterToSend; peer.m_fee_filter_sent = filterToSend;
} }
peer.m_tx_relay->m_next_send_feefilter = GetExponentialRand(current_time, AVG_FEEFILTER_BROADCAST_INTERVAL); peer.m_next_send_feefilter = GetExponentialRand(current_time, AVG_FEEFILTER_BROADCAST_INTERVAL);
} }
// If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY // If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY
// until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY. // until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < peer.m_tx_relay->m_next_send_feefilter && else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < peer.m_next_send_feefilter &&
(currentFilter < 3 * peer.m_tx_relay->m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_tx_relay->m_fee_filter_sent / 3)) { (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
peer.m_tx_relay->m_next_send_feefilter = current_time + GetRandomDuration<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY); peer.m_next_send_feefilter = current_time + GetRandomDuration<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY);
} }
} }