[DO NOT MERGE] Erlay: bandwidth-efficient transaction relay protocol (Full implementation) #30277

pull sr-gi wants to merge 33 commits into bitcoin:master from sr-gi:202406-erlay-full-draft changing 18 files +3839 −326
  1. sr-gi commented at 5:18 pm on June 12, 2024: member

    Erlay Project Tracking: #30249


    This is a full implementation of Erlay. Its purpose is to check the integrity and correctness of the implementation against changes/additions that may originate from the review process and/or rebases on top of newer functionality.

    This is not to be merged. Functionality will be spread across multiple smaller PRs to ease the review process.


    Approach

    The implementation approach builds on the following assumptions:

    • Fanout (the current relay method) is faster than Erlay, but less bandwidth efficient
    • Fanout is optimal if the node we want to announce a certain transaction doesn’t know about it (but of course, we don’t have that information)

    The general approach works as follows:

    Reconciliation is used alongside fanout to relay transactions across the network. For Erlay nodes, the relay method will be decided per-transaction, instead of per connection, meaning that Erlay connections will do both fanout and reconciliation depending on the transaction (legacy connections will do only fanout, obviously).

    The parameters selected for fanout are minimized to maximize the bandwidth saving. The current selected defaults are 4 outbound peers and 10% of inbounds. The relay logic depends on the type of connection and how the transaction has been received:

    • For outbound connections, if the transaction was received via fanout (or originates in us), we fanout until up to N peers know about it. We do this by checking the m_tx_inventory_known_filter, so their announcements also count. If the transaction was received via reconciliation, we simply reconcile with the rest of our peers.
    • For inbounds, we select 10% of our connections and rotate that selection periodically.

    The reasoning for this is trying to guess how far the transaction has made it into the network with imperfect information. Knowing that fanout is faster than reconciliation, we want to have a higher fanout rate at the very beginning of the propagation, to get as far as we can, being fully efficient. This can be tied to how many of our peers know about the transaction already. Once the transaction is sufficiently spread, we can just reconcile it with the rest of our peers. This does not apply to inbounds, as they are not trusted, and the metric will be easily abused, plus it may be used to leak transaction origin information. For them, we just keep a low fanout rate.

    Testing and simulating

    The last two commits of this PR are currently for simulation only. They allow to easily config the inbound/outbound fanout rate without having to recompile the code, and make full reconciliation more efficient.

  2. DrahtBot commented at 5:18 pm on June 12, 2024: contributor

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

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/30277.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #32699 (docs: adds correct updated documentation links by Zeegaths)
    • #31974 (Drop testnet3 by Sjors)
    • #30116 (p2p: Fill reconciliation sets (Erlay) attempt 2 by sr-gi)
    • #28690 (build: Introduce internal kernel library by TheCharlatan)
    • #28463 (p2p: Increase inbound capacity for block-relay only connections by mzumsande)

    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.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • In RelayTransaction comment: “we do no reconcile by txid” → “we do not reconcile by txid” [fix negation for clarity]
    • In RelayTransaction inner comment: “Skipp it otherwiese.” → “Skip it otherwise.” [correct spelling]

    No other grammatical or typographic errors impacting comprehension were found.

    drahtbot_id_4_m

  3. sr-gi marked this as a draft on Jun 12, 2024
  4. sr-gi force-pushed on Jun 12, 2024
  5. DrahtBot added the label CI failed on Jun 13, 2024
  6. DrahtBot commented at 4:17 am on June 13, 2024: contributor

    🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the documentation.

    Possibly this is due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    Leave a comment here, if you need help tracking down a confusing failure.

    Debug: https://github.com/bitcoin/bitcoin/runs/26144314909

  7. sr-gi force-pushed on Jun 13, 2024
  8. sr-gi force-pushed on Jun 13, 2024
  9. sr-gi force-pushed on Jun 14, 2024
  10. sr-gi force-pushed on Jun 14, 2024
  11. DrahtBot removed the label CI failed on Jun 14, 2024
  12. hebasto commented at 9:22 pm on June 18, 2024: member
  13. DrahtBot added the label CI failed on Jun 19, 2024
  14. sr-gi force-pushed on Jun 20, 2024
  15. DrahtBot added the label Needs rebase on Jun 20, 2024
  16. sr-gi force-pushed on Jun 20, 2024
  17. DrahtBot removed the label Needs rebase on Jun 20, 2024
  18. sr-gi force-pushed on Jun 21, 2024
  19. DrahtBot removed the label CI failed on Jun 21, 2024
  20. DrahtBot added the label Needs rebase on Jul 4, 2024
  21. sr-gi force-pushed on Mar 26, 2025
  22. sr-gi force-pushed on Mar 26, 2025
  23. DrahtBot removed the label Needs rebase on Mar 26, 2025
  24. DrahtBot added the label CI failed on Mar 26, 2025
  25. sr-gi force-pushed on Mar 27, 2025
  26. sr-gi force-pushed on Mar 31, 2025
  27. sr-gi force-pushed on Mar 31, 2025
  28. sr-gi force-pushed on Apr 1, 2025
  29. sr-gi force-pushed on Apr 1, 2025
  30. sr-gi force-pushed on Apr 1, 2025
  31. sr-gi force-pushed on Apr 1, 2025
  32. sr-gi force-pushed on Apr 1, 2025
  33. sr-gi force-pushed on Apr 2, 2025
  34. sr-gi force-pushed on Apr 2, 2025
  35. sr-gi force-pushed on Apr 2, 2025
  36. sr-gi force-pushed on Apr 3, 2025
  37. sr-gi force-pushed on Apr 8, 2025
  38. sr-gi force-pushed on Apr 8, 2025
  39. DrahtBot removed the label CI failed on Apr 8, 2025
  40. sr-gi force-pushed on Apr 14, 2025
  41. sr-gi force-pushed on Apr 14, 2025
  42. DrahtBot added the label CI failed on Apr 14, 2025
  43. DrahtBot commented at 9:07 pm on April 14, 2025: contributor

    🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/40538402994

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  44. sr-gi force-pushed on Apr 14, 2025
  45. sr-gi force-pushed on Apr 15, 2025
  46. sr-gi force-pushed on Apr 15, 2025
  47. sr-gi force-pushed on Apr 15, 2025
  48. sr-gi force-pushed on Apr 16, 2025
  49. sr-gi force-pushed on Apr 16, 2025
  50. DrahtBot removed the label CI failed on Apr 16, 2025
  51. sr-gi force-pushed on Apr 18, 2025
  52. sr-gi force-pushed on Apr 18, 2025
  53. sr-gi force-pushed on Apr 18, 2025
  54. DrahtBot added the label CI failed on Apr 18, 2025
  55. DrahtBot commented at 8:13 pm on April 18, 2025: contributor

    🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/40799139881

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  56. sr-gi force-pushed on Apr 18, 2025
  57. sr-gi force-pushed on Apr 21, 2025
  58. sr-gi force-pushed on Apr 21, 2025
  59. sr-gi force-pushed on Apr 21, 2025
  60. DrahtBot removed the label CI failed on Apr 21, 2025
  61. sr-gi force-pushed on Apr 22, 2025
  62. DrahtBot added the label CI failed on Apr 22, 2025
  63. DrahtBot removed the label CI failed on Apr 24, 2025
  64. DrahtBot added the label Needs rebase on Apr 29, 2025
  65. sr-gi force-pushed on Jun 18, 2025
  66. dergoegge commented at 3:43 pm on June 20, 2025: member

    I was fuzzing this branch with fuzzamoto and it looks like it actually found a remotely reachable assertion.

     02025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: reqsketchext (64 bytes) peer=5
     12025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=5
     22025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=5
     32025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=5
     42025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=5
     52025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: sendtxrcncl (71 bytes) peer=5
     62025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sendtxrcncl received after verack, disconnecting peer=5
     72025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] Resetting socket for peer=5
     82025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [txreconciliation] Forget txreconciliation state of peer=5
     92025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] Cleared nodestate for peer=5
    102025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: sketch (64 bytes) peer=7
    112025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] ProcessMessages(sketch, 64 bytes): Exception 'DataStream::read(): end of data: iostream error' (NSt8ios_base7failureB5cxx11E) caught
    122025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=7
    132025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=7
    142025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=7
    152025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=7
    162025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: reqsketchext (64 bytes) peer=7
    172025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=7
    182025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=7
    192025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: ping (8 bytes) peer=7
    202025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] sending pong (8 bytes) peer=7
    212025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) [net] received: sketch (71 bytes) peer=0
    222025-06-20T15:12:09Z (mocktime: 2011-02-02T23:20:02Z) Using Minisketch implementation number 1
    23bitcoind: minisketch/include/minisketch.h:342: Minisketch &Minisketch::Deserialize(const T &, typename std::enable_if<std::is_convertible<typename std::remove_pointer<decltype(obj.data())>::type (*)[], const unsigned char (*)[]>::value && std::is_convertible<decltype(obj.size()), std::size_t>::value, std::nullptr_t>::type) [T = std::vector<unsigned char>]: Assertion `GetSerializedSize() == obj.size()' failed.
    24[2025-06-20T15:12:09Z ERROR fuzzamoto::runners] Test case failed: Target is not alive: Failed to check if node is alive: JsonRpc(Transport(Minreq(IoError(Os { code: 111, kind: ConnectionRefused, message: "Connection refused" }))))
    

    I’m surprised our existing fuzz tests do not catch this (process_messages might but I haven’t tried), but it looks like we actually never call Minisketch::Deserialize with bytes straight from the fuzzer but rather only with result from Minisketch::Serialize (maybe to avoid the assertion? not sure):

    https://github.com/bitcoin/bitcoin/blob/154b98a7aaae248f5d40ca567d1ec51410d09bae/src/test/fuzz/minisketch.cpp#L68-L69

    Bsae64 of the bytes passed to Deserialize: 0NDf7u7u0NDQ7u7u7u7u7u7Q7u7u7u7qKSm40NDQ0NDQ

  67. sr-gi force-pushed on Jun 20, 2025
  68. sr-gi force-pushed on Jun 20, 2025
  69. sr-gi commented at 8:08 pm on June 20, 2025: member

    @dergoegge It should be fixed now.

    When computing sketches, the capacity was derived from the size of the received data, but it was never checked that the received data size was a multiple of the sketch element size {BYTES_PER_SKETCH_CAPACITY}. Therefore, a sketch could be created such that the capacity was smaller than the data to be decoded into it, making it crash.

    Happy to run the fuzzer over the new code in case I’ve missed anything.

  70. sr-gi force-pushed on Jun 20, 2025
  71. dergoegge commented at 4:45 pm on June 23, 2025: member
    Have been running the fuzzer all day and the bug appears to be fixed (and no other bugs so far).
  72. sr-gi force-pushed on Jun 23, 2025
  73. maflcko commented at 3:34 pm on June 26, 2025: member

    I’m surprised our existing fuzz tests do not catch this (process_messages might but I haven’t tried), but it looks like we actually never call Minisketch::Deserialize with bytes straight from the fuzzer but rather only with result from Minisketch::Serialize (maybe to avoid the assertion? not sure):

    I tried this by starting 8 fuzz processes 5 days ago. 7 still run and one of them crashed after two days. I minimized the input:

     0$ git log -1 
     1commit bd242fd6e3f42e03a8c8abf23f9e9275d3580336 (HEAD)
     2
     3$ echo 'AAAAAABkZVNcAHNlbmR0eHJjbmNsADvN19f/102t//94AFxnd3R4aWRyZWxheQBsXAB2ZXJhY2sA
     4//96z3pcAHNrZXRjaAD/AAkJCQkJCQ0JcmVjb25jcgCtrQEAAAnhCQkJCQkJCQkJCQkJCQCtrQEA
     5AFxnYa2tAQBh/G6pWyYAACFnAAAAra0BAAAAAAAAY2ZjaGVjZCFnAAAAra0BAADTqVsmAAAhZwAA
     6AK2tAQAA' | base64 --decode > /tmp/a.crash
     7
     8
     9$ FUZZ=process_messages ./bld-cmake/bin/fuzz /tmp/a.crash 
    10INFO: Running with entropic power schedule (0xFF, 100).
    11INFO: Seed: 3544817665
    12INFO: Loaded 1 modules   (389355 inline 8-bit counters): 389355 [0x60e155e10eb0, 0x60e155e6ff9b), 
    13INFO: Loaded 1 PC tables (389355 PCs): 389355 [0x60e155e6ffa0,0x60e156460e50), 
    14./bld-cmake/bin/fuzz: Running 1 inputs 1 time(s) each.
    15Running: /tmp/a.crash
    16fuzz: minisketch/include/minisketch.h:342: Minisketch &Minisketch::Deserialize(const T &, typename std::enable_if<std::is_convertible<typename std::remove_pointer<decltype(obj.data())>::type (*)[], const unsigned char (*)[]>::value && std::is_convertible<decltype(obj.size()), std::size_t>::value, std::nullptr_t>::type) [T = std::vector<unsigned char>]: Assertion `GetSerializedSize() == obj.size()' failed.
    17...
    
  74. sr-gi force-pushed on Jul 17, 2025
  75. DrahtBot removed the label Needs rebase on Jul 17, 2025
  76. DrahtBot added the label Needs rebase on Jul 18, 2025
  77. sr-gi force-pushed on Jul 18, 2025
  78. DrahtBot removed the label Needs rebase on Jul 19, 2025
  79. sr-gi force-pushed on Jul 23, 2025
  80. sr-gi force-pushed on Jul 23, 2025
  81. sr-gi force-pushed on Jul 23, 2025
  82. DrahtBot added the label CI failed on Jul 23, 2025
  83. DrahtBot commented at 9:10 pm on July 23, 2025: contributor

    🚧 At least one of the CI tasks failed. Task CentOS, depends, gui: https://github.com/bitcoin/bitcoin/runs/46596474277 LLM reason (✨ experimental): The CI failure is caused by an assertion failure in the txreconciliation.cpp file during the txreconciliation_tests, leading to the test subprocess abort.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  84. DrahtBot removed the label CI failed on Jul 24, 2025
  85. sr-gi force-pushed on Jul 24, 2025
  86. sr-gi force-pushed on Jul 24, 2025
  87. sr-gi force-pushed on Jul 24, 2025
  88. sr-gi force-pushed on Jul 25, 2025
  89. sr-gi force-pushed on Jul 25, 2025
  90. sr-gi force-pushed on Jul 28, 2025
  91. sr-gi force-pushed on Jul 28, 2025
  92. sr-gi force-pushed on Jul 28, 2025
  93. sr-gi force-pushed on Jul 28, 2025
  94. sr-gi force-pushed on Jul 28, 2025
  95. sr-gi force-pushed on Jul 28, 2025
  96. sr-gi force-pushed on Jul 28, 2025
  97. sr-gi force-pushed on Jul 28, 2025
  98. DrahtBot added the label CI failed on Jul 29, 2025
  99. DrahtBot commented at 4:10 am on July 29, 2025: contributor

    🚧 At least one of the CI tasks failed. Task tidy: https://github.com/bitcoin/bitcoin/runs/46894854808 LLM reason (✨ experimental): Missing constructor arguments and undefined identifiers caused the build to fail.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  100. sr-gi force-pushed on Jul 29, 2025
  101. DrahtBot removed the label CI failed on Jul 29, 2025
  102. DrahtBot added the label Needs rebase on Jul 30, 2025
  103. sr-gi force-pushed on Jul 31, 2025
  104. sr-gi force-pushed on Jul 31, 2025
  105. sr-gi force-pushed on Jul 31, 2025
  106. DrahtBot added the label CI failed on Jul 31, 2025
  107. DrahtBot commented at 8:26 pm on July 31, 2025: contributor

    🚧 At least one of the CI tasks failed. Task lint: https://github.com/bitcoin/bitcoin/runs/47151055383 LLM reason (✨ experimental): The CI failure was caused by a lint error due to missing a required trailing newline.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  108. DrahtBot removed the label Needs rebase on Jul 31, 2025
  109. sr-gi force-pushed on Aug 1, 2025
  110. sr-gi force-pushed on Aug 1, 2025
  111. sr-gi force-pushed on Aug 1, 2025
  112. sr-gi force-pushed on Aug 1, 2025
  113. sr-gi force-pushed on Aug 1, 2025
  114. sr-gi force-pushed on Aug 1, 2025
  115. sr-gi force-pushed on Aug 1, 2025
  116. DrahtBot removed the label CI failed on Aug 2, 2025
  117. sr-gi force-pushed on Aug 4, 2025
  118. sr-gi force-pushed on Aug 6, 2025
  119. sr-gi force-pushed on Aug 7, 2025
  120. sr-gi force-pushed on Aug 7, 2025
  121. sr-gi force-pushed on Aug 7, 2025
  122. sr-gi force-pushed on Aug 11, 2025
  123. sr-gi force-pushed on Aug 11, 2025
  124. sr-gi force-pushed on Aug 11, 2025
  125. DrahtBot added the label CI failed on Aug 11, 2025
  126. DrahtBot commented at 8:56 pm on August 11, 2025: contributor

    🚧 At least one of the CI tasks failed. Task CentOS, depends, gui: https://github.com/bitcoin/bitcoin/runs/47850758479 LLM reason (✨ experimental): The failure is caused by compilation errors due to missing constructor overload and incorrect usage of std::floor.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  127. sr-gi force-pushed on Aug 11, 2025
  128. sr-gi force-pushed on Aug 12, 2025
  129. sr-gi force-pushed on Aug 12, 2025
  130. sr-gi force-pushed on Aug 12, 2025
  131. sr-gi force-pushed on Aug 12, 2025
  132. sr-gi force-pushed on Aug 13, 2025
  133. DrahtBot removed the label CI failed on Aug 13, 2025
  134. sr-gi force-pushed on Aug 13, 2025
  135. DrahtBot added the label CI failed on Aug 13, 2025
  136. sr-gi force-pushed on Aug 14, 2025
  137. refactor: redesigns txreconciliation file split and namespace
    Splits the txreconciliation logic in three files instead of two, allowing the
    TxreconciliationState to be properly tested, instead of being internal to
    txreconciliation.cpp.
    
    Also defines includes everything in the node namespace, instead of being part
    of an anonymous one.
    d1388c0f9a
  138. refactor: remove legacy comments
    These comments became irrelevant in one of the previous code changes.
    They simply don't make sense anymore.
    a5ad054842
  139. refactor: Defines generic error to be used in several reconciliation methods 218e8fd2ea
  140. refactor: use LogDebug instead of LogPrintLevel in txreconciliation 09315916f9
  141. p2p: Functions to add/remove wtxids to tx reconciliation sets
    They will be used later on.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    262e21ffc4
  142. p2p: Add PeerManager method to count the amount of inbound/outbounds fanout peers b8ca50c23d
  143. p2p: Cache inbound reconciling peers count
    It helps to avoid recomputing every time we consider
    a transaction for fanout/reconciliation.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    0a80697fd1
  144. p2p: Add method to decided whether to fanout or reconcile a transactions
    Fanout or reconciliation is decided on a transaction basis, based on the following criteria:
    
    If the peer is inbound, we fanout to a pre-defined subset of peers (which is rotated periodically).
    If the peer is outbound, we will reconcile the transaction if we received it via reconciliation, or
    defer the decision to relay time otherwise. At relay time, we will fanout to outbounds until a threshold is met
    (selecting peers in the order their timers go off) and reconcile with the rest.
    
    With this approach we try to fanout when we estimate to be early in the propagation of the transaction,
    and reconcile otherwise. Notice these heuristics don't apply to inbound peers, since they would be easily
    exploitable. For inbounds we just aim for a target subset picked at random.
    984f1c5100
  145. p2p: Add transactions to reconciliation sets
    Transactions eligible for reconciliation are added to the reconciliation sets. For the remaining txs, low-fanout is used.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    18ef701733
  146. p2p: Add helper to compute reconciliation tx short ids and a cache of short ids to wtxids 44edf74dd1
  147. p2p: Deal with shortid collisions for reconciliation sets
    If a transaction to be added to a peer's recon set has a shot id collisions (a previously
    added wtxid maps to the same short id), both transaction should be fanout, given
    our peer may have added the opposite transaction to our recon set, and these two
    transaction won't be reconciled.
    e5f1244d68
  148. p2p: Add peers to reconciliation queue on negotiation
    When we're finalizing negotiation, we should add the peers
    for which we will initiate reconciliations to the queue.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    7c4f38f127
  149. p2p: Track reconciliation requests schedule
    We initiate reconciliation by looking at the queue periodically
    with equal intervals between peers to achieve efficiency.
    
    This will be later used to see whether it's time to initiate.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    b10d5a0e41
  150. p2p: Initiate reconciliation round
    When the time comes for the peer, we send a
    reconciliation request with the parameters which
    will help the peer to construct a (hopefully) sufficient
    reconciliation sketch for us. We will then use that
    sketch to find missing transactions.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    f9e90f5923
  151. test: Functional test for reqtxrcncl
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    1565ee99c9
  152. p2p: Handle reconciliation request
    Store the parameters the peer sent us inside th reconciliation request.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    72b1272c81
  153. p2p: Add helper to compute sketches for tx reconciliation
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    a4f652ee65
  154. p2p: Respond to a reconciliation request
    When the time comes, we should send a sketch of our
    local reconciliation set to the reconciliation initiator.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    eef78293ac
  155. p2p: Add a function to identify local/remote missing txs
    When the sketches from both sides are combined successfully,
    the diff is produced. Then this diff can (together with the local txs)
    be used to identified which transactions are missing locally and remotely.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    a817497b56
  156. Use txid/uint256 in CompareInvMempoolOrder
    This will help to reuse the code later on in the function to announce transactions.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    f9b5fa26ed
  157. p2p: Handle reconciliation sketch and successful decoding
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    980463e5c5
  158. SQUASH-ME: Flags tx as received via recon if it was requested via recondiff
    TODO: We may be OK defining a smaller m_recently_requested_short_ids, since
    its contents only really matters for less than a minute
    6686213c4f
  159. p2p: Request extension if decoding failed
    If after decoding a reconciliation sketch it turned out
    to be insufficient to find set difference, request extension.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    1bcb8e0789
  160. p2p: Be ready to receive sketch extension
    Store the initial sketches so that we are able to process
    extension sketch while avoiding transmitting the same data.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    ac6e06ce91
  161. p2p: Prepare for sketch extension request
    To be ready to respond to a sketch extension request
    from our peer, we should store a snapshot of our state
    and capacity of the initial sketch, so that we compute
    extension of the same size and over the exact same
    transactions.
    
    Transactions arriving during this reconciliation will
    be instead stored in the regular set.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    4f17cd9026
  162. p2p: Keep track of announcements during txrcncl extension
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    ebf896631c
  163. p2p: Handle reconciliation extension request
    If peer failed to reconcile based on our initial response sketch,
    they will ask us for a sketch extension. Store this request to respond later.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    3e39fd871f
  164. p2p: Respond to sketch extension request
    Sending an extension may allow the peer to reconcile
    transactions, because now the full sketch has twice
    as much capacity.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    797dcc94ab
  165. p2p: Handle sketch extension
    If a peer sent us an extension sketch, we should
    reconstruct a full sketch from it with the snapshot
    we stored initially, and attempt to decode the difference.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    3b34b4059a
  166. p2p: Add a finalize incoming reconciliation function
    This currently unused function is supposed to be used once
    a reconciliation round is done. It cleans the state corresponding
    to the passed reconciliation.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    06e20f76a0
  167. p2p: Handle reconciliation finalization message
    Once a peer tells us reconciliation is done, we should behave as follows:
    - if it was successful, just respond them with the transactions they asked
      by short ID.
    - if it was a full failure, respond with all local transactions from the reconciliation
      set snapshot
    - if it was a partial failure (only low or high part was failed after a bisection),
      respond with all transactions which were asked for by short id,
      and announce local txs which belong to the failed chunk.
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    8fa7b8347a
  168. p2p, test: Add tx reconciliation functional tests
    We may still need to add more tests, specially around extensions (if we keep them)
    
    Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
    3f79937866
  169. REMOVE-ME, SIMS-ONLY: Adds options to configure in/out fanout rates f6d810a595
  170. sr-gi force-pushed on Aug 14, 2025
  171. DrahtBot removed the label CI failed on Aug 14, 2025

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: 2025-08-15 18:12 UTC

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