Skip to content

Conversation

@davecgh
Copy link
Member

@davecgh davecgh commented Feb 9, 2026

Requires #2627.

This builds on the work in #2627 to finalize a few remaining review items that we decided to do separately.

The following is an overview of the changes:

  • Consolidate address version selection logic in the server
  • Remove old style methods from new addrv2 message
  • Rename IP -> EncodedAddr to more accurately reflect the field's purpose
  • Misc cleanup to avoid some additional allocs, use standard test formatting, and remove some unnecessary nil checks
  • Keep TorV3 support as part of the new addrv2 protocol version (12) instead doing two simultaneous version bumps
  • Reduce allocations in new addv2 writes
  • Rename all "TOR" references to the more canonical "Tor"

See each commit for a more detailed description.

sefbkn added 11 commits February 6, 2026 01:23
This adds the addrv2 message type to allow extensible peer address
exchange. It also defines the protocol version AddrV2Version (12)
for future negotiations, but does not advertise it on the peer to
peer network or use it outside of the wire package.

The structure of the addrv2 message is depicted below for reference.

MsgAddrV2 wire format:
+---------------------------+
| Count (varint, [1..1000]) |
+---------------------------+
| NetAddressV2[N]           |
| (see below)               |
+---------------------------+
| ...                       |
+---------------------------+

The varint Count prefix of the MsgAddrV2 payload describes how many
NetAddressV2 entries exist in the message. This value must indicate
at least 1 entry and no more than 1000 entries to be considered a
valid message.  This differs from the addr message in that it does
not allow zero entries.

NetAddressV2 wire format:
+-----------+----------+--------+----------------+---------+
| Timestamp | Services |  Type  |     Address    |  Port   |
+-----------+----------+--------+----------------+---------+
|  8 bytes  | 8 bytes  | 1 byte | variable bytes | 2 bytes |
+-----------+----------+--------+----------------+---------+

The Type field of the NetAddressV2 payload informs the reader
of both the network type that the address belongs to as well as
allowing the reader to infer how many bytes to read from the
address field.

The addr message is also modified to now fail when encoding/decoding
when the negotiated protocol version >= AddrV2Version.

The following is an overview of the changes:

- Add NetAddressV2 type
  - This includes a constructor NewNetAddressV2 that will be
    needed in a future commit for directly constructing
    v2 wire network addresses with varying types.
- Add MsgAddrV2 type implementing Message interface
- Define AddrV2Version constant (12)
- Reject MsgAddr for negotiated protocol version >= 12
- Add ErrTooFewAddrs error
- Add test coverage
Upcoming changes to the peer module will include breaking changes to
the public API.  Therefore, this follows the process for introducing
major API changes, which consists of:

- Bump the major version in the go.mod of the peer module
- Update all imports in the repo to use the new major version as necessary
- Tidy all modules in the repository to ensure they are updated to use
  the latest versions
This breaking change modifies the Peer.na field from
wire.NetAddress to wire.NetAddressV2 to accommodate
responses from addrv2.

Since the addrmgr module uses its own NetAddress type,
this adds conversion functions in server.go to translate
between wire.NetAddressV2 and addrmgr.NetAddress.

It also adds an NA function on serverPeer that returns
an addrmgr.NetAddress.  This is done because every
instance of the peer's network address needs to be
converted to an addrmgr.NetAddress anyways,
so shadowing the embedded type removes boilerplate.
Alternatives considered include updating the explicit
conversion function in every usage of NA, coupling the
peer module to the addrmgr module and make Peer.na an
addrmgr.NetAddress, or creating a new netaddr module to
avoid coupling wire and addrmgr, and adding NA to
serverPeer appeared to be the cleanest approach for
the immediate effort of integrating the addrv2 message
into the codebase.

The following is an overview of the changes:

peer:
- Change Peer.na from wire.NetAddress to wire.NetAddressV2
- Add supporting code to convert between NetAddress types

server:
- Move connectionsWithIP func definition closer to its usage
- Update HostToNetAddress callback to return wire.NetAddressV2
- Add NA function on serverPeer to return addrmgr.NetAddress
- Add conversion functions in server.go
- Update OnAddr handler for new types
This adds support for the addrv2 message to the peer module,
including the ability to send and receive addrv2 messages
for IPv4 and IPv6 network address types.

The following is an overview of the changes:

- Bump peer.MaxProtocolVersion to AddrV2Version (12)
- Add OnAddrV2 callback to MessageListeners
- Add PushAddrV2Msg method
- Add MsgAddrV2 handler in inHandler dispatch loop
- Log addrv2 messages in messageSummary
- Add test coverage for addrv2 functionality
This enables addrv2 message handling and makes the addrv2 message
active and usable on the peer to peer network for IPv4 and IPv6
network address types.

With this, the response to a getaddr message will either be an
addr or addrv2 message, varying based on the negotiated protocol
version.

For negotiated protocol version
   <  12, respond to getaddr with addr
   >= 12, respond to getaddr with addrv2

The following is an overview of the changes:

- Bump maxProtocolVersion to AddrV2Version (12)
- Add conversion function wireToAddrmgrNetAddressesV2
- Add pushAddrV2Msg method
- Update OnVersion to send addr or addrv2 based on negotiated version
- Update OnGetAddr to respond with either addr or addrv2
- Add OnAddrV2 handler to process incoming addrv2 messages
- Register OnAddrV2 message listener when constructing peer
This change modifies wire to

- introduce a new TORv3Version protocol version
- adds new TORv3Address network address type
- ensure the TORv3Address network address type is
  only serialized and deserialized at protocol
  version >= 13
This updates the max protocol version supported by
the peer module to TORv3Version (13).
Upcoming changes to the addrmgr module will include breaking changes to
the public API.  Therefore, this follows the process for introducing
major API changes, which consists of:

- Bump the major version in the go.mod of the addrmgr module
- Update all imports in the repo to use the new major version as necessary
- Tidy all modules in the repository to ensure they are updated to use
  the latest versions
This introduces a breaking change to the address manager by
adding a filter parameter to GetAddress to allow callers to specify
wanted address types.  It also introduces per-bucket statistics to
efficiently track address type counts, which allows tried and new
buckets to be filtered without scanning their contents.  This
allows for identifying whether a bucket contains addresses matching
the network address type filter in constant time rather than
needing to do a linear scan of all addresses within the bucket.
Note that deciding whether a bucket contains any addresses matching
the filter is a distinct operation from retrieving an address from
a bucket that is known to contain an address matching the filter.

This prepares for new address types that will be added in the
future.  Filtering will allow callers to prevent address types
that they cannot use or would otherwise be undesirable from being
returned by the address manager.

The following is an overview of the changes:

- Add filter parameter to GetAddress (breaking change)
- Add bucketStats to track address counts per bucket
- Add and update tests
This adds TORv3 address support to the address manager, including
serialization logic, validation, persistence and retrieval of TORv3
.onion addresses.  Sharing TORv3 addresses over the peer to peer
network is not yet supported and will be added in a later commit.

The following is an overview of the changes:

- Add TORv3Address constant (4) to NetAddressType
- Add TORv3 parsing to EncodeHost
- Add various TORv3 helper functions
- Update ipString to serialze TORv3 addresses to .onion format
- Update deriveNetAddressType to recognize TORv3
- Add Private constant to NetAddressReach for TORv3
- Update getRemoteReachabilityFromLocal for TORv3
- Add tests
This bumps the advertised protocol version to 13 and allows sharing
TORv3 addresses on the peer to peer network for peers with a
negotiated protocol version of TORv3Version (13).

The following is an overview of the changes:

- Modify converters to support translating between the wire and
  addrmgr TORv3Address network address type enums.
- Add isSupportedNetAddressTypeV2 func to allow torv3 addresses
  to be read from the address manager for negotiated protocol
  version TORv3Version.
- Ensure server only receives TORv3 addresses from address
  manager if an onion proxy is configured when calling
  GetAddress.
- Avoid dns lookups for TORv3 .onion addresses
  - this allows the --connect and --addpeer flags to
    accept TORv3 .onion addresses.
@davecgh davecgh added this to the 2.2.0 milestone Feb 9, 2026
@davecgh davecgh force-pushed the multi_misc_addrv2_cleanup branch 2 times, most recently from dabbfe9 to c5955cd Compare February 9, 2026 20:39
@davecgh davecgh force-pushed the multi_misc_addrv2_cleanup branch from c5955cd to ca39014 Compare February 10, 2026 02:19
This consolidates the logic for choosing which version address message
to send to the remote peers based on the protocol version to a single
function and updates the callers to make use of it.
The vast majority of the code in the wire package was written nearly a
decade and a half ago when Go was still quite new and many of the
patterns are less than ideal as a result.

For example, methods that add items one at a time along with a
conditional check are inefficient and realistically unnecessary because
the caller is already expected to make use of the exported constants to
avoid errors to begin with and the messages will fail to encode and
decode if they exceed the max allowed anyway.

Not only that, in order to allow those types of methods and avoid a
bunch of additional allocations due to multiple appends, the
constructors have to create a slice with a large capacity with no
information as to what a good guess would be which is rather wasteful.

So, in practice, callers are much better off just creating the list with
the exact size they know they need and set it at message creation time.

Unfortunately, since the wire package is used as the base of virtually
every single other package, changing the API in a breaking way that
would cause a major module version bump would be a massive undertaking
and thus care has been taken to avoid requiring one.

However, the new MsgAddrV2 type was just added and a new version has not
been tagged yet, so it is safe to modify the API for the message in a
breaking way.

With the aforementioned in mind, this removes the AddAddress,
AddAddresses, and ClearAddresses methods from the newly introduced
MsgAddrV2 type.
This renames the IP field of the new wire.NetAddressV2 struct to
EncodedAddr to more accurately reflect its use.

This is a breaking API change and thus ordinarily would not be allowed,
but since the struct was recently introduced and a new version of the
wire modules has not been tagged yet, it is safe to modify the API in a
breaking way.
This contains some basic housekeeping and does not make any functional
changes:

- Use nil instead of empty instances to avoid some allocs
- Use standard formatting in some of the tests
- Remove unnecessary checks for nil slices on len checks since taking
  the length of a nil slice is already 0
- Correct a wire comment regarding network addresses
@davecgh davecgh force-pushed the multi_misc_addrv2_cleanup branch from ca39014 to f8b8383 Compare February 10, 2026 04:11
This removes the additional TORv3Version protocol version bump in favor
of keeping the TorV3 additions as part of the AddrV2Version protool
bump.

This is a breaking API change and thus ordinarily would not be allowed,
but since the struct was recently introduced and a new version of the
wire modules has not been tagged yet, it is safe to modify the API in a
breaking way.
This converts the encoding logic for the new MsgAddrV2 to avoid
allocations by using pointers to the data to be written and also
introduces fast paths in the writeElement function for the new types.
This modifies the logic for serializing version 2 network addresses to
avoid additional copies into local arrays for the various address types
by directly writing the encoded address after the switch that verifies
the encoded address is the right size for the type.
This renames all mentions of TORv3 to the more canonical TorV3.  All
references to Tor on the main project site, and basically everywhere
else, refer to the network as "Tor", not "TOR".
@davecgh davecgh force-pushed the multi_misc_addrv2_cleanup branch from f8b8383 to eea28cd Compare February 11, 2026 03:09
@davecgh
Copy link
Member Author

davecgh commented Feb 11, 2026

Updated to add a commit to rename all "TOR" references to the more canonical "Tor". All references to Tor on the main project site, and basically everywhere else, refer to the network as "Tor", not "TOR".

Copy link
Contributor

@matthawkins90 matthawkins90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very excited to finally have sef's work and TorV3!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants