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

net processing: Extract addr send functionality into MaybeSendAddr() #21236

Merged
merged 7 commits into from
Apr 1, 2021

Conversation

jnewbery
Copy link
Contributor

This continues the work of moving application layer data into net_processing. It refactors addr send functionality into its own function MaybeSendAddr() and flattens/simplifies the code. Isolating and simplifying the addr handling code makes subsequent changes (which will move addr data and logic into net processing) easier to review.

This is a pure refactor. There are no functional changes.

For motivation of the project, see #19398.

src/net_processing.cpp Outdated Show resolved Hide resolved
@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 19, 2021

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.

@jnewbery
Copy link
Contributor Author

Rebased on master to pick up fix for interface_zmq.py in #21008.

Copy link
Contributor

@ajtowns ajtowns left a comment

Choose a reason for hiding this comment

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

Haven't thoroughly reviewed the "Refactor MaybeSendAddr" commit; seems like separating it into three or four commits would be clearer (early exit; invariants; skip vAddr check; one-pass erase)?

src/net.h Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
@jnewbery jnewbery force-pushed the 2021-02-maybe-send-addr branch 2 times, most recently from 5d2d6ea to 98f5e5d Compare February 28, 2021 11:52
@jnewbery
Copy link
Contributor Author

Thanks for the review @ajtowns. I've addressed your comments.

@jnewbery
Copy link
Contributor Author

Oops. I missed taking the new lock in one of the call sites. Will fix up tomorrow.

@jnewbery jnewbery force-pushed the 2021-02-maybe-send-addr branch 4 times, most recently from 5b483e3 to 4ebc1ed Compare March 1, 2021 17:56
@jnewbery
Copy link
Contributor Author

jnewbery commented Mar 1, 2021

Once all of the addr data has been moved into net_processing, I intend to guard it with a single lock (see the m_addr_relay struct in https://github.com/jnewbery/bitcoin/tree/2021-02-lazy-init-peer). However, it's proving difficult to get lock orders right while the data is still in net. I've decided to punt on doing that until after this PR.

To avoid simply removing the guard from m_next_addr_send and m_next_local_addr_send, I've introduced the new m_addr_mutex lock in this PR. Once the data is moved into Peer, I'll extend that mutex to guard the remaining addr data.

Copy link
Member

@fanquake fanquake 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 - this seems like a fairly good simplification. I like consolidating logic and returning early when possible. If this SendMessages() logic is going to be split up even more, you could consider a call to GetTime<>() at the start, and just pass that into MaybeSendPing, MaybeSendAddr, MaybeSomeOtherFunc etc.

This doesn't currently compile:

net_processing.cpp:4408:91: error: no member named 'm_addr_mutex' in 'CNode'
    auto addr_already_known = [&node](const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(node.m_addr_mutex)
                                                                                     ~~~~ ^
./threadsafety.h:31:79: note: expanded from macro 'EXCLUSIVE_LOCKS_REQUIRED'
#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__)))
                                                                              ^~~~~~~~~~~
1 error generated.

src/net_processing.cpp Outdated Show resolved Hide resolved
src/net_processing.cpp Outdated Show resolved Hide resolved
@jnewbery
Copy link
Contributor Author

jnewbery commented Mar 3, 2021

Thanks for the review, @fanquake! The compile error was due to an annotation that I'd left from a previous branch. It's now fixed.

If this SendMessages() logic is going to be split up even more, you could consider a call to GetTime<>() at the start, and just pass that into MaybeSendPing, MaybeSendAddr, MaybeSomeOtherFunc etc.

Good idea. Done!

We currently call GetTime() 4 times in SendMessages(). Consolidate this to
once GetTime() call.
Reviewer hint: review with

 `git diff --color-moved=dimmed-zebra --ignore-all-space`
Change name of CNode parameter to node now that it's no longer a
pointer.
Add early exit guard clauses if node.RelayAddrsWithConn() is false or if
current_time < node.m_next_addr_send. Add comments.

This commit leaves some lines over-indented. Those will be fixed in a
subsequent whitespace-only commit.
Reviewer hint: review with `git diff --ignore-all-space`.
@jnewbery
Copy link
Contributor Author

Thanks for the review @hebasto! Responding to your points:

I see two calls of three are consolidated. What about the third one [...]

I was also counting the call inside MaybeSendPing(), which is called from SendMessages(). I've now removed the additional call to GetTime() as suggested, which required a duration cast.

I believe that this commit is not a clean refactoring. To be precise, change behavior could be expected as even LOCK(cs_main); could take unpredictable time. But the scale of such changes seems insignificant to P2P, right?

Good observation! However, I think it's fine to treat time as constant within a call to SendMessages(), since it's observationally equivalent to any actors outside net_processing.

The commit "[net processing] Extract addr send functionality into MaybeSendAddr()" (97e1013) allows to localize acquiring of the CNode::cs_sendProcessing mutex

The fact that you've raised this independently has made me reconsider the discussion here #21236 (comment). It doesn't make sense for a mutex to be guarding variables/functions across multiple layers, so I've moved the addr send time vars under their own mutex.

Early return skips

 // we only send the big addr message once 
 if (node.vAddrToSend.capacity() > 40) { 
     node.vAddrToSend.shrink_to_fit(); 
 } 

That differs from original behavior.

Another great observation! Although again, I don't think it matters. This logic is for when we've sent a response to the peer's getaddr message. In such cases, we'd expect to send up to 1000 addresses, and for the address filter to not yet be filled, so we wouldn't exit early.

@hebasto
Copy link
Member

hebasto commented Mar 29, 2021

RecursiveMutex cs_sendProcessing guards nothing. Let's burn it :)

@hebasto
Copy link
Member

hebasto commented Mar 29, 2021

pico-nit: I find myself more comfortable to reason about the code when the same variable is placed on the same position in similar logical operations. Consider

bitcoin/src/net_processing.cpp

Lines 4154 to 4155 in b4d7d3d

if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload() &&
node.m_next_local_addr_send < current_time) {
and
if (current_time <= node.m_next_addr_send) return;

Could current_time position be consistent?

@jnewbery
Copy link
Contributor Author

pico-nit: I find myself more comfortable to reason about the code when the same variable is placed on the same position in similar logical operations.

I tend to agree and think that generally the variable should be placed on the left and the thing it's being compared to on the right. Others disagreed with me on previous PRs and told me to always place the smaller thing on the left. I think it's just a matter of taste 🤷

@jnewbery jnewbery changed the title Net processing: Extract addr send functionality into MaybeSendAddr() net processing: Extract addr send functionality into MaybeSendAddr() Mar 30, 2021
Changes to make MaybeSendAddr simpler and easier to maintain/update:

- assert invariant that node.vAddrToSend.size() can never exceed
  MAX_ADDR_TO_SEND
- erase known addresses from vAddrToSend in one pass
- no check for (vAddr.size() >= MAX_ADDR_TO_SEND) during iteration,
  since vAddr can never exceed MAX_ADDR_TO_SEND.
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.

ACK 935d488, I have reviewed the code and it looks OK, I agree it can be merged.

@sipa
Copy link
Member

sipa commented Mar 31, 2021

utACK 935d488

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

review ACK 935d488 🐑

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

review ACK 935d4889228e7e361c8b0020761fa0e08a55fb48 🐑
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUh7Hgv/dmVk2jwk66OpRVhWiCUITNoKMBCZFBA8+k63KsptFTEUV0oneUoiMVTm
Ftw+YVO60MZdNQjBet3CC3IyTUv098/H2+e9cODLgbRpRMJaLewzevxUy0o6RToQ
BzHalKxNnrGEUnJB/6zm4HzXWIPJWppY947BlLEuZ+HM7J8HgAmFVPZWa/VubsrN
YhY6rBbtHuJKGamsdE/LkNfNEMhP4dIOksl1WteXg2xoSeBHQeHL6nFLKFjJohbj
Y34ZSnxo0jJFpz+bSVlzelJh5EL7/G+fZzvE5vbOa39+5unZ2mFx70ftvGYgRK6V
qLfhnyeTMABXjs5bwU3HcjVGqa1ZsApIhY+sLs6lwSQmNAG2UjOxPcl7EDcXnZha
fV//g/jdU5qTyNQiriWrA0TEtwPm7X1lgJFYBgpfSAfnSIxbLk/uZWkPqFVVbt5P
Mh2PXN7lIqJ/irxKTBscAXqX4RrIbHXHVv5TaUvS3kI2igSLaKjUhj2Nqoea6UZ3
XBBbfMvT
=sVrE
-----END PGP SIGNATURE-----

Timestamp of file with hash 2166a9ff7592f66162db55121e31cb0376f60455376bea865e5631ad552a2fc6 -

@maflcko maflcko merged commit 539e4ee into bitcoin:master Apr 1, 2021
@jnewbery jnewbery deleted the 2021-02-maybe-send-addr branch April 1, 2021 07:07
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Apr 1, 2021
luke-jr pushed a commit to bitcoinknots/bitcoin that referenced this pull request Jun 27, 2021
We currently call GetTime() 4 times in SendMessages(). Consolidate this to
once GetTime() call.

Github-Pull: bitcoin#21236
Rebased-From: c02fa47
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 28, 2022
Summary:
We currently call GetTime() 4 times in SendMessages(). Consolidate this to once GetTime() call.

This is a backport of [[bitcoin/bitcoin#21236 | core#21236]] [1/6]
bitcoin/bitcoin@c02fa47

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10915
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 28, 2022
Summary:
Reviewer hint: review with

 `git diff --color-moved=dimmed-zebra --ignore-all-space`

This is a backport of [[bitcoin/bitcoin#21236 | core#21236]] [3/6]
bitcoin/bitcoin@ad71929

Depends on D10916

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10917
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 28, 2022
Summary:
Change name of CNode parameter to node now that it's no longer a pointer.

This is a backport of [[bitcoin/bitcoin#21236 | core#21236]] [4/6]
bitcoin/bitcoin@c87423c

Depends on D10917

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10918
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 28, 2022
Summary:
Add early exit guard clauses if node.RelayAddrsWithConn() is false or if
current_time < node.m_next_addr_send. Add comments.

This is a backport of [[bitcoin/bitcoin#21236 | core#21236]] [5/6]
bitcoin/bitcoin@38c0be5
bitcoin/bitcoin@01a79ff

Depends on D10918

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10919
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Jan 28, 2022
Summary:
Changes to make MaybeSendAddr simpler and easier to maintain/update:

- assert invariant that node.vAddrToSend.size() can never exceed
  MAX_ADDR_TO_SEND
- erase known addresses from vAddrToSend in one pass
- no check for (vAddr.size() >= MAX_ADDR_TO_SEND) during iteration,
  since vAddr can never exceed MAX_ADDR_TO_SEND.

Note: we used `GetMaxAddrToSend()` instead of `MAX_ADDR_TO_SEND` because it can be overriden by the  `-maxaddrtosend` command line option (D10823]

This concludes backport of [[bitcoin/bitcoin#21236 | core#21236]] [6/6]
bitcoin/bitcoin@935d488

Depends on D10919

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D10920
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
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.

9 participants