Fix two issues in p2p_private_broadcast.py #34646

pull vasild wants to merge 2 commits into bitcoin:master from vasild:test_pb_aborttx_at_end changing 1 files +20 −20
  1. vasild commented at 6:06 pm on February 21, 2026: contributor

    test: move abortprivatebroadcast test at the end

    The piece of p2p_private_broadcast.py which tests the correctness of abortprivatebroadcast issues a new sendrawtransaction call. That call schedules up to 3 new connections: peer=13, peer=14 and possibly peer=15 before it gets aborted.

    These up to 3 in-the-process-of-opening private broadcast connections have CNode::m_connected set early - when the CNode object is created. Later in the test the mock time is advanced by 20 minutes and those “old” connections pick a transaction for rebroadcast but that triggers PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME immediately:

    02026-02-21T13:28:14.209766Z [privbcast] [net.cpp:4006] [CNode] [net] Added connection peer=20
    12026-02-21T13:28:14.309792Z (mocktime: 2026-02-21T13:48:14Z) [msghand] [net.cpp:4074] [PushMessage] [net] sending inv (37 bytes) peer=20
    22026-02-21T13:28:14.309801Z (mocktime: 2026-02-21T13:48:14Z) [msghand] [net_processing.cpp:5745] [SendMessages] [privatebroadcast] Disconnecting: did not complete the transaction send within 180 seconds, peer=20
    

    This prematurely stops the private broadcast connection and results in a failure like:

    0AssertionError: ... not({} == {'ping': 1, 'tx': 1})
    

    test: don’t always assert NUM_PRIVATE_BROADCAST_PER_TX broadcasts

    In p2p_private_broadcast.py in the function check_broadcasts() we should assert that the broadcast was done to broadcasts_to_expect peers, not to NUM_PRIVATE_BROADCAST_PER_TX. This is because in the “Basic” test we check the first broadcast manually because it is done to nodes[1] and then check the other two by check_broadcasts(..., NUM_PRIVATE_BROADCAST_PER_TX - 1, ...). The first broadcast might not have fully concluded by the time we call check_broadcasts() to check the remaining 2.

    Demanding always NUM_PRIVATE_BROADCAST_PER_TX can lead to:

     0Traceback (most recent call last):
     1  File "/home/vd/gh/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 142, in main
     2    self.run_test()
     3    ~~~~~~~~~~~~~^^
     4  File "/tmp/build/clang22/test/functional/p2p_private_broadcast.py", line 347, in run_test
     5    self.check_broadcasts("Basic", txs[0], NUM_PRIVATE_BROADCAST_PER_TX - 1, NUM_INITIAL_CONNECTIONS + 1)
     6    ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     7  File "/tmp/build/clang22/test/functional/p2p_private_broadcast.py", line 313, in check_broadcasts
     8    assert_greater_than_or_equal(sum(1 for p in peers if "received" in p), NUM_PRIVATE_BROADCAST_PER_TX)
     9    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    10  File "/home/vd/gh/bitcoin/bitcoin/test/functional/test_framework/util.py", line 94, in assert_greater_than_or_equal
    11    raise AssertionError("%s < %s" % (str(thing1), str(thing2)))
    12AssertionError: 2 < 3
    
  2. test: move abortprivatebroadcast test at the end
    The piece of `p2p_private_broadcast.py` which tests the correctness of
    `abortprivatebroadcast` issues a new `sendrawtransaction` call. That
    call schedules up to 3 new connections: peer=13, peer=14 and possibly
    peer=15 before it gets aborted.
    
    These up to 3 in-the-process-of-opening private broadcast connections
    have `CNode::m_connected` set early - when the `CNode` object is
    created. Later in the test the mock time is advanced by 20 minutes and
    those "old" connections pick a transaction for rebroadcast but that
    triggers `PRIVATE_BROADCAST_MAX_CONNECTION_LIFETIME` immediately:
    
    ```
    2026-02-21T13:28:14.209766Z [privbcast] [net.cpp:4006] [CNode] [net] Added connection peer=20
    2026-02-21T13:28:14.309792Z (mocktime: 2026-02-21T13:48:14Z) [msghand] [net.cpp:4074] [PushMessage] [net] sending inv (37 bytes) peer=20
    2026-02-21T13:28:14.309801Z (mocktime: 2026-02-21T13:48:14Z) [msghand] [net_processing.cpp:5745] [SendMessages] [privatebroadcast] Disconnecting: did not complete the transaction send within 180 seconds, peer=20
    ```
    
    This prematurely stops the private broadcast connection and results in
    a failure like:
    
    ```
    AssertionError: ... not({} == {'ping': 1, 'tx': 1})
    ```
    3710566305
  3. test: don't always assert NUM_PRIVATE_BROADCAST_PER_TX broadcasts
    In `p2p_private_broadcast.py` in the function `check_broadcasts()` we
    should assert that the broadcast was done to `broadcasts_to_expect`
    peers, not to `NUM_PRIVATE_BROADCAST_PER_TX`. This is because in the
    "Basic" test we check the first broadcast manually because it is done to
    `nodes[1]` and then check the other two by
    `check_broadcasts(..., NUM_PRIVATE_BROADCAST_PER_TX - 1, ...)`.
    The first broadcast might not have fully concluded by the time we call
    `check_broadcasts()` to check the remaining 2.
    
    Demanding always `NUM_PRIVATE_BROADCAST_PER_TX` can lead to:
    
    ```
    Traceback (most recent call last):
      File "/home/vd/gh/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 142, in main
        self.run_test()
        ~~~~~~~~~~~~~^^
      File "/tmp/build/clang22/test/functional/p2p_private_broadcast.py", line 347, in run_test
        self.check_broadcasts("Basic", txs[0], NUM_PRIVATE_BROADCAST_PER_TX - 1, NUM_INITIAL_CONNECTIONS + 1)
        ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/tmp/build/clang22/test/functional/p2p_private_broadcast.py", line 313, in check_broadcasts
        assert_greater_than_or_equal(sum(1 for p in peers if "received" in p), NUM_PRIVATE_BROADCAST_PER_TX)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/home/vd/gh/bitcoin/bitcoin/test/functional/test_framework/util.py", line 94, in assert_greater_than_or_equal
        raise AssertionError("%s < %s" % (str(thing1), str(thing2)))
    AssertionError: 2 < 3
    ```
    c462e54f9d
  4. DrahtBot commented at 6:07 pm on February 21, 2026: contributor

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

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    ACK andrewtoth, l0rinc, achow101

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

  5. DrahtBot added the label CI failed on Feb 21, 2026
  6. andrewtoth approved
  7. andrewtoth commented at 8:52 pm on February 21, 2026: contributor
    ACK c462e54f9df431434e6480d8293060645468d3ab
  8. sedited added this to the milestone 31.0 on Feb 23, 2026
  9. sedited added this to the milestone 31.0 on Feb 23, 2026
  10. sedited requested review from l0rinc on Feb 23, 2026
  11. sedited requested review from danielabrozzoni on Feb 23, 2026
  12. l0rinc commented at 1:47 pm on February 23, 2026: contributor

    ACK c462e54f9df431434e6480d8293060645468d3ab

    This PR is meant to fix private broadcast test flakiness (affecting most new PRs) by removing two races:

    • in-progress private-broadcast connections created during an abort test polluting the following tests;
    • an overly broad assertion when the test is only expecting a subset to have completed.

    The first commit is move-only; the second narrows the assertion without weakening peer-selection coverage. I don’t think this move is just papering over a real failure, seem like a mocktime artifact. Rebased locally, all tests are passing.


    Note: the failure is very likely not caused by the PR.

  13. achow101 commented at 9:37 pm on February 23, 2026: member
    ACK c462e54f9df431434e6480d8293060645468d3ab
  14. achow101 merged this on Feb 23, 2026
  15. achow101 closed this on Feb 23, 2026

  16. vasild deleted the branch on Feb 24, 2026

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: 2026-03-16 03:13 UTC

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