Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 23768cc

Browse files
authored
Faster joins: fix rejected events becoming un-rejected during resync (#13413)
Make sure that we re-check the auth rules during state resync, otherwise rejected events get un-rejected.
1 parent d548d8f commit 23768cc

File tree

3 files changed

+32
-6
lines changed

3 files changed

+32
-6
lines changed

changelog.d/13413.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Faster room joins: fix a bug which caused rejected events to become un-rejected during state syncing.

synapse/handlers/federation_event.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ async def update_state_for_partial_state_event(
581581
event.event_id,
582582
)
583583
return
584+
585+
# since the state at this event has changed, we should now re-evaluate
586+
# whether it should have been rejected. We must already have all of the
587+
# auth events (from last time we went round this path), so there is no
588+
# need to pass the origin.
589+
await self._check_event_auth(None, event, context)
590+
584591
await self._store.update_state_for_partial_state_event(event, context)
585592
self._state_storage_controller.notify_event_un_partial_stated(
586593
event.event_id
@@ -1624,13 +1631,15 @@ async def prep(event: EventBase) -> None:
16241631
)
16251632

16261633
async def _check_event_auth(
1627-
self, origin: str, event: EventBase, context: EventContext
1634+
self, origin: Optional[str], event: EventBase, context: EventContext
16281635
) -> None:
16291636
"""
16301637
Checks whether an event should be rejected (for failing auth checks).
16311638
16321639
Args:
1633-
origin: The host the event originates from.
1640+
origin: The host the event originates from. This is used to fetch
1641+
any missing auth events. It can be set to None, but only if we are
1642+
sure that we already have all the auth events.
16341643
event: The event itself.
16351644
context:
16361645
The event context.
@@ -1876,7 +1885,7 @@ async def _check_for_soft_fail(
18761885
event.internal_metadata.soft_failed = True
18771886

18781887
async def _load_or_fetch_auth_events_for_event(
1879-
self, destination: str, event: EventBase
1888+
self, destination: Optional[str], event: EventBase
18801889
) -> Collection[EventBase]:
18811890
"""Fetch this event's auth_events, from database or remote
18821891
@@ -1892,12 +1901,19 @@ async def _load_or_fetch_auth_events_for_event(
18921901
Args:
18931902
destination: where to send the /event_auth request. Typically the server
18941903
that sent us `event` in the first place.
1904+
1905+
If this is None, no attempt is made to load any missing auth events:
1906+
rather, an AssertionError is raised if there are any missing events.
1907+
18951908
event: the event whose auth_events we want
18961909
18971910
Returns:
18981911
all of the events listed in `event.auth_events_ids`, after deduplication
18991912
19001913
Raises:
1914+
AssertionError if some auth events were missing and no `destination` was
1915+
supplied.
1916+
19011917
AuthError if we were unable to fetch the auth_events for any reason.
19021918
"""
19031919
event_auth_event_ids = set(event.auth_event_ids())
@@ -1909,6 +1925,13 @@ async def _load_or_fetch_auth_events_for_event(
19091925
)
19101926
if not missing_auth_event_ids:
19111927
return event_auth_events.values()
1928+
if destination is None:
1929+
# this shouldn't happen: destination must be set unless we know we have already
1930+
# persisted the auth events.
1931+
raise AssertionError(
1932+
"_load_or_fetch_auth_events_for_event() called with no destination for "
1933+
"an event with missing auth_events"
1934+
)
19121935

19131936
logger.info(
19141937
"Event %s refers to unknown auth events %s: fetching auth chain",

synapse/storage/databases/main/state.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,15 @@ def _update_state_for_partial_state_event_txn(
419419
# anything that was rejected should have the same state as its
420420
# predecessor.
421421
if context.rejected:
422-
assert context.state_group == context.state_group_before_event
422+
state_group = context.state_group_before_event
423+
else:
424+
state_group = context.state_group
423425

424426
self.db_pool.simple_update_txn(
425427
txn,
426428
table="event_to_state_groups",
427429
keyvalues={"event_id": event.event_id},
428-
updatevalues={"state_group": context.state_group},
430+
updatevalues={"state_group": state_group},
429431
)
430432

431433
self.db_pool.simple_delete_one_txn(
@@ -440,7 +442,7 @@ def _update_state_for_partial_state_event_txn(
440442
txn.call_after(
441443
self._get_state_group_for_event.prefill,
442444
(event.event_id,),
443-
context.state_group,
445+
state_group,
444446
)
445447

446448

0 commit comments

Comments
 (0)