Ensure room keys are always shared
Currently, when creating a new room key, we're persisting the outbound session in a different transaction as the share_key operation. If you close the application at just the right time, or an error is thrown between both transactions, the key would be created but never shared with the current members. This could be more robust by doing it in a single transaction.
The reason that we do this in 2 different transactions is because getting the devices with who to share the key can involve network requests, which would auto-commit any ongoing transaction.
With the following steps, we should be able to do this in one transaction:
- decide whether we need to create a new outbound session (but don't create it).
- If so, track the room and fetch only the users we need to share with, not yet the devices. This will allow us to create the outbound session right after calling /members. Any incoming membership changes during the /members request will be included in the resulting member list. Any that come in during /keys/query wont. Besides, we write the user ids, not devices in the share_key operation so don't really need the devices until we're about to actually send the keys.
-
Create the new outbound session if needed (and encrypt a message with it if we're doing that and not pre-sharing).
It is theoretically possible that we don't have a session but decided we don't need a new one because something discarded it in the meantime. But if we already have a session, we should already be tracking the room, so we won't call members. Hence there is little change to race here with something discarding the session. If it does happen, we throw an error and encryption has to be retried.
- store a share_key operation with the previously fetched user ids
-
Share the room key (possibly in the background)
- until successful:
- fetch the devices for the user ids (this will call /keys/query)
- send the key to the devices
- until successful:
So, steps:
- allow to get all matching user ids from the device tracker, without already calling /keys/query
- check in advance whether we need to create an outbound session
- fetch user ids before creating outbound session
- fetch devices as part of the send device keys step
- create outbound session if we decided to create one earlier
- open single transaction in RoomEncryption and pass it to megolm encryption
This is less severe since #239 was fixed
I have messages that are only visible in hydrogen where I wrote them. Eleweb shows "** Unable to decrypt: The sender's device has not sent us the keys for this message. **" And key share requests don't result in anything. Eleand shows "waiting for this messages, this may take a while"
I have messages that are only visible in hydrogen where I wrote them. Eleweb shows "** Unable to decrypt: The sender's device has not sent us the keys for this message. **" And key share requests don't result in anything. Eleand shows "waiting for this messages, this may take a while"
Hey, sorry I missed this. Please file a new issue for UTDs.
related: #1115