-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
Relay own transactions only via short-lived Tor or I2P connections #27509
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
Concept ACK - cool! Not sure about "only" relaying to Tor and I2P but seems useful as an option.
#4432 comes to mind |
Concept ACK |
1 similar comment
Concept ACK |
Looking at the current implementation, I am not sure how useful this is going to be, if the transaction is sent along with the potentially uniquely identifying UA comment, or other fingerprints in the version message. Maybe it makes sense to define a static version message, similar to how the tor browser replaces headers with constants? |
@MarcoFalke Good idea! Perhaps it's worth mimicking |
Or it could randomize it, from the list of different version strings. |
One shot connections + immediate tx broadcast without inv,getdata exchange leaks that the tx is likely being broadcast for the first time (easy to censor the tx as the receiver). Perhaps it is worth combining this with #27213 and instead of one-shot connections we broadcast only to existing selected connections on these privacy networks. Our own transactions would then still benefit from being broadcast along side other transactions. |
Concept ACK. Not sure if this should be the default or an optional mode (in some cases, a faster and more reliable transmission may be more important than privacy). It might also be helpful to combine this with some heuristics that the tx percolated through the network: |
added to the TODO in the OP
Yes. I was thinking its probably ok to broadcast to a few peers, not just one. And if they blackhole it, then the code will retry. We can retry more aggressively if it keeps being blackholed. I think it is ok to assume that there are some honest nodes in our addrman.
There are two aspects of this:
Right, also assuming there will be bugs/unexpected things - maybe have an option to enable/disable this. Hardest would be to introduce it without an option to disable it. Softest approach would be: 1. introduce under an option with default off, 2. in next version flip the default to on (if it seems to be working well)
I actually changed the behavior to do something like that in 512077b |
I think that in the suggested approach we might reveal information by not inv'ing our own tx to others. |
@mzumsande, right, ideally, after the initial broadcast via the short-lived connection, the node should behave as if it does not know the tx:
|
Concept ACK. Might be good to have some way of being able to configure where to connect to for sensitive relay, defaulting to tor/i2p, but so that you could perhaps enable specific ipv4/ipv6 addresses as well, particularly for testing purposes. |
concept ACK a high level question: the privacy benefit comes from the guarantees of using the altnets - the lifecycle of the connection is expected to reveal that the tx is an initial broadcast. if a spy is able to reliably fingerprint a node between networks, this mechanism could potentially degrade privacy. could it be worthwhile to mitigate this by occasionally broadcast non-wallet txs via the same short-lived connections, or broadcast a couple additional txs over the same connection? obv some big tradeoffs, just want to consider the possibility. even if we are able to ensure no leaks now, it is difficult to guarantee this over time of developing the project. |
Concept ACK |
Disagree with: opened regardless of max connections limits The connection should be established after another tor/i2p connection is dropped - this way the connection appears to be just another connection - nothing special about it. |
It may also be useful to randomize the duration of the connection? Additionally - padding the connection with dummy txs during its lifecycle may help obfuscate the real payload? |
Concept ACK |
This applies only if sensitive relay is used. Before this change, we would consider a local transaction relayed successfully to the network right after we push it to a peer (when `PushMessage()` returns, we still have not even sent it to the peer yet). Instead wait for somebody to send us `INV` about that transaction, then retrieve it with `GETDATA` (as if we don't have it already) and only after receiving it, consider it relayed. This is a better indication that the peer we sent it to has successfully received it, not blackholed it and the transaction has propagated to the network.
This is used in both cases - TCP server (accept) and TCP client (connect). The message "Connected & Listening address:port" is confusing. Print both ends of the TCP connection.
…tion If requested, make the SOCKS5 Python proxy redirect connections to a set of given destinations. Actually act as a real proxy, connecting the client to a destination, except that the destination is not what the client asked for. This would enable us to "connect" to Tor addresses from the functional tests.
6e6f83b
to
36074c0
Compare
|
🐙 This pull request conflicts with the target branch and needs rebase. |
@vasild Re your question on IRC about the wallet when not adding the tx to the mempool: Not counting non-mempool change is a pre-existing issue with the wallet, and I think should be fixed unrelated to this pull request. As I said previously, this can be observed with current wallet settings, see #27509 (comment). So I think all you'd need to do here is add yet another setting to the wallet (disabled by default) to enable this feature. Conceptually, it seems easier to fix, review and test the local wallet issue about counting change, than it is to fix the remote p2p behavior of withholding or supplying transactions that are in or out of the mempool. |
I'm noticing this in the log when sending a tx:
but we are not actually submitting anything to the mempool, right ...? Or yes we are but not to the part of the mempool where we relay to peers over clear net? (i.e. is that what "m_unbroadcast_txids" is?) |
@pinheadmz that log is from before this PR and I did not modify it. It is true that right now on However, given the feedback above and on IRC, I will change this to not add the transaction to the mempool. I am just figuring out how to exactly handle it. Then this message "Submitting ... to mempool for relay" would be inaccurate. It is a good opportunity to discuss this f2f. |
@@ -600,6 +600,7 @@ void SetupServerArgs(ArgsManager& argsman) | |||
OptionsCategory::NODE_RELAY); | |||
argsman.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)", | |||
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); | |||
argsman.AddArg("-sensitiverelayowntx", strprintf("Relay locally submitted transactions via short lived connections to Tor or I2P for improved privacy. There are two aspects of this - linking transaction-origin/Bitcoin-owner with IP-address/geolocation and linking seemingly unrelated transactions to the same owner/origin (this applies even if the node is running in tor-only mode) (default: %u)", DEFAULT_SENSITIVE_RELAY_OWN_TX), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe -walletsensitiverelay
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used "own" instead of "wallet" because local transactions could originate also from the RPC and they may have nothing to do with the wallet, there may not be a wallet at all. Come to think about this, maybe "private" is better word than "sensitive" and "broadcast" is better than "relay". So, maybe I should change this to something like -privatebroadcast
...
we discussed this proposal in person, and I wanted to share some of my current thoughts here:
my recommendation is to make this PR a draft until you have a new proposal and are ready for further review. happy to take a look when the new approach is figured out :) |
Concept ACK. Looking for the next actions w.r.t not adding to the mempool. |
There hasn't been much activity lately and the patch still needs rebase. What is the status here?
|
This is relevant and I am rewriting it as per the discussions above. |
I opened a new PR at #29415 to continue with this.
@amitiuttarwar, I was thinking about this, but realized that once connman has opened N private broadcast connections they are identical from peerman's point of view. They don't have to be tied to transactions like "connection1 for txA", "connection2 for txB". Since connection1 and connection2 are identical, it may as well be "connection2 for txA" and "connection1 for txB". To avoid the variability, e.g. one transaction to be broadcast more times than another, I introduced a priority for the transactions based on how many times one has been broadcast and how recently. Then peerman picks the tx with a higher priority when it starts processing a private broadcast connection. I don't feel strongly about this, but it seems to be working well and avoids communication between peerman and connman like:
Also, if a transaction is quickly received back from the network and removed from the broadcast list, then the remaining connections created due to it will be used for broadcasting others instead. |
To improve privacy, relay locally submitted transactions (from the wallet or via RPC) to the P2P network only via Tor or I2P short-lived connections.
Introduce a new connection type for relaying sensitive data (our own transactions) with the following properties:
Relay locally submitted transactions (from the wallet or via RPC) using this new mechanism, to a few Tor or I2P peers.
Hide those transactions from
GETDATA
andMEMPOOL
requests, as if we don't have them.Once we get an
INV
from somebody, request the transaction withGETDATA
, as if we didn't have it before.After we receive the full transaction as a
TX
message, in reply to ourGETDATA
request, only then consider the transaction has propagated through the network and remove it from the unbroadcast list.INV
it to others as a result of theTX
message we get, like what we do with transactions that are not ours.The messages exchange should look like this:
Whenever a new local transaction is received (from the wallet or RPC), the node will send it to 5 (
SENSITIVE_RELAY_NUM_BROADCAST_PER_TX
) recipients right away. If after 10-15 mins we still have not heard anything about the transaction from the network, then it will be sent to 5 more peers (seePeerManagerImpl::ReattemptInitialBroadcast()
).A few considerations:
TODO:
-connect
is used or Tor and I2P are not reachable.VERSION
message. Done: took the suggestion below.master
which is ok right after pushing the tx to a peer). We could wait for more than one INV, from peers that we have selected (outbound) and that are specifically not the ones we broadcasted to (via short-lived connection). Edit: OneINV
should be enough because after that we broadcast the transaction to everybody we are connected to (like if it is not ours).This is supposed to address:
#3828
#14692
#19042
#24557
#25450