Good point! That behavior would be surprising and documenting it is sub-optimal. Better don't advertise our persistent address over I2P outgoing connections that use transient addresses. I extended the commit net: create a transient I2P session if -i2ptransientout is given with the following diff to achieve that:
<details>
<summary>[patch] don't self-advertise</summary>
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 74d1bf44d2..17c67ae7a5 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -2773,12 +2773,32 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
} else {
LOCK(cs_main);
mapBlockSource.erase(block->GetHash());
}
}
+/**
+ * Decide if we should send our own address to a given peer as a self-advertisement.
+ * We do the self-advertisement:
+ * - initially after establishing the connection and
+ * - periodically every ~24h (AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL).
+ */
+static bool ShouldSelfAdvertiseTo(const CNode& node)
+{
+ if (!fListen) {
+ return false;
+ }
+
+ // Don't self-advertise if this is an I2P outbound connection and -i2ptransientout=1.
+ // If we do so, then we would self-advertise our persistent I2P address, used for
+ // accepting incoming connections, which would defeat the purpose of using transient
+ // addresses for outgoing connections.
+ return !node.addrBind.IsI2P() || node.IsInboundConn() ||
+ !gArgs.GetBoolArg("-i2ptransientout", DEFAULT_I2P_TRANSIENT_OUT);
+}
+
void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
{
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId());
@@ -2924,14 +2944,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// empty and no one will know who we are, so these mechanisms are
// important to help us connect to the network.
//
// We skip this for block-relay-only peers. We want to avoid
// potentially leaking addr information and we do not want to
// indicate to the peer that we will participate in addr relay.
- if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
- {
+ if (ShouldSelfAdvertiseTo(pfrom) && !m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
+
CAddress addr{GetLocalAddress(pfrom.addr), peer->m_our_services, (uint32_t)GetAdjustedTime()};
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
PushAddress(*peer, addr, insecure_rand);
@@ -4670,13 +4690,13 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
{
// Nothing to do for non-address-relay peers
if (!peer.m_addr_relay_enabled) return;
LOCK(peer.m_addr_send_times_mutex);
// Periodically advertise our local address to the peer.
- if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
+ if (ShouldSelfAdvertiseTo(node) && !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
peer.m_next_local_addr_send < current_time) {
// If we've sent before, clear the bloom filter for the peer, so that our
// self-announcement will actually go out.
// This might be unnecessary if the bloom filter has already rolled
// over since our last self-announcement, but there is only a small
// bandwidth cost that we can incur by doing this (which happens
</details>
Since this PR had two ACKs without the above, let me know if it is ok or if I should remove it (@jonatack, @mzumsande).