Skip to content

Conversation

@sr-gi
Copy link
Member

@sr-gi sr-gi commented Jun 12, 2024

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.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 12, 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/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:

  • #33892 (policy: Remove individual transaction <minrelay restriction by instagibbs)
  • #33629 (Cluster mempool by sdaftuar)
  • #33565 (net_processing: rename RelayTransaction to better describe what it does by vasild)
  • #32545 (Replace cluster linearization algorithm with SFL by sipa)
  • #31974 (Drop testnet3 by Sjors)
  • #30988 (Split CConnman by vasild)
  • #29415 (Broadcast own transactions only via short-lived Tor or I2P connections by vasild)
  • #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

@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/26144314909

@hebasto
Copy link
Member

hebasto commented Jun 18, 2024

@sr-gi

Feel free to grab hebasto@ffed2ab to fix the MSVC build.

sr-gi and others added 17 commits August 14, 2025 14:42
Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
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>
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>
This will help to reuse the code later on in the function to announce transactions.

Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
…ondiff

TODO: We may be OK defining a smaller m_recently_requested_short_ids, since
its contents only really matters for less than a minute
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>
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>
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>
Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
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>
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>
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>
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>
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>
We may still need to add more tests, specially around extensions (if we keep them)

Co-authored-by: Gleb Naumenko <naumenko.gs@gmail.com>
@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants