net: guard vRecvGetData with cs_vRecv and orphan_work_set with g_cs_orphans #19911

pull narula wants to merge 6 commits into bitcoin:master from narula:cs_vRecv changing 2 files +79 −49
  1. narula commented at 7:32 pm on September 7, 2020: contributor

    Add annotations to guard vRecvGetData and orphan_work_set and fix up places where they were accessed without a lock. There is no current data race because they happen to be accessed by only one thread, but this might not always be the case.

    Original discussion: #18861 (review)

  2. practicalswift commented at 7:38 pm on September 7, 2020: contributor
    Concept ACK
  3. DrahtBot added the label P2P on Sep 7, 2020
  4. DrahtBot added the label Needs rebase on Sep 7, 2020
  5. in src/net_processing.cpp:2922 in a4d7f3dc31 outdated
    2882@@ -2880,7 +2883,10 @@ void PeerLogicValidation::ProcessMessage(CNode& pfrom, const std::string& msg_ty
    2883             CInv inv;
    2884             inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
    2885             inv.hash = req.blockhash;
    2886-            pfrom.vRecvGetData.push_back(inv);
    2887+            {
    2888+                LOCK(pfrom.cs_vRecv);
    2889+                pfrom.vRecvGetData.push_back(inv);
    2890+            }
    


    jnewbery commented at 7:54 pm on September 7, 2020:

    Consider using the WITH_LOCK macro for simple one-line statements:

    0            WITH_LOCK(pfrom.cs_vRecv, pfrom.vRecvGetData.push_back(inv));
    

    narula commented at 9:15 pm on September 7, 2020:
    done!
  6. in src/net_processing.cpp:3866 in a4d7f3dc31 outdated
    3860@@ -3855,15 +3861,20 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
    3861     //
    3862     bool fMoreWork = false;
    3863 
    3864-    if (!pfrom->vRecvGetData.empty())
    3865-        ProcessGetData(*pfrom, chainparams, m_connman, m_mempool, interruptMsgProc);
    3866+    {
    3867+        LOCK(pfrom->cs_vRecv);
    3868+        if (!pfrom->vRecvGetData.empty())
    


    jnewbery commented at 8:14 pm on September 7, 2020:
    style: consider adding braces to if blocks when touching code, to conform with the current style guide.

    narula commented at 9:16 pm on September 7, 2020:
    done! did not do so to adjacent code i wasn’t touching.
  7. jnewbery commented at 8:14 pm on September 7, 2020: member

    Concept ACK.

    I’ve left a couple of style comments inline. Will review fully once this is rebased.

  8. narula force-pushed on Sep 7, 2020
  9. narula force-pushed on Sep 7, 2020
  10. DrahtBot removed the label Needs rebase on Sep 7, 2020
  11. narula commented at 10:46 pm on September 7, 2020: contributor
    The thread sanitizer is complaining about locking order; I’m looking into it.
  12. in src/net_processing.cpp:1725 in 3fe40815bf outdated
    1721@@ -1722,7 +1722,7 @@ static CTransactionRef FindTxForGetData(const CTxMemPool& mempool, const CNode&
    1722     return {};
    1723 }
    1724 
    1725-void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
    1726+void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(pfrom.cs_vRecv) LOCKS_EXCLUDED(cs_main)
    


    hebasto commented at 7:28 am on September 8, 2020:
    0static void ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc)
    1    EXCLUSIVE_LOCKS_REQUIRED(!cs_main, pfrom.cs_vRecv)
    

    narula commented at 10:49 pm on September 8, 2020:

    Thanks @hebasto! TIL. It’s certainly shorter, but I’m worried people might miss the ! if reading quickly, and think this function requires cs_main.

    Could you share why you suggest switching from void static to static void? Is it for general cleanup?


    hebasto commented at 5:44 am on September 9, 2020:

    Thanks @hebasto! TIL. It’s certainly shorter, but I’m worried people might miss the ! if reading quickly, and think this function requires cs_main.

    It is not about “shorter” :) See:

    Could you share why you suggest switching from void static to static void? Is it for general cleanup?

    E.g., fa0572d0f3b083b4c8e2e883a66e2b198c6779f1 by @MarcoFalke

  13. hebasto commented at 7:28 am on September 8, 2020: member
    Concept ACK.
  14. in src/net.h:829 in 3fe40815bf outdated
    825@@ -825,7 +826,7 @@ class CNode
    826 
    827     RecursiveMutex cs_sendProcessing;
    828 
    829-    std::deque<CInv> vRecvGetData;
    830+    std::deque<CInv> vRecvGetData GUARDED_BY(cs_vRecv);
    


    jnewbery commented at 8:19 am on September 8, 2020:

    I don’t think it’s right to reuse this mutex to guard vRecvGetData (despite the name similarities). cs_vRecv was added in 321d0fc6b6624c65508f8b9059418cb936f0bbbe to guard nRecvBytes and mapRecvBytesPerMsgCmd, which are statistics used in the net layer. vRecvGetData is a data structure used in the application layer (and should eventually move to the Peer struct), so should be guarded by a different mutex.

    I do have some commits that move both vRecvGetData and orphan_work_set to the Peer struct in https://github.com/jnewbery/bitcoin/commits/2020-06-cs-main-split-needs-rebase (everything from END move tx data to net processing // START move work queue data to net processing to END move work queue data to net processing // START move subversion to net_processing). It’s slightly orthogonal to this PR, but perhaps we should just do that now while we’re touching these fields?


    hebasto commented at 9:59 am on September 8, 2020:

    vRecvGetData is a data structure used in the application layer (and should eventually move to the Peer struct)…

    Maybe start from moving, and then introduce a mutex?


    jnewbery commented at 10:39 am on September 8, 2020:

    Maybe start from moving, and then introduce a mutex?

    I think that’s probably the cleanest order, but I don’t want to scope-creep @narula’s PR if she thinks it’s better to add the mutex first. I can do the move later.


    hebasto commented at 7:14 am on September 14, 2020:

    I don’t think it’s right to reuse this mutex to guard vRecvGetData (despite the name similarities).

    I agree on not reusing of irrelevant mutex. To keep this PR focused, would it more correctly to introduce a new Mutex m_recvgetdata_mutex?


    narula commented at 1:51 pm on September 14, 2020:
    I agree on a new mutex; I was wondering about that but assumed @sipa had some reason for suggesting using cs_vRecv to guard it in the first place.
  15. hebasto commented at 8:34 am on September 8, 2020: member

    @narula

    The thread sanitizer is complaining about locking order; I’m looking into it.

    Could I suggest some code reorganization to keep locking order constant: https://github.com/hebasto/bitcoin/commits/pr19911-0908 ?

  16. in src/net_processing.cpp:3869 in 3fe40815bf outdated
    3866+    {
    3867+        LOCK(pfrom->cs_vRecv);
    3868+        if (!pfrom->vRecvGetData.empty()) return true;
    3869+    }
    3870+    {
    3871+        LOCK2(cs_main, g_cs_orphans);
    


    jnewbery commented at 9:54 am on September 8, 2020:
    I don’t think cs_main is required here.

    narula commented at 10:29 pm on September 13, 2020:
    right!
  17. narula force-pushed on Sep 13, 2020
  18. in src/net_processing.cpp:2880 in eadbad9d27 outdated
    2894-
    2895-        SendBlockTransactions(pfrom, block, req);
    2896+        LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
    2897+        inv.hash = req.blockhash;
    2898+        WITH_LOCK(pfrom.cs_vRecv, pfrom.vRecvGetData.push_back(inv));
    2899+        // The message processing loop will go around again (without pausing) and we'll respond then (without cs_main)
    


    jnewbery commented at 8:24 am on September 14, 2020:
    This would be a slight sequencing change, but perhaps we should either call ProcessGetData() here, or not call it in the GETDATA processing for consistency. It seems from this comment that the only reason we weren’t calling ProcessGetData() here was that cs_main was being held, which is no longer the case.

    narula commented at 1:55 pm on September 14, 2020:
    Would this be a behavior change?
  19. narula force-pushed on Sep 14, 2020
  20. narula commented at 1:54 pm on September 14, 2020: contributor

    I’ve pushed a new series of commits which move vRecvGetData and orphan_work_set to Peer and then guard them appropriately. It’s a bit more of a change, but happy to help move things over there if that’s the end goal.

    I do have some commits that move both vRecvGetData and orphan_work_set to the Peer struct in https://github.com/jnewbery/bitcoin/commits/2020-06-cs-main-split-needs-rebase (everything from END move tx data to net processing // START move work queue data to net processing to END move work queue data to net processing // START move subversion to net_processing). It’s slightly orthogonal to this PR, but perhaps we should just do that now while we’re touching these fields? @jnewbery I tried to cherry-pick some of your commits but they did not move cleanly given the scope of your branch’s change; I also didn’t do one of the renames you did to minimize the change. Let me know if there’s an appropriate way to credit you.

  21. in src/net_processing.cpp:1733 in e15554c134 outdated
    1729@@ -1722,11 +1730,11 @@ static CTransactionRef FindTxForGetData(const CTxMemPool& mempool, const CNode&
    1730     return {};
    1731 }
    1732 
    1733-void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
    1734+void static ProcessGetData(CNode& pfrom, PeerRef peer, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(!cs_main, peer->cs_vRecvGetData)
    


    jnewbery commented at 3:33 pm on September 14, 2020:

    PeerRef is a shared pointer, so by passing it by value here, you’re incrementing the ref count, and decrementing it again when you leave the function, which incurs a performance cost, since those operations need to be atomic.

    This function doesn’t need to take shared ownership of the underlying Peer object, so you should pass by Peer& (see http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r30-take-smart-pointers-as-parameters-only-to-explicitly-express-lifetime-semantics).


    narula commented at 0:19 am on September 30, 2020:
    thanks for the pointer! fixed.
  22. in src/net_processing.cpp:2346 in e15554c134 outdated
    2341@@ -2334,6 +2342,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
    2342         return;
    2343     }
    2344 
    2345+    PeerRef peer = GetPeerRef(pfrom.GetId());
    2346+    assert(peer);
    


    jnewbery commented at 3:35 pm on September 14, 2020:
    I think it’s probably safer to just return if you can’t find the Peer object here (as all other instances of GetPeerRef() except the FinalizeNode() call do) rather than assert.

    narula commented at 0:19 am on September 30, 2020:
    addressed.
  23. jnewbery commented at 3:35 pm on September 14, 2020: member
    Thanks Neha! A couple of small comments inline.
  24. DrahtBot commented at 1:45 pm on September 19, 2020: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #20158 (tree-wide: De-globalize ChainstateManager by dongcarl)
    • #19910 (net processing: Move peer_map to PeerManager by jnewbery)
    • #19829 (net processing: Move block inventory state to net_processing by jnewbery)
    • #9245 (Drop IO priority to idle while reading blocks for peer requests and startup verification by luke-jr)

    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.

  25. DrahtBot added the label Needs rebase on Sep 29, 2020
  26. narula force-pushed on Sep 29, 2020
  27. narula force-pushed on Sep 29, 2020
  28. narula force-pushed on Sep 30, 2020
  29. narula force-pushed on Sep 30, 2020
  30. DrahtBot removed the label Needs rebase on Sep 30, 2020
  31. in src/net_processing.cpp:2990 in 418cc40c35 outdated
    2986@@ -2984,6 +2987,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
    2987         }
    2988 
    2989         std::list<CTransactionRef> lRemovedTxn;
    2990+        PeerRef peer = GetPeerRef(pfrom.GetId());
    


    jnewbery commented at 11:27 am on September 30, 2020:

    In commit “Move m_orphan_work_set to net_processing”: I think you should put this call at the top of ProcessMessage() in this commit, rather than putting it here, and then moving it up in a later commit.

    Alternatively, you could change the ProcessMessage() signature to take a Peer&. I don’t think that’s necessary, but you may prefer it to fetching the PeerRef in ProcessMessages() and then again in ProcessMessage().


    narula commented at 6:28 pm on September 30, 2020:
    done. I am fine with calling GetPeerRef again, so will leave as is and not change the signature of ProcessMessage().
  32. in src/net_processing.cpp:510 in fe476e0c51 outdated
    492+    std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
    493+
    494+    /** Protects vRecvGetData **/
    495+    Mutex cs_vRecvGetData;
    496+    /** Work queue of items requested by this peer **/
    497+    std::deque<CInv> vRecvGetData GUARDED_BY(cs_vRecvGetData);
    


    jnewbery commented at 11:48 am on September 30, 2020:
    Since you’re touching every line that vRecvGetData is on already, you may as well add a scripted-diff commit to this branch that updates the name to modern style guidelines, e.g. something like m_get_data_requests or similar. Same for the mutex name - it could be renamed to m_get_data_requests_mutex or similar.

    narula commented at 6:26 pm on September 30, 2020:
    done
  33. jnewbery commented at 11:50 am on September 30, 2020: member
    You’ve made the choice to make cs_vRecvGetData be held before cs_main. The alternative would be to make cs_main be held before cs_vRecvGetData, which would mean you don’t need to change the logic in GETBLOCKTXN handling, but would need to change the internals of ProcessGetData(). I think both options are fine.
  34. jnewbery commented at 2:30 pm on September 30, 2020: member
    Sorry - needs rebase :grimacing:
  35. DrahtBot added the label Needs rebase on Sep 30, 2020
  36. narula force-pushed on Sep 30, 2020
  37. narula force-pushed on Sep 30, 2020
  38. narula force-pushed on Sep 30, 2020
  39. narula force-pushed on Sep 30, 2020
  40. DrahtBot removed the label Needs rebase on Sep 30, 2020
  41. narula commented at 6:29 pm on September 30, 2020: contributor
    This is rebased and I think all comments have been addressed.
  42. in src/net_processing.cpp:2895 in 348202f27b outdated
    2897+                SendBlockTransactions(pfrom, block, req);
    2898+                return;
    2899+            }
    2900 
    2901-        if (pindex->nHeight < ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) {
    2902             // If an older block is requested (should never happen in practice,
    


    jnewbery commented at 6:03 pm on October 8, 2020:

    Rather than splitting this logic up (hoisting the CInv declaration above the code block, fetching the type inside the cs_main scope, and then putting the rest of the logic outside the cs_main scope), I recommend you keep all the logic together:

     0--- a/src/net_processing.cpp
     1+++ b/src/net_processing.cpp
     2@@ -2872,8 +2872,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
     3             return;
     4         }
     5 
     6-        CInv inv;
     7-
     8         {
     9             LOCK(cs_main);
    10 
    11@@ -2892,17 +2890,18 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
    12                 return;
    13             }
    14 
    15-            // If an older block is requested (should never happen in practice,
    16-            // but can happen in tests) send a block response instead of a
    17-            // blocktxn response. Sending a full block response instead of a
    18-            // small blocktxn response is preferable in the case where a peer
    19-            // might maliciously send lots of getblocktxn requests to trigger
    20-            // expensive disk reads, because it will require the peer to
    21-            // actually receive all the data read from disk over the network.
    22-            inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
    23         }
    24 
    25+        // If an older block is requested (should never happen in practice,
    26+        // but can happen in tests) send a block response instead of a
    27+        // blocktxn response. Sending a full block response instead of a
    28+        // small blocktxn response is preferable in the case where a peer
    29+        // might maliciously send lots of getblocktxn requests to trigger
    30+        // expensive disk reads, because it will require the peer to
    31+        // actually receive all the data read from disk over the network.
    32         LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
    33+        CInv inv;
    34+        inv.type = WITH_LOCK(cs_main, return State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);
    35         inv.hash = req.blockhash;
    

    It’s slightly wasteful that cs_main is released and then taken again, but I think it’s ok because:

    1. As the comment says, we don’t expect this to happen except in tests
    2. fWantsCmpctWitness should move to the Peer struct eventually, removing the need to take cs_main

    narula commented at 10:46 pm on October 13, 2020:

    Agreed, this is nicer! Changed.

    Interestingly, your exact suggestion didn’t work: I had to move the assignment to inv.type inside the WITH_LOCK macro. I got the following error the other way:

    0./sync.h:257:45: note: expanded from macro 'WITH_LOCK'
    1#define WITH_LOCK(cs, code) [&] { LOCK(cs); code; }()
    2                                            ^~~~
    3net_processing.cpp:2934:20: error: assigning to 'uint32_t' (aka 'unsigned int') from incompatible type 'void'
    4        inv.type = WITH_LOCK(cs_main, State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);
    5                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6./sync.h:257:29: note: expanded from macro 'WITH_LOCK'
    7#define WITH_LOCK(cs, code) [&] { LOCK(cs); code; }()
    8                            ^~~~~~~~~~~~~~~~~~~~~~~~~
    

    jnewbery commented at 8:42 am on October 14, 2020:

    It looks like you missed out the return from inside the WITH_LOCK macro’s second argument:

    inv.type = WITH_LOCK(cs_main, return State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);

    But your way is also fine!

  43. in src/net_processing.cpp:519 in 348202f27b outdated
    500@@ -501,6 +501,14 @@ struct Peer {
    501     /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
    502     bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
    503 
    504+    /** Set of txids to reconsider once their parent transactions have been accepted **/
    505+    std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
    506+
    507+    /** Protects m_getdata_requests **/
    508+    Mutex m_getdata_requests_mutex;
    


    jnewbery commented at 6:05 pm on October 8, 2020:
    Just realised you add this as cs_vRecvGetData in one commit and then change it with a scripted diff in the subsequent commit. You can just name it m_getdata_requests_mutex in the first commit!
  44. jnewbery commented at 6:05 pm on October 8, 2020: member
    Couple of style/ordering suggestions, but otherwise looks good to me!
  45. DrahtBot added the label Needs rebase on Oct 12, 2020
  46. [Rename only] Rename orphan_work_set to m_orphan_work_set.
    This helps distinguish the member from any local variables.
    9c47cb29f9
  47. narula force-pushed on Oct 13, 2020
  48. promag commented at 11:03 pm on October 13, 2020: member
    Concept ACK and almost code review ACK, still reviewing 939880b7005386d75e2eb31869f2357e82f64a67.
  49. DrahtBot removed the label Needs rebase on Oct 13, 2020
  50. jnewbery commented at 9:12 am on October 14, 2020: member

    In commit Move m_orphan_work_set to net_processing, you’re not removing CNode::m_orphan_work_set.

    Other than that, looks good!

  51. Move m_orphan_work_set to net_processing 8803aee668
  52. Lock before checking if orphan_work_set is empty; indicate it is guarded 673247b58c
  53. Move vRecvGetData to net processing 2d9f2fca43
  54. Guard vRecvGetData (now in net processing) with its own mutex
    This requires slightly reorganizing the logic in GETBLOCKTXN to
    maintain locking order.
    ba951812ec
  55. scripted-diff: rename vRecvGetData
    -BEGIN VERIFY SCRIPT-
    sed -i 's/vRecvGetData/m_getdata_requests/g' src/net_processing.cpp
    -END VERIFY SCRIPT-
    da0988daf1
  56. narula force-pushed on Oct 14, 2020
  57. narula commented at 2:11 pm on October 14, 2020: contributor

    In commit Move m_orphan_work_set to net_processing, you’re not removing CNode::m_orphan_work_set.

    Other than that, looks good!

    Good catch, I lost that in the last rebase! Fixed.

  58. jnewbery commented at 2:35 pm on October 14, 2020: member
    Code review ACK da0988daf1d665a4644ad3f1ddf3f8a8bdd88cde
  59. in src/net_processing.cpp:515 in 8803aee668 outdated
    511@@ -512,6 +512,9 @@ struct Peer {
    512     /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
    513     bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
    514 
    515+    /** Set of txids to reconsider once their parent transactions have been accepted **/
    


    hebasto commented at 2:55 pm on October 14, 2020:

    8803aee66813d27ddbdfce937ab9c35f8f7c35bc

    To describe a member //! is recommended:

    0    //! Set of txids to reconsider once their parent transactions have been accepted.
    

    jnewbery commented at 3:55 pm on October 14, 2020:
    I see lots of examples of /** being used for member comments throughout the codebase. We should update the developer docs to say both styles are allowed rather than try to change all comments to fit to one style.

    hebasto commented at 3:57 pm on October 14, 2020:
    Agree.

    narula commented at 10:06 pm on October 14, 2020:
    Resolution: I’ll leave this as is.
  60. in src/net_processing.cpp:2370 in 8803aee668 outdated
    2365@@ -2363,6 +2366,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
    2366         return;
    2367     }
    2368 
    2369+    PeerRef peer = GetPeerRef(pfrom.GetId());
    2370+    if (peer == nullptr) return;
    


    hebasto commented at 2:56 pm on October 14, 2020:

    8803aee66813d27ddbdfce937ab9c35f8f7c35bc, nit:

    0    if (!peer) return;
    


    hebasto commented at 6:27 am on October 15, 2020:
    I don’t think it is required to be consistent with a bad style of the surrounding code. Are we going to check every raw/smart pointer against nullptr explicitly everywhere in the code?

    jnewbery commented at 9:06 am on October 15, 2020:
    I think both are fine. We don’t express a preference in our style guide. I think @hebasto’s suggestion is more idiomatic, and if I were writing those lines again, I’d use the !ptr form.
  61. in src/net_processing.cpp:3874 in 8803aee668 outdated
    3869@@ -3865,12 +3870,15 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgP
    3870 {
    3871     bool fMoreWork = false;
    3872 
    3873+    PeerRef peer = GetPeerRef(pfrom->GetId());
    3874+    if (peer == nullptr) return false;
    


    hebasto commented at 2:58 pm on October 14, 2020:

    8803aee66813d27ddbdfce937ab9c35f8f7c35bc, nit:

    0    if (!peer) return false;
    
  62. in src/net_processing.cpp:516 in 673247b58c outdated
    512@@ -513,7 +513,7 @@ struct Peer {
    513     bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
    514 
    515     /** Set of txids to reconsider once their parent transactions have been accepted **/
    516-    std::set<uint256> m_orphan_work_set;
    517+    std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
    


    hebasto commented at 3:08 pm on October 14, 2020:

    673247b58cd1252ab7e99f7d63ead05cc100cef2, nit:

    0    std::set<uint256> m_orphan_work_set GUARDED_BY(::g_cs_orphans);
    

    narula commented at 10:21 pm on October 14, 2020:
    Thank you for the suggestion! Could you point me towards anything which indicates why this might be preferred? Based on my understanding, it seems like a style preference. 1) Globals are already prefixed with g_ making it very unlikely to have a conflicting local variable 2) I don’t see anywhere else in the codebase using this operator for globals.

    hebasto commented at 6:19 am on October 15, 2020:

    git grep ::cs or https://github.com/bitcoin/bitcoin/blob/f2e6d14430137a271d153348d207df6ab8086bc6/src/init.cpp#L216

    Based on my understanding, it seems like a style preference.

    Correct. Feel free to ignore this nit.

  63. in src/net_processing.cpp:3893 in 673247b58c outdated
    3888@@ -3887,7 +3889,10 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgP
    3889     // this maintains the order of responses
    3890     // and prevents vRecvGetData to grow unbounded
    3891     if (!pfrom->vRecvGetData.empty()) return true;
    3892-    if (!peer->m_orphan_work_set.empty()) return true;
    3893+    {
    3894+        LOCK(g_cs_orphans);
    


    hebasto commented at 3:08 pm on October 14, 2020:

    673247b58cd1252ab7e99f7d63ead05cc100cef2, nit:

    0        LOCK(::g_cs_orphans);
    
  64. in src/net_processing.cpp:518 in 2d9f2fca43 outdated
    514@@ -515,6 +515,9 @@ struct Peer {
    515     /** Set of txids to reconsider once their parent transactions have been accepted **/
    516     std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
    517 
    518+    /** Work queue of items requested by this peer **/
    


    hebasto commented at 3:10 pm on October 14, 2020:

    2d9f2fca43aadcdda4d644cddab36dca88b40b97

    To describe a member //! is recommended:

    0    //! Work queue of items requested by this peer.
    

    narula commented at 10:07 pm on October 14, 2020:
    As noted above, leaving this as is.
  65. in src/net_processing.cpp:1761 in 2d9f2fca43 outdated
    1756@@ -1754,7 +1757,10 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
    1757 {
    1758     AssertLockNotHeld(cs_main);
    1759 
    1760-    std::deque<CInv>::iterator it = pfrom.vRecvGetData.begin();
    1761+    PeerRef peer = GetPeerRef(pfrom.GetId());
    1762+    if (peer == nullptr) return;
    


    hebasto commented at 3:11 pm on October 14, 2020:

    2d9f2fca43aadcdda4d644cddab36dca88b40b97, nit:

    0    if (!peer) return;
    
  66. in src/net_processing.cpp:1763 in 2d9f2fca43 outdated
    1756@@ -1754,7 +1757,10 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
    1757 {
    1758     AssertLockNotHeld(cs_main);
    1759 
    1760-    std::deque<CInv>::iterator it = pfrom.vRecvGetData.begin();
    1761+    PeerRef peer = GetPeerRef(pfrom.GetId());
    1762+    if (peer == nullptr) return;
    1763+
    1764+    std::deque<CInv>::iterator it = peer->vRecvGetData.begin();
    


    hebasto commented at 3:11 pm on October 14, 2020:

    2d9f2fca43aadcdda4d644cddab36dca88b40b97, nit:

    0    auto it = peer->vRecvGetData.begin();
    

    jnewbery commented at 9:08 am on October 15, 2020:
    We don’t have guidance about auto usage in our style guide. I personally think auto should only be used if the type is immediately obvious from the surrounding code, and it’s saving redundant and verbose keystrokes.

    hebasto commented at 9:19 am on October 15, 2020:

    We don’t have guidance about auto usage in our style guide.

    Yes. And I think we should have it.

    I personally think auto should only be used if the type is immediately obvious from the surrounding code, and it’s saving redundant and verbose keystrokes.

    https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/


    jnewbery commented at 10:23 am on October 15, 2020:

    Thanks @hebasto. I hadn’t seen that particular blog post before, but I am familiar with the arguments for and against auto. Scott Meyers also dedicates a chapter to it in Exceptional Modern C++.

    Here, I think it’s useful to explicitly name the type, since CInv is part of the interface. Sure, we could switch out std::deque for another container at some point, but to know what it->IsGenTxMsg() is doing a few lines further down, you need to know that it is an iterator over some container of CInvs. I’d much rather the code told me that explicitly than having to go find out what m_getdata_requests is from somewhere else.


    hebasto commented at 10:30 am on October 15, 2020:
    ok.

    narula commented at 7:14 pm on October 15, 2020:
    That is a very interesting post! I’m not sure I entirely agree with his reasoning against the readability argument, but perhaps we could debate that somewhere else :) I think this could go either way, and I prefer having the type explicit.
  67. in src/net_processing.cpp:3932 in 2d9f2fca43 outdated
    3927@@ -3921,7 +3928,7 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgP
    3928         ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc);
    3929         if (interruptMsgProc)
    3930             return false;
    3931-        if (!pfrom->vRecvGetData.empty())
    3932+        if (!peer->vRecvGetData.empty())
    3933             fMoreWork = true;
    


    hebasto commented at 3:12 pm on October 14, 2020:

    2d9f2fca43aadcdda4d644cddab36dca88b40b97

    nit: add braces or make one line?

  68. in src/net_processing.cpp:518 in ba951812ec outdated
    514@@ -515,8 +515,10 @@ struct Peer {
    515     /** Set of txids to reconsider once their parent transactions have been accepted **/
    516     std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
    517 
    518+    /** Protects vRecvGetData **/
    


    hebasto commented at 3:14 pm on October 14, 2020:

    ba951812ec0cc8ebee5911a582f188525b76ff0a

    To describe a member //! is recommended:

    0    //! Protects vRecvGetData.
    
  69. in src/net_processing.cpp:2934 in ba951812ec outdated
    2955+        // might maliciously send lots of getblocktxn requests to trigger
    2956+        // expensive disk reads, because it will require the peer to
    2957+        // actually receive all the data read from disk over the network.
    2958+        LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
    2959+        CInv inv;
    2960+        WITH_LOCK(cs_main, inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);
    


    hebasto commented at 3:29 pm on October 14, 2020:

    I think this could change behavior as between two consequent ::cs_main holding the guarded state could be changed.

    Maybe just place State call into the guarded block above?


    jnewbery commented at 3:54 pm on October 14, 2020:
    Whether a peer prefers witness data is independent from whether the block can be fetched from disk. The fact that they both happen to be guarded by cs_main is more of a historic accident than anything else. I think it’s fine to release and retake cs_main here.

    hebasto commented at 3:56 pm on October 14, 2020:
    @jnewbery Thanks!
  70. hebasto commented at 3:31 pm on October 14, 2020: member

    Approach ACK da0988daf1d665a4644ad3f1ddf3f8a8bdd88cde.

    Mind making the first rename commit a scripted-diff as well?

  71. jnewbery commented at 3:56 pm on October 14, 2020: member

    Mind making the first rename commit a scripted-diff as well?

    It can’t be, since orphan_work_set is currently used as the name for both a member variable and a local variable.

  72. hebasto commented at 3:59 pm on October 14, 2020: member

    Mind making the first rename commit a scripted-diff as well?

    It can’t be, since orphan_work_set is currently used as the name for both a member variable and a local variable.

    Indeed. Sorry.

  73. narula commented at 7:19 pm on October 15, 2020: contributor

    I think all comments have been addressed except the remaining review comments which I can summarize to the following nits:

    1. change if (peer == nullptr) to if (!peer) in the places where I add a new nullptr check
    2. fix up an existing if without braces: #19911 (review) in a line I touch

    I don’t think these are important, and I already have one ACK on the code so I’d prefer not to change them. However, if others disagree, I can do so.

  74. hebasto approved
  75. hebasto commented at 7:35 pm on October 16, 2020: member

    ACK da0988daf1d665a4644ad3f1ddf3f8a8bdd88cde, I have reviewed the code and it looks correct, I agree it can be merged.

    My only concern was resolved by @jnewbery. My other comments are non-blocking nits obviously.

    I don’t think these are important, and I already have one ACK on the code so I’d prefer not to change them. However, if others disagree, I can do so.

    Now you’ve got two of them :smiley:

  76. MarcoFalke added the label Refactoring on Oct 17, 2020
  77. MarcoFalke commented at 4:17 pm on October 17, 2020: member

    review ACK da0988daf1d665a4644ad3f1ddf3f8a8bdd88cde 🐬

    Signature:

     0-----BEGIN PGP SIGNED MESSAGE-----
     1Hash: SHA512
     2
     3review ACK da0988daf1d665a4644ad3f1ddf3f8a8bdd88cde 🐬
     4-----BEGIN PGP SIGNATURE-----
     5
     6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
     7pUh3Kwv/Z92YkezB0vKDt8zCSK2kekyViu2esvi5EQIv7t59sPpc1lksTFvC75lX
     8rmr8hVvOHb6l1pMTGEXLJHVgamn4B/xd5jnJCEGcI9GR1bamL6wRlSKLZEyhnVjV
     9Siyp7qPFIQPTQxUsUhgJxeLqqYWV1TLmxRvekBnwtfksqpHTBR6icrBsQpg7Nu7Q
    10f9uiggfUZq3UrnyzF9dJqYUG5CyGiymnRH9YUE89W+7cg/L7RllSQh6K5lrbeb9b
    11WwAbJL64iDR3Npv4d9bwIQkZNgadyZA8yYw/kskriD9Gt+Qxg7V0VnBbExhve3mp
    12vc2i6mpPqgDS0n4a+tv3pB7g4zvv9w8kLNt4wXiBIETVdbfH5acdDw3GvTOAhQBl
    13Nwu0KhCxCkXtWDP56vJo2D0V8WsaHMQv53DUAjsAKHot7c0ihXd+V3zhwUHhJXEP
    14d1BHU3W+II9DB0c2e9gXyiS/ZHWbEhzwvtdj2pVAtETJG6dt8gM9aEmdzh7Lnfga
    15QWbax8bo
    16=//W2
    17-----END PGP SIGNATURE-----
    

    Timestamp of file with hash 350e455a9cfde318c3ab04c709fac25fca0a0b8205b4cfd5c3a0765e95f4dff4 -

  78. fanquake merged this on Oct 19, 2020
  79. fanquake closed this on Oct 19, 2020

  80. sidhujag referenced this in commit 0075365b36 on Oct 19, 2020
  81. Fabcien referenced this in commit 17eafd308f on Nov 25, 2021
  82. Fabcien referenced this in commit cc175463ab on Nov 25, 2021
  83. Fabcien referenced this in commit 68ee81260c on Nov 25, 2021
  84. Fabcien referenced this in commit 0ee7f5a6f2 on Nov 25, 2021
  85. Fabcien referenced this in commit 95cde14da7 on Nov 25, 2021
  86. Fabcien referenced this in commit 093f9ba30b on Nov 25, 2021
  87. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-01 13:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me