-
Notifications
You must be signed in to change notification settings - Fork 1
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
Prevent mempool leaks #10
Comments
There are maybe a few ways of doing this. It might be necessary to consider tradeoffs and work out just what privacy guarantee we'd be getting in each case. One option is to have each node forget entirely about the stem transaction after relaying it. No inserting in mempool, not even inserting in However, if we skip placing the transaction in mempool, then we would potentially relay the same transaction over again in stem mode. Or worse, we'd even relay "double spend" transactions. Doesn't this mean we'd be contributing to DoS? Maybe not.... one reason why this is OK is because "stem mode" never amplifies the propagation, i.e. we only propagate to 1 other peer, not all 30+ish of our peers. No exponential propagation begins until "fluff" mode, at which point ordinary mempool rules apply. |
Ugh, I can't find an easy way to validate if a transaction could be accepted into mempool without actually placing it in mempool. Perhaps an option is to perform minimal validation of stem-propagated tx's? But then, there would be a problem if an Maybe it would be acceptable to add a |
Thinking through this yet more... there are some tricky interactions with other mechanisms in propagation, mainly a) replacement of txs in mempool by txs with higher fees, and b) handling chains of descendent transactions that might get processed out of order. We're proposing to have stem transactions bypass mempool. So basically what we'd be doing is letting stem transactions propagate with only a subset of these checks, but get processed by mempool rules when they switch. So we would need to guarantee that as long as the subset of "stem checks" are passed, then the next node that receives it and puts it in mempool cannot assign a misbehavior score to the stem relayer. |
Here's a new plan.... (after spending a day trying to implement this by avoiding mempool, it requires too much tricky duplication of behavior). Instead, we will actually insert transactions in mempool, and mask them another way, by setting a time-limited "embargo". Requests for mempool etc. during an embargo will simply skip over the dandelion transaction and hide it. Robustness will be enabled by expiring the embargo with a random delay per #9. There is still a big challenge remaining in handling orphans and out-of-order transactions. If we treat each transaction independently for the sake of stem propagation, then it's possible for a child transaction to enter "fluff" mode before the parent. This will cause our peers to request the parent from us, even if we did not relay the INV for the parent (since the parent was in stem node). This cannot be treated as just an edge case, since simple usage patterns (calling "sendtoaddress" multiple times in rapid succession) will typically create a chain of dependent transactions... so it's important these don't get stuck, and ideally still benefit from dandelion privacy. So, here is a new suggestion:
There are still several tricky cases though. Suppose So in short, it's going to be really tricky to simultaneously 1) retain as much of the same policy of existing Bitcoin in terms of validation / DoS-scoring behavior, but also 2) avoid behaving differently whether we have seen a stem transaction or not. |
OK, the plan described above is partially implemented in fee2593 (what an unfortunate commit hash!) Items are requested even if they've been fetched before. This is accomplished by:
Furthermore, responses to "getdata" fee2593#diff-eff7adeaec73a769788bb78858815c91R1220 and "mempool" Finally, to avoid out of order problems, only 1 dandelion node is chosen (for minimalism here in this preliminary version, it's just the first outgoing connection), and a child is guaranteed to be routed as a "stem" if any of the inputs it depends on are currently treated as stems. Does this embargo mechanism provide adequate protection against the spy attacker probing the node's mempool? Here are the concerns I think are left:
|
A received dinv should be checked against the same filters that a normal inv is (mempool, setknown, rejects) and then requested even if the txn has already been fetched before. When the txn is received it should be tested against the mempool but not inserted into the mempool-- because the presences of a transaction can be interrogated out of a nodes mempool (e.g. via mempool rpc or by observing the effects of conflicts). A separate peer-specific relay pool may be required to prevent third parties from querying for propagation by attempting to fetch a txn which only passed through a node in stem mode.
(thanks gmaxwell for this suggestion)
The text was updated successfully, but these errors were encountered: