net_processing: ignore transactions while in IBD #21327

pull glozow wants to merge 2 commits into bitcoin:master from glozow:2021-02-ibd-txrelay changing 3 files +57 −2
  1. glozow commented at 4:27 pm on March 1, 2021: member

    This is basically a mini, IBD-only version of #21224

    Incoming transactions aren’t really relevant until we’re caught up. That’s why we send a giant feefilter and don’t send tx getdatas, but we also shouldn’t process them if peers send them anyway. Simply ignore them.

  2. DrahtBot added the label P2P on Mar 1, 2021
  3. DrahtBot commented at 10:24 pm on March 1, 2021: 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:

    • #20277 (test: Extend p2p_ibd_tx_relay.py to verify no-transaction are requested during IBD by ariard)

    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. in src/net_processing.cpp:3211 in 5b9036ef70 outdated
    3205@@ -3206,6 +3206,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
    3206             return;
    3207         }
    3208 
    3209+        // Also stop processing the transaction early if we are still in IBD since we don't
    3210+        // have enough information to validate it yet. Not a protocol violation.
    3211+        if (::ChainstateActive().IsInitialBlockDownload()) return;
    


    MarcoFalke commented at 10:11 am on March 2, 2021:
    Any reason to add a silent merge conflict with dongcarl’s work? Could simply use m_chainman.ActiveChainstate().IsInitialBlockDownload()

    MarcoFalke commented at 10:14 am on March 2, 2021:
    Using the member also mirrors the check used in NetMsgType::INV processing.

    MarcoFalke commented at 10:16 am on March 2, 2021:
    Could log the rejection to the debug NET category?

    amitiuttarwar commented at 6:05 pm on March 2, 2021:

    Could log the rejection to the debug NET category?

    we considered adding logging, but it seemed like it could be annoying if you’re connected to a client who keeps sending TXs? seems like if you get 1 you might get many?


    MarcoFalke commented at 7:10 pm on March 2, 2021:

    I think you will already log that a message of type tx has been received, so adding another line wouldn’t make things worse than they are now?

    My thinking is that this code path should rarely be hit, because outbound connections generally don’t announce txs via raw tx messages and inbound connections would only connect to you once your address is well propagated on the network, in which case you’ll have left IBD.

    If a peer wants to annoy you, they can already send a message that will log at least one line in the NET debug category (before and after this pull).


    glozow commented at 7:17 pm on March 2, 2021:
    I also thought we’d go by this comment that says not to log too much unnecessarily? My goal here is to do as little as possible when there’s peers sending us unsolicited transactions we have no use for (which apparently does happen - there’s a bit of discussion here).

    MarcoFalke commented at 7:35 pm on March 2, 2021:
    Ah, that comment is about the unconditional log, which probably shouldn’t be used in net at all. The conditional NET log doesn’t have that concern. (If it did, we already have a massive problem, because on a medium activity node the NET log category eats up about 1TB of disk every 6 months)

    amitiuttarwar commented at 7:51 pm on March 2, 2021:
    @MarcoFalke seems like you think this information useful to surface to the user, can you share why? what could a node operator do with this information?

    ariard commented at 9:21 pm on March 2, 2021:
    As a transaction received during IBD is necessary unsolicited, you might want to setban the faultive peer because that’s a hint of a peer non-compliant with the inv-getdata sequence ?

    glozow commented at 10:20 pm on March 2, 2021:
    You could use the “received: tx (x bytes) peer=x” log if you wanted to look for tx messages in IBD

    MarcoFalke commented at 8:53 am on March 3, 2021:
    Fair enough. The existing debug log statements are sufficient to determine whether this code path was hit. Though, for an easy grep I’d still prefer a specific log statement, but I guess I can add this myself.
  5. MarcoFalke commented at 10:17 am on March 2, 2021: member
    While this probably has no effect in practice, it shouldn’t hurt to do either.
  6. in src/net_processing.cpp:3209 in 5b9036ef70 outdated
    3205@@ -3206,6 +3206,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
    3206             return;
    3207         }
    3208 
    3209+        // Also stop processing the transaction early if we are still in IBD since we don't
    


    jnewbery commented at 5:51 pm on March 2, 2021:
    Perhaps remove “Also”. Comments have a habit of migrating around and not getting updated, so the “also” that this is referring to may no longer make sense in future.

    glozow commented at 7:18 pm on March 2, 2021:
    Done!
  7. in test/functional/p2p_ibd_txrelay.py:5 in 5b9036ef70 outdated
    4@@ -5,9 +5,23 @@
    5 """Test fee filters during and after IBD."""
    


    jnewbery commented at 5:51 pm on March 2, 2021:
    Maybe update this, since the test is now testing more.

    glozow commented at 7:18 pm on March 2, 2021:
    Done!
  8. in test/functional/p2p_ibd_txrelay.py:58 in 5b9036ef70 outdated
    46+        peer_inver = self.nodes[0].add_p2p_connection(P2PDataStore())
    47+        txid = 0xdeadbeef
    48+        peer_inver.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=txid)]))
    49+        # assert peer_inver doesn't receive a getdata for the txid
    50+        with p2p_lock:
    51+            assert txid not in peer_inver.getdata_requests
    


    jnewbery commented at 5:53 pm on March 2, 2021:
    I don’t think this is testing anything. If a node receives an INV for a transaction from an inbound connection, it won’t request it for at least two seconds (see AddTxAnnouncement()), so this assert would pass even if the node wasn’t in IBD.

    glozow commented at 7:19 pm on March 2, 2021:
    Oopsie! Added a sleep + sync with ping

    jnewbery commented at 9:33 am on March 3, 2021:
    Thanks. Looks good.
  9. jnewbery commented at 5:58 pm on March 2, 2021: member
    Concept ACK. Thanks for adding tests!
  10. glozow force-pushed on Mar 2, 2021
  11. in test/functional/p2p_ibd_txrelay.py:33 in d6314481ef outdated
    30 from test_framework.test_framework import BitcoinTestFramework
    31+from test_framework.util import hex_str_to_bytes
    32 
    33 MAX_FEE_FILTER = Decimal(9170997) / COIN
    34 NORMAL_FEE_FILTER = Decimal(100) / COIN
    35+NONPREF_PEER_TX_DELAY = 2
    


    ariard commented at 9:40 pm on March 2, 2021:
    Note this is also used in p2p_tx_download.py, can you move this in p2p.py ? If we update the production NONPREF_PEER_TX_DELAY, it’s easier to have corresponding test constants in one place.

    glozow commented at 10:05 pm on March 24, 2021:
    Done!
  12. ariard commented at 9:42 pm on March 2, 2021: member

    Thanks for tackling this, I exercised new test coverage, works as expected!

    W.r.t to Marco point, I don’t think logging this minor rejection case is that important.

  13. jnewbery commented at 9:14 am on March 3, 2021: member
    utACK d6314481efa4ff054dc036e980b4923ee5d1d736
  14. in src/net_processing.cpp:3210 in 9687b98b21 outdated
    3205@@ -3206,6 +3206,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
    3206             return;
    3207         }
    3208 
    3209+        // Stop processing the transaction early if we are still in IBD since we don't
    3210+        // have enough information to validate it yet. Not a protocol violation.
    


    sdaftuar commented at 4:27 pm on March 4, 2021:

    This comment is confusing to me – have we decided whether it’s protocol-violating to not process unrequested transactions? That was exactly what I proposed we do elsewhere, in general, but there was debate over whether such a change would be breaking or whether it was useful.

    If it’s not useful for our software to do this in general, I don’t know why it’s useful to do in this smaller specific case? And on the flip side, if it’s not a protocol violation here, why exactly would it be a protocol violation to do this in general?

    Note also that being in IBD happens not just when we’re syncing the whole blockchain, but whenever a node is started up again after being off for a few days. So I believe that if there are any software projects that send unrequested transactions at all, this would be a potentially observable change for them – as far as I can tell, even while in IBD we can at least sometimes validate and relay a transaction just fine, if a transaction were only spending utxos that are already confirmed… (Unless I’m missing some other interaction that would prevent that from working?)

    Not to say that this change can’t be made, I’m just looking for reasoning and a comment that explains our actual thinking, because so far I think the reasoning has been contradictory. If it’s not a protocol violation to ignore unrequested transactions, I don’t see the harm in us always doing it and avoiding gating yet another behavior on whether we are in IBD (which has always been a source of headaches when developers try to understand why something isn’t working as expected). If it is a protocol violation or potentially breaking, we should note that here and have a better justification for doing it than has been provided so far (particularly if a transaction were coming from a PF_RELAY or PF_FORCERELAY peer, where you might expect us to try harder to pass the transaction on).


    glozow commented at 4:51 pm on March 4, 2021:

    For some context, the comment is meant to convey that sending us unsolicited transactions is not a protocol violation, and I wanted to distinguish from the case above in which we disconnect the peer in addition to ignoring the transaction for violating no-tx-relay. Something like “since the peer has not violated protocol, don’t punish” is what I meant. The comment could definitely be clearer.

    My goal is just to fail early when we don’t expect to be able to validate a transaction. It’s definitely a good point that we could be perfectly able to validate despite being in IBD. I wonder if we could improve the condition with a better heuristic than “if in IBD?”


    sdaftuar commented at 4:59 pm on March 4, 2021:

    Ah, yes I completely misparsed that protocol violation comment, thanks for explaining that.

    I’m still looking to understand why this change is beneficial, but a broader change that includes IBD as a subset and also allows for PF_RELAY peers to bypass it, would not be.


    ariard commented at 8:37 pm on March 4, 2021:

    I think we can consider this change as beneficial as it’s a small resources saving during IBD, a period during which our resources should be allocated on a more prioritized task. W.r.t to a broader change adopting this behavior beyond IBD (e.g #21224) we have an explicit concern about silently harming other bitcoin softwares deployed on the tx-relay network. As it’s a reasonable assumption to expect only a minority fraction of nodes doing IBD at anytime, this change might be considered as a far lesser disruption.

    Though, we could also say that disruption would be limited for a broader change as we expect deployment cycles to be gradual.

    I wonder if we could improve the condition with a better heuristic than “if in IBD?”

    You can definitely validate while in IBD. But “already confirmed utxos” at your-IBD-tip doesn’t mean those have not been spent at network tip. If your last synced block is 100, your valid transaction might already have been double-spent at block 200, so validation cost would have been lost. IMO, utxo set view should be assumed to fluctuate quickly during IBD.

    Also, you won’t request transactions so your mempool is likely to be empty and you won’t be able to accurately weight transaction feerate. Relying on those heuristics, better to save on resources until your node is more able to assert with certainty if the transaction is a good candidate for propagation and block inclusion.


    naumenkogs commented at 8:07 am on March 8, 2021:

    Ah, yes I completely misparsed that protocol violation comment, thanks for explaining that.

    I just had the same confusion.

  15. luke-jr approved
  16. luke-jr commented at 6:30 pm on March 9, 2021: member
    utACK
  17. sdaftuar commented at 11:49 pm on March 9, 2021: member

    Issues like those being explored in #21106 — where IBD may kick in at unintuitive times, complicating our understanding of the network due to special-case interactions throughout our codebase — are why I think we should hesitate before adding more checks gated on IBD and ensure we have a good reason for doing so.

    In this case, I think our code is simpler to understand if we either always or never processed unrequested transactions (and the benefit to skipping this while in IBD seems small in comparison).

  18. brunoerg approved
  19. brunoerg commented at 2:49 pm on March 13, 2021: member

    tACK d6314481efa4ff054dc036e980b4923ee5d1d736

    Ubuntu 20.04

    • Ran the test individually and via test_runner (with all tests)
    • Code looks fine (comments/docs are very good - they explains each test step perfectly)
  20. DrahtBot commented at 4:49 pm on March 15, 2021: member

    🕵️ @sipa has been requested to review this pull request as specified in the REVIEWERS file.

  21. glozow force-pushed on Mar 24, 2021
  22. glozow commented at 10:05 pm on March 24, 2021: member

    Just pushed some changes addressing @ariard’s review comment and clarifying the comment about “not a protocol violation.”

    On why add a gate for unsolicited transactions in IBD but not the general case:

    There can perhaps be an observable difference if we stop processing unsolicited transactions in the general case - someone mentioned in #21224 that there are clients that wouldn’t be able to broadcast their transactions because they don’t follow the inv/getdata dialogue. I’m not sure what the status is on that discussion so I won’t speak to it too much.

    On the other hand, I don’t think there’s any downside to ignoring unsolicited transactions in IBD. We just have less wasted effort: Right now, if we can’t validate the transaction yet, we waste time putting it into orphan pool. If it conflicts with a block tx we see later on, we need to go through removing it from our mempool. If it’s valid and we can validate it, doing so while in IBD doesn’t benefit us - even if we come out of IBD really quickly (e.g. on a restart), we can download it again in a rebroadcast (or, later on, a reconciliation with Erlay). My personal opinion is that getting to exit early is worth the complexity of an extra IsIBD check, even if we later change it to ignore all unsolicited transactions.

  23. jnewbery commented at 12:32 pm on June 9, 2021: member
    Code review ACK 89ebd01de2
  24. in test/functional/p2p_ibd_txrelay.py:56 in 89ebd01de2 outdated
    47@@ -28,6 +48,32 @@ def run_test(self):
    48             assert node.getblockchaininfo()['initialblockdownload']
    49             self.wait_until(lambda: all(peer['minfeefilter'] == MAX_FEE_FILTER for peer in node.getpeerinfo()))
    50 
    51+        self.log.info("Check that nodes don't send getdatas for transactions while still in IBD")
    52+        peer_inver = self.nodes[0].add_p2p_connection(P2PDataStore())
    53+        txid = 0xdeadbeef
    54+        peer_inver.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=txid)]))
    55+        # The node should not send a getdata, but if it did, it would first delay 2 seconds
    56+        time.sleep(NONPREF_PEER_TX_DELAY)
    


    MarcoFalke commented at 5:37 pm on June 9, 2021:
    Can mocktime be used here?

    glozow commented at 9:47 am on June 11, 2021:
    Right, fixed
  25. in test/functional/p2p_ibd_txrelay.py:71 in 89ebd01de2 outdated
    66+            "04402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e168" + \
    67+            "1a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696a" + \
    68+            "d990364e555c271ad504b88ac00000000"
    69+        assert self.nodes[1].decoderawtransaction(rawhex) # returns a dict, should not throw
    70+        tx = CTransaction()
    71+        tx.deserialize(BytesIO(hex_str_to_bytes(rawhex)))
    


    MarcoFalke commented at 9:10 am on June 11, 2021:
    0        tx = FromHex(CTransaction(), rawhex)
    

    glozow commented at 9:47 am on June 11, 2021:
    Done
  26. MarcoFalke approved
  27. glozow force-pushed on Jun 11, 2021
  28. in test/functional/p2p_ibd_txrelay.py:56 in 1665bbdb28 outdated
    51+        peer_inver = self.nodes[0].add_p2p_connection(P2PDataStore())
    52+        txid = 0xdeadbeef
    53+        peer_inver.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=txid)]))
    54+        # The node should not send a getdata, but if it did, it would first delay 2 seconds
    55+        self.nodes[0].setmocktime(int(time.time() + NONPREF_PEER_TX_DELAY))
    56+        peer_inver.sync_with_ping()
    


    MarcoFalke commented at 9:56 am on June 11, 2021:
    0        peer_inver.sync_send_with_ping()
    

    To account for the possibility that pongs are sent before getdata?


    glozow commented at 10:04 am on June 11, 2021:
    Yes :brain:

    glozow commented at 10:05 am on June 11, 2021:
    Wait, isn’t there a ping after the inv? since we’re calling send_and_ping()?

    MarcoFalke commented at 10:16 am on June 11, 2021:

    There is, but it doesn’t matter. The pong in this line (after mocktime) will be sent out here:

    0            // Receive messages
    1            bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
    

    At this point no messages have been sent out (no getdata etc). Sending will happen right after, but may take a long time if the thread is put aside or the buffer is full.


    glozow commented at 10:24 am on June 11, 2021:
    Rebased for #21785 and added this
  29. MarcoFalke approved
  30. glozow force-pushed on Jun 11, 2021
  31. jnewbery commented at 12:31 pm on June 11, 2021: member
    ACK 648c5c73aef8785e49b7f23622f9d6e87b72f013
  32. lsilva01 approved
  33. lsilva01 commented at 9:43 pm on June 22, 2021: contributor
    Tested ACK https://github.com/bitcoin/bitcoin/pull/21327/commits/648c5c73aef8785e49b7f23622f9d6e87b72f013 on Ubuntu 20.04. This simplifies the IBD logic a bit.
  34. luke-jr referenced this in commit 082295561c on Jun 27, 2021
  35. luke-jr referenced this in commit 15088af1be on Jun 27, 2021
  36. naumenkogs commented at 10:28 am on September 29, 2021: member
    The code 648c5c73aef8785e49b7f23622f9d6e87b72f013 looks correct, but I share the hesitation suhas expressed above.
  37. in test/functional/p2p_ibd_txrelay.py:18 in 648c5c73ae outdated
    15-from test_framework.messages import COIN
    16+from test_framework.messages import (
    17+        CInv,
    18+        COIN,
    19+        CTransaction,
    20+        FromHex,
    


    luke-jr commented at 9:31 pm on October 10, 2021:
    Silent conflict. This needs to get renamed to from_hex

    glozow commented at 3:37 pm on October 28, 2021:
    thanks, rebased
  38. luke-jr changes_requested
  39. [net_processing] ignore all transactions during ibd
    Co-authored-by: Amiti Uttarwar <amiti@uttarwar.org>
    b9e105b664
  40. [test] tx processing before and after ibd
    Co-authored-by: Amiti Uttarwar <amiti@uttarwar.org>
    6aed8b7e9b
  41. glozow force-pushed on Oct 28, 2021
  42. jnewbery commented at 1:05 pm on November 2, 2021: member
    reACK 6aed8b7e9b
  43. laanwj commented at 6:05 pm on November 30, 2021: member
    Code review ACK 6aed8b7e9b206e728367fee9edfeb85b536bba69 I’ve always shared Suhas’ hesitation with regard to gating things on some (pretty arbitrary) “initial block download” criterion. But in this specific case, without an up-to-date view of blocks it’s not that useful to process transactions, so I think it makes sense.
  44. laanwj merged this on Nov 30, 2021
  45. laanwj closed this on Nov 30, 2021

  46. sidhujag referenced this in commit 6b96aff5dd on Dec 1, 2021
  47. RandyMcMillan referenced this in commit ea4fa52083 on Dec 23, 2021
  48. glozow deleted the branch on Jan 27, 2022
  49. DrahtBot locked this on Jan 27, 2023

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-12-18 21:12 UTC

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