Connecting to an I2P peer consists of creating a session (the
SESSION CREATE
command) and then connecting to the peer using that
session (STREAM CONNECT ID=session_id ...
).
This change is only relevant for transient sessions because when a persistent session is used it is created once and used for all connections.
Before this change Bitcoin Core would create the session and use it in
quick succession. That is, the SESSION CREATE
command would be
immediately followed by STREAM CONNECT
. This could ease network
activity monitoring by an adversary.
To mitigate that, this change creates sessions upfront without an
immediate demand for new sessions and later uses them. This creates a
time gap between SESSION CREATE
and STREAM CONNECT
. Note that there
is always some demand for new I2P connections due to disconnects.
Summary of the changes in the code:
-
Create the session from the
Session
constructor (sendSESSION CREATE
to the I2P SAM proxy). This constructor was only called when transient sessions were needed and was immediately followed byConnect()
which would have created the session. So this is a noop change if viewed in isolation. -
Every time we try to connect to any peer (not just I2P) create a new I2P session, up to a limit (currently 10). This way a bunch of sessions are created (
SESSION CREATE
) at times that are decoupled from the time when sessions will be used (STREAM CONNECT
). -
Tweak the code in
CConnman::ConnectNode()
to avoid creating session objects while holdingm_unused_i2p_sessions_mutex
because now creatingi2p::sam::Session
involves network activity and could take a few seconds.
Before (note the timestamps):
2025-03-13T09:23:40Z [opencon] [i2p:info] Transient SAM session cd7ea49a7e created 2025-03-13T09:23:43Z [opencon] [i2p] -> STREAM CONNECT ID=cd7ea49a7e DESTINATION=…
2025-03-13T09:23:51Z [opencon] [i2p:info] Transient SAM session cb0956207e created 2025-03-13T09:23:52Z [opencon] [i2p] -> STREAM CONNECT ID=cb0956207e DESTINATION=…
2025-03-13T09:24:04Z [opencon] [i2p:info] Transient SAM session 35ad67f343 created 2025-03-13T09:24:04Z [opencon] [i2p] -> STREAM CONNECT ID=35ad67f343 DESTINATION=…
After:
2025-03-13T17:08:58Z [opencon] [i2p:info] Transient SAM session 16098cd4ea created 2025-03-13T17:09:34Z [opencon] [i2p] -> STREAM CONNECT ID=16098cd4ea DESTINATION=…
2025-03-13T17:09:38Z [opencon] [i2p:info] Transient SAM session 5d209bf1bc created 2025-03-13T17:09:59Z [opencon] [i2p] -> STREAM CONNECT ID=5d209bf1bc DESTINATION=…
2025-03-13T17:09:50Z [opencon] [i2p:info] Transient SAM session e78aa6d2e7 created 2025-03-13T17:12:09Z [opencon] [i2p] -> STREAM CONNECT ID=e78aa6d2e7 DESTINATION=…
This was suggested by @eyedeekay some time ago (in 2023 actually) and has been lingering in my TODO since then :eyes:. A further suggestion is to also add a time gap between the activity cease and the closing of the session. For this, when CNode
is destroyed CNode::m_i2p_sam_session
would have to be moved elsewhere and destroyed at a later time. cc @zzzi2p