diff --git a/synapse/__init__.py b/synapse/__init__.py
index 01d6bf17f0..c9a445c8fe 100644
--- a/synapse/__init__.py
+++ b/synapse/__init__.py
@@ -47,7 +47,7 @@ try:
except ImportError:
pass
-__version__ = "1.39.0rc2"
+__version__ = "1.39.0rc3"
if bool(os.environ.get("SYNAPSE_TEST_PATCH_LOG_CONTEXTS", False)):
# We import here so that we don't have to install a bunch of deps when
diff --git a/synapse/api/constants.py b/synapse/api/constants.py
index 56e7233b9e..a40d6d7961 100644
--- a/synapse/api/constants.py
+++ b/synapse/api/constants.py
@@ -128,6 +128,14 @@ class ToDeviceEventTypes:
RoomKeyRequest = "m.room_key_request"
+class DeviceKeyAlgorithms:
+ """Spec'd algorithms for the generation of per-device keys"""
+
+ ED25519 = "ed25519"
+ CURVE25519 = "curve25519"
+ SIGNED_CURVE25519 = "signed_curve25519"
+
+
class EduTypes:
Presence = "m.presence"
diff --git a/synapse/app/phone_stats_home.py b/synapse/app/phone_stats_home.py
index 96defac1d2..86ad7337a9 100644
--- a/synapse/app/phone_stats_home.py
+++ b/synapse/app/phone_stats_home.py
@@ -109,7 +109,7 @@ async def phone_stats_home(hs, stats, stats_process=_stats_process):
for name, count in r30_results.items():
stats["r30_users_" + name] = count
- r30v2_results = await store.count_r30_users()
+ r30v2_results = await store.count_r30v2_users()
for name, count in r30v2_results.items():
stats["r30v2_users_" + name] = count
diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py
index 525f3d39b1..6a05a65305 100644
--- a/synapse/handlers/_base.py
+++ b/synapse/handlers/_base.py
@@ -15,8 +15,6 @@
import logging
from typing import TYPE_CHECKING, Optional
-import synapse.state
-import synapse.storage
import synapse.types
from synapse.api.constants import EventTypes, Membership
from synapse.api.ratelimiting import Ratelimiter
diff --git a/synapse/handlers/sync.py b/synapse/handlers/sync.py
index 150a4f291e..f30bfcc93c 100644
--- a/synapse/handlers/sync.py
+++ b/synapse/handlers/sync.py
@@ -1093,6 +1093,10 @@ class SyncHandler:
one_time_key_counts: JsonDict = {}
unused_fallback_key_types: List[str] = []
if device_id:
+ # TODO: We should have a way to let clients differentiate between the states of:
+ # * no change in OTK count since the provided since token
+ # * the server has zero OTKs left for this device
+ # Spec issue: https://github.com/matrix-org/matrix-doc/issues/3298
one_time_key_counts = await self.store.count_e2e_one_time_keys(
user_id, device_id
)
diff --git a/synapse/storage/databases/main/end_to_end_keys.py b/synapse/storage/databases/main/end_to_end_keys.py
index 78ae68ec68..1edc96042b 100644
--- a/synapse/storage/databases/main/end_to_end_keys.py
+++ b/synapse/storage/databases/main/end_to_end_keys.py
@@ -21,6 +21,7 @@ from canonicaljson import encode_canonical_json
from twisted.enterprise.adbapi import Connection
+from synapse.api.constants import DeviceKeyAlgorithms
from synapse.logging.opentracing import log_kv, set_tag, trace
from synapse.storage._base import SQLBaseStore, db_to_json
from synapse.storage.database import DatabasePool, make_in_list_sql_clause
@@ -381,9 +382,15 @@ class EndToEndKeyWorkerStore(EndToEndKeyBackgroundStore):
" GROUP BY algorithm"
)
txn.execute(sql, (user_id, device_id))
- result = {}
+
+ # Initially set the key count to 0. This ensures that the client will always
+ # receive *some count*, even if it's 0.
+ result = {DeviceKeyAlgorithms.SIGNED_CURVE25519: 0}
+
+ # Override entries with the count of any keys we pulled from the database
for algorithm, key_count in txn:
result[algorithm] = key_count
+
return result
return await self.db_pool.runInteraction(
|