Skip to content
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

Refactoring and minor improvement for self-advertisements #19843

Closed

Conversation

naumenkogs
Copy link
Member

@naumenkogs naumenkogs commented Aug 31, 2020

We have (almost) the same code chunk used twice. Improve that by slight refactoring.

The only behavior change is that the following will be also applied to the first (pre-VERACK) self-announcement:

// If discovery is enabled, sometimes give our peer the address it
// tells us that it sees us as in case it has a better idea of our
// address than we do.

And I think it's a good change anyway.

The last commit is just to consider the first self-announcement as regular and reset the timer, so that we don't send the second self-announcement too soon.
Note that since the first self-announcement is made at the end of processing VERSION, at that point addrLocal would be already filled with what the peers tells us we are, so this self-announcement would be no worse than any further one.

@fanquake fanquake added the P2P label Aug 31, 2020
@promag
Copy link
Contributor

promag commented Aug 31, 2020

Build failing

net_processing.cpp:2478:27: error: writing variable 'm_next_local_addr_send' requires holding mutex 'pfrom.cs_sendProcessing' exclusively [-Werror,-Wthread-safety-analysis]
                    pfrom.m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 31, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@hebasto
Copy link
Member

hebasto commented Sep 21, 2020

Concept ACK.

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

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

c0fc4ee

While AdvertiseLocal() is refactored, mind adding a descriptive Doxygen comment to its declaration?

Moving the responsibility to check fListen to callers looks a bit fragile. Maybe it would better to self-document it with the Assert(fListen); ?

@naumenkogs naumenkogs force-pushed the 2020-08-refactor-advertiselocal branch 2 times, most recently from 3d4322c to af81f77 Compare September 23, 2020 07:12
@naumenkogs naumenkogs closed this Sep 24, 2020
@naumenkogs naumenkogs reopened this Sep 24, 2020
Copy link
Contributor

@amitiuttarwar amitiuttarwar left a comment

Choose a reason for hiding this comment

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

concept ACK. have read through the code, but I'm still understanding the specifics of address semantics to work towards being able to leave a review ACK.

some structural feedback- it took a while for me to discern which parts were pure refactor vs behavioral change. breaking the first commit into 2 separate parts to clarify those boundaries would help ease review.

src/net_processing.cpp Show resolved Hide resolved
@naumenkogs
Copy link
Member Author

@amitiuttarwar how would you suggest to split the first commit into two? I'd be happy to take suggestions :)
I don't see a way to do it, because the refactor is to merge two a little different chunks of code into one (AdvertiseLocal).

The only way I see is to add a flag to AdvertiseLocal to discern the two, and then drop the flag right in the next commit ("behaviour change"). But do you think that would make the code easier to follow? :)

src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.h Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
@naumenkogs naumenkogs force-pushed the 2020-08-refactor-advertiselocal branch from af81f77 to 85c9839 Compare October 6, 2020 07:29
@robot-dreams
Copy link
Contributor

Per @amitiuttarwar 's suggestion, here's one way I might split your first commit 89c77a0 into two separate parts for easier review:

Alternatively, here's a more fine-grained approach, in which I split your first commit 89c77a0 into 8 separate commits, 5 refactoring only commits and 3 behavior changes:

a0a422c...e2c1c58

The more fine-grained approach might also be helpful for PR Review Club participants who are trying to understand exactly what changed in your first commit.

Copy link
Contributor

@jnewbery jnewbery left a comment

Choose a reason for hiding this comment

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

The first commit seems ok, although it should be restructured to separate the pure refactor parts from the behaviour change parts.

I'm not sure that the second commit actually achieves anything. We have a rolling bloom filter m_addr_known for each peer that prevents us from resending the same address multiple times, so I think even if we do call AdvertiseLocal() again shortly after the verack, it won't actually result in us sending our address again.

src/net.cpp Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.h Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
@naumenkogs
Copy link
Member Author

@jnewbery thanks for the feedback, all addressed.
I agree with your hesitation regarding the further commit. It probably doesn't change behavior at all, I just thought it would make it easier to understand what's going on (despite adding 2 extra lines).

Let's see others' preferences, I'm fine with dropping this commit too.

@naumenkogs naumenkogs force-pushed the 2020-08-refactor-advertiselocal branch 2 times, most recently from eb59506 to b77272e Compare October 6, 2020 11:13
src/net.h Show resolved Hide resolved
Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

Thanks, I think I have a better understanding what's going on after your response. Just some nitty ideas. :)

src/net.h Outdated Show resolved Hide resolved
src/net.cpp Outdated Show resolved Hide resolved
src/net.h Outdated
bool IsPeerAddrLocalGood(CNode& pnode);

/**
* Add our "best" local address to the batch of addresses we are planning
Copy link
Contributor

Choose a reason for hiding this comment

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

If we hear multiple addresses for ourselves from peers, how do we determine "best"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Expanded this comment a bit to refer to GetLocal.
Evaluating the security of GetLocal is on my TODO list, but for now we can assume it works I guess...

Copy link
Contributor

@fjahr fjahr left a comment

Choose a reason for hiding this comment

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

Concept ACK

src/net.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
@naumenkogs naumenkogs force-pushed the 2020-08-refactor-advertiselocal branch from b77272e to 25e674e Compare October 7, 2020 06:38
Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

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

I've re-reviewed. My comments have been addressed and I have no further comments at the moment.

naumenkogs and others added 7 commits December 18, 2020 10:07
…_local_addr_send

This locking was mistakenly introduced in PR bitcoin#13123.
Related conversation:
bitcoin#13123 (comment)

Making these fields atomic would ensure safety
if multiple RPC accesses them.
They're not called outside net.cpp, so they only need internal linkage.
These functions can't be called with null ptrs, so change the signatures
to take references.
…Local

This is a pure refactor commit and moves the checks to the calling function.
Previously AdvertiseLocal() used either the address a peer thinks we are,
or the address we think we are.

Use both instead (assuming the local one is routable), as it would increase our
chances of getting connected to.
Previously, we would prepare to self-announce to a new peer while
parsing a VERSION message from that peer. This is useless,
because we do something very similar in AdvertiseLocal(),
although there are a couple differences:
1) AdvertiseLocal() does this for all peers, not just outbound
2) AdvertiseLocal() always asks the peer to advertise based on what
they think we are AND what we think we are (assuming it's routable),
while PushAddress(self) on VERSION always does one of the two.

(1) and the fact that AdvertiseLocal() is called right before
actually sending out ADDR message with our address makes it fully
encompassing PushAddress(self) on VERSION.

Per (2), AdvertiseLocal() seems like a better version of
PushAddress(self) on VERSION.

Thus, it's fine to drop PushAddress(self) on VERSION.
@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 7, 2021

🐙 This pull request conflicts with the target branch and needs rebase.

Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft".

@naumenkogs
Copy link
Member Author

Much changed since I opened this PR. Pretty sure dropping a redundant self-announcement from ProcessMessage still makes sense, but perhaps we should revisit that after #21186 lands.

@naumenkogs naumenkogs closed this Apr 16, 2021
@jnewbery
Copy link
Contributor

Pretty sure dropping a redundant self-announcement from ProcessMessage still makes sense, but perhaps we should revisit that after #21186 lands.

@naumenkogs - do you plan on picking this up now that #21186 is merged? Should we mark this PR up for grabs?

@naumenkogs
Copy link
Member Author

@jnewbery Yeah I'd be happy to let someone else lead this. Let's mark it up for grabs.

@fanquake
Copy link
Member

fanquake commented Aug 5, 2022

@dergoegge @mzumsande either of you might be interested in following up with the final commit, 99f6768, if it's still relevant?

@mzumsande
Copy link
Contributor

@dergoegge @mzumsande either of you might be interested in following up with the final commit, 99f6768, if it's still relevant?

Only saw this now, because I was looking at the self-advertising logic, and I think it's still relevant, so I'm planing on following up.

Another problem with the self-advertising within Version message processing is that it doesn't work well with addrv2:
If the local address we want to advertise is an outbound peer is an .onion address, then we don't actually advertise it (IsAddrCompatible() returns false) because we haven't received a sendaddrv2 yet at this point. So that is another reason why it makes sense to wait with the advertising until feature negotiation is finished.

maflcko pushed a commit to maflcko/bitcoin-core that referenced this pull request Dec 12, 2022
956c670 refactor, doc: Improve SetupAddressRelay call in version processing (Martin Zumsande)
3c43d9d p2p: Don't self-advertise during VERSION processing (Gleb Naumenko)

Pull request description:

  This picks up the last commit from bitcoin#19843.

  Previously, we would prepare to self-announce to a new peer while parsing a `version` message from that peer.
  This is redundant, because we do something very similar in `MaybeSendAddr()`, which is called from `SendMessages()` after
  the version handshake is finished.

  There are a couple of differences:

  1) `MaybeSendAddr()` self-advertises to all peers we do address relay with, not just outbound ones.
  2) `GetLocalAddrForPeer()` called from `MaybeSendAddr()` makes a probabilistic decision to either advertise what they think we are or what we think we are, while `PushAddress()` on `version` deterministically only does the former if the address from the latter is unroutable.
  3) During `version` processing, we haven't received a potential sendaddrv2 message from our peer yet, so self-advertisements with addresses from addrV2-only networks would always be dropped in `PushAddress()`.

  Since it's confusing to have two slightly different mechanisms for self-advertising, and the one in `MaybeSendAddr()` is better, remove the one in `version`.

ACKs for top commit:
  stratospher:
    ACK  956c670
  naumenkogs:
    ACK 956c670
  amitiuttarwar:
    reACK 956c670

Tree-SHA512: 933d40615289f055c022170dde7bad0ac0a1d4be377538bfe9ba64375cfeb03bcd803901591f0739ac4850c880e8475a68fd1ab0330800030ab7f19e38c00274
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Dec 12, 2022
956c670 refactor, doc: Improve SetupAddressRelay call in version processing (Martin Zumsande)
3c43d9d p2p: Don't self-advertise during VERSION processing (Gleb Naumenko)

Pull request description:

  This picks up the last commit from bitcoin#19843.

  Previously, we would prepare to self-announce to a new peer while parsing a `version` message from that peer.
  This is redundant, because we do something very similar in `MaybeSendAddr()`, which is called from `SendMessages()` after
  the version handshake is finished.

  There are a couple of differences:

  1) `MaybeSendAddr()` self-advertises to all peers we do address relay with, not just outbound ones.
  2) `GetLocalAddrForPeer()` called from `MaybeSendAddr()` makes a probabilistic decision to either advertise what they think we are or what we think we are, while `PushAddress()` on `version` deterministically only does the former if the address from the latter is unroutable.
  3) During `version` processing, we haven't received a potential sendaddrv2 message from our peer yet, so self-advertisements with addresses from addrV2-only networks would always be dropped in `PushAddress()`.

  Since it's confusing to have two slightly different mechanisms for self-advertising, and the one in `MaybeSendAddr()` is better, remove the one in `version`.

ACKs for top commit:
  stratospher:
    ACK  956c670
  naumenkogs:
    ACK 956c670
  amitiuttarwar:
    reACK 956c670

Tree-SHA512: 933d40615289f055c022170dde7bad0ac0a1d4be377538bfe9ba64375cfeb03bcd803901591f0739ac4850c880e8475a68fd1ab0330800030ab7f19e38c00274
@bitcoin bitcoin locked and limited conversation to collaborators Sep 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.