forked from MirrorHub/synapse
Merge pull request #6343 from matrix-org/rav/event_auth/4
Refactor _update_auth_events_and_context_for_auth
This commit is contained in:
commit
651d930f16
2 changed files with 45 additions and 37 deletions
1
changelog.d/6343.misc
Normal file
1
changelog.d/6343.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Refactor some code in the event authentication path for clarity.
|
|
@ -2040,8 +2040,10 @@ class FederationHandler(BaseHandler):
|
||||||
auth_events (dict[(str, str)->synapse.events.EventBase]):
|
auth_events (dict[(str, str)->synapse.events.EventBase]):
|
||||||
Map from (event_type, state_key) to event
|
Map from (event_type, state_key) to event
|
||||||
|
|
||||||
What we expect the event's auth_events to be, based on the event's
|
Normally, our calculated auth_events based on the state of the room
|
||||||
position in the dag. I think? maybe??
|
at the event's position in the DAG, though occasionally (eg if the
|
||||||
|
event is an outlier), may be the auth events claimed by the remote
|
||||||
|
server.
|
||||||
|
|
||||||
Also NB that this function adds entries to it.
|
Also NB that this function adds entries to it.
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -2091,30 +2093,35 @@ class FederationHandler(BaseHandler):
|
||||||
origin (str):
|
origin (str):
|
||||||
event (synapse.events.EventBase):
|
event (synapse.events.EventBase):
|
||||||
context (synapse.events.snapshot.EventContext):
|
context (synapse.events.snapshot.EventContext):
|
||||||
|
|
||||||
auth_events (dict[(str, str)->synapse.events.EventBase]):
|
auth_events (dict[(str, str)->synapse.events.EventBase]):
|
||||||
|
Map from (event_type, state_key) to event
|
||||||
|
|
||||||
|
Normally, our calculated auth_events based on the state of the room
|
||||||
|
at the event's position in the DAG, though occasionally (eg if the
|
||||||
|
event is an outlier), may be the auth events claimed by the remote
|
||||||
|
server.
|
||||||
|
|
||||||
|
Also NB that this function adds entries to it.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
defer.Deferred[EventContext]: updated context
|
defer.Deferred[EventContext]: updated context
|
||||||
"""
|
"""
|
||||||
event_auth_events = set(event.auth_event_ids())
|
event_auth_events = set(event.auth_event_ids())
|
||||||
|
|
||||||
if event.is_state():
|
# missing_auth is the set of the event's auth_events which we don't yet have
|
||||||
event_key = (event.type, event.state_key)
|
# in auth_events.
|
||||||
else:
|
|
||||||
event_key = None
|
|
||||||
|
|
||||||
# if the event's auth_events refers to events which are not in our
|
|
||||||
# calculated auth_events, we need to fetch those events from somewhere.
|
|
||||||
#
|
|
||||||
# we start by fetching them from the store, and then try calling /event_auth/.
|
|
||||||
missing_auth = event_auth_events.difference(
|
missing_auth = event_auth_events.difference(
|
||||||
e.event_id for e in auth_events.values()
|
e.event_id for e in auth_events.values()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# if we have missing events, we need to fetch those events from somewhere.
|
||||||
|
#
|
||||||
|
# we start by checking if they are in the store, and then try calling /event_auth/.
|
||||||
if missing_auth:
|
if missing_auth:
|
||||||
# TODO: can we use store.have_seen_events here instead?
|
# TODO: can we use store.have_seen_events here instead?
|
||||||
have_events = yield self.store.get_seen_events_with_rejections(missing_auth)
|
have_events = yield self.store.get_seen_events_with_rejections(missing_auth)
|
||||||
logger.debug("Got events %s from store", have_events)
|
logger.debug("Found events %s in the store", have_events)
|
||||||
missing_auth.difference_update(have_events.keys())
|
missing_auth.difference_update(have_events.keys())
|
||||||
else:
|
else:
|
||||||
have_events = {}
|
have_events = {}
|
||||||
|
@ -2169,15 +2176,17 @@ class FederationHandler(BaseHandler):
|
||||||
event.auth_event_ids()
|
event.auth_event_ids()
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
# FIXME:
|
|
||||||
logger.exception("Failed to get auth chain")
|
logger.exception("Failed to get auth chain")
|
||||||
|
|
||||||
if event.internal_metadata.is_outlier():
|
if event.internal_metadata.is_outlier():
|
||||||
|
# XXX: given that, for an outlier, we'll be working with the
|
||||||
|
# event's *claimed* auth events rather than those we calculated:
|
||||||
|
# (a) is there any point in this test, since different_auth below will
|
||||||
|
# obviously be empty
|
||||||
|
# (b) alternatively, why don't we do it earlier?
|
||||||
logger.info("Skipping auth_event fetch for outlier")
|
logger.info("Skipping auth_event fetch for outlier")
|
||||||
return context
|
return context
|
||||||
|
|
||||||
# FIXME: Assumes we have and stored all the state for all the
|
|
||||||
# prev_events
|
|
||||||
different_auth = event_auth_events.difference(
|
different_auth = event_auth_events.difference(
|
||||||
e.event_id for e in auth_events.values()
|
e.event_id for e in auth_events.values()
|
||||||
)
|
)
|
||||||
|
@ -2191,27 +2200,22 @@ class FederationHandler(BaseHandler):
|
||||||
different_auth,
|
different_auth,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# now we state-resolve between our own idea of the auth events, and the remote's
|
||||||
|
# idea of them.
|
||||||
|
|
||||||
room_version = yield self.store.get_room_version(event.room_id)
|
room_version = yield self.store.get_room_version(event.room_id)
|
||||||
|
different_event_ids = [
|
||||||
|
d for d in different_auth if d in have_events and not have_events[d]
|
||||||
|
]
|
||||||
|
|
||||||
different_events = yield make_deferred_yieldable(
|
if different_event_ids:
|
||||||
defer.gatherResults(
|
# XXX: currently this checks for redactions but I'm not convinced that is
|
||||||
[
|
# necessary?
|
||||||
run_in_background(
|
different_events = yield self.store.get_events_as_list(different_event_ids)
|
||||||
self.store.get_event, d, allow_none=True, allow_rejected=False
|
|
||||||
)
|
|
||||||
for d in different_auth
|
|
||||||
if d in have_events and not have_events[d]
|
|
||||||
],
|
|
||||||
consumeErrors=True,
|
|
||||||
)
|
|
||||||
).addErrback(unwrapFirstError)
|
|
||||||
|
|
||||||
if different_events:
|
|
||||||
local_view = dict(auth_events)
|
local_view = dict(auth_events)
|
||||||
remote_view = dict(auth_events)
|
remote_view = dict(auth_events)
|
||||||
remote_view.update(
|
remote_view.update({(d.type, d.state_key): d for d in different_events})
|
||||||
{(d.type, d.state_key): d for d in different_events if d}
|
|
||||||
)
|
|
||||||
|
|
||||||
new_state = yield self.state_handler.resolve_events(
|
new_state = yield self.state_handler.resolve_events(
|
||||||
room_version,
|
room_version,
|
||||||
|
@ -2231,13 +2235,13 @@ class FederationHandler(BaseHandler):
|
||||||
auth_events.update(new_state)
|
auth_events.update(new_state)
|
||||||
|
|
||||||
context = yield self._update_context_for_auth_events(
|
context = yield self._update_context_for_auth_events(
|
||||||
event, context, auth_events, event_key
|
event, context, auth_events
|
||||||
)
|
)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def _update_context_for_auth_events(self, event, context, auth_events, event_key):
|
def _update_context_for_auth_events(self, event, context, auth_events):
|
||||||
"""Update the state_ids in an event context after auth event resolution,
|
"""Update the state_ids in an event context after auth event resolution,
|
||||||
storing the changes as a new state group.
|
storing the changes as a new state group.
|
||||||
|
|
||||||
|
@ -2246,18 +2250,21 @@ class FederationHandler(BaseHandler):
|
||||||
|
|
||||||
context (synapse.events.snapshot.EventContext): initial event context
|
context (synapse.events.snapshot.EventContext): initial event context
|
||||||
|
|
||||||
auth_events (dict[(str, str)->str]): Events to update in the event
|
auth_events (dict[(str, str)->EventBase]): Events to update in the event
|
||||||
context.
|
context.
|
||||||
|
|
||||||
event_key ((str, str)): (type, state_key) for the current event.
|
|
||||||
this will not be included in the current_state in the context.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Deferred[EventContext]: new event context
|
Deferred[EventContext]: new event context
|
||||||
"""
|
"""
|
||||||
|
# exclude the state key of the new event from the current_state in the context.
|
||||||
|
if event.is_state():
|
||||||
|
event_key = (event.type, event.state_key)
|
||||||
|
else:
|
||||||
|
event_key = None
|
||||||
state_updates = {
|
state_updates = {
|
||||||
k: a.event_id for k, a in iteritems(auth_events) if k != event_key
|
k: a.event_id for k, a in iteritems(auth_events) if k != event_key
|
||||||
}
|
}
|
||||||
|
|
||||||
current_state_ids = yield context.get_current_state_ids(self.store)
|
current_state_ids = yield context.get_current_state_ids(self.store)
|
||||||
current_state_ids = dict(current_state_ids)
|
current_state_ids = dict(current_state_ids)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue