Skip to content

Commit f82cf97

Browse files
committed
Fix crash due to broken filter provided nodes merge
The filter provided nodes were added to a read-only List and this lead to crashes at start-up. We didn't catch the bug before because the lists in the tests are mutable. Now the FederatedBtcNodeProvider.getNodes method operates on Streams.
1 parent f079e26 commit f82cf97

File tree

3 files changed

+41
-50
lines changed

3 files changed

+41
-50
lines changed

core/src/main/java/bisq/core/btc/nodes/BtcNodesSetupPreferences.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.Collections;
2727
import java.util.List;
2828
import java.util.Set;
29+
import java.util.stream.Stream;
2930

3031
import org.slf4j.Logger;
3132
import org.slf4j.LoggerFactory;
@@ -66,9 +67,9 @@ public List<BtcNode> selectPreferredNodes(BtcNodes btcNodes) {
6667
break;
6768
case PROVIDED:
6869
default:
69-
List<BtcNode> hardcodedBtcNodes = btcNodes.getProvidedBtcNodes();
70-
List<String> filterProvidedBtcNodes = config.filterProvidedBtcNodes;
71-
List<String> bannedBtcNodes = config.bannedBtcNodes;
70+
Stream<BtcNode> hardcodedBtcNodes = btcNodes.getProvidedBtcNodes().stream();
71+
Stream<String> filterProvidedBtcNodes = config.filterProvidedBtcNodes.stream();
72+
Stream<String> bannedBtcNodes = config.bannedBtcNodes.stream();
7273
result = FederatedBtcNodeProvider.getNodes(hardcodedBtcNodes, filterProvidedBtcNodes, bannedBtcNodes);
7374
break;
7475
}

core/src/main/java/bisq/core/btc/nodes/FederatedBtcNodeProvider.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Objects;
77
import java.util.Set;
88
import java.util.stream.Collectors;
9+
import java.util.stream.Stream;
910

1011
import lombok.extern.slf4j.Slf4j;
1112

@@ -14,24 +15,23 @@
1415
@Slf4j
1516
public class FederatedBtcNodeProvider {
1617

17-
static List<BtcNodes.BtcNode> getNodes(List<BtcNodes.BtcNode> hardcodedBtcNodes,
18-
List<String> filterProvidedBtcNodesConfig,
19-
List<String> bannedBtcNodesConfig) {
20-
Set<BtcNodes.BtcNode> filterProvidedBtcNodes = filterProvidedBtcNodesConfig.stream()
18+
static List<BtcNodes.BtcNode> getNodes(Stream<BtcNodes.BtcNode> hardcodedBtcNodes,
19+
Stream<String> filterProvidedBtcNodesConfig,
20+
Stream<String> bannedBtcNodesConfig) {
21+
Stream<BtcNodes.BtcNode> filterProvidedBtcNodes = filterProvidedBtcNodesConfig
2122
.filter(n -> !n.isEmpty())
2223
.map(FederatedBtcNodeProvider::getNodeAddress)
2324
.filter(Objects::nonNull)
24-
.map(nodeAddress -> new BtcNodes.BtcNode(null, nodeAddress.getHostName(), null, nodeAddress.getPort(), "Provided by filter"))
25-
.collect(Collectors.toSet());
26-
hardcodedBtcNodes.addAll(filterProvidedBtcNodes);
25+
.map(nodeAddress -> new BtcNodes.BtcNode(null, nodeAddress.getHostName(), null,
26+
nodeAddress.getPort(), "Provided by filter"));
2727

28-
Set<NodeAddress> bannedBtcNodeHostNames = bannedBtcNodesConfig.stream()
28+
Set<NodeAddress> bannedBtcNodeHostNames = bannedBtcNodesConfig
2929
.filter(n -> !n.isEmpty())
3030
.map(FederatedBtcNodeProvider::getNodeAddress)
3131
.filter(Objects::nonNull)
3232
.collect(Collectors.toSet());
3333

34-
return hardcodedBtcNodes.stream()
34+
return Stream.concat(hardcodedBtcNodes, filterProvidedBtcNodes)
3535
.filter(btcNode -> {
3636
String nodeAddress = btcNode.hasOnionAddress() ? btcNode.getOnionAddress() :
3737
btcNode.getHostNameOrAddress();

core/src/test/java/bisq/core/btc/nodes/FederatedBtcNodeProviderTest.java

+28-38
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package bisq.core.btc.nodes;
22

3-
import java.util.ArrayList;
4-
import java.util.Collections;
53
import java.util.List;
4+
import java.util.stream.Stream;
65

76
import org.junit.jupiter.api.Test;
87

@@ -20,12 +19,11 @@ void onlyHardcodedNodes() {
2019
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
2120
);
2221

23-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
24-
List<String> filterProvidedBtcNodes = Collections.emptyList();
25-
List<String> bannedBtcNodes = Collections.emptyList();
22+
Stream<String> filterProvidedBtcNodes = Stream.empty();
23+
Stream<String> bannedBtcNodes = Stream.empty();
2624

2725
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
28-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
26+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
2927

3028
assertIterableEquals(hardcodedNodes, selectedNodes);
3129
}
@@ -43,13 +41,12 @@ void bannedIpV4Node() {
4341
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
4442
);
4543

46-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
47-
List<String> filterProvidedBtcNodes = Collections.emptyList();
44+
Stream<String> filterProvidedBtcNodes = Stream.empty();
4845
String bannedFullAddress = bannedAddress + ":" + port;
49-
List<String> bannedBtcNodes = List.of(bannedFullAddress);
46+
Stream<String> bannedBtcNodes = Stream.of(bannedFullAddress);
5047

5148
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
52-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
49+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
5350

5451
var expected = List.of(
5552
new BtcNodes.BtcNode(null, "alice.onion", null,
@@ -72,13 +69,12 @@ void bannedIpV4NodeWrongPort() {
7269
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
7370
);
7471

75-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
76-
List<String> filterProvidedBtcNodes = Collections.emptyList();
72+
Stream<String> filterProvidedBtcNodes = Stream.empty();
7773
String bannedFullAddress = bannedAddress + ":" + 1234;
78-
List<String> bannedBtcNodes = List.of(bannedFullAddress);
74+
Stream<String> bannedBtcNodes = Stream.of(bannedFullAddress);
7975

8076
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
81-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
77+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
8278

8379
assertIterableEquals(hardcodedNodes, selectedNodes);
8480
}
@@ -96,13 +92,12 @@ void bannedIpV6Node() {
9692
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
9793
);
9894

99-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
100-
List<String> filterProvidedBtcNodes = Collections.emptyList();
95+
Stream<String> filterProvidedBtcNodes = Stream.empty();
10196
String bannedFullAddress = "[" + bannedAddress + "]" + ":" + port;
102-
List<String> bannedBtcNodes = List.of(bannedFullAddress);
97+
Stream<String> bannedBtcNodes = Stream.of(bannedFullAddress);
10398

10499
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
105-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
100+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
106101

107102
var expected = List.of(
108103
new BtcNodes.BtcNode(null, "alice.onion", null,
@@ -125,13 +120,12 @@ void bannedIpV6NodeWrongPort() {
125120
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
126121
);
127122

128-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
129-
List<String> filterProvidedBtcNodes = Collections.emptyList();
123+
Stream<String> filterProvidedBtcNodes = Stream.empty();
130124
String bannedFullAddress = "[" + bannedAddress + "]" + ":" + 1234;
131-
List<String> bannedBtcNodes = List.of(bannedFullAddress);
125+
Stream<String> bannedBtcNodes = Stream.of(bannedFullAddress);
132126

133127
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
134-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
128+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
135129

136130
assertIterableEquals(hardcodedNodes, selectedNodes);
137131
}
@@ -149,12 +143,11 @@ void bannedHostNameNode() {
149143
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
150144
);
151145

152-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
153-
List<String> filterProvidedBtcNodes = Collections.emptyList();
154-
List<String> bannedBtcNodes = List.of(bannedHostName + ":" + port);
146+
Stream<String> filterProvidedBtcNodes = Stream.empty();
147+
Stream<String> bannedBtcNodes = Stream.of(bannedHostName + ":" + port);
155148

156149
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
157-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
150+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
158151

159152
var expected = List.of(
160153
new BtcNodes.BtcNode(null, "alice.onion", null,
@@ -177,12 +170,11 @@ void bannedHostNameNodeWrongPort() {
177170
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
178171
);
179172

180-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
181-
List<String> filterProvidedBtcNodes = Collections.emptyList();
182-
List<String> bannedBtcNodes = List.of(bannedHostName + ":" + 1234);
173+
Stream<String> filterProvidedBtcNodes = Stream.empty();
174+
Stream<String> bannedBtcNodes = Stream.of(bannedHostName + ":" + 1234);
183175

184176
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
185-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
177+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
186178

187179
assertIterableEquals(hardcodedNodes, selectedNodes);
188180
}
@@ -200,12 +192,11 @@ void bannedOnionNode() {
200192
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
201193
);
202194

203-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
204-
List<String> filterProvidedBtcNodes = Collections.emptyList();
205-
List<String> bannedBtcNodes = List.of(bannedOnionAddress + ":" + BtcNodes.BtcNode.DEFAULT_PORT);
195+
Stream<String> filterProvidedBtcNodes = Stream.empty();
196+
Stream<String> bannedBtcNodes = Stream.of(bannedOnionAddress + ":" + BtcNodes.BtcNode.DEFAULT_PORT);
206197

207198
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
208-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
199+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
209200

210201
var expected = List.of(
211202
new BtcNodes.BtcNode(null, "alice.onion", null,
@@ -229,12 +220,11 @@ void bannedOnionNodeWrongPort() {
229220
BtcNodes.BtcNode.DEFAULT_PORT, "@charlie")
230221
);
231222

232-
List<BtcNodes.BtcNode> mutableHardcodedList = new ArrayList<>(hardcodedNodes);
233-
List<String> filterProvidedBtcNodes = Collections.emptyList();
234-
List<String> bannedBtcNodes = List.of(bannedOnionAddress + ":" + 1234);
223+
Stream<String> filterProvidedBtcNodes = Stream.empty();
224+
Stream<String> bannedBtcNodes = Stream.of(bannedOnionAddress + ":" + 1234);
235225

236226
List<BtcNodes.BtcNode> selectedNodes = FederatedBtcNodeProvider
237-
.getNodes(mutableHardcodedList, filterProvidedBtcNodes, bannedBtcNodes);
227+
.getNodes(hardcodedNodes.stream(), filterProvidedBtcNodes, bannedBtcNodes);
238228

239229
assertIterableEquals(hardcodedNodes, selectedNodes);
240230
}

0 commit comments

Comments
 (0)