Skip to content

Commit 62a2af4

Browse files
committed
refactor: Simplify key bundle importing after invite to one entrypoint.
- Remove `onReceiveToDeviceEvent` from `CryptoBackend`. - Copy old room key bundle importing logic to `preprocessToDeviceEvents`.
1 parent c6ff37c commit 62a2af4

File tree

3 files changed

+49
-37
lines changed

3 files changed

+49
-37
lines changed

src/client.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,7 +2010,6 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
20102010
this.on(ClientEvent.Event, (event) => {
20112011
rustCrypto.onLiveEventFromSync(event);
20122012
});
2013-
this.on(ClientEvent.ReceivedToDeviceMessage, (payload) => rustCrypto.onReceiveToDeviceMessage(payload));
20142013

20152014
// re-emit the events emitted by the crypto impl
20162015
this.reEmitter.reEmit(rustCrypto, [
@@ -2413,7 +2412,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
24132412
const bundleDownloaded = await this.cryptoBackend.maybeAcceptKeyBundle(roomId, inviter);
24142413
// If this fails, i.e. we haven't received this message yet, we need to wait until the to-device message arrives.
24152414
if (!bundleDownloaded) {
2416-
this.cryptoBackend.markRoomAsPendingKeyBundle(roomId, inviter);
2415+
this.cryptoBackend.markRoomAsPendingKeyBundle(roomId);
24172416
}
24182417
}
24192418

src/common-crypto/CryptoBackend.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,12 @@ export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
9797

9898
/**
9999
* Mark a room as pending a key bundle under MSC4268. The backend will listen for room key bundle messages, and if
100-
* it sees one matching the room and inviter specified, it will automatically import it.
100+
* it sees one matching the room specified, it will automatically import it as long as the message author's ID matches
101+
* the inviter's ID.
101102
*
102103
* @param roomId - The room we were invited to, for which we did not receive a key bundle before accepting the invite.
103-
*
104-
* @param inviter - The user who invited us to the room and is expected to send us the room key bundle.
105104
*/
106-
markRoomAsPendingKeyBundle(roomId: string, inviter: string): void;
105+
markRoomAsPendingKeyBundle(roomId: string): void;
107106
}
108107

109108
/** The methods which crypto implementations should expose to the Sync api

src/rust-crypto/rust-crypto.ts

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
130130
private roomEncryptors: Record<string, RoomEncryptor> = {};
131131

132132
/** mapping of room ID -> inviter ID for rooms pending MSC4268 key bundles */
133-
private roomsPendingKeyBundles: Record<string, string> = {};
133+
private roomsPendingKeyBundles: Set<string> = new Set();
134134

135135
private eventDecryptor: EventDecryptor;
136136
private keyClaimManager: KeyClaimManager;
@@ -401,8 +401,8 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
401401
/**
402402
* Implementation of {@link CryptoBackend.markRoomAsPendingKeyBundle}.
403403
*/
404-
public markRoomAsPendingKeyBundle(roomId: string, inviterId: string): void {
405-
this.roomsPendingKeyBundles[roomId] = inviterId;
404+
public markRoomAsPendingKeyBundle(roomId: string): void {
405+
this.roomsPendingKeyBundles.add(roomId);
406406
}
407407

408408
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1734,6 +1734,21 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
17341734
}
17351735
}
17361736

1737+
// If any of the received events are room key bundle messages, and we have previously
1738+
// marked the room IDs they referenced as pending key bundles, tell the Rust SDK to
1739+
// try and accept them, just in case they were received after invite.
1740+
//
1741+
// We don't actually need to validate the contents of the bundle message, since the
1742+
// Rust SDK does that for us when it process it during the above `receiveSyncChanges`.
1743+
for (const payload of received
1744+
.filter(isRoomKeyBundleMessage)
1745+
.filter((payload) => this.roomsPendingKeyBundles.has(payload.message.content.room_id))) {
1746+
const success = await this.maybeAcceptKeyBundle(payload.message.content.room_id, payload.message.sender);
1747+
if (success) {
1748+
this.roomsPendingKeyBundles.delete(payload.message.content.room_id);
1749+
}
1750+
}
1751+
17371752
return received;
17381753
}
17391754

@@ -2151,34 +2166,6 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
21512166
public async getOwnIdentity(): Promise<RustSdkCryptoJs.OwnUserIdentity | undefined> {
21522167
return await this.olmMachine.getIdentity(new RustSdkCryptoJs.UserId(this.userId));
21532168
}
2154-
2155-
/**
2156-
* Handles the receipt of a to-device message, specifically for processing
2157-
* "io.element.msc4268.room_key_bundle" message types.
2158-
*
2159-
* @param payload - The received to-device message payload, which includes
2160-
* the message content and optional encryption information.
2161-
*/
2162-
public async onReceiveToDeviceMessage(payload: ReceivedToDeviceMessage): Promise<void> {
2163-
if (payload.message.type != "io.element.msc4268.room_key_bundle") {
2164-
return;
2165-
}
2166-
2167-
const { message, encryptionInfo } = payload;
2168-
const claimedSender = encryptionInfo?.sender ?? message.sender;
2169-
2170-
const roomId = message.content.room_id;
2171-
if (typeof roomId !== "string") {
2172-
return;
2173-
}
2174-
2175-
// Check if the room is in the map of rooms we expect to receive bundles from, otherwise discard.
2176-
if (this.roomsPendingKeyBundles[roomId] !== claimedSender) {
2177-
return;
2178-
}
2179-
2180-
await this.maybeAcceptKeyBundle(roomId, claimedSender);
2181-
}
21822169
}
21832170

21842171
class EventDecryptor {
@@ -2511,3 +2498,30 @@ function rustEncryptionInfoToJsEncryptionInfo(
25112498

25122499
type CryptoEvents = (typeof CryptoEvent)[keyof typeof CryptoEvent];
25132500
type RustCryptoEvents = Exclude<CryptoEvents, CryptoEvent.LegacyCryptoStoreMigrationProgress>;
2501+
2502+
interface RoomKeyBundleMessage {
2503+
message: {
2504+
type: "io.element.msc4268.room_key_bundle";
2505+
content: {
2506+
room_id: string;
2507+
};
2508+
};
2509+
}
2510+
2511+
/**
2512+
* Determines if the given payload is a RoomKeyBundleMessage.
2513+
*
2514+
* A RoomKeyBundleMessage is identified by having a specific message type
2515+
* ("io.element.msc4268.room_key_bundle") and a valid room_id in its content.
2516+
*
2517+
* @param payload - The received to-device message to check.
2518+
* @returns True if the payload matches the RoomKeyBundleMessage structure, false otherwise.
2519+
*/
2520+
function isRoomKeyBundleMessage(
2521+
payload: ReceivedToDeviceMessage,
2522+
): payload is ReceivedToDeviceMessage & RoomKeyBundleMessage {
2523+
return (
2524+
payload.message.type === "io.element.msc4268.room_key_bundle" &&
2525+
typeof payload.message.content.room_id === "string"
2526+
);
2527+
}

0 commit comments

Comments
 (0)