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

Constant-bandwidth constant-time protocol for mempool access, sending, and receiving #307

Open
defuse opened this issue Sep 21, 2020 · 0 comments

Comments

@defuse
Copy link
Collaborator

defuse commented Sep 21, 2020

The wallets already poll lightwalletd for the mempool contents. This is a sketch of a proposal to hijack that polling to enable sending and receiving transactions from lightwalletd in constant bandwidth and constant time.

The first change is to make the requests and responses for mempool polling a constant size, and to change lightwalletd so that it always responds to the request in a constant amount of time. To make it constant-size, the gRPC API will need to be changed. To make it constant time, the maximum response time needs to be measured, and the response is to be scheduled to occur after that amount of time. The actual request processing happens on another thread, and results are queued until their scheduled response time.

The second change is to make it possible to replace mempool polling requests and responses with requests that send transactions or fetch memos.

This might look something like the following.

Request format sketch:

    +-----------------------+
    | Outgoing TX 1         |
    | Outgoing TX 2         |
    | Outgoing TX 3         |
    | ...                   |
    | Outgoing TX N         |
    | TX download request 1 |
    | TX download request 2 |
    | TX download request 3 |
    | ...                   |
    | TX download request M |
    +-----------------------+

    - Total size of the packet is constant.
    - To simply request the mempool without submitting a transaction or
      requesting to download a transaction, all bytes are set to zero.

Response format sketch:

    +-----------------------+
    | Response Status Code  |
    +-----------------------+
    | Mempool TX 1          |
    | Mempool TX 2          |
    | ...                   |
    | Mempool TX N          |
    +-----------------------+
    | Full TX 1             |
    | Full TX 2             |
    | ...                   |
    | Full TX M             |
    +-----------------------+

    - Total size of the packet is constant.
    - When no transaction downloads were requested, the entire response is
      filled with mempool transactions, and any remaining space is filled with
      zeroes.

The third change is to make the mempool access protocol stateless. This is not required to address the traffic-analysis side channels this suggested change is intending to defend against, but it will help prevent wallets from being actively watermarked by lightwalletd, so that they can be re-identified when they reconnect. I suggest:

  1. Initialize an empty circular buffer.
  2. When a transaction enters the mempool, insert it into the circular buffer.
  3. When a wallet requests the mempool, select a random index into the circular buffer and return as many mempool transactions as will fit into the response from that random index onward.

When the mempool is small, wallets will be re-sent the entire mempool contents in every request. As the mempool grows larger, it takes each wallet more and more requests to obtain all of the transactions, so latency degrades. It may be safe to have the wallet store SOME ephemeral state, such as an index into the circular buffer, but this should be done with great care.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant