p2p: refactor AlreadyHave(), CInv::type, INV/TX processing #19610

pull jonatack wants to merge 10 commits into bitcoin:master from jonatack:CInv-block-message-helpers changing 4 files +71 −71
  1. jonatack commented at 11:01 am on July 28, 2020: member

    Building on #19590 and the recent wtxid and GenTxid changes, this is a refactoring and cleanup PR to simplify and improve some of the net processing code.

    Some of the diffs are best reviewed with -w to ignore spacing.

    Co-authored by John Newbery.

  2. DrahtBot added the label P2P on Jul 28, 2020
  3. DrahtBot commented at 5:03 pm on July 28, 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:

    • #19753 (p2p: don’t add AlreadyHave transactions to recentRejects by troygiorshev)
    • #19339 (validation: re-delegate absurd fee checking from mempool to clients by gzhao408)
    • #18261 (Erlay: bandwidth-efficient transaction relay protocol by naumenkogs)

    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.

  4. laanwj referenced this in commit 17de75b028 on Jul 30, 2020
  5. jonatack force-pushed on Jul 30, 2020
  6. sidhujag referenced this in commit fc7030c8fe on Jul 31, 2020
  7. DrahtBot added the label Needs rebase on Jul 31, 2020
  8. in src/protocol.h:426 in 517152034a outdated
    443     bool IsMsgWitnessTx() const { return type == MSG_WITNESS_TX; }
    444+    bool IsMsgFilteredWitnessBlk() const { return type == MSG_FILTERED_WITNESS_BLOCK; }
    445 
    446     // Combined-message helper methods
    447-    bool IsGenTxMsg()     const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    448+    bool IsGenTxMsg() const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    


    fjahr commented at 7:52 pm on August 1, 2020:
    Could re-use the helper methods from above here in the combined helpers

    jonatack commented at 1:41 pm on August 3, 2020:
    Thanks Fabian. I mulled on doing this, but I think I’d rather keep the method definitions independent.
  9. fjahr commented at 8:02 pm on August 1, 2020: member
    Code review ACK 82c92976792f9c9c11b38cb0092f18728c97e64e
  10. jnewbery commented at 4:09 pm on August 3, 2020: member
    I think a better approach than the changes within AlreadyHave() is to split that function up into AlreadyHaveTx() and AlreadyHaveBlock() since those are two totally separate concepts. @jonatack would you be interested in taking the commits from here: https://github.com/jnewbery/bitcoin/commits/2020-07-split-already-have? (see also #19569 (review))
  11. in src/protocol.h:447 in 82c9297679 outdated
    445 
    446     // Combined-message helper methods
    447-    bool IsGenTxMsg()     const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    448+    bool IsGenTxMsg() const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    449+    bool IsMsgBlkOrMsgWitnessBlk() const { return type == MSG_BLOCK || type == MSG_WITNESS_BLOCK; }
    450+    bool IsGenBlkMsg() const { return type == MSG_BLOCK || type == MSG_FILTERED_BLOCK || type == MSG_CMPCT_BLOCK || type == MSG_WITNESS_BLOCK; }
    


    jnewbery commented at 4:25 pm on August 4, 2020:
    Should this contain MSG_FILTERED_WITNESS_BLOCK?

    jonatack commented at 2:02 pm on August 8, 2020:
    Well-spotted; added it in the rebase for now. The one place this helper is currently used (https://github.com/bitcoin/bitcoin/pull/19610/files#diff-eff7adeaec73a769788bb78858815c91L1763) did not include MSG_FILTERED_WITNESS_BLOCK, so we’d need to be sure including it doesn’t change behavior (or was an oversight).

    jnewbery commented at 11:28 am on August 11, 2020:
    Oh, it looks like MSG_FILTERED_WITNESS_BLOCK isn’t actually used and is ‘reserved for future use’: https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki#relay. I recommend removing it from here, removing IsMsgFilteredWitnessBlk() (since it’s not used anywhere) and adding a comment to MSG_FILTERED_WITNESS_BLOCK saying it’s unused (I think we could even comment out the value since it’s unused in the code).
  12. jnewbery commented at 4:25 pm on August 4, 2020: member
    Concept ACK. Needs rebase.
  13. jonatack renamed this:
    p2p, refactor: add `CInv` block message helpers; use in net processing
    p2p: refactor AlreadyHave(), CInv::type and inv/tx processing
    on Aug 8, 2020
  14. jonatack renamed this:
    p2p: refactor AlreadyHave(), CInv::type and inv/tx processing
    p2p: refactor AlreadyHave(), CInv::type, INV/TX processing
    on Aug 8, 2020
  15. jonatack force-pushed on Aug 8, 2020
  16. jonatack force-pushed on Aug 8, 2020
  17. jonatack commented at 2:12 pm on August 8, 2020: member
    Rebased with four commits pulled in from @jnewbery’s https://github.com/bitcoin/bitcoin/compare/master...jnewbery:2020-07-split-already-have branch as well as the changes in #19611.
  18. DrahtBot removed the label Needs rebase on Aug 8, 2020
  19. laanwj commented at 6:49 pm on August 9, 2020: member

    I think a better approach than the changes within AlreadyHave() is to split that function up into AlreadyHaveTx() and AlreadyHaveBlock() since those are two totally separate concepts.

    Great idea. The block and transaction paths have drifted apart so much that it no longer makes sense to have a common function there.

  20. in src/protocol.h:403 in 4789cff6f6 outdated
    399@@ -400,9 +400,11 @@ enum GetDataMsg : uint32_t {
    400 /** inv message data */
    401 class CInv
    402 {
    403+private:
    


    laanwj commented at 6:52 pm on August 9, 2020:
    Personally I don’t really know if it makes sense for “plain-data” network message types like CInv to have private fields. I see it more as a struct with helper methods than really an encapsulated object with functionality.

    jonatack commented at 3:55 am on August 10, 2020:
    Oh ok, in that case we may want to make CInv a struct to avoid confusion. As a class, it looked like encapsulation was desirable, and only one place in the code was still accessing CInv::type from the outside so it was easy to make it private.

    jonatack commented at 10:59 am on August 11, 2020:
    Er, renaming CInv to Inv to make it a struct would be too much noise. Done, dropped the last commit “p2p: refactor CInv::type from public to private class member”.
  21. fanquake deleted a comment on Aug 10, 2020
  22. DrahtBot added the label Needs rebase on Aug 10, 2020
  23. jonatack force-pushed on Aug 10, 2020
  24. DrahtBot removed the label Needs rebase on Aug 10, 2020
  25. jonatack force-pushed on Aug 11, 2020
  26. in src/protocol.h:422 in 806f12427d outdated
    411@@ -412,14 +412,22 @@ class CInv
    412     std::string ToString() const;
    413 
    414     // Single-message helper methods
    415-    bool IsMsgTx()        const { return type == MSG_TX; }
    416-    bool IsMsgWtx()       const { return type == MSG_WTX; }
    417+    bool IsUndefined() const { return type == UNDEFINED; }
    418+    bool IsMsgTx() const { return type == MSG_TX; }
    419+    bool IsMsgBlk() const { return type == MSG_BLOCK; }
    


    vasild commented at 11:00 am on August 11, 2020:

    [continuing conversation from another PR]

    nit: s/Blk/Block/

    0$ git grep -i blk src |wc -l
    1     108
    2$ git grep -i block src |wc -l
    3   11014
    

    jonatack commented at 2:40 pm on August 19, 2020:
    I prefer to pass on this for these reasons: (a) to maintain a consistent naming style in CInv (tx, blk) (b) block would make the methods names longer (c) blk is an established abbreviation: in the codebase, block data files called blk*.dat, etc. (d) the shorter blk seems more consistent with the abbreviated naming style in use in recent PRs like #19569
  27. in src/protocol.h:426 in 806f12427d outdated
    424     bool IsMsgWitnessTx() const { return type == MSG_WITNESS_TX; }
    425+    bool IsMsgFilteredWitnessBlk() const { return type == MSG_FILTERED_WITNESS_BLOCK; }
    426 
    427     // Combined-message helper methods
    428-    bool IsGenTxMsg()     const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    429+    bool IsGenTxMsg() const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }
    


    jnewbery commented at 11:11 am on August 11, 2020:
    Did you consider making these switch statements without defaults, so that the compiler warns if a new type is added to the enum but not here?

    jonatack commented at 3:57 pm on August 19, 2020:

    Did you consider making these switch statements without defaults, so that the compiler warns if a new type is added to the enum but not here?

    I think that requires turning enum GetDataMsg into an enum class, and changing the enum type from int to GetDataMsg would break the remaining five GetDataMsg::MSG_BLOCK/MSG_WTX | GetFetchFlags(pfrom) operations.

  28. jnewbery commented at 11:30 am on August 11, 2020: member

    One inline comment. A couple more suggestions:

    • squash the p2p: remove unused nFetchFlags from NetMsgType::INV processing and p2p: remove unused nFetchFlags from NetMsgType::TX processing commits
    • remove the p2p: change CInv::type from int to uint32_t commit. I don’t think it’s useful here.
  29. in src/net_processing.cpp:1759 in 806f12427d outdated
    1760@@ -1771,7 +1761,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
    1761     // expensive to process.
    1762     if (it != pfrom.vRecvGetData.end() && !pfrom.fPauseSend) {
    1763         const CInv &inv = *it++;
    1764-        if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
    1765+        if (inv.IsGenBlkMsg()) {
    


    vasild commented at 11:44 am on August 11, 2020:

    Could this result in unintended behavioral change?

    Previously if inv.type == MSG_FILTERED_WITNESS_BLOCK we would not execute the code inside this if block. With this patch we would execute it.

    Related to #19610 (review)


    jonatack commented at 2:20 pm on August 19, 2020:
    That message type is unused (see #19610 (review)) and has since been commented out by #19721 (merged).

    jonatack commented at 2:21 pm on August 19, 2020:
    Removing it in the rebase.
  30. vasild commented at 11:52 am on August 11, 2020: member

    In commits p2p: remove unused nFetchFlags from NetMsgType::(TX|INV) processing - why would it be unused? It looks used to me. Maybe I am missing something obscure? If that is the case, then maybe the commit messages warrant some more elaborate explanations?

    The change

    0-            } else {
    1+            } else if (inv.IsGenTxMsg()) {
    

    does not belong to commit [net processing] Remove mempool argument from AlreadyHaveBlock()

  31. jnewbery commented at 1:49 pm on August 11, 2020: member

    In commits p2p: remove unused nFetchFlags from NetMsgType::(TX|INV) processing - why would it be unused? It looks used to me. Maybe I am missing something obscure? If that is the case, then maybe the commit messages warrant some more elaborate explanations?

    Because GetFetchFlags() can only add the MSG_WITNESS_FLAG, which is added to the CInv.type field. That CInv only passed to AlreadyHave() or ToGenTxid() and neither of those functions do anything different depending on whether the CInv type is MSG_TX MSG_WITNESS_TX`. I agree that the git commit log could be expanded to explain this.

    The change […] does not belong to commit [net processing] Remove mempool argument from AlreadyHaveBlock()

    It’s an important change. See #19569 (review) for context. Perhaps it should be split into a separate commit or have a commit log explaining why it’s needed.

  32. jnewbery commented at 9:26 am on August 18, 2020: member
    Needs rebase now that #19721 is merged.
  33. jnewbery commented at 7:47 am on August 20, 2020: member
    Still awaiting rebase
  34. jnewbery added the label Needs rebase on Aug 20, 2020
  35. DrahtBot removed the label Needs rebase on Aug 20, 2020
  36. jonatack force-pushed on Aug 20, 2020
  37. jonatack commented at 11:47 am on August 20, 2020: member
    • rebased and updated
    • dropped the change CInv::type from int to uint32_t commit
    • squashed the 2 commits remove unused nFetchFlags from NetMsgType::INV processing and remove unused nFetchFlags from NetMsgType::TX processing and added explanatory notes to the commit message
    • split the IsGenMsgTx() conditional check to a separate commit, ensure inv is GenMsgTx before ToGenTxid in inv processing, and added explanatory notes in the commit message
  38. jnewbery commented at 11:02 am on August 21, 2020: member

    utACK 1723d0025b744f12b853935aead9acd9f8f32b42

    The last commit is tagged as authored by and co-authored by me. I don’t think we need both tags!

  39. jonatack force-pushed on Aug 21, 2020
  40. jonatack commented at 2:23 pm on August 21, 2020: member

    utACK 1723d00

    The last commit is tagged as authored by and co-authored by me. I don’t think we need both tags!

    Fixed

  41. in src/net_processing.cpp:2675 in 2a2ee28a2a outdated
    2680@@ -2697,14 +2681,18 @@ void ProcessMessage(
    2681                     // then fetch the blocks we need to catch up.
    2682                     best_block = &inv.hash;
    2683                 }
    2684-            } else {
    2685+            } else if (inv.IsGenTxMsg()) {
    


    jnewbery commented at 3:51 pm on August 21, 2020:
    Perhaps we should add an else branch after this that logs that an unknown INV type was received. Previously we’d log it as AlreadyHave.

    jonatack commented at 8:58 am on August 22, 2020:
    Done in the same commit and updated the commit message, and proposed a commit to move the code immediately after, which sends and logs a GETHEADERS message, into the inv.IsMsgBlk() section where it’s used.

    jnewbery commented at 9:36 am on August 22, 2020:

    proposed a commit to move the code immediately after, which sends and logs a GETHEADERS message, into the inv.IsMsgBlk() section where it’s used.

    This is a (bad) behaviour change. It means if a peer sends us an inv message with multiple MSG_BLOCK items, we’ll send a getheaders for each of those items instead of just the last one. Each getheaders contains a locator, so this could result in a lot of bandwidth usage.


    jonatack commented at 2:22 pm on August 22, 2020:

    Oops, I misread the nesting level and the tests didn’t mind. Thank you! Dropped the commit, and fixed up the bracket as follows in 3b79249dbd45b43

    0-        for (CInv &inv : vInv)
    1-        {
    2+        for (CInv& inv : vInv) {
    
  42. jnewbery commented at 3:53 pm on August 21, 2020: member

    utACK 2a2ee28a2ac2d2cc11ad8a44b036bb4218c13d9a

    One suggestion for improving logging inline.

  43. jonatack force-pushed on Aug 22, 2020
  44. jonatack force-pushed on Aug 22, 2020
  45. jonatack commented at 2:23 pm on August 22, 2020: member
    Thanks @jnewbery! Updated per git diff 2a2ee28 25176e6.
  46. jnewbery commented at 9:28 am on August 24, 2020: member
    utACK 25176e62d0e60a3bca92aa758f935ee782531f75
  47. DrahtBot added the label Needs rebase on Aug 24, 2020
  48. jonatack force-pushed on Aug 24, 2020
  49. jonatack commented at 4:34 pm on August 24, 2020: member

    Rebased.

    git range-diff 7f609f6 25176e6 ac0617d

  50. DrahtBot removed the label Needs rebase on Aug 24, 2020
  51. jnewbery commented at 10:51 am on August 25, 2020: member

    utACK ac0617d3718ac3e330a70b30ef1edd8a46faaf9a

    Verified the range-diff locally

  52. in src/protocol.h:421 in ac0617d371 outdated
    417@@ -418,12 +418,24 @@ class CInv
    418     std::string ToString() const;
    419 
    420     // Single-message helper methods
    421-    bool IsMsgTx()        const { return type == MSG_TX; }
    422-    bool IsMsgWtx()       const { return type == MSG_WTX; }
    423+    bool IsUndefined() const { return type == UNDEFINED; }
    


    vasild commented at 12:39 pm on August 25, 2020:
    nit: the methods IsUndefined() and IsMsgWitnessTx() are unused.

    jonatack commented at 9:54 am on August 26, 2020:
    Good point; probably worth removing them for now.

    jonatack commented at 10:06 am on August 26, 2020:
    Done
  53. vasild approved
  54. vasild commented at 12:41 pm on August 25, 2020: member

    ACK ac0617d37

    Looks good, compiled locally and ran tests.

  55. Crypt-iQ commented at 3:44 pm on August 25, 2020: contributor
    I think the CInv::type change from int to uint32_t change should be added back (not necessarily the private qualifier). While fuzzing it brings up the following complaint https://github.com/bitcoin/bitcoin/issues/19678
  56. jonatack commented at 8:35 pm on August 25, 2020: member
    Thank you @Crypt-iQ, if you have the chance, would you please let me know if 533a9a0d2c307330497e61d5af4229c924db8372 resolves the issue on your side?
  57. Crypt-iQ commented at 6:29 am on August 26, 2020: contributor
    @jonatack That UBSan complaint goes away with this patch 👍 Tested on macOS v10.15.4, brew-installed clang.
  58. vasild approved
  59. vasild commented at 7:53 am on August 26, 2020: member

    ACK 533a9a0d2

    I can’t make sense of the CI failure (and tell whether it is related to this PR).

  60. jonatack commented at 9:51 am on August 26, 2020: member

    Thanks @Crypt-iQ and @vasild.

    The CI failed on the wallet_import_rescan functional test and should be unrelated. Restarted; it’s now green.

  61. p2p: add CInv block message helper methods 471714e1f0
  62. p2p: remove nFetchFlags from NetMsgType TX and INV processing
    The nFetchFlags code can be removed here because GetFetchFlags() can only add
    the MSG_WITNESS_FLAG, which is added to the CInv::type field. That CInv is only
    passed to AlreadyHave() or ToGenTxid(), and neither of those functions do
    anything different depending on whether the CInv type is MSG_TX or
    MSG_WITNESS_TX.
    
    Co-authored by: John Newbery <john@johnnewbery.com>
    39f1dc9445
  63. [net processing] Split AlreadyHave() into separate block and tx functions 42ca5618ca
  64. [net processing] Remove mempool argument from AlreadyHaveBlock() 430e183b89
  65. [net processing] Change AlreadyHaveBlock() to take block_hash argument 5fdfb80b86
  66. [net processing] Change AlreadyHaveTx() to take a GenTxid acd6642167
  67. p2p: use CInv block message helpers in net_processing.cpp b1c855453b
  68. p2p: make gtxid(.hash) and fAlreadyHave localvars const 24ee4f01ea
  69. test: use CInv::MSG_WITNESS_TX flag in p2p_segwit aa3621385e
  70. p2p: ensure inv is GenMsgTx before ToGenTxid in inv processing
    and otherwise log that an unknown INV type was received.
    
    In INV processing, when handling transaction type inv messages,
    ToGenTxid() expects that we constructed the CInv ourselves or
    that we verified that it is for a transaction type CInv.
    
    Therefore, change this `else` branch into an `else if (inv.GenMsgTx())`
    to make this safer and log any INVs that fall through.
    fb56d37612
  71. jonatack force-pushed on Aug 26, 2020
  72. jonatack commented at 10:07 am on August 26, 2020: member
    Removed the unused helper methods from the first commit per git diff 533a9a0 125468a
  73. vasild approved
  74. vasild commented at 1:14 pm on August 26, 2020: member
    ACK 125468af9
  75. jnewbery commented at 3:32 pm on August 26, 2020: member

    I think the CInv::type change from int to uint32_t change should be added back (not necessarily the private qualifier). While fuzzing it brings up the following complaint #19678

    Why? This seems unrelated to this PR (the UBSan warning happens before this PR). Changing the type of CInv.type (which is serialized/deserialized for network messages) is a very different change from the internal refactors in this PR. Can you save it for a different PR?

  76. Crypt-iQ commented at 4:18 pm on August 26, 2020: contributor
    @jnewbery I thought since it was already added previously, it would fit into the scope of the PR. No problem to be added into another PR, either I or somebody else could do that.
  77. jonatack force-pushed on Aug 27, 2020
  78. jonatack commented at 9:14 am on August 27, 2020: member
    Dropped the CInv::type type change commit in favor of #19818. Thanks everyone.
  79. laanwj commented at 1:10 pm on August 27, 2020: member
    Code review ACK fb56d37612dea6666e7da73d671311a697570dae Agree it’s better to split out the P2P change.
  80. jnewbery commented at 8:50 am on September 1, 2020: member
    utACK fb56d37612dea6666e7da73d671311a697570dae
  81. vasild approved
  82. vasild commented at 9:04 am on September 2, 2020: member
    ACK fb56d3761
  83. laanwj merged this on Sep 2, 2020
  84. laanwj closed this on Sep 2, 2020

  85. jonatack deleted the branch on Sep 2, 2020
  86. laanwj referenced this in commit bd60a9a8ed on Sep 3, 2020
  87. sidhujag referenced this in commit 98e01510c0 on Sep 3, 2020
  88. sidhujag referenced this in commit addddc0053 on Sep 3, 2020
  89. Fabcien referenced this in commit 8f921089e9 on May 12, 2021
  90. Fabcien referenced this in commit 1a19225299 on May 12, 2021
  91. Fabcien referenced this in commit 63d5b8764b on May 12, 2021
  92. Fabcien referenced this in commit 216399a4b4 on May 12, 2021
  93. Fabcien referenced this in commit 2960f55f44 on May 12, 2021
  94. Fabcien referenced this in commit 0f5b42a26d on May 12, 2021
  95. Fabcien referenced this in commit 0f0d105ce2 on May 12, 2021
  96. Fabcien referenced this in commit 25996e7e23 on May 12, 2021
  97. 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-06-29 07:13 UTC

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