Skip to content

Conversation

sr-gi
Copy link
Member

@sr-gi sr-gi commented May 15, 2024

This is a re-attempt of #28765

The new approach differs from the previous in how peers are selected for fanout:

For Erlay-enabled peers, fanout targets are chosen for each transaction individually. Once the fanout target is reached, the transaction is reconciled with the rest of our peers. Whether a peer is selected for fanout depends on factors like peer type (inbound or outbound), how the transaction was received (via fanout or reconciliation), and how many of our peers are already aware of it.

For outbound peers:
If the transaction was received through fanout (or we originated it), we set a fanout rate threshold OUTBOUND_FANOUT_THRESHOLD{4}. As long as the transaction has been announced to (or received from) fewer than this number of peers, we continue faning out based on the order in which peers' Poisson timers go off.

If the transaction was received via reconciliation, we simply reconcile it with the rest of our peers.

For inbound peers:
We select a subset of inbound peers as fanout targets and send all transactions to them within a set time interval. Once the interval ends, the selection is randomly rotated.

This approach helps scale the transaction fanout rate for outbound peers by approximating how widely a transaction has already been propagated. For inbound peers, we use a random selection strategy to prevent them from easily exploiting our heuristic.

You may notice 398078a is not currently being used. It is likely to be dropped and brought back in a follow-up. Currently, we are picking Erlay fanout targets independently of whether we already have other non-erlay peers (which are always fanout). We may want to scale the selection based on non-Erlay connections, but I think that can be addressed on it's own PR.

Erlay Project Tracking: #30249

@DrahtBot
Copy link
Contributor

DrahtBot commented May 15, 2024

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/30116.

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:

  • #33029 (net: make m_mempool optional in PeerManager by naiyoma)
  • #28690 (build: Introduce internal kernel library by TheCharlatan)

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:

  • “Returns a error if the registering proccess fails for any reason, nullopt otherwise.”
    -> “Returns an error if the registering process fails for any reason, nullopt otherwise.” [“a error” should be “an error”; “proccess” is a typo]

  • “Skip. We do no reconcile by txid”
    -> “Skip. We do not reconcile by txid” [wrong negation word]

  • “Non-registered of simply pre-registered peers not count a registered.”
    -> “Non-registered or simply pre-registered peers do not count as registered.” [incorrect conjunction and grammar makes the sentence unintelligible]

drahtbot_id_4_m

@DrahtBot DrahtBot added the P2P label May 15, 2024
@sr-gi
Copy link
Member Author

sr-gi commented May 15, 2024

I've talked to @naumenkogs about picking this up and he was happy about it. I'm happy to close this if he changes his mind.

@sr-gi sr-gi changed the title p2p: Fill reconciliation sets (Erlay) attempt: 2 p2p: Fill reconciliation sets (Erlay) attempt 2 May 15, 2024
@sr-gi
Copy link
Member Author

sr-gi commented May 31, 2024

I've slightly extended the approach adding 3 commits to deal with short id collisions, which were not taken into account. Some of this may be squashable, I've added them separately for now so they are easy to diff/review.

This would be missing an additional commit/amend to deal with #28765 (comment), which I overlooked when addressing the outstanding comments

@DrahtBot
Copy link
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/25659971810

@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task ARM, unit tests, no functional tests: https://github.com/bitcoin/bitcoin/runs/46868137690
LLM reason (✨ experimental): The CI failure is caused by unresolved version control conflict markers remaining in the source code file.

Hints

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.

@sr-gi sr-gi force-pushed the 2023-11-erlay2.1 branch 6 times, most recently from 1a58a43 to e7d426a Compare July 28, 2025 19:48
@sr-gi sr-gi force-pushed the 2023-11-erlay2.1 branch from e7d426a to 3eab0e8 Compare August 1, 2025 21:09
@sr-gi
Copy link
Member Author

sr-gi commented Aug 1, 2025

I've rebased to account for the recent GenTxid changes by @marcofleon.

I've also decided to clean the design while I was at it, to make things easier to follow and test. As part of this, the file structure has been changed from two files (txreconciliation.h and txreconciliation.cpp) to three (txreconciliation.h, txreconciliation_impl.h and txreconciliation_impl.cpp), following a similar approach as txdownloadman.

The code is split as follows:

  • txreconciliation.h contains the general reconciliation stuff, and everything that is not implementation dependent (coming from BIP 330). This also includes the TxReconciliationState, which was previously defined in txreconciliation.cpp and was therefore not exposed, nor tested.
  • txreconciliation_impl.h defined the TransactionReconciliationTracker using PIMPL
  • txreconciliation_impl.cpp has the actual implementation of the tracker

@sr-gi sr-gi force-pushed the 2023-11-erlay2.1 branch 2 times, most recently from 7e4c66f to ac0a2a0 Compare August 14, 2025 17:47
@DrahtBot
Copy link
Contributor

🚧 At least one of the CI tasks failed.
Task CentOS, depends, gui: https://github.com/bitcoin/bitcoin/runs/48113343987
LLM reason (✨ experimental): The CI failure is caused by compilation errors due to incompatible usage of transaction identifier types and constructor calls.

Hints

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.

sr-gi and others added 11 commits August 14, 2025 13:56
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.
These comments became irrelevant in one of the previous code changes.
They simply don't make sense anymore.
They will be used later on.

Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
It helps to avoid recomputing every time we consider
a transaction for fanout/reconciliation.

Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
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.
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>
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants