mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-08 00:25:06 -04:00
Faster joins: Support for calling /federation/v1/state
(#12013)
This is an endpoint that we have server-side support for, but no client-side support. It's going to be useful for resyncing partial-stated rooms, so let's introduce it.
This commit is contained in:
parent
066171643b
commit
7273011f60
7 changed files with 377 additions and 17 deletions
|
@ -419,26 +419,90 @@ class FederationClient(FederationBase):
|
|||
|
||||
return state_event_ids, auth_event_ids
|
||||
|
||||
async def get_room_state(
|
||||
self,
|
||||
destination: str,
|
||||
room_id: str,
|
||||
event_id: str,
|
||||
room_version: RoomVersion,
|
||||
) -> Tuple[List[EventBase], List[EventBase]]:
|
||||
"""Calls the /state endpoint to fetch the state at a particular point
|
||||
in the room.
|
||||
|
||||
Any invalid events (those with incorrect or unverifiable signatures or hashes)
|
||||
are filtered out from the response, and any duplicate events are removed.
|
||||
|
||||
(Size limits and other event-format checks are *not* performed.)
|
||||
|
||||
Note that the result is not ordered, so callers must be careful to process
|
||||
the events in an order that handles dependencies.
|
||||
|
||||
Returns:
|
||||
a tuple of (state events, auth events)
|
||||
"""
|
||||
result = await self.transport_layer.get_room_state(
|
||||
room_version,
|
||||
destination,
|
||||
room_id,
|
||||
event_id,
|
||||
)
|
||||
state_events = result.state
|
||||
auth_events = result.auth_events
|
||||
|
||||
# we may as well filter out any duplicates from the response, to save
|
||||
# processing them multiple times. (In particular, events may be present in
|
||||
# `auth_events` as well as `state`, which is redundant).
|
||||
#
|
||||
# We don't rely on the sort order of the events, so we can just stick them
|
||||
# in a dict.
|
||||
state_event_map = {event.event_id: event for event in state_events}
|
||||
auth_event_map = {
|
||||
event.event_id: event
|
||||
for event in auth_events
|
||||
if event.event_id not in state_event_map
|
||||
}
|
||||
|
||||
logger.info(
|
||||
"Processing from /state: %d state events, %d auth events",
|
||||
len(state_event_map),
|
||||
len(auth_event_map),
|
||||
)
|
||||
|
||||
valid_auth_events = await self._check_sigs_and_hash_and_fetch(
|
||||
destination, auth_event_map.values(), room_version
|
||||
)
|
||||
|
||||
valid_state_events = await self._check_sigs_and_hash_and_fetch(
|
||||
destination, state_event_map.values(), room_version
|
||||
)
|
||||
|
||||
return valid_state_events, valid_auth_events
|
||||
|
||||
async def _check_sigs_and_hash_and_fetch(
|
||||
self,
|
||||
origin: str,
|
||||
pdus: Collection[EventBase],
|
||||
room_version: RoomVersion,
|
||||
) -> List[EventBase]:
|
||||
"""Takes a list of PDUs and checks the signatures and hashes of each
|
||||
one. If a PDU fails its signature check then we check if we have it in
|
||||
the database and if not then request if from the originating server of
|
||||
that PDU.
|
||||
"""Checks the signatures and hashes of a list of events.
|
||||
|
||||
If a PDU fails its signature check then we check if we have it in
|
||||
the database, and if not then request it from the sender's server (if that
|
||||
is different from `origin`). If that still fails, the event is omitted from
|
||||
the returned list.
|
||||
|
||||
If a PDU fails its content hash check then it is redacted.
|
||||
|
||||
The given list of PDUs are not modified, instead the function returns
|
||||
Also runs each event through the spam checker; if it fails, redacts the event
|
||||
and flags it as soft-failed.
|
||||
|
||||
The given list of PDUs are not modified; instead the function returns
|
||||
a new list.
|
||||
|
||||
Args:
|
||||
origin
|
||||
pdu
|
||||
room_version
|
||||
origin: The server that sent us these events
|
||||
pdus: The events to be checked
|
||||
room_version: the version of the room these events are in
|
||||
|
||||
Returns:
|
||||
A list of PDUs that have valid signatures and hashes.
|
||||
|
@ -469,11 +533,16 @@ class FederationClient(FederationBase):
|
|||
origin: str,
|
||||
room_version: RoomVersion,
|
||||
) -> Optional[EventBase]:
|
||||
"""Takes a PDU and checks its signatures and hashes. If the PDU fails
|
||||
its signature check then we check if we have it in the database and if
|
||||
not then request if from the originating server of that PDU.
|
||||
"""Takes a PDU and checks its signatures and hashes.
|
||||
|
||||
If then PDU fails its content hash check then it is redacted.
|
||||
If the PDU fails its signature check then we check if we have it in the
|
||||
database; if not, we then request it from sender's server (if that is not the
|
||||
same as `origin`). If that still fails, we return None.
|
||||
|
||||
If the PDU fails its content hash check, it is redacted.
|
||||
|
||||
Also runs the event through the spam checker; if it fails, redacts the event
|
||||
and flags it as soft-failed.
|
||||
|
||||
Args:
|
||||
origin
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue