-
Notifications
You must be signed in to change notification settings - Fork 36.4k
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
p2p: Add 2 outbound block-relay-only connections #15759
Conversation
I agree with the concept. I wish we could announce our own addresses to these peers, but I think doing so results in a topology leak. :( The reason I'd like this is that if an attacker eclipses a node except for its blocks only links it will eventually eclipse its blocks-only links too through control of the addrman state. |
This approach was motivated by the TxProbe paper. Fundamentally, transaction relay is going to leak information about our node's peers (as long as we care about not wasting bandwidth). Rather than combat transaction-relay based inferences, which I think is a lost cause in the long-run even if there are improvements we can make in the short-term, I figure we can directly address why we care about keeping the graph private. Some considerations I had while working on this:
|
Can you run these simulations assuming x% of the 10,000 peers are black holes (don't connect the graph), for various values of x%? 2 might be fine for now, but ultimately I'd like to optimize memory usage for both inbound and outbound blocksonly links, then at least double the inbound connection limit for blocks only links, and make 8 blocks only links. (I suspect running that simulation assuming reasonable number of black hole peers will show that 2 is not really enough). |
To the uninformed p2p reader this reason is? |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
|
This table shows my simulation results for various black hole rates, with various values of how many outbound connections we make (k=2 is what I've implemented in this PR). This is on a 10,000 node graph with no non-listening nodes. Each table entry shows the success count (where success is defined as "the subgraph of non-black-hole nodes is connected") out of 1000 simulations.
This is roughly what I have in mind as well. I think we need a p2p protocol change to allow negotiating blocks-only links (so that the peer on the other side of our connection knows that the inbound peer won't turn transaction relay on later), so I figured we could start small for now. |
@sdaftuar Thanks for sharing the results of the analysis! Would you be willing to share the simulation scripts? |
@practicalswift My simulation code is unreadable, and also may have bugs, so I'd prefer that anyone interested in this would independently corroborate my results from scratch. |
This is indeed a good idea. I also see it as a small step towards peer rotation, I think this suggestion makes it easier to reason about rotation. I'm not sure if this is strongly related to the data you provided, but I'm also curious how many nodes have to be attacked (suspended?) to split network in halves etc. |
Wouldn't this break all the benefits of compact blocks? (Ignoring that with the current implementation, block relay would likely still occur on the normal connections.) |
@luke-jr I don't think so. The idea is that nodes are still expected to do transaction relay with other peers, and my belief is that transaction propagation is good enough that compact block relay works just fine on these blocksonly links. I believe my testing of this branch confirms that as well, but I'd welcome additional testers to corroborate those results in case I'm overlooking something. |
Concept ACK: I like the idea |
7402e34
to
1b90f9c
Compare
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 commits up to 7f2ce0a could be in a separate pull request.
src/net.h
Outdated
int64_t nNextAddrSend GUARDED_BY(cs_sendProcessing){0}; | ||
int64_t nNextLocalAddrSend GUARDED_BY(cs_sendProcessing){0}; | ||
struct AddrRelay { | ||
CCriticalSection cs_addrsend; |
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.
Could explain why the new mutex? This commit isn't just refactor.
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 think one issue is that I wasn't sure how to do the GUARDED_BY
annotations with a variable that didn't live in the class. But also I thought it might make sense to explicitly lock things in this class with its own mutex, as that seems like a clearer design for making this code modular.
The reason I included this refactor commit at all was in preparation for being able to optionally not instantiate this data structure, if there was concern about minimizing resource utilization as much as possible for these additional blocksonly
connections. Since I ended up not doing that (I believe I concluded that it probably wasn't all that much additional memory?), I could also drop this commit instead.
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.
Thanks for the explanation, I'll review again with that in mind.
Concept ACK. |
}; | ||
|
||
AddrRelay m_addr_relay; | ||
const bool m_addr_relay_peer; |
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.
nit: m_addr_relay_peer
could be private
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.
Meh, going to leave this as-is.
src/init.cpp
Outdated
@@ -1777,6 +1777,7 @@ bool AppInitMain(InitInterfaces& interfaces) | |||
connOptions.nLocalServices = nLocalServices; | |||
connOptions.nMaxConnections = nMaxConnections; | |||
connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections); | |||
connOptions.nMaxOutboundBlocksOnly = std::min(MAX_BLOCKS_ONLY_CONNECTIONS, std::max(connOptions.nMaxOutbound-6, 0)); |
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.
Trying to understand the logic here...
According to the commit description, bitcoind
will make 2 additional outbound connections, but with this logic, if connOptions.nMaxOutbound <= 6
then there will be no additional outbound connections: https://www.wolframalpha.com/input/?i=min(2,+max(x-6,+0))
From elsewhere in this commit, it seems like we consider the accounting for nMaxOutboundBlocksOnly
as separate from that of nMaxOutbound
, so perhaps just
connOptions.nMaxOutboundBlocksOnly = MAX_BLOCKS_ONLY_CONNECTIONS;
would do?
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.
This - 6
is a little confusing and requires that you look up the default value of connOptions.nMaxOutbound
to understand what this is doing. Also echoing @dongcarl comments that this doesn't work well when connOptions.nMaxOutbound <= 6
.
Given that this fails for particular values and you only want 2 block only outbound why not change this to:
connOptions.nMaxOutboundBlocksOnly = MAX_BLOCKS_ONLY_CONNECTIONS
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.
Perhaps the accounting logic should be improved to be clearer, but I believe the behavior here is at least (roughly) correct. The way this works is that if a user sets -maxconnections
very low, that will be a hard limit on the number of inbound, outbound and outbound-blocks-only connections. Before this PR, it would take the user setting their max connections value to less than 8 to change the number of outbound connections we make (we first reduce all the inbound we take and only then reduce the outbound).
This PR adds new blocks-only connections and preferences those connections over regular outbound connections (whenever we make an outbound connection, we check to see if we are below our blocks-only target, and if so we initiate the connection as blocks-only). As a result, I thought it didn't make sense to have any blocks-only links if we have too few regular outbound connections, because I don't think it makes sense to have blocks-only links at the expense of transaction relay.
In particular, the problem with the suggestion of just setting nMaxOutboundBlocksOnly to 2 is that if the user passes -maxconnections=2
, then they'll only have 2 blocksonly peers and won't receive any transactions.
So I believe the way I implemented things here is that we try to reserve 6 connections as regular outbound, and then if we add additional connections we will have those be blocks-only until we get to 2, and then any further connections are regular outbounds up to 8, and then finally any additional ones are used for feelers and inbounds.
Of course we could change this to be more conservative and only allocate blocks-only connections if we have all 8 regular outbounds. However I don't think we should be less conservative and risk having fewer regular outbounds.
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 think just do std::min(MAX_BLOCKS_ONLY_CONNECTIONS, std::max(connOptions.nMaxConnections - MAX_OUTBOUND_CONNECTIONS, 0)).
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.
@TheBlueMatt I pushed a commit that changes the behavior so that the first 8 outbounds are reserved to be regular full-relay peers, and only then do we allocate up to 2 blocksonly peers.
c408a7b
to
bacfdab
Compare
Rebased and addressed review comments. |
@jonasschnelli With 2 blocks-only connections, and if we assume 5% of nodes are useless black holes, then my simulation suggests we have a 3% chance of the network graph being connected by only the blocks-only connections. For additional robustness, we will want to add more blocks-only connections in the future -- but for resource utilization reasons I don't want to do that until we add better support at the p2p protocol layer for establishing these connections. Note that we are still going to relay blocks on the existing 8 outbound connections, so this PR is purely additive robustness, at the cost of a little more resource utilization. We now will have 10 outbound peers, rather than 8, which are able to provide blocks to us. (We just aren't going to do tx relay on the two additional connections.) One issue I'd like to flag for reviewers is how these new blocksonly peers interact with outbound peer disconnection (introduced in #11560 and #11490). I believe I've implemented this so that the new blocksonly peers will not be subject to other forms of disconnection, because non-tx-relay outbounds are excluded from being outbound disconnection candidates. However, it's worth verifying the implementation is correct and worth thinking about whether this behavior is the best choice. |
I think that this should be correct code in case someone wants to set it up to tabulate against Suhas's simulation. Edit: I've rewritten it to be much much better. Scipy is so cool! import random
import copy
import scipy
import scipy.sparse
import scipy.linalg
import numpy as np
N = 1000
def biased_coin(bias):
return random.random() <= bias
def make_graph(n_outbound, p_blackhole, n_total = N):
graph = np.zeros((n_total, n_total))
for i in range(n_total):
if not biased_coin(p_blackhole):
for j in range(n_outbound):
graph[i][j] = 1
# rejection sample no self-edges
while True:
np.random.shuffle(graph[i])
if not graph[i][i]:
break
return graph
def is_connected(graph):
return scipy.sparse.csgraph.connected_components(graph, directed=True, return_labels=False) == 1
print(sum(is_connected(make_graph(8, 0.05, 1000)) for x in range(100))) My results were, for 100 samples, 92. This suggests Suhas's simulation was not correct. edit: Nevermind, Suhas's simulation was on n=10,000. will re-run |
Improved the code for the above sim, in case anyone's following by email-only. |
Deep apologies for the noise; I missed Suhas's earlier note about the connectivity of the non black hole nodes, not the total connectivity. The below should work for that. import random
import copy
import scipy
import scipy.sparse
import scipy.linalg
import numpy as np
N = 1000
def biased_coin(bias):
return random.random() <= bias
def make_graph(n_outbound, p_blackhole, n_total = N):
graph = np.zeros((n_total, n_total))
count = 0
for i in range(n_total):
if not biased_coin(p_blackhole):
count += 1
for j in range(n_outbound):
graph[i][j] = 1
# rejection sample no self-edges
while True:
np.random.shuffle(graph[i])
if not graph[i][i]:
break
return (graph,count)
def is_connected(graph, count):
first_non_blackhole = None
for (i,row) in enumerate(graph):
if any(r != 0 for r in row):
first_non_blackhole = i
break
if first_non_blackhole is None:
return False
n, labels = scipy.sparse.csgraph.connected_components(graph, directed=True, return_labels=True)
label = labels[first_non_blackhole]
size = sum(l == label for l in labels)
return size >= count
print(sum(is_connected(*make_graph(8,0.05,10000)) for _ in range(10))) |
Summary: This is a partial backport of Core [[bitcoin/bitcoin#15759 | PR15759]] : bitcoin/bitcoin@26a93bc Test Plan: ninja all check Reviewers: #bitcoin_abc, nakihito Reviewed By: nakihito Differential Revision: https://reviews.bitcoinabc.org/D6399
Block-relay-only peers were introduced by bitcoin#15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as deleted comment leans to think of.
Block-relay-only peers were introduced by bitcoin#15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as modified comment leans to think of. Clearly indicate that outbound block-relay peers aren't protected from eviction by the bad/lagging chain logic.
Block-relay-only peers were introduced by bitcoin#15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as modified comment leans to think of. Clearly indicate that outbound block-relay peers aren't protected from eviction by the bad/lagging chain logic.
Block-relay-only peers were introduced by bitcoin#15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as modified comment leans to think of. Clearly indicate that outbound block-relay peers aren't protected from eviction by the bad/lagging chain logic.
…lock-relay peers d769254 [doc] Clarify semantic of peer's m_protect w.r.t to outbound eviction logics (Antoine Riard) ac71fe9 [doc] Clarify scope of eviction protection of outbound block-relay peers (Antoine Riard) Pull request description: Block-relay-only peers were introduced by #15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as modified comment leans to think of. Clearly indicate that outbound block-relay peers aren't protected from eviction by the bad/lagging chain logic. Fix #19863 ACKs for top commit: naumenkogs: ACK d769254 jonatack: ACK d769254 Tree-SHA512: 597fbd62838a6e39276024165b11514cad20a2e9d33cf9202d261cbadcb62b2df427c858e0cb57e585840d4c1d4600104aa53916bb868541f2580e4eed9b4b52
…bound block-relay peers d769254 [doc] Clarify semantic of peer's m_protect w.r.t to outbound eviction logics (Antoine Riard) ac71fe9 [doc] Clarify scope of eviction protection of outbound block-relay peers (Antoine Riard) Pull request description: Block-relay-only peers were introduced by bitcoin#15759. According to its author, it was intented to make them only immune to outbound peer rotation-based eviction and not from all eviction as modified comment leans to think of. Clearly indicate that outbound block-relay peers aren't protected from eviction by the bad/lagging chain logic. Fix bitcoin#19863 ACKs for top commit: naumenkogs: ACK d769254 jonatack: ACK d769254 Tree-SHA512: 597fbd62838a6e39276024165b11514cad20a2e9d33cf9202d261cbadcb62b2df427c858e0cb57e585840d4c1d4600104aa53916bb868541f2580e4eed9b4b52
…ons during restart a490d07 doc: Add anchors.dat to files.md (Hennadii Stepanov) 0a85e5a p2p: Try to connect to anchors once (Hennadii Stepanov) 5543c7a p2p: Fix off-by-one error in fetching address loop (Hennadii Stepanov) 4170b46 p2p: Integrate DumpAnchors() and ReadAnchors() into CConnman (Hennadii Stepanov) bad16af p2p: Add CConnman::GetCurrentBlockRelayOnlyConns() (Hennadii Stepanov) c29272a p2p: Add ReadAnchors() (Hennadii Stepanov) 567008d p2p: Add DumpAnchors() (Hennadii Stepanov) Pull request description: This is an implementation of #17326: - all (currently 2) outbound block-relay-only connections (#15759) are dumped to `anchors.dat` file - on restart a node tries to connect to the addresses from `anchors.dat` This PR prevents a type of eclipse attack when an attacker exploits a victim node restart to force it to connect to new, probably adversarial, peers. ACKs for top commit: jnewbery: code review ACK a490d07 laanwj: Code review ACK a490d07 Tree-SHA512: 0f5098a3882f2814be1aa21de308cd09e6654f4e7054b79f3cfeaf26bc02b814ca271497ed00018d199ee596a8cb9b126acee8b666a29e225b08eb2a49b02ddd
…onnections during restart a490d07 doc: Add anchors.dat to files.md (Hennadii Stepanov) 0a85e5a p2p: Try to connect to anchors once (Hennadii Stepanov) 5543c7a p2p: Fix off-by-one error in fetching address loop (Hennadii Stepanov) 4170b46 p2p: Integrate DumpAnchors() and ReadAnchors() into CConnman (Hennadii Stepanov) bad16af p2p: Add CConnman::GetCurrentBlockRelayOnlyConns() (Hennadii Stepanov) c29272a p2p: Add ReadAnchors() (Hennadii Stepanov) 567008d p2p: Add DumpAnchors() (Hennadii Stepanov) Pull request description: This is an implementation of bitcoin#17326: - all (currently 2) outbound block-relay-only connections (bitcoin#15759) are dumped to `anchors.dat` file - on restart a node tries to connect to the addresses from `anchors.dat` This PR prevents a type of eclipse attack when an attacker exploits a victim node restart to force it to connect to new, probably adversarial, peers. ACKs for top commit: jnewbery: code review ACK a490d07 laanwj: Code review ACK a490d07 Tree-SHA512: 0f5098a3882f2814be1aa21de308cd09e6654f4e7054b79f3cfeaf26bc02b814ca271497ed00018d199ee596a8cb9b126acee8b666a29e225b08eb2a49b02ddd
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.
src/init.cpp
PushInventory() is currently called with a CInv object, which can be a MSG_TX or MSG_BLOCK. PushInventory() only uses the type to determine whether to add the hash to setInventoryTxToSend or vInventoryBlockToSend. Since the caller always knows what type of inventory they're pushing, the CInv is wastefully constructed and thrown away, and tx/block relay is being split out, we split the function into PushTxInventory() and PushBlockInventory(). (cherry picked from commit bitcoin/bitcoin@f52d403) Zcash: Adjusted to account for bitcoin/bitcoin#15759 not having been backported.
0ba0802 Disconnect peers violating blocks-only mode (Suhas Daftuar) 937eba9 doc: improve comments relating to block-relay-only peers (Suhas Daftuar) 430f489 Don't relay addr messages to block-relay-only peers (Suhas Daftuar) 3a5e885 Add 2 outbound block-relay-only connections (Suhas Daftuar) b83f51a Add comment explaining intended use of m_tx_relay (Suhas Daftuar) e75c39c Check that tx_relay is initialized before access (Suhas Daftuar) c4aa2ba [refactor] Change tx_relay structure to be unique_ptr (Suhas Daftuar) 4de0dba [refactor] Move tx relay state to separate structure (Suhas Daftuar) 26a93bc Remove unused variable (Suhas Daftuar) Pull request description: Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) ACKs for top commit: sipa: ACK 0ba0802 ajtowns: ACK 0ba0802 -- code review, ran tests. ran it on mainnet for a couple of days with MAX_BLOCKS_ONLY_CONNECTIONS upped from 2 to 16 and didn't observe any unexpected behaviour: it disconnected a couple of peers that tried sending inv's, and it successfully did compact block relay with some block relay peers. TheBlueMatt: re-utACK 0ba0802. Pointed out that stats.fRelayTxes was sometimes uninitialized for blocksonly peers (though its not a big deal and only effects RPC), which has since been fixed here. Otherwise changes are pretty trivial so looks good. jnewbery: utACK 0ba0802 jamesob: ACK bitcoin@0ba0802 Tree-SHA512: 4c3629434472c7dd4125253417b1be41967a508c3cfec8af5a34cad685464fbebbb6558f0f8f5c0d4463e3ffa4fa3aabd58247692cb9ab8395f4993078b9bcdf
0ba0802 Disconnect peers violating blocks-only mode (Suhas Daftuar) 937eba9 doc: improve comments relating to block-relay-only peers (Suhas Daftuar) 430f489 Don't relay addr messages to block-relay-only peers (Suhas Daftuar) 3a5e885 Add 2 outbound block-relay-only connections (Suhas Daftuar) b83f51a Add comment explaining intended use of m_tx_relay (Suhas Daftuar) e75c39c Check that tx_relay is initialized before access (Suhas Daftuar) c4aa2ba [refactor] Change tx_relay structure to be unique_ptr (Suhas Daftuar) 4de0dba [refactor] Move tx relay state to separate structure (Suhas Daftuar) 26a93bc Remove unused variable (Suhas Daftuar) Pull request description: Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) ACKs for top commit: sipa: ACK 0ba0802 ajtowns: ACK 0ba0802 -- code review, ran tests. ran it on mainnet for a couple of days with MAX_BLOCKS_ONLY_CONNECTIONS upped from 2 to 16 and didn't observe any unexpected behaviour: it disconnected a couple of peers that tried sending inv's, and it successfully did compact block relay with some block relay peers. TheBlueMatt: re-utACK 0ba0802. Pointed out that stats.fRelayTxes was sometimes uninitialized for blocksonly peers (though its not a big deal and only effects RPC), which has since been fixed here. Otherwise changes are pretty trivial so looks good. jnewbery: utACK 0ba0802 jamesob: ACK bitcoin@0ba0802 Tree-SHA512: 4c3629434472c7dd4125253417b1be41967a508c3cfec8af5a34cad685464fbebbb6558f0f8f5c0d4463e3ffa4fa3aabd58247692cb9ab8395f4993078b9bcdf
…-relay-only connections 9db82f1 [net processing] Don't initialize TxRelay for non-tx-relay peers. (John Newbery) b0a4ac9 [net processing] Add m_tx_relay_mutex to protect m_tx_relay ptr (John Newbery) 290a8da [net processing] Comment all TxRelay members (John Newbery) 42e3250 [net processing] [refactor] Move m_next_send_feefilter and m_fee_filter_sent (John Newbery) Pull request description: block-relay-only connections are additional outbound connections that bitcoind makes since v0.19. They participate in block relay, but do not propagate transactions or addresses. They were introduced in #15759. When creating an outbound block-relay-only connection, since we know that we're never going to announce transactions over that connection, we can save on memory usage by not a `TxRelay` data structure for that connection. When receiving an inbound connection, we don't know whether the connection was opened by the peer as block-relay-only or not, and therefore we always construct a `TxRelay` data structure for inbound connections. However, it is possible to tell whether an inbound connection will ever request that we start announcing transactions to it. The `fRelay` field in the `version` message may be set to `0` to indicate that the peer does not wish to receive transaction announcements. The peer may later request that we start announcing transactions to it by sending a `filterload` or `filterclear` message, **but only if we have offered `NODE_BLOOM` services to that peer**. `NODE_BLOOM` services are disabled by default, and it has been recommended for some time that users not enable `NODE_BLOOM` services on public connections, for privacy and anti-DoS reasons. Therefore, if we have not offered `NODE_BLOOM` to the peer _and_ it has set `fRelay` to `0`, then we know that it will never request transaction announcements, and that we can save resources by not initializing the `TxRelay` data structure. ACKs for top commit: MarcoFalke: review ACK 9db82f1 🖖 dergoegge: Code review ACK 9db82f1 naumenkogs: ACK 9db82f1 Tree-SHA512: 83a449a56cd6bf6ad05369f5ab91516e51b8c471c07ae38c886d51461e942d492ca34ae63d329c46e56d96d0baf59a3e34233e4289868f911db3b567072bdc41
0ba0802 Disconnect peers violating blocks-only mode (Suhas Daftuar) 937eba9 doc: improve comments relating to block-relay-only peers (Suhas Daftuar) 430f489 Don't relay addr messages to block-relay-only peers (Suhas Daftuar) 3a5e885 Add 2 outbound block-relay-only connections (Suhas Daftuar) b83f51a Add comment explaining intended use of m_tx_relay (Suhas Daftuar) e75c39c Check that tx_relay is initialized before access (Suhas Daftuar) c4aa2ba [refactor] Change tx_relay structure to be unique_ptr (Suhas Daftuar) 4de0dba [refactor] Move tx relay state to separate structure (Suhas Daftuar) 26a93bc Remove unused variable (Suhas Daftuar) Pull request description: Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) ACKs for top commit: sipa: ACK 0ba0802 ajtowns: ACK 0ba0802 -- code review, ran tests. ran it on mainnet for a couple of days with MAX_BLOCKS_ONLY_CONNECTIONS upped from 2 to 16 and didn't observe any unexpected behaviour: it disconnected a couple of peers that tried sending inv's, and it successfully did compact block relay with some block relay peers. TheBlueMatt: re-utACK 0ba0802. Pointed out that stats.fRelayTxes was sometimes uninitialized for blocksonly peers (though its not a big deal and only effects RPC), which has since been fixed here. Otherwise changes are pretty trivial so looks good. jnewbery: utACK 0ba0802 jamesob: ACK bitcoin@0ba0802 Tree-SHA512: 4c3629434472c7dd4125253417b1be41967a508c3cfec8af5a34cad685464fbebbb6558f0f8f5c0d4463e3ffa4fa3aabd58247692cb9ab8395f4993078b9bcdf
0ba0802 Disconnect peers violating blocks-only mode (Suhas Daftuar) 937eba9 doc: improve comments relating to block-relay-only peers (Suhas Daftuar) 430f489 Don't relay addr messages to block-relay-only peers (Suhas Daftuar) 3a5e885 Add 2 outbound block-relay-only connections (Suhas Daftuar) b83f51a Add comment explaining intended use of m_tx_relay (Suhas Daftuar) e75c39c Check that tx_relay is initialized before access (Suhas Daftuar) c4aa2ba [refactor] Change tx_relay structure to be unique_ptr (Suhas Daftuar) 4de0dba [refactor] Move tx relay state to separate structure (Suhas Daftuar) 26a93bc Remove unused variable (Suhas Daftuar) Pull request description: Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) ACKs for top commit: sipa: ACK 0ba0802 ajtowns: ACK 0ba0802 -- code review, ran tests. ran it on mainnet for a couple of days with MAX_BLOCKS_ONLY_CONNECTIONS upped from 2 to 16 and didn't observe any unexpected behaviour: it disconnected a couple of peers that tried sending inv's, and it successfully did compact block relay with some block relay peers. TheBlueMatt: re-utACK 0ba0802. Pointed out that stats.fRelayTxes was sometimes uninitialized for blocksonly peers (though its not a big deal and only effects RPC), which has since been fixed here. Otherwise changes are pretty trivial so looks good. jnewbery: utACK 0ba0802 jamesob: ACK bitcoin@0ba0802 Tree-SHA512: 4c3629434472c7dd4125253417b1be41967a508c3cfec8af5a34cad685464fbebbb6558f0f8f5c0d4463e3ffa4fa3aabd58247692cb9ab8395f4993078b9bcdf
0ba0802 Disconnect peers violating blocks-only mode (Suhas Daftuar) 937eba9 doc: improve comments relating to block-relay-only peers (Suhas Daftuar) 430f489 Don't relay addr messages to block-relay-only peers (Suhas Daftuar) 3a5e885 Add 2 outbound block-relay-only connections (Suhas Daftuar) b83f51a Add comment explaining intended use of m_tx_relay (Suhas Daftuar) e75c39c Check that tx_relay is initialized before access (Suhas Daftuar) c4aa2ba [refactor] Change tx_relay structure to be unique_ptr (Suhas Daftuar) 4de0dba [refactor] Move tx relay state to separate structure (Suhas Daftuar) 26a93bc Remove unused variable (Suhas Daftuar) Pull request description: Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) ACKs for top commit: sipa: ACK 0ba0802 ajtowns: ACK 0ba0802 -- code review, ran tests. ran it on mainnet for a couple of days with MAX_BLOCKS_ONLY_CONNECTIONS upped from 2 to 16 and didn't observe any unexpected behaviour: it disconnected a couple of peers that tried sending inv's, and it successfully did compact block relay with some block relay peers. TheBlueMatt: re-utACK 0ba0802. Pointed out that stats.fRelayTxes was sometimes uninitialized for blocksonly peers (though its not a big deal and only effects RPC), which has since been fixed here. Otherwise changes are pretty trivial so looks good. jnewbery: utACK 0ba0802 jamesob: ACK bitcoin@0ba0802 Tree-SHA512: 4c3629434472c7dd4125253417b1be41967a508c3cfec8af5a34cad685464fbebbb6558f0f8f5c0d4463e3ffa4fa3aabd58247692cb9ab8395f4993078b9bcdf
…#4862) * Remove unused variable * [refactor] Move tx relay state to separate structure * [refactor] Change tx_relay structure to be unique_ptr * Check that tx_relay is initialized before access * Add comment explaining intended use of m_tx_relay * Add 2 outbound block-relay-only connections Transaction relay is primarily optimized for balancing redundancy/robustness with bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology. Network topology is better kept private for (at least) two reasons: (a) Knowledge of the network graph can make it easier to find the source IP of a given transaction. (b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split). We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary. After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).) * Don't relay addr messages to block-relay-only peers We don't want relay of addr messages to leak information about these network links. * doc: improve comments relating to block-relay-only peers * Disconnect peers violating blocks-only mode If we set fRelay=false in our VERSION message, and a peer sends an INV or TX message anyway, disconnect. Since we use fRelay=false to minimize bandwidth, we should not tolerate remaining connected to a peer violating the protocol. * net_processing. Removed comment + fixed formatting * Refactoring net_processing, removed duplicated code * Refactor some bool in a many-arguments function to enum It's made to avoid possible typos with arguments, because some of them have default values and it's very high probability to make a mistake here. * Added UI debug option for Outbound * Fixed data race related to `setInventoryTxToSend`, introduced in `[refactor] Move tx relay state to separate structure` Co-authored-by: Suhas Daftuar <[email protected]>
Transaction relay is optimized for a combination of redundancy/robustness as well as bandwidth minimization -- as a result transaction relay leaks information that adversaries can use to infer the network topology.
Network topology is better kept private for (at least) two reasons:
(a) Knowledge of the network graph can make it easier to find the source IP of a given transaction.
(b) Knowledge of the network graph could be used to split a target node or nodes from the honest network (eg by knowing which peers to attack in order to achieve a network split).
We can eliminate the risks of (b) by separating block relay from transaction relay; inferring network connectivity from the relay of blocks/block headers is much more expensive for an adversary.
After this commit, bitcoind will make 2 additional outbound connections that are only used for block relay. (In the future, we might consider rotating our transaction-relay peers to help limit the effects of (a).)