From 2c5dc1e308dc951a85134dcfa81f0049554ea91b Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 11:47:03 +0100 Subject: [PATCH 01/30] deepcopy batched_auth_events --- synapse/event_auth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index d922c8dc35b..76415d74688 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -21,6 +21,7 @@ # import collections.abc +import copy import logging import typing from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union @@ -177,7 +178,7 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... if batched_auth_events: # Copy the batched auth events to avoid mutating them. - auth_events = dict(batched_auth_events) + auth_events = copy.deepcopy(batched_auth_events) needed_auth_event_ids = set(event.auth_event_ids()) - batched_auth_events.keys() if needed_auth_event_ids: auth_events.update( From 661134155a70212150a10f8db83d793129151527 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 12:02:15 +0100 Subject: [PATCH 02/30] add changelog --- changelog.d/16968.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/16968.bugfix diff --git a/changelog.d/16968.bugfix b/changelog.d/16968.bugfix new file mode 100644 index 00000000000..9cff5f2a3e9 --- /dev/null +++ b/changelog.d/16968.bugfix @@ -0,0 +1 @@ +Fix a potential deadlock when checking state independent auth rules by creating a deepcopy of authentication events. Contributed by @ggogel. \ No newline at end of file From 0bf1f1fb514260e28afdc0d8d33da962fb44c406 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 17:58:29 +0100 Subject: [PATCH 03/30] create copy with make_event_from_dict --- synapse/event_auth.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 76415d74688..507839d73e9 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -21,7 +21,6 @@ # import collections.abc -import copy import logging import typing from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union @@ -31,6 +30,7 @@ from signedjson.sign import SignatureVerifyException, verify_signed_json from typing_extensions import Protocol from unpaddedbase64 import decode_base64 +from synapse.events import make_event_from_dict from synapse.api.constants import ( MAX_PDU_SIZE, @@ -178,7 +178,14 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... if batched_auth_events: # Copy the batched auth events to avoid mutating them. - auth_events = copy.deepcopy(batched_auth_events) + auth_events = {} + for key, value in batched_auth_events.items(): + auth_events[key] = make_event_from_dict( + event_dict=value.get_dict(), + room_version=value.room_version, + rejected_reason=value.rejected_reason + ) + needed_auth_event_ids = set(event.auth_event_ids()) - batched_auth_events.keys() if needed_auth_event_ids: auth_events.update( From 80fc96e001d02cf1514ed88b9621e24d87e247f1 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 18:39:22 +0100 Subject: [PATCH 04/30] deepcopy event_dict --- synapse/event_auth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 507839d73e9..f6657ba3efc 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -21,6 +21,7 @@ # import collections.abc +import copy import logging import typing from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union @@ -181,7 +182,7 @@ async def check_state_independent_auth_rules( auth_events = {} for key, value in batched_auth_events.items(): auth_events[key] = make_event_from_dict( - event_dict=value.get_dict(), + event_dict=copy.deepcopy(value.get_dict()), room_version=value.room_version, rejected_reason=value.rejected_reason ) From ccf3011f8820a28b348ba5ccb77f6a2ae4f67cf3 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 19:54:03 +0100 Subject: [PATCH 05/30] only copy required attributes --- synapse/event_auth.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index f6657ba3efc..d384f822958 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -182,7 +182,11 @@ async def check_state_independent_auth_rules( auth_events = {} for key, value in batched_auth_events.items(): auth_events[key] = make_event_from_dict( - event_dict=copy.deepcopy(value.get_dict()), + event_dict={ + "type": value.get("type"), + "state_key": value.get_state_key(), + "room_id": value.get("room_id") + }, room_version=value.room_version, rejected_reason=value.rejected_reason ) From 1687238494ae82dcf030de573ca06b605ef523cb Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 27 Feb 2024 23:13:36 +0100 Subject: [PATCH 06/30] remove auth_events copy and update logic --- synapse/event_auth.py | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index d384f822958..9efa1fa311d 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -177,35 +177,13 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... + auth_events = await store.get_events( + event.auth_event_ids(), + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) if batched_auth_events: - # Copy the batched auth events to avoid mutating them. - auth_events = {} - for key, value in batched_auth_events.items(): - auth_events[key] = make_event_from_dict( - event_dict={ - "type": value.get("type"), - "state_key": value.get_state_key(), - "room_id": value.get("room_id") - }, - room_version=value.room_version, - rejected_reason=value.rejected_reason - ) - - needed_auth_event_ids = set(event.auth_event_ids()) - batched_auth_events.keys() - if needed_auth_event_ids: - auth_events.update( - await store.get_events( - needed_auth_event_ids, - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) - ) - else: - auth_events = await store.get_events( - event.auth_event_ids(), - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) + auth_events.update(batched_auth_events) room_id = event.room_id auth_dict: MutableStateMap[str] = {} From af20b240e62acf0af9782a5084ed4240dbad0496 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 00:36:42 +0100 Subject: [PATCH 07/30] only update needed auth events --- synapse/event_auth.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 9efa1fa311d..d0b4e0d5c62 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -177,13 +177,23 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events = await store.get_events( - event.auth_event_ids(), - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) if batched_auth_events: - auth_events.update(batched_auth_events) + auth_events = batched_auth_events + needed_auth_event_ids = set(event.auth_event_ids()) - set(batched_auth_events) + if needed_auth_event_ids: + auth_events.update( + await store.get_events( + needed_auth_event_ids, + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) + ) + else: + auth_events = await store.get_events( + event.auth_event_ids(), + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True + ) room_id = event.room_id auth_dict: MutableStateMap[str] = {} From f780f5b6afe1cdb0718c2a11129bc1867d1f0e93 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 00:37:19 +0100 Subject: [PATCH 08/30] remove import copy --- synapse/event_auth.py | 1 - 1 file changed, 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index d0b4e0d5c62..fcb2ce53a18 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -21,7 +21,6 @@ # import collections.abc -import copy import logging import typing from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union From 711a57d9561ec34c7833740a977eca3f4832a7ce Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 00:37:46 +0100 Subject: [PATCH 09/30] remove import make_event_from_dict --- synapse/event_auth.py | 1 - 1 file changed, 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index fcb2ce53a18..e9de96e593c 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -30,7 +30,6 @@ from signedjson.sign import SignatureVerifyException, verify_signed_json from typing_extensions import Protocol from unpaddedbase64 import decode_base64 -from synapse.events import make_event_from_dict from synapse.api.constants import ( MAX_PDU_SIZE, From a3bfc23cb21511db68c1b0cb6844f47e512579e7 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 00:39:34 +0100 Subject: [PATCH 10/30] update changelog --- changelog.d/16968.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/16968.bugfix b/changelog.d/16968.bugfix index 9cff5f2a3e9..75a982f23a9 100644 --- a/changelog.d/16968.bugfix +++ b/changelog.d/16968.bugfix @@ -1 +1 @@ -Fix a potential deadlock when checking state independent auth rules by creating a deepcopy of authentication events. Contributed by @ggogel. \ No newline at end of file +Do not create a shallow copy of batched_auth_events to prevent a potential deadlock. Contributed by @ggogel. \ No newline at end of file From 0263502c4390674737505fd85a920761e0028dd6 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 09:31:10 +0100 Subject: [PATCH 11/30] Revert "only update needed auth events" This reverts commit 59e3c1b4ac507d9a218578e84e06e78d4686f850. --- synapse/event_auth.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index e9de96e593c..f26a6e7c6cc 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -175,23 +175,13 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... + auth_events = await store.get_events( + event.auth_event_ids(), + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) if batched_auth_events: - auth_events = batched_auth_events - needed_auth_event_ids = set(event.auth_event_ids()) - set(batched_auth_events) - if needed_auth_event_ids: - auth_events.update( - await store.get_events( - needed_auth_event_ids, - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) - ) - else: - auth_events = await store.get_events( - event.auth_event_ids(), - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True - ) + auth_events.update(batched_auth_events) room_id = event.room_id auth_dict: MutableStateMap[str] = {} From 05a00b2de6907c41c9b8f859e3dff58e0c482706 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 12:40:21 +0100 Subject: [PATCH 12/30] Revert "Revert "only update needed auth events"" This reverts commit c7ea377919f9a39cc1ef746fa8c8790a8a7b3209. --- synapse/event_auth.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index f26a6e7c6cc..e9de96e593c 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -175,13 +175,23 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events = await store.get_events( - event.auth_event_ids(), - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) if batched_auth_events: - auth_events.update(batched_auth_events) + auth_events = batched_auth_events + needed_auth_event_ids = set(event.auth_event_ids()) - set(batched_auth_events) + if needed_auth_event_ids: + auth_events.update( + await store.get_events( + needed_auth_event_ids, + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) + ) + else: + auth_events = await store.get_events( + event.auth_event_ids(), + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True + ) room_id = event.room_id auth_dict: MutableStateMap[str] = {} From 7d1f98cb303b11c02365b03e9a6f0f21fedd210a Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 12:47:12 +0100 Subject: [PATCH 13/30] do not nest store.get_events in update --- synapse/event_auth.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index e9de96e593c..7fa84f8c16c 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -179,13 +179,12 @@ async def check_state_independent_auth_rules( auth_events = batched_auth_events needed_auth_event_ids = set(event.auth_event_ids()) - set(batched_auth_events) if needed_auth_event_ids: - auth_events.update( - await store.get_events( - needed_auth_event_ids, - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, - ) + needed_auth_events = await store.get_events( + needed_auth_event_ids, + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True ) + auth_events.update(needed_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), From e1cc6846bbe358323752f02ad8e5be835c2b9c4a Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Wed, 28 Feb 2024 13:51:36 +0100 Subject: [PATCH 14/30] use a list comprehension instead of set operation --- synapse/event_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 7fa84f8c16c..f7682c5322c 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -177,7 +177,7 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... if batched_auth_events: auth_events = batched_auth_events - needed_auth_event_ids = set(event.auth_event_ids()) - set(batched_auth_events) + needed_auth_event_ids = [event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events] if needed_auth_event_ids: needed_auth_events = await store.get_events( needed_auth_event_ids, From e63563703506478f518037120141ffcff19aaa75 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 4 Mar 2024 21:15:03 +0100 Subject: [PATCH 15/30] linting --- synapse/event_auth.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index f7682c5322c..234d9753101 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -177,19 +177,23 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... if batched_auth_events: auth_events = batched_auth_events - needed_auth_event_ids = [event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events] + needed_auth_event_ids = [ + event_id + for event_id in event.auth_event_ids() + if event_id not in batched_auth_events + ] if needed_auth_event_ids: needed_auth_events = await store.get_events( needed_auth_event_ids, redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True + allow_rejected=True, ) auth_events.update(needed_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True + allow_rejected=True, ) room_id = event.room_id From e65cabd82a57b6821997515f0ad95d684c4787ca Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 4 Mar 2024 21:57:31 +0100 Subject: [PATCH 16/30] type auth_events --- synapse/event_auth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 234d9753101..40e508f5b4a 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -23,7 +23,7 @@ import collections.abc import logging import typing -from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union +from typing import Any, Dict, Iterable, List, Mapping, MutableMapping, Optional, Set, Tuple, Union from canonicaljson import encode_canonical_json from signedjson.key import decode_verify_key_bytes @@ -175,6 +175,7 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... + auth_events: MutableMapping[str, "EventBase"] if batched_auth_events: auth_events = batched_auth_events needed_auth_event_ids = [ From a4534ed06552ae9ce1f5dae025105dd612b49eea Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 5 Mar 2024 13:40:11 +0100 Subject: [PATCH 17/30] dict batched_auth_events --- synapse/event_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 40e508f5b4a..52a78f51aa9 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -177,7 +177,7 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... auth_events: MutableMapping[str, "EventBase"] if batched_auth_events: - auth_events = batched_auth_events + auth_events = dict(batched_auth_events) needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() From 8197f84e79964f4ea0d30d48d1144fff07c8ec43 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 5 Mar 2024 13:55:38 +0100 Subject: [PATCH 18/30] isort lint --- synapse/event_auth.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 52a78f51aa9..45aee341a04 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -23,7 +23,18 @@ import collections.abc import logging import typing -from typing import Any, Dict, Iterable, List, Mapping, MutableMapping, Optional, Set, Tuple, Union +from typing import ( + Any, + Dict, + Iterable, + List, + Mapping, + MutableMapping, + Optional, + Set, + Tuple, + Union, +) from canonicaljson import encode_canonical_json from signedjson.key import decode_verify_key_bytes From e199b27fcdef6461ad335cfccb30b0814c325713 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Tue, 5 Mar 2024 14:11:33 +0100 Subject: [PATCH 19/30] update changelog --- changelog.d/16968.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/16968.bugfix b/changelog.d/16968.bugfix index 75a982f23a9..57ed851178f 100644 --- a/changelog.d/16968.bugfix +++ b/changelog.d/16968.bugfix @@ -1 +1 @@ -Do not create a shallow copy of batched_auth_events to prevent a potential deadlock. Contributed by @ggogel. \ No newline at end of file +Prevent locking up when checking auth rules that are independent of room state for batched auth events. Contributed by @ggogel. \ No newline at end of file From deba2ceb5aadca903756eaea57e7383633d0de4c Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Fri, 8 Mar 2024 00:45:30 +0100 Subject: [PATCH 20/30] Revert "dict batched_auth_events" This reverts commit dfac2cab3f425b99d5c17cb9cc6e20915e751e99. --- synapse/event_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 45aee341a04..b1e78686958 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -188,7 +188,7 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... auth_events: MutableMapping[str, "EventBase"] if batched_auth_events: - auth_events = dict(batched_auth_events) + auth_events = batched_auth_events needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() From a3fa5535f5a0873067bd34aa116a3690f3a1e513 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Fri, 8 Mar 2024 01:44:34 +0100 Subject: [PATCH 21/30] use update --- synapse/event_auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index b1e78686958..d151024c172 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -186,9 +186,8 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events: MutableMapping[str, "EventBase"] + auth_events: MutableMapping[str, "EventBase"] = {} if batched_auth_events: - auth_events = batched_auth_events needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() @@ -201,6 +200,7 @@ async def check_state_independent_auth_rules( allow_rejected=True, ) auth_events.update(needed_auth_events) + auth_events.update(batched_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), From 3826b99bbf507c9561a99693f3c8134494f58a82 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Fri, 8 Mar 2024 12:59:58 +0100 Subject: [PATCH 22/30] Revert "use update" This reverts commit 22df933f38c21166bf652d6cbaebfcbe00d22fa2. --- synapse/event_auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index d151024c172..b1e78686958 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -186,8 +186,9 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events: MutableMapping[str, "EventBase"] = {} + auth_events: MutableMapping[str, "EventBase"] if batched_auth_events: + auth_events = batched_auth_events needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() @@ -200,7 +201,6 @@ async def check_state_independent_auth_rules( allow_rejected=True, ) auth_events.update(needed_auth_events) - auth_events.update(batched_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), From 31bf88b80a25b96eec1845090eeb00cb1fabcbdb Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Fri, 8 Mar 2024 15:24:10 +0100 Subject: [PATCH 23/30] add items individually --- synapse/event_auth.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index b1e78686958..030a746df22 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -186,14 +186,18 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events: MutableMapping[str, "EventBase"] + auth_events: MutableMapping[str, "EventBase"] = {} if batched_auth_events: - auth_events = batched_auth_events + # Add items individually to prevent locking the whole mapping + for key, value in batched_auth_events.items(): + auth_events[key] = value + needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events ] + if needed_auth_event_ids: needed_auth_events = await store.get_events( needed_auth_event_ids, From eee0a2b1883cf706369b101744b03b4517515be1 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Fri, 8 Mar 2024 21:56:14 +0100 Subject: [PATCH 24/30] use unpacking operator --- synapse/event_auth.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 030a746df22..30d0a2ae3d2 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -186,25 +186,23 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events: MutableMapping[str, "EventBase"] = {} if batched_auth_events: - # Add items individually to prevent locking the whole mapping - for key, value in batched_auth_events.items(): - auth_events[key] = value - needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events ] + needed_auth_events: MutableMapping[str, "EventBase"] = {} + if needed_auth_event_ids: needed_auth_events = await store.get_events( needed_auth_event_ids, redact_behaviour=EventRedactBehaviour.as_is, allow_rejected=True, ) - auth_events.update(needed_auth_events) + + auth_events: Mapping[str, "EventBase"] = {**batched_auth_events, **needed_auth_events} else: auth_events = await store.get_events( event.auth_event_ids(), From d13f298099332078b8ec70c221ff1220ea037808 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Sat, 9 Mar 2024 00:17:29 +0100 Subject: [PATCH 25/30] use cast --- synapse/event_auth.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 30d0a2ae3d2..9e7d06c54f5 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -34,6 +34,7 @@ Set, Tuple, Union, + cast, ) from canonicaljson import encode_canonical_json @@ -186,6 +187,7 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... + auth_events: MutableMapping[str, "EventBase"] = {} if batched_auth_events: needed_auth_event_ids = [ event_id @@ -202,7 +204,8 @@ async def check_state_independent_auth_rules( allow_rejected=True, ) - auth_events: Mapping[str, "EventBase"] = {**batched_auth_events, **needed_auth_events} + auth_events = cast(MutableMapping[str, "EventBase"], batched_auth_events) + auth_events.update(needed_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), From 5bd7d937301dc6b20ff6054e17edaf08cd62dbb8 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Sat, 9 Mar 2024 08:04:15 +0100 Subject: [PATCH 26/30] update only if needed auth events exist --- synapse/event_auth.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 9e7d06c54f5..8545b3f909c 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -189,23 +189,20 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... auth_events: MutableMapping[str, "EventBase"] = {} if batched_auth_events: + auth_events = cast(MutableMapping[str, "EventBase"], batched_auth_events) needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events ] - - needed_auth_events: MutableMapping[str, "EventBase"] = {} - if needed_auth_event_ids: - needed_auth_events = await store.get_events( - needed_auth_event_ids, - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, + auth_events.update( + await store.get_events( + needed_auth_event_ids, + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) ) - - auth_events = cast(MutableMapping[str, "EventBase"], batched_auth_events) - auth_events.update(needed_auth_events) else: auth_events = await store.get_events( event.auth_event_ids(), From 7ccf264791e7bcf98a01622baf8525f8fa40bb6f Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 11 Mar 2024 11:41:05 +0100 Subject: [PATCH 27/30] use ChainMap --- synapse/event_auth.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 8545b3f909c..52440cb75cb 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -35,6 +35,7 @@ Tuple, Union, cast, + ChainMap, ) from canonicaljson import encode_canonical_json @@ -187,16 +188,16 @@ async def check_state_independent_auth_rules( return # 2. Reject if event has auth_events that: ... - auth_events: MutableMapping[str, "EventBase"] = {} + auth_events: ChainMap[str, EventBase] = ChainMap() if batched_auth_events: - auth_events = cast(MutableMapping[str, "EventBase"], batched_auth_events) + auth_events = auth_events.new_child(cast(MutableMapping[str, "EventBase"], batched_auth_events)) needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids() if event_id not in batched_auth_events ] if needed_auth_event_ids: - auth_events.update( + auth_events = auth_events.new_child( await store.get_events( needed_auth_event_ids, redact_behaviour=EventRedactBehaviour.as_is, @@ -204,10 +205,12 @@ async def check_state_independent_auth_rules( ) ) else: - auth_events = await store.get_events( - event.auth_event_ids(), - redact_behaviour=EventRedactBehaviour.as_is, - allow_rejected=True, + auth_events = auth_events.new_child( + await store.get_events( + event.auth_event_ids(), + redact_behaviour=EventRedactBehaviour.as_is, + allow_rejected=True, + ) ) room_id = event.room_id From 1fc776caaa9349f35c34788c66c5bac6882153af Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 11 Mar 2024 11:42:09 +0100 Subject: [PATCH 28/30] fix isort --- synapse/event_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 52440cb75cb..058f62256b1 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -25,6 +25,7 @@ import typing from typing import ( Any, + ChainMap, Dict, Iterable, List, @@ -35,7 +36,6 @@ Tuple, Union, cast, - ChainMap, ) from canonicaljson import encode_canonical_json From b6bba1049d1bcfe0cf92458140834b88a620e4e9 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 11 Mar 2024 11:50:47 +0100 Subject: [PATCH 29/30] add comments --- synapse/event_auth.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 058f62256b1..25e92c86cc6 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -190,6 +190,10 @@ async def check_state_independent_auth_rules( # 2. Reject if event has auth_events that: ... auth_events: ChainMap[str, EventBase] = ChainMap() if batched_auth_events: + # batched_auth_events can become very large. To avoid repeatedly copying it, which + # would significantly impact performance, we use a ChainMap. + # batched_auth_events must be cast to MutableMapping because .new_child() requires + # this type. This casting is safe as the mapping is never mutated. auth_events = auth_events.new_child(cast(MutableMapping[str, "EventBase"], batched_auth_events)) needed_auth_event_ids = [ event_id From 5fd55d17f65f0769623eab5b88d5c630ed4fbf28 Mon Sep 17 00:00:00 2001 From: Gerrit Gogel Date: Mon, 11 Mar 2024 12:46:53 +0100 Subject: [PATCH 30/30] linting --- synapse/event_auth.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/synapse/event_auth.py b/synapse/event_auth.py index 25e92c86cc6..c8b06f760eb 100644 --- a/synapse/event_auth.py +++ b/synapse/event_auth.py @@ -194,7 +194,9 @@ async def check_state_independent_auth_rules( # would significantly impact performance, we use a ChainMap. # batched_auth_events must be cast to MutableMapping because .new_child() requires # this type. This casting is safe as the mapping is never mutated. - auth_events = auth_events.new_child(cast(MutableMapping[str, "EventBase"], batched_auth_events)) + auth_events = auth_events.new_child( + cast(MutableMapping[str, "EventBase"], batched_auth_events) + ) needed_auth_event_ids = [ event_id for event_id in event.auth_event_ids()