Add some assertions about outliers (#10773)

I think I have finally teased apart the codepaths which handle outliers, and those that handle non-outliers. 
Let's add some assertions to demonstrate my newfound knowledge.
code_spécifique_watcha
Richard van der Hoff 3 years ago committed by GitHub
parent 5724883ac2
commit aacdce8fc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      changelog.d/10773.misc
  2. 148
      synapse/handlers/federation_event.py

@ -0,0 +1 @@
Clean up some of the federation event authentication code for clarity.

@ -173,6 +173,9 @@ class FederationEventHandler:
pdu: received PDU pdu: received PDU
""" """
# We should never see any outliers here.
assert not pdu.internal_metadata.outlier
room_id = pdu.room_id room_id = pdu.room_id
event_id = pdu.event_id event_id = pdu.event_id
@ -232,77 +235,71 @@ class FederationEventHandler:
) )
return None return None
# Check that the event passes auth based on the state at the event. This is # Try to fetch any missing prev events to fill in gaps in the graph
# done for events that are to be added to the timeline (non-outliers). prevs = set(pdu.prev_event_ids())
# seen = await self._store.have_events_in_timeline(prevs)
# Get missing pdus if necessary: missing_prevs = prevs - seen
# - Fetching any missing prev events to fill in gaps in the graph
# - Fetching state if we have a hole in the graph
if not pdu.internal_metadata.is_outlier():
prevs = set(pdu.prev_event_ids())
seen = await self._store.have_events_in_timeline(prevs)
missing_prevs = prevs - seen
if missing_prevs: if missing_prevs:
# We only backfill backwards to the min depth. # We only backfill backwards to the min depth.
min_depth = await self.get_min_depth_for_context(pdu.room_id) min_depth = await self.get_min_depth_for_context(pdu.room_id)
logger.debug("min_depth: %d", min_depth) logger.debug("min_depth: %d", min_depth)
if min_depth is not None and pdu.depth > min_depth: if min_depth is not None and pdu.depth > min_depth:
# If we're missing stuff, ensure we only fetch stuff one # If we're missing stuff, ensure we only fetch stuff one
# at a time. # at a time.
logger.info(
"Acquiring room lock to fetch %d missing prev_events: %s",
len(missing_prevs),
shortstr(missing_prevs),
)
with (await self._room_pdu_linearizer.queue(pdu.room_id)):
logger.info( logger.info(
"Acquiring room lock to fetch %d missing prev_events: %s", "Acquired room lock to fetch %d missing prev_events",
len(missing_prevs), len(missing_prevs),
shortstr(missing_prevs),
) )
with (await self._room_pdu_linearizer.queue(pdu.room_id)):
logger.info( try:
"Acquired room lock to fetch %d missing prev_events", await self._get_missing_events_for_pdu(
len(missing_prevs), origin, pdu, prevs, min_depth
) )
except Exception as e:
raise Exception(
"Error fetching missing prev_events for %s: %s"
% (event_id, e)
) from e
try: # Update the set of things we've seen after trying to
await self._get_missing_events_for_pdu( # fetch the missing stuff
origin, pdu, prevs, min_depth seen = await self._store.have_events_in_timeline(prevs)
) missing_prevs = prevs - seen
except Exception as e:
raise Exception( if not missing_prevs:
"Error fetching missing prev_events for %s: %s" logger.info("Found all missing prev_events")
% (event_id, e)
) from e if missing_prevs:
# since this event was pushed to us, it is possible for it to
# Update the set of things we've seen after trying to # become the only forward-extremity in the room, and we would then
# fetch the missing stuff # trust its state to be the state for the whole room. This is very
seen = await self._store.have_events_in_timeline(prevs) # bad. Further, if the event was pushed to us, there is no excuse
missing_prevs = prevs - seen # for us not to have all the prev_events. (XXX: apart from
# min_depth?)
if not missing_prevs: #
logger.info("Found all missing prev_events") # We therefore reject any such events.
logger.warning(
if missing_prevs: "Rejecting: failed to fetch %d prev events: %s",
# since this event was pushed to us, it is possible for it to len(missing_prevs),
# become the only forward-extremity in the room, and we would then shortstr(missing_prevs),
# trust its state to be the state for the whole room. This is very )
# bad. Further, if the event was pushed to us, there is no excuse raise FederationError(
# for us not to have all the prev_events. (XXX: apart from "ERROR",
# min_depth?) 403,
# (
# We therefore reject any such events. "Your server isn't divulging details about prev_events "
logger.warning( "referenced in this event."
"Rejecting: failed to fetch %d prev events: %s", ),
len(missing_prevs), affected=pdu.event_id,
shortstr(missing_prevs), )
)
raise FederationError(
"ERROR",
403,
(
"Your server isn't divulging details about prev_events "
"referenced in this event."
),
affected=pdu.event_id,
)
await self._process_received_pdu(origin, pdu, state=None) await self._process_received_pdu(origin, pdu, state=None)
@ -885,8 +882,13 @@ class FederationEventHandler:
state: Optional[Iterable[EventBase]], state: Optional[Iterable[EventBase]],
backfilled: bool = False, backfilled: bool = False,
) -> None: ) -> None:
"""Called when we have a new pdu. We need to do auth checks and put it """Called when we have a new non-outlier event.
through the StateHandler.
This is called when we have a new event to add to the room DAG - either directly
via a /send request, retrieved via get_missing_events after a /send request, or
backfilled after a client request.
We need to do auth checks and put it through the StateHandler.
Args: Args:
origin: server sending the event origin: server sending the event
@ -901,6 +903,7 @@ class FederationEventHandler:
notification to clients, and validation of device keys.) notification to clients, and validation of device keys.)
""" """
logger.debug("Processing event: %s", event) logger.debug("Processing event: %s", event)
assert not event.internal_metadata.outlier
try: try:
context = await self._state_handler.compute_event_context( context = await self._state_handler.compute_event_context(
@ -1263,11 +1266,13 @@ class FederationEventHandler:
Possibly incomplete, and possibly including events that are not yet Possibly incomplete, and possibly including events that are not yet
persisted, or authed, or in the right room. persisted, or authed, or in the right room.
Only populated where we may not already have persisted these events - Only populated when populating outliers.
for example, when populating outliers.
backfilled: True if the event was backfilled. backfilled: True if the event was backfilled.
""" """
# claimed_auth_event_map should be given iff the event is an outlier
assert bool(claimed_auth_event_map) == event.internal_metadata.outlier
context = await self._check_event_auth( context = await self._check_event_auth(
origin, origin,
event, event,
@ -1306,15 +1311,16 @@ class FederationEventHandler:
Possibly incomplete, and possibly including events that are not yet Possibly incomplete, and possibly including events that are not yet
persisted, or authed, or in the right room. persisted, or authed, or in the right room.
Only populated where we may not already have persisted these events - Only populated when populating outliers.
for example, when populating outliers, or the state for a backwards
extremity.
backfilled: True if the event was backfilled. backfilled: True if the event was backfilled.
Returns: Returns:
The updated context object. The updated context object.
""" """
# claimed_auth_event_map should be given iff the event is an outlier
assert bool(claimed_auth_event_map) == event.internal_metadata.outlier
room_version = await self._store.get_room_version_id(event.room_id) room_version = await self._store.get_room_version_id(event.room_id)
room_version_obj = KNOWN_ROOM_VERSIONS[room_version] room_version_obj = KNOWN_ROOM_VERSIONS[room_version]

Loading…
Cancel
Save