Skip to content

Commit 5f4e713

Browse files
committed
Support matrix_room_id in PFS info response
This changes the is-pfs-on-the-same-federation check to use the new `matrix_room_id` field from the PFS info response. See raiden-network/raiden-services#858 for details
1 parent ab3d10f commit 5f4e713

File tree

11 files changed

+148
-59
lines changed

11 files changed

+148
-59
lines changed

raiden/network/pathfinding.py

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class PFSInfo:
7575
version: str
7676
confirmed_block_number: BlockNumber
7777
matrix_server: str
78+
matrix_room_id: Optional[str]
7879

7980

8081
@dataclass
@@ -164,6 +165,7 @@ def get_pfs_info(url: str) -> PFSInfo:
164165
version=infos["version"],
165166
confirmed_block_number=infos["network_info"]["confirmed_block"]["number"],
166167
matrix_server=matrix_server_info.netloc,
168+
matrix_room_id=infos.get("matrix_room_id"),
167169
)
168170
except RequestException as e:
169171
msg = "Selected Pathfinding Service did not respond"
@@ -248,7 +250,6 @@ def configure_pfs_or_exit(
248250
node_network_id: ChainID,
249251
token_network_registry_address: TokenNetworkRegistryAddress,
250252
pathfinding_max_fee: TokenAmount,
251-
matrix_servers: List[str],
252253
) -> PFSInfo:
253254
"""
254255
Take in the given pfs_address argument, the service registry and find out a
@@ -315,17 +316,6 @@ def configure_pfs_or_exit(
315316
f"Raiden will shut down. Please choose a different Pathfinding Service."
316317
)
317318

318-
server_in_federation = any(
319-
pathfinding_service_info.matrix_server in matrix_server for matrix_server in matrix_servers
320-
)
321-
# Only check if PFS is right federation when matrix server is not given explicitely
322-
if len(matrix_servers) > 0 and not server_in_federation:
323-
raise RaidenError(
324-
f"The Pathfinding Service {pfs_url} is not connected to the same matrix federation. "
325-
f"Please check your settings for PFS and matrix server, if manually chosen. "
326-
f"Otherwise, check your environment-type."
327-
)
328-
329319
click.secho(
330320
f"You have chosen the Pathfinding Service at {pfs_url}.\n"
331321
f"Operator: {pathfinding_service_info.operator}, "
@@ -341,6 +331,48 @@ def configure_pfs_or_exit(
341331
return pathfinding_service_info
342332

343333

334+
def check_pfs_transport_configuration(
335+
pfs_info: PFSInfo,
336+
pfs_was_autoselected: bool,
337+
transport_pfs_broadcast_room_id: str,
338+
matrix_server_url: str,
339+
matrix_server_was_autoselected: bool,
340+
) -> None:
341+
if pfs_info.matrix_room_id is None:
342+
# Special case until all PFSs are upgraded to >= 0.12.0
343+
log.warning(
344+
"Can't check PFS transport configuration",
345+
pfs_version=pfs_info.version,
346+
min_required_version="0.12.0",
347+
pfs_url=pfs_info.url,
348+
)
349+
return
350+
if pfs_info.matrix_room_id != transport_pfs_broadcast_room_id:
351+
msg = (
352+
f"The Pathfinding Service at {pfs_info.url} is not connected to the "
353+
f"same Matrix transport federation as this Raiden node."
354+
)
355+
if matrix_server_was_autoselected and pfs_was_autoselected:
356+
msg += (
357+
f"\nBoth the Matrix transport server at {matrix_server_url} and the PFS were "
358+
f"automatically selected. This points to a server-side misconfiguration. "
359+
f"Please report this issue at "
360+
f"https://github.com/raiden-network/raiden/issues/new?template=bug_report.md"
361+
)
362+
else:
363+
msg += (
364+
"\nPlease verify that the Matrix transport server and PFS service you selected "
365+
"are intended to be used together or use the automatic server selection."
366+
)
367+
msg += (
368+
f"\n\n"
369+
f"- Transport server PFS broadcast room-id: {transport_pfs_broadcast_room_id}\n"
370+
f"- PFS server broadcast room-id: {pfs_info.matrix_room_id}"
371+
)
372+
373+
raise RaidenError(msg)
374+
375+
344376
def check_pfs_for_production(
345377
service_registry: Optional[ServiceRegistry], pfs_info: PFSInfo
346378
) -> None:

raiden/network/transport/matrix/transport.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -384,15 +384,15 @@ def _http_retry_delay() -> Iterable[float]:
384384
None, self._handle_web_rtc_messages, self._handle_sdp_callback
385385
)
386386

387-
self._server_url = self._client.api.base_url
388-
self._server_name = urlparse(self._server_url).netloc
387+
self.server_url = self._client.api.base_url
388+
self._server_name = urlparse(self.server_url).netloc
389389

390390
self.greenlets: List[gevent.Greenlet] = list()
391391

392392
self._address_to_retrier: Dict[Address, _RetryQueue] = dict()
393393
self._displayname_cache = DisplayNameCache()
394394

395-
self._broadcast_rooms: Dict[str, Room] = dict()
395+
self.broadcast_rooms: Dict[str, Room] = dict()
396396
self._broadcast_queue: JoinableQueue[Tuple[str, Message]] = JoinableQueue()
397397

398398
self._started = False
@@ -734,11 +734,11 @@ def _broadcast(room_name: str, serialized_message: str) -> None:
734734
f"Known public rooms: {self._config.broadcast_rooms}."
735735
)
736736
room_name = make_room_alias(self.chain_id, room_name)
737-
if room_name not in self._broadcast_rooms:
737+
if room_name not in self.broadcast_rooms:
738738
room = join_broadcast_room(self._client, f"#{room_name}:{self._server_name}")
739-
self._broadcast_rooms[room_name] = room
739+
self.broadcast_rooms[room_name] = room
740740

741-
existing_room = self._broadcast_rooms.get(room_name)
741+
existing_room = self.broadcast_rooms.get(room_name)
742742
assert existing_room, f"Unknown broadcast room: {room_name!r}"
743743

744744
self.log.debug(
@@ -803,7 +803,7 @@ def _initialize_first_sync(self) -> None:
803803
# Call sync to fetch the inventory rooms and new invites, the sync
804804
# limit prevents fetching the messages.
805805
filter_id = self._client.create_sync_filter(
806-
not_rooms=self._broadcast_rooms.values(), limit=0
806+
not_rooms=self.broadcast_rooms.values(), limit=0
807807
)
808808
prev_sync_filter_id = self._client.set_sync_filter_id(filter_id)
809809
# Need to reset this here, otherwise we might run into problems after a restart
@@ -883,14 +883,14 @@ def _join_broadcast_room(transport: MatrixTransport, room_name: str) -> None:
883883
transport.log.debug(
884884
"Joining broadcast room", broadcast_room_alias=broadcast_room_alias
885885
)
886-
transport._broadcast_rooms[room_name] = join_broadcast_room(
886+
transport.broadcast_rooms[room_name] = join_broadcast_room(
887887
client=transport._client, broadcast_room_alias=broadcast_room_alias
888888
)
889889

890890
for suffix in self._config.broadcast_rooms:
891891
alias_prefix = make_room_alias(self.chain_id, suffix)
892892

893-
if alias_prefix not in self._broadcast_rooms:
893+
if alias_prefix not in self.broadcast_rooms:
894894
pool.apply_async(_join_broadcast_room, args=(self, alias_prefix))
895895

896896
pool.join(raise_error=True)
@@ -908,10 +908,10 @@ def _initialize_sync(self) -> None:
908908
"sync thread, since that is necessary to properly generate the "
909909
"filters."
910910
)
911-
assert self._broadcast_rooms, msg
911+
assert self.broadcast_rooms, msg
912912

913913
broadcast_filter_id = self._client.create_sync_filter(
914-
not_rooms=self._broadcast_rooms.values()
914+
not_rooms=self.broadcast_rooms.values()
915915
)
916916
self._client.set_sync_filter_id(broadcast_filter_id)
917917

@@ -1085,7 +1085,7 @@ def _handle_member_join(self, room: Room) -> None:
10851085
if self._is_broadcast_room(room):
10861086
raise AssertionError(
10871087
f"Broadcast room events should be filtered in syncs: {room.canonical_alias}."
1088-
f"Joined Broadcast Rooms: {list(self._broadcast_rooms.keys())}"
1088+
f"Joined Broadcast Rooms: {list(self.broadcast_rooms.keys())}"
10891089
f"Should be joined to: {self._config.broadcast_rooms}"
10901090
)
10911091

raiden/tests/integration/network/test_pathfinding.py

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import dataclasses
2+
import logging
13
from unittest.mock import patch
24

35
import pytest
@@ -14,6 +16,7 @@
1416
from raiden.network.pathfinding import (
1517
PFSInfo,
1618
check_pfs_for_production,
19+
check_pfs_transport_configuration,
1720
configure_pfs_or_exit,
1821
session,
1922
)
@@ -51,6 +54,7 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
5154
"version": "0.0.1",
5255
"payment_address": to_checksum_address(privatekey_to_address(private_keys[0])),
5356
"matrix_server": "http://matrix.example.com",
57+
"matrix_room_id": "!room-id:matrix.example.com",
5458
}
5559

5660
response = mocked_json_response(response_data=json_data)
@@ -64,7 +68,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
6468
node_network_id=chain_id,
6569
token_network_registry_address=token_network_registry_address_test_default,
6670
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
67-
matrix_servers=["http://matrix.example.com"],
6871
)
6972

7073
# With private routing configure_pfs should raise assertion
@@ -76,7 +79,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
7679
node_network_id=chain_id,
7780
token_network_registry_address=token_network_registry_address_test_default,
7881
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
79-
matrix_servers=["http://matrix.example.com"],
8082
)
8183

8284
# Asking for auto address
@@ -90,7 +92,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
9092
node_network_id=chain_id,
9193
token_network_registry_address=token_network_registry_address_test_default,
9294
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
93-
matrix_servers=["matrix.example.com"],
9495
)
9596
assert config.url in urls
9697
assert is_canonical_address(config.payment_address)
@@ -105,7 +106,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
105106
node_network_id=chain_id,
106107
token_network_registry_address=token_network_registry_address_test_default,
107108
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
108-
matrix_servers=["matrix.example.com"],
109109
)
110110
assert config.url == given_address
111111
assert is_same_address(config.payment_address, json_data["payment_address"])
@@ -123,7 +123,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
123123
node_network_id=chain_id,
124124
token_network_registry_address=token_network_registry_address_test_default,
125125
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
126-
matrix_servers=["http://matrix.example.com"],
127126
)
128127

129128
# Addresses of token network registries of pfs and client conflict, should exit the client
@@ -139,7 +138,6 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
139138
to_canonical_address("0x2222222222222222222222222222222222222221")
140139
),
141140
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
142-
matrix_servers=["http://matrix.example.com"],
143141
)
144142

145143
# ChainIDs of pfs and client conflict, should exit the client
@@ -153,22 +151,59 @@ def test_configure_pfs(service_registry_address, private_keys, web3, contract_ma
153151
node_network_id=ChainID(chain_id + 1),
154152
token_network_registry_address=token_network_registry_address_test_default,
155153
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
156-
matrix_servers=["http://matrix.example.com"],
157154
)
158155

159-
# Wrong matrix server
160-
response = mocked_json_response(response_data=json_data)
161-
with pytest.raises(RaidenError, match="matrix server"):
162-
with patch.object(session, "get", return_value=response):
163-
configure_pfs_or_exit(
164-
pfs_url="http://foo",
165-
routing_mode=RoutingMode.PFS,
166-
service_registry=service_registry,
167-
node_network_id=ChainID(chain_id),
168-
token_network_registry_address=token_network_registry_address_test_default,
169-
pathfinding_max_fee=DEFAULT_PATHFINDING_MAX_FEE,
170-
matrix_servers=["matrix.doesnotexist.com"],
171-
)
156+
157+
def test_check_pfs_transport_configuration(chain_id, private_keys, caplog):
158+
matrix_server_url = "http://matrix.example.com"
159+
matrix_room_id = "!room-id:matrix.example.com"
160+
pfs_info = PFSInfo(
161+
url="http://foo",
162+
price=TokenAmount(0),
163+
chain_id=chain_id,
164+
token_network_registry_address=token_network_registry_address_test_default,
165+
payment_address=to_canonical_address("0x2222222222222222222222222222222222222221"),
166+
message="",
167+
operator="",
168+
version="",
169+
user_deposit_address=privatekey_to_address(private_keys[1]),
170+
confirmed_block_number=BlockNumber(10),
171+
matrix_server=matrix_server_url,
172+
matrix_room_id=matrix_room_id,
173+
)
174+
175+
# Room id mismatch, must raise
176+
with pytest.raises(RaidenError):
177+
check_pfs_transport_configuration(
178+
pfs_info=pfs_info,
179+
pfs_was_autoselected=True,
180+
transport_pfs_broadcast_room_id="!this-is-not-the-room-youre-looking-for:example.com",
181+
matrix_server_url=matrix_server_url,
182+
matrix_server_was_autoselected=True,
183+
)
184+
185+
# Room ids match, must not raise
186+
check_pfs_transport_configuration(
187+
pfs_info=pfs_info,
188+
pfs_was_autoselected=True,
189+
transport_pfs_broadcast_room_id=matrix_room_id,
190+
matrix_server_url=matrix_server_url,
191+
matrix_server_was_autoselected=True,
192+
)
193+
194+
# With the matrix_room_id missing from the PFS response the check can't be performed
195+
pfs_info_no_room_id = dataclasses.replace(pfs_info, matrix_room_id=None)
196+
with caplog.at_level(logging.WARNING):
197+
check_pfs_transport_configuration(
198+
pfs_info=pfs_info_no_room_id,
199+
pfs_was_autoselected=True,
200+
transport_pfs_broadcast_room_id="!not-this-again:matrix.org",
201+
matrix_server_url=matrix_server_url,
202+
matrix_server_was_autoselected=True,
203+
)
204+
assert "Can't check PFS transport configuration" in (
205+
record.msg["event"] for record in caplog.records
206+
)
172207

173208

174209
def test_check_pfs_for_production(
@@ -195,6 +230,7 @@ def test_check_pfs_for_production(
195230
user_deposit_address=privatekey_to_address(private_keys[1]),
196231
confirmed_block_number=BlockNumber(10),
197232
matrix_server="http://matrix.example.com",
233+
matrix_room_id="!room-id:matrix.example.com",
198234
)
199235
with pytest.raises(RaidenError):
200236
check_pfs_for_production(service_registry=service_registry, pfs_info=pfs_info)
@@ -212,6 +248,7 @@ def test_check_pfs_for_production(
212248
user_deposit_address=privatekey_to_address(private_keys[1]),
213249
confirmed_block_number=BlockNumber(10),
214250
matrix_server="http://matrix.example.com",
251+
matrix_room_id="!room-id:matrix.example.com",
215252
)
216253
with pytest.raises(RaidenError):
217254
check_pfs_for_production(service_registry=service_registry, pfs_info=pfs_info)

raiden/tests/integration/network/transport/test_matrix_transport.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ def test_join_invalid_discovery(
426426
transport.start(raiden_service, [], None)
427427
transport.log = MagicMock()
428428
discovery_room_name = make_room_alias(transport.chain_id, "discovery")
429-
assert isinstance(transport._broadcast_rooms.get(discovery_room_name), Room)
429+
assert isinstance(transport.broadcast_rooms.get(discovery_room_name), Room)
430430

431431
transport.stop()
432432
transport.greenlet.get()
@@ -492,7 +492,7 @@ def test_matrix_discovery_room_offline_server(
492492

493493
discovery_room_name = make_room_alias(transport.chain_id, "discovery")
494494
with gevent.Timeout(1):
495-
while not isinstance(transport._broadcast_rooms.get(discovery_room_name), Room):
495+
while not isinstance(transport.broadcast_rooms.get(discovery_room_name), Room):
496496
gevent.sleep(0.1)
497497

498498
transport.stop()
@@ -524,7 +524,7 @@ def test_matrix_broadcast(
524524
gevent.idle()
525525

526526
ms_room_name = make_room_alias(transport.chain_id, MONITORING_BROADCASTING_ROOM)
527-
ms_room = transport._broadcast_rooms.get(ms_room_name)
527+
ms_room = transport.broadcast_rooms.get(ms_room_name)
528528
assert isinstance(ms_room, Room)
529529

530530
ms_room.send_text = MagicMock(spec=ms_room.send_text)
@@ -585,7 +585,7 @@ def test_monitoring_broadcast_messages(
585585
transport.start(raiden_service, [], None)
586586

587587
ms_room_name = make_room_alias(transport.chain_id, MONITORING_BROADCASTING_ROOM)
588-
ms_room = transport._broadcast_rooms.get(ms_room_name)
588+
ms_room = transport.broadcast_rooms.get(ms_room_name)
589589
assert isinstance(ms_room, Room)
590590
ms_room.send_text = MagicMock(spec=ms_room.send_text)
591591

@@ -666,7 +666,7 @@ def test_monitoring_broadcast_messages_in_production_if_bigger_than_threshold(
666666
transport.start(raiden_service, [], None)
667667

668668
ms_room_name = make_room_alias(transport.chain_id, MONITORING_BROADCASTING_ROOM)
669-
ms_room = transport._broadcast_rooms.get(ms_room_name)
669+
ms_room = transport.broadcast_rooms.get(ms_room_name)
670670
assert isinstance(ms_room, Room)
671671
ms_room.send_text = MagicMock(spec=ms_room.send_text)
672672

@@ -757,7 +757,7 @@ def test_pfs_broadcast_messages(
757757
transport.start(raiden_service, [], None)
758758

759759
pfs_room_name = make_room_alias(transport.chain_id, PATH_FINDING_BROADCASTING_ROOM)
760-
pfs_room = transport._broadcast_rooms.get(pfs_room_name)
760+
pfs_room = transport.broadcast_rooms.get(pfs_room_name)
761761
assert isinstance(pfs_room, Room)
762762
pfs_room.send_text = MagicMock(spec=pfs_room.send_text)
763763

@@ -1219,7 +1219,7 @@ def _handle_responses(
12191219
transport2.start(raiden_service2, [], None)
12201220

12211221
pfs_broadcast_room_alias = make_room_alias(transport0.chain_id, PATH_FINDING_BROADCASTING_ROOM)
1222-
pfs_broadcast_room_t0 = transport0._broadcast_rooms[pfs_broadcast_room_alias]
1222+
pfs_broadcast_room_t0 = transport0.broadcast_rooms[pfs_broadcast_room_alias]
12231223

12241224
# Get the sync helper to control flow of asynchronous syncs
12251225
sync_progress1 = transport1._client.sync_progress

0 commit comments

Comments
 (0)