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
net: Drop v2 garbage authentication packet #28525
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. |
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.
Concept ACK
Approach ACK assuming BIP change is accepted |
8753b6a
to
f02fb71
Compare
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.
Code review ACK, with minor nits. I'm also on board with the corresponding BIP change (see the discussion there).
f02fb71
to
ac96c38
Compare
See also bitcoin/bips#1498 The benefit is a simpler implementation: - The protocol state machine does not need separate states for garbage authentication and version phases. - The special case of "ignoring the ignore bit" is removed. - The freedom to choose the contents of the garbage authentication packet is removed. This simplifies testing.
ac96c38
to
e3720bc
Compare
The CI failure seems unrelated: |
ACK e3720bc |
ACK e3720bc. Re-ran the v2 transport fuzzer overnight. |
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.
Concept ACK
/** During GARBAUTH, the garbage received during GARB_GARBTERM. */ | ||
std::vector<uint8_t> m_recv_garbage GUARDED_BY(m_recv_mutex); | ||
/** AAD expected in next received packet (currently used only for garbage). */ | ||
std::vector<uint8_t> m_recv_aad GUARDED_BY(m_recv_mutex); |
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.
Conceptually it's a bit weird to receive an AAD in one message but then verify it in the next message. Perhaps it's cleaner to to keep m_recv_garbage
around and explicitly move it into m_recv_aad
as soon as we start receiving bytes for the decoy/version message?
That way we can Assume
that m_recv_aad
is empty when start receiving bytes and clear it when we're done processing a message. (this commit already does the latter)
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.
Perhaps it's cleaner to to keep m_recv_garbage around and explicitly move it into m_recv_aad as soon as we start receiving bytes for the decoy/version message?
We receive data into m_recv_buffer
, and by the time we process it, we're effectively already done with it. So what you're suggesting would just amount to moving/shrinking from m_recv_buffer
to m_recv_garbage
and immediately after (on the next line) moving that to m_recv_aad
.
I think the better way of looking at it is not that the AAD is data received at all; it's a side effect of processing data in a particular phase that results in a requirement that the next message commit to it. For now, the only place where this happens is that during the processing of received bytes in the GARB_TERM
phase the garbage needs to be committed to (but not all the data received during that phase, as it doesn't include the terminator).
That way we can
Assume
thatm_recv_aad
is empty when start receiving bytes and clear it when we're done processing a message. (this commit already does the latter).
I don't think that works? At the start of the version phase, the previous garbage will be in m_recv_aad
.
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.
Conceptually it's a bit weird to receive an AAD in one message but then verify it in the next message. Perhaps it's cleaner to to keep
m_recv_garbage
around and explicitly move it intom_recv_aad
as soon as we start receiving bytes for the decoy/version message?
If I understand correctly, this is roughly equivalent to dropping the second commit again, and I don't think this was cleaner.
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.
At the start of the version phase, the previous garbage will be in
m_recv_aad
.
This is the part that feels a bit strange to me. But may it's not too bad:
We could instead Assume
that m_recv_aad
is empty when we enter the APP
and when we enter the APP_READY
state. It can be cleared in the VERSION
state and after each normal message in the APP
state, which indeed this PR does.
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 suppose an Assume
in APP
may or may not be future proof, because it depends on how AADs will be used: do we know what to expect for the next message (as is the case here for garbage), do we infer it from the current message, is it some time dependent thing or even a constant?
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 suppose an
Assume
inAPP
may or may not be future proof, because it depends on how AADs will be used: do we know what to expect for the next message (as is the case here for garbage), do we infer it from the current message, is it some time dependent thing or even a constant?
Well, if we ever have a v3 that uses AAD for more than the garbage, we could drop the Assume
, so I guess that's not a big deal.
On the other hand, I don't see that much value in adding an Assume
. The sender and receiver code are sufficiently independent. So unless we have the exact same bug in the sender logic, a bug in the receiver logic that leads to m_recv_aad
being non-empty would lead to an immediate disconnect. That is, such a bug will certainly be noticed during testing, even without the Assume
. (The Assume
would just make it easier to find the cause.)
My current thinking is that I don't want to touch the PR now that it has three ACKs. But I'll add an Assume
if there's another good reason to touch it (or if you have strong opinions on this, of course.)
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.
Not totally relevant to the PR but some remarks:
do we know what to expect for the next message (as is the case here for garbage)
do we infer it from the current message,
I think one of these two is true in 99.9% of the cases I can imagine.
As for inferring it from current message: Inferring it from the contents of the AEAD is excluded by design (you can't decrypt a ciphertext that doesn't verify). It would just be possible for data in the "outer" header (currently that's just the length field). But even if we want some additional data in the outer header, this doesn't really contradict the current logic in the code (e.g., we could concatenate the current-message thing to whatever m_recv_aad
is, or then start Assuming it's empty).
is it some time dependent thing
That will be too fragile, i.e., we would abort the connection if clocks are off.
even a constant?
Then there will be no reason to include 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.
Thanks for the clarifications. Agree that adding an Assume
can wait.
Concept ACK |
Observation during discussion with @achow101: the old behavior is actually equivalent to the new behavior, but with the added rule that the very first packet is implicitly a decoy (whether the bit is set or not). |
Interesting observation, and this confirms that the old behavior is somewhat unnatural. |
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.
utACK e3720bc
Timing wise, I plan to run this on mainnet once it's added to the integration PR.
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.
Code-review ACK e3720bc
I didn't follow the full discussion in the BIP change PR yet, but to my understanding, this approach simplifies the state machine and doesn't have any drawbacks (other than adaptions needed in #24748 and a temporary incompatibility between BIP324 nodes running old/new version, obviously).
RFM but waiting for BIP change to be merged first. |
ACK e3720bc - simpler and more flexible, nice |
BIP has been merged |
FYI this is what happens if you don't upgrade your node and try to connect to an upgrade one:
(bangs head on table for forgetting The other way around, if you upgrade but connect to a node that didn't upgrade, you get something like:
|
ACK e3720bc |
e3720bc net: Simplify v2 recv logic by decoupling AAD from state machine (Tim Ruffing) b0f5175 net: Drop v2 garbage authentication packet (Tim Ruffing) Pull request description: Note that this is a breaking change, see also bitcoin/bips#1498 The benefit is a simpler implementation: - The protocol state machine does not need separate states for garbage authentication and version phases. - The special case of "ignoring the ignore bit" is removed. - The freedom to choose the contents of the garbage authentication packet is removed. This simplifies testing. ACKs for top commit: naumenkogs: ACK e3720bc sipa: ACK e3720bc. Re-ran the v2 transport fuzzer overnight. ajtowns: ACK e3720bc - simpler and more flexible, nice achow101: ACK e3720bc Sjors: utACK e3720bc theStack: Code-review ACK e3720bc Tree-SHA512: 16600ed868c8a346828de075c4072e37cf86440751d08ab099fe8b58ff71d8b371a90397d6a4247096796db68794275e7e0403f218859567d04838e0411dadd6
Note that this is a breaking change, see also bitcoin/bips#1498
The benefit is a simpler implementation: