diff --git a/synapse/events/builder.py b/synapse/events/builder.py index 487f58e6d6..ef60f252e5 100644 --- a/synapse/events/builder.py +++ b/synapse/events/builder.py @@ -146,7 +146,9 @@ class EventBuilder: based on the prev_events. prev_state_events: The event IDs to use as prev_state_events. Only applicable on MSC4242 state DAG rooms. If this is supplied, auth_event_ids - must not be specified. + must not be specified unless this event is part of a batch such that the builder + will be unable to compute the auth_event_ids due to the events not being persisted + yet. Returns: The signed and hashed event. """ diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index a4b18b7173..66b4d4440c 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -1487,7 +1487,9 @@ class RoomCreationHandler: # the most recently created event prev_event: list[str] = [] # the most recently created state event - prev_state_event: list[str] = [] + prev_state_event: list[str] | None = ( + [] if room_version.msc4242_state_dags else None + ) # a map of event types, state keys -> event_ids. We collect these mappings this as events are # created (but not persisted to the db) to determine state for future created events @@ -1574,7 +1576,8 @@ class RoomCreationHandler: ignore_shadow_ban=True, ) last_sent_event_id = ev.event_id - prev_state_event = [ev.event_id] + if room_version.msc4242_state_dags: + prev_state_event = [ev.event_id] member_event_id, _ = await self.room_member_handler.update_membership( creator, @@ -1589,7 +1592,8 @@ class RoomCreationHandler: prev_state_events=prev_state_event, ) prev_event = [member_event_id] - prev_state_event = [member_event_id] + if room_version.msc4242_state_dags: + prev_state_event = [member_event_id] # update the depth and state map here as the membership event has been created # through a different code path diff --git a/tests/storage/test_msc4242_state_dag.py b/tests/storage/test_msc4242_state_dag.py index 6107ce66f6..9fe1dcabd4 100644 --- a/tests/storage/test_msc4242_state_dag.py +++ b/tests/storage/test_msc4242_state_dag.py @@ -57,16 +57,16 @@ class MSC4242StateDagsTests(HomeserverTestCase): for non-state events. """ # they don't change for messages - first_id = self.helper.send(self.room_id, body="test1")["event_id"] - first_pae = self._get_prev_state_events(first_id) - assert len(first_pae) == 1 + first_event_id = self.helper.send(self.room_id, body="test1")["event_id"] + first_prev_state_event = self._get_prev_state_events(first_event_id) + assert len(first_prev_state_event) == 1 second_id = self.helper.send(self.room_id, body="test2")["event_id"] - second_pae = self._get_prev_state_events(second_id) - assert len(second_pae) == 1 - self.assertEquals(first_pae, second_pae) + second_prev_state_event = self._get_prev_state_events(second_id) + assert len(second_prev_state_event) == 1 + self.assertEquals(first_prev_state_event, second_prev_state_event) - # send another auth event, which should change the prev_state_events on subsequent events - jr_id = self.helper.send_state( + # send an auth event, which should change the prev_state_events on *subsequent* events + join_rule_state_event_id = self.helper.send_state( self.room_id, EventTypes.JoinRules, { @@ -74,25 +74,29 @@ class MSC4242StateDagsTests(HomeserverTestCase): }, tok="nope", )["event_id"] - jr_pae = self._get_prev_state_events(jr_id) - self.assertEquals(second_pae, jr_pae) + join_rule_prev_state_event_ids = self._get_prev_state_events( + join_rule_state_event_id + ) + self.assertEquals(second_prev_state_event, join_rule_prev_state_event_ids) # prev_state_events should always point to the join rule now - third_id = self.helper.send(self.room_id, body="test3")["event_id"] - third_pae = self._get_prev_state_events(third_id) - self.assertEquals(third_pae, [jr_id]) - # ..including for non-auth state - # TODO FIXME KEGAN - # name_id = self.helper.send_state( - # self.room_id, - # EventTypes.Name, - # { - # "name": "State DAGs!", - # }, - # tok="nope", - # )["event_id"] - # name_pae = self._get_prev_state_events(name_id) - # self.assertEquals(name_pae, [jr_id]) + third_event_id = self.helper.send(self.room_id, body="test3")["event_id"] + third_prev_state_event = self._get_prev_state_events(third_event_id) + self.assertEquals(third_prev_state_event, [join_rule_state_event_id]) + # and non-auth state should also update prev_state_events + name_state_event_id = self.helper.send_state( + self.room_id, + EventTypes.Name, + { + "name": "State DAGs!", + }, + tok="nope", + )["event_id"] + name_prev_state_event_ids = self._get_prev_state_events(name_state_event_id) + self.assertEquals(name_prev_state_event_ids, [join_rule_state_event_id]) + fourth_event_id = self.helper.send(self.room_id, body="test4")["event_id"] + fourth_prev_state_event = self._get_prev_state_events(fourth_event_id) + self.assertEquals(fourth_prev_state_event, [name_state_event_id]) class MSC4242EventPersistenceAuthDagsStoreTestCase(HomeserverTestCase): @@ -135,6 +139,7 @@ class MSC4242EventPersistenceAuthDagsStoreTestCase(HomeserverTestCase): id: str, prev_state_events: list[str], rejected: bool = False, + soft_failed: bool = False, ) -> tuple[FrozenEventVMSC4242, EventContext]: ev = make_event_from_dict( { @@ -149,6 +154,8 @@ class MSC4242EventPersistenceAuthDagsStoreTestCase(HomeserverTestCase): }, room_version=RoomVersions.MSC4242v12, ) + if soft_failed: + ev.internal_metadata.soft_failed = True assert isinstance(ev, FrozenEventVMSC4242) ev._event_id = id ctx = Mock() @@ -162,17 +169,23 @@ class MSC4242EventPersistenceAuthDagsStoreTestCase(HomeserverTestCase): want_new_extrems: set[str], want_raises: bool = False, ) -> None: - promise = self.persistence._calculate_new_state_dag_extremities( + """ + Tests the logic of _calculate_new_state_dag_extremities. + + Tests that the new extremities calculated as a result of processing current_fwds and new_events + matches want_new_extrems or raises if want_raises is True. + """ + coroutine = self.persistence._calculate_new_state_dag_extremities( self.room_id, frozenset(current_fwds), new_events, ) if want_raises: - f = self.get_failure(promise, SynapseError) + f = self.get_failure(coroutine, SynapseError) assert f is not None return - new_extrems = set(self.get_success(promise)) + new_extrems = set(self.get_success(coroutine)) self.assertEqual( new_extrems, want_new_extrems, diff --git a/tests/test_event_auth.py b/tests/test_event_auth.py index 3b3d3c0ffa..9258f0d4dc 100644 --- a/tests/test_event_auth.py +++ b/tests/test_event_auth.py @@ -389,7 +389,6 @@ class EventAuthTestCase(unittest.TestCase): create_event = make_event_from_dict( { - "room_id": TEST_ROOM_ID, "type": "m.room.create", "sender": creator, "state_key": "", @@ -399,9 +398,22 @@ class EventAuthTestCase(unittest.TestCase): }, room_version, ) + create_event_2 = make_event_from_dict( + { + "type": "m.room.create", + "sender": creator, + "state_key": "", + "content": {"creator": creator, "another": "room"}, + "prev_events": [], + "prev_state_events": [], + }, + room_version, + ) + room_id = create_event.room_id + another_room_id = create_event_2.room_id join_event = make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.member", "sender": creator, "state_key": creator, @@ -414,7 +426,7 @@ class EventAuthTestCase(unittest.TestCase): ) event_in_another_room = make_event_from_dict( { - "room_id": f"!another_room:{TEST_DOMAIN}", + "room_id": another_room_id, "type": "m.room.join_rules", "sender": creator, "state_key": "", @@ -427,7 +439,7 @@ class EventAuthTestCase(unittest.TestCase): ) msg_event = make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.message", "sender": creator, "content": {"msgtype": "m.text", "body": "I am a message"}, @@ -439,7 +451,7 @@ class EventAuthTestCase(unittest.TestCase): ) rejected_event = make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.name", "sender": creator, "state_key": "", @@ -457,24 +469,18 @@ class EventAuthTestCase(unittest.TestCase): rejecting_test_cases = [ RejectingTestCase( name="create event has prev_state_events", - events_in_store=[create_event, join_event], + events_in_store=[], test_event=make_event_from_dict( { - "room_id": TEST_ROOM_ID, "type": "m.room.create", "sender": creator, "state_key": "", "content": {"creator": creator}, "prev_events": [], - "prev_state_events": [join_event.event_id], + "prev_state_events": [create_event.event_id], }, room_version, - { - "calculated_auth_event_ids": [ - create_event.event_id, - join_event.event_id, - ] - }, + {}, ), ), RejectingTestCase( @@ -482,7 +488,7 @@ class EventAuthTestCase(unittest.TestCase): events_in_store=[create_event, join_event, event_in_another_room], test_event=make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.name", "sender": creator, "state_key": "", @@ -504,7 +510,7 @@ class EventAuthTestCase(unittest.TestCase): events_in_store=[create_event, join_event, msg_event], test_event=make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.name", "sender": creator, "state_key": "", @@ -526,7 +532,7 @@ class EventAuthTestCase(unittest.TestCase): events_in_store=[create_event, join_event, rejected_event], test_event=make_event_from_dict( { - "room_id": TEST_ROOM_ID, + "room_id": room_id, "type": "m.room.name", "sender": creator, "state_key": "",