-
Notifications
You must be signed in to change notification settings - Fork 5.9k
BIP 155: addrv2 BIP proposal #766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Assigned BIP 155 |
|
Thanks! |
| <ref>[https://bitcoin.org/en/developer-reference#addr Bitcoin Developer Reference: addr message]</ref>, with the difference that the | ||
| fixed 16-byte IP address is replaced by a network ID and a variable-length address, and the time and services format has been changed to VARINT. | ||
|
|
||
| This means that the message contains a serialized <code>std::vector</code> of the following structure: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is how bips were written in the past, but I'd slightly prefer not to leak cpp details or Bitcoin Core implementation details such as std::vector (can be replaced by "list" or "vector"), pchCommand (can be replaced by "message type"), and static const int GOSSIP_ADDRV2_VERSION (can be omitted without loss of information).
If someone is eager to look at the cpp implementation, there is already a section that links to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fine with me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I went with explicit C++ types here for clarity as to how things would be serialized, after all there is not really a spec of the serialization format (and how the certain structures are named, like "how to serialize a list", wouldn't "a list" be vague and ambigious?) besides the implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our python implementation calls it "string" https://github.com/bitcoin/bitcoin/blob/e5abb59a9a66723dd1d9a01f65e467636eb24f2d/test/functional/test_framework/messages.py#L89
Anyway, no strong opinion 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string seems to be worse as it implies a human-readable text
| Send <code>addrv2</code> messages only, and exclusively, when the peer has a certain protocol version (or higher): | ||
| <source lang="c++"> | ||
| //! gossiping using `addrv2` messages starts with this version | ||
| static const int GOSSIP_ADDRV2_VERSION = 70016; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't put much thought into this, but could you explain the tradeoffs here a bit? I think there are two ways to announce support for a new p2p feature:
- Bump the protocol version
- Send a p2p message to announce your support for the feature
Bumping the minimum protocol version seems to imply that nodes would have to support all protocol features that were introduced prior (like compactblocks, feefilter, ...)
Whereas with a new protocol message, even mobile wallets could make use of the new feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does add a new protocol message (that's the addrv2), but the version tells it that the other side understands them
would you prefer to add another protocol message to signal support, which is always sent after version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you can keep this as is. mobile wallets tend to get their addresses from dns seeds, so this shouldn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In light of yesterday's IRC discussion and on further thought, I think support for addrv2 should be announced by a service bit. This has the following advantages:
- leech nodes (nodes that only want to consume addrv2 messages, e.g. "SPV clients") can find addrv2 nodes by the service bit and they can expect them to respond to
sendaddrv2messages - address relay between address relay nodes (e.g. full nodes/Bitcoin Core nodes) can be made explicit, instead of relying on heuristics such as
NODE_NETWORK. See p2p: Avoid relaying ADDR messages to SPV clients bitcoin#17163 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* address relay between address relay nodes (e.g. full nodes/Bitcoin Core nodes) can be made explicit, instead of relying on heuristics such as `NODE_NETWORK`. See [bitcoin/bitcoin#17163 (comment)](https://github.com/bitcoin/bitcoin/pull/17163#issuecomment-543072194)
To be clear, you mean address relay can be made explicit by an additional service bit, e.g. NODE_ADDR_GOSSIP or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, you mean address relay can be made explicit by an additional service bit, e.g. NODE_ADDR_GOSSIP or something like that?
Yes. Currently we use heuristics such as NODE_NETWORK for that, which is fragile and not future proof. For example, pruned nodes may not have any NODE_NETWORK* bit set. See also bitcoin/bitcoin#17194
| |- | ||
| | <code>VARINT</code> (unsigned) | ||
| | <code>time</code> | ||
| | Time that this node was last seen as connected to the network. A time in Unix epoch time format, up to 64 bits wide. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would help to explain what "last seen" means, since it appears easy to get wrong. E.g. bitcoin/bitcoin#5860 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The meaning of this field doesn't change from the current implementation. I'm fine with adding an explanation though, if you supply it, but I'm not sure what to add here.
|
Came up during discussion on IRC, need to be explicit about representing IPv4 as network ID IPV4, that the old wrapped representation is no longer allowed:
(thanks @dongcarl) |
|
As for changing the signaling from protocol version-based to sending a message. I think this message, when sent from one peer to another, would signal support for the first peer to receive I wish we had some kind of standard message for this. I think for simplicy of implementation we'd want to mandate that this should be sent after Edit2: This |
|
There was some discussion on IRC that there should be a max cap for network addresses, but it should not be 256 bits, but more something like 512 bytes, to accommodate future extensions but have some kind of limit for DoS. Currently it says:
Change this to: a maximum of 512 bytes, and the whole message (not just the single address) SHOULD be rejected if it contains any larger item. |
|
@laanwj Just to be clear, addrv2 entries that claims they are IPv6 but come with either the IPv4-prefix, OnionCat-prefix, or CJDNS-prefix should be ignored? For Bitcoin Core, I'm assuming our weird |
It would seems that that addrMe has been deprecated: bitcoin/bitcoin#8740 |
I think relaying unknown networks is very important, because the nodes are often multi-homed. So this might be actually useful for somebody who your node thinks is simply ipv4. There is no reason to not. If an attacker wants to spend our bandwidth, might as well flood with ipv4, we don't check if the node is alive before forwarding them. Storing is another thing. With the current rate-limiting, the bandwidth we're spending here is pretty low. But addrman size is bounded, so I wouldn't store everything. Maybe, storing a couple exotic things might make sense if you will be switching in future. |
* Increase the maximum length of an address from 32 to 64 bytes and clarify that the entire message should be rejected if it contains a longer address. (from bitcoin#766 (comment)) * Remove a contradiction about unknown address types - "MUST ignore" VS "MAY store and gossip". * Recommend gossiping addresses for unknown network ID and for networks to which the node is not currently connected to. (from bitcoin#766 (comment)) * Clarify that the entire message should be rejected if it contains an address with unexpected size (e.g. IPv4 address with length 5).
* Increase the maximum length of an address from 32 to 512 bytes and clarify that the entire message should be rejected if it contains a longer address. (from bitcoin#766 (comment)) * Remove a contradiction about unknown address types - "MUST ignore" VS "MAY store and gossip". * Recommend gossiping addresses for unknown network ID and for networks to which the node is not currently connected to. (from bitcoin#766 (comment)) * Clarify that the entire message should be rejected if it contains an address with unexpected size (e.g. IPv4 address with length 5).
|
Following up on a discussion started in #907 (comment)
To overgeneralize, I think that all else being the same I prefer the "new message" mechanism over the "service bit" mechanism over the "protocol version" mechanism. However, the "service bit" mechanism is well-suited for making sure that certain specific node configurations can discover useful peers. The support signaling can be broken down into 2 parts: Something for my node to signal to peers that it wants
|
What about using a service bit (different one) also for the first capability? The second capability is actually
|
I don't remember what this post to the mailing list said: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-October/017428.html, so it might prove my point invalid. But I think it said something that both those properties should be negotiated on a per-link (per-connection) basis. In which case both should be done via a new message type. If you think of service bits as a "static global" across the whole Bitcoin network, then it makes sense to only use them for things that don't change often and don't change on a per-connection basis. E.g. |
Unfortunately, it is not
I'm think that the "my node wants
Perhaps @naumenkogs has more thoughts. |
I meant two service bits:
So, for example, a multi-homed |
* Increase the maximum length of an address from 32 to 512 bytes and clarify that the entire message should be rejected if it contains a longer address. (from bitcoin#766 (comment)) * Remove a contradiction about unknown address types - "MUST ignore" VS "MAY store and gossip". * Recommend gossiping addresses for networks to which the node is not currently connected to. (from bitcoin#766 (comment)) * Clarify that the entire message should be rejected if it contains an address with unexpected size (e.g. IPv4 address with length 5).
That particular version is now used for
|
|
@Sjors, #907 updates the signalling mechanism. Here is a render preview of it: https://github.com/bitcoin/bips/blob/350189a/bip-0155.mediawiki#signaling-support-and-compatibility |
Proposal for wider v2 address messages.
Last time this went around (as a github gist) there were some considerations still to be discussed, for lack of a working mailing list I'll post them here:
Considerations
''Client MAY store and gossip address formats that they do not know about'': does it ever make sense to gossip addresses outside a certain overlay network? Say, I2P addresses to Tor? I'm not sure. Especially for networks that have no exit nodes as there is no overlap with the globally routed internet at all.
Lower precision of
timefield? seconds precision seems overkill, and can even be harmful, there have been attacks that exploited high precision timestamps for mapping the current network topology.Rolling
portintoaddr, or making the port optional, would make it possible to shave off two bytes for address types that don't have ports (however, all of the currently listed formats have a concept of port.). It could also be an optional data item (see below).(gmaxwell) Optional (per-service) data could be useful for various things:
Node-flavors for striping (signalling which slice of the blocks the node has in selective pruning)
Payload for is alternative ports for other transports (e.g. UDP ports)
If we want optional flags. I guess the best thing would just be a byte to include the count of them, then a byte "type" for each one where the type also encodes if the payload is 0/8/16/32 bits. (using the two MSB of the type to encode the length). And then bound the count of them so that the total is still reasonably sized.