Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erlay: bandwidth-efficient transaction relay protocol #21515

Draft
wants to merge 28 commits into
base: master
Choose a base branch
from

Conversation

naumenkogs
Copy link
Member

@naumenkogs naumenkogs commented Mar 23, 2021

Erlay Project Tracking: #28646


This is an implementation of Erlay , using primitives in the BIP-330 (see the updated spec here ). Please refer to these two to understand the design. My talk is here.

Abstract

Erlay uses both flooding (announcing using INV messages to all peers) and reconciliation to announce transactions. Flooding is expensive, so Erlay seeks to use it sparingly and in strategic locations - only well-connected publicly reachable nodes flood transactions to other publicly reachable nodes via outbound connections. Since every unreachable node is directly connected to several reachable nodes, this policy ensures that a transaction is quickly propagated to be within one hop from most of the nodes in the network.

All transactions not propagated through flooding are propagated through efficient set reconciliation. To do this, every node keeps a reconciliation set for each peer, in which transactions are placed which would have been announced using INV messages absent this protocol. Every 2 seconds every node chooses a peer from its outbound connections in a predetermined order to reconcile with, resulting in both sides learning the transactions known to the other side. After every reconciliation round, the corresponding reconciliation set is cleared.

I think both paper and the BIP motives the changes, but I’ll mention them briefly once again here:

  • save 40% of the bandwidth consumed by a node
  • increase network connectivity for almost no bandwidth or latency cost
  • improves privacy as a side-effect

How to review

I suggest doing make clean && autogen.sh && configure before you try building it locally.

Copy link
Member

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed it's marked as draft, I'll resume once you mark it ready for review.

src/txreconciliation.h Outdated Show resolved Hide resolved
src/txreconciliation.h Outdated Show resolved Hide resolved
src/txreconciliation.cpp Outdated Show resolved Hide resolved
@naumenkogs naumenkogs force-pushed the 2021-03-erlay branch 3 times, most recently from 707618c to 20ac0f4 Compare March 24, 2021 09:30
@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 24, 2021

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
Concept NACK ghost, rebroad
Concept ACK glozow
Stale ACK promag

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #28912 (refactor: VectorWriter and SpanReader without nVersion by maflcko)
  • #28892 (refactor: P2P transport without serialize version and type by maflcko)
  • #28765 (p2p: Fill reconciliation sets (Erlay) by naumenkogs)
  • #28463 (p2p: Increase inbound capacity for block-relay only connections by mzumsande)
  • #28451 (refactor: Remove unused SER_DISK, SER_NETWORK, SER_GETHASH by maflcko)
  • #28429 (Do not log p2p bip61 reject messages, improve log, add tests by jonatack)
  • #27826 (validation: log which peer sent us a header by Sjors)

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.

This will help to reuse the code later on in the function
to announce transactions.
If after decoding a reconciliation sketch it turned out
to be insufficient to find set difference, request extension.
Store the initial sketches so that we are able to process
extension sketch while avoiding transmitting the same data.
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.
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.
Sending an extension may allow the peer to reconcile
transactions, because now the full sketch has twice
as much capacity.
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.

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.
This currently unused function is supposed to be used once
a reconciliation round is done. It cleans the state corresponding
to the passed reconciliation.
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.
First, extend the timeout to facilitate reconciliation
relay which might take longer than previously.

Second, since reconciliation can't guarantee that
descendants of same-degree (from the parent) are
relayed in the same order they were received, loosen
the check for descendant limit.
This is the case because, if the parent is flooded,
the children might be both flooded and reconciled,
and the decision is made independently. So even if
one arrived earlier, it can be relayed later because
flooding.
Note, it's possible to make txreconciliation.cpp be aware
of the order of adding transactions to the set, but this
won't help to solve the above issue.
@DrahtBot
Copy link
Contributor

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

@DrahtBot
Copy link
Contributor

⌛ There hasn't been much activity lately and the patch still needs rebase. What is the status here?

  • Is it still relevant? ➡️ Please solve the conflicts to make it ready for review and to ensure the CI passes.
  • Is it no longer relevant? ➡️ Please close.
  • Did the author lose interest or time to work on this? ➡️ Please close it and mark it 'Up for grabs' with the label, so that it can be picked up in the future.

@DrahtBot
Copy link
Contributor

⌛ There hasn't been much activity lately and the patch still needs rebase. What is the status here?

  • Is it still relevant? ➡️ Please solve the conflicts to make it ready for review and to ensure the CI passes.
  • Is it no longer relevant? ➡️ Please close.
  • Did the author lose interest or time to work on this? ➡️ Please close it and mark it 'Up for grabs' with the label, so that it can be picked up in the future.

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.

None yet