Skip to content

Commit f71d86f

Browse files
authored
Element-R: pass device list change notifications into rust crypto-sdk (#3254)
1 parent 70e34ff commit f71d86f

File tree

7 files changed

+39
-28
lines changed

7 files changed

+39
-28
lines changed

spec/integ/sliding-sync-sdk.spec.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -662,13 +662,17 @@ describe("SlidingSyncSdk", () => {
662662
});
663663

664664
it("can update device lists", () => {
665+
client!.crypto!.processDeviceLists = jest.fn();
665666
ext.onResponse({
666667
device_lists: {
667668
changed: ["@alice:localhost"],
668669
left: ["@bob:localhost"],
669670
},
670671
});
671-
// TODO: more assertions?
672+
expect(client!.crypto!.processDeviceLists).toHaveBeenCalledWith({
673+
changed: ["@alice:localhost"],
674+
left: ["@bob:localhost"],
675+
});
672676
});
673677

674678
it("can update OTK counts and unused fallback keys", () => {

src/common-crypto/CryptoBackend.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import type { IToDeviceEvent } from "../sync-accumulator";
17+
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
1818
import { MatrixEvent } from "../models/event";
1919
import { Room } from "../models/room";
2020
import { CryptoApi } from "../crypto-api";
@@ -113,6 +113,14 @@ export interface SyncCryptoCallbacks {
113113
*/
114114
processKeyCounts(oneTimeKeysCounts?: Record<string, number>, unusedFallbackKeys?: string[]): Promise<void>;
115115

116+
/**
117+
* Handle the notification from /sync that device lists have
118+
* been changed.
119+
*
120+
* @param deviceLists - device_lists field from /sync
121+
*/
122+
processDeviceLists(deviceLists: IDeviceLists): Promise<void>;
123+
116124
/**
117125
* Called by the /sync loop whenever an m.room.encryption event is received.
118126
*

src/crypto/index.ts

+5-14
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ import { CryptoStore } from "./store/base";
7171
import { IVerificationChannel } from "./verification/request/Channel";
7272
import { TypedEventEmitter } from "../models/typed-event-emitter";
7373
import { IContent } from "../models/event";
74-
import { ISyncResponse, IToDeviceEvent } from "../sync-accumulator";
74+
import { IDeviceLists, ISyncResponse, IToDeviceEvent } from "../sync-accumulator";
7575
import { ISignatures } from "../@types/signed";
7676
import { IMessage } from "./algorithms/olm";
7777
import { CryptoBackend, OnSyncCompletedData } from "../common-crypto/CryptoBackend";
@@ -2893,21 +2893,12 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
28932893
}
28942894

28952895
/**
2896-
* Handle the notification from /sync or /keys/changes that device lists have
2896+
* Handle the notification from /sync that device lists have
28972897
* been changed.
28982898
*
2899-
* @param syncData - Object containing sync tokens associated with this sync
2900-
* @param syncDeviceLists - device_lists field from /sync, or response from
2901-
* /keys/changes
2899+
* @param deviceLists - device_lists field from /sync
29022900
*/
2903-
public async handleDeviceListChanges(
2904-
syncData: ISyncStateData,
2905-
syncDeviceLists: Required<ISyncResponse>["device_lists"],
2906-
): Promise<void> {
2907-
// Initial syncs don't have device change lists. We'll either get the complete list
2908-
// of changes for the interval or will have invalidated everything in willProcessSync
2909-
if (!syncData.oldSyncToken) return;
2910-
2901+
public async processDeviceLists(deviceLists: IDeviceLists): Promise<void> {
29112902
// Here, we're relying on the fact that we only ever save the sync data after
29122903
// sucessfully saving the device list data, so we're guaranteed that the device
29132904
// list store is at least as fresh as the sync token from the sync store, ie.
@@ -2916,7 +2907,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
29162907
// If we didn't make this assumption, we'd have to use the /keys/changes API
29172908
// to get key changes between the sync token in the device list and the 'old'
29182909
// sync token used here to make sure we didn't miss any.
2919-
await this.evalDeviceListChanges(syncDeviceLists);
2910+
await this.evalDeviceListChanges(deviceLists);
29202911
}
29212912

29222913
/**

src/rust-crypto/rust-crypto.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-js";
1818

1919
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
20-
import type { IToDeviceEvent } from "../sync-accumulator";
20+
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
2121
import type { IEncryptedEventInfo } from "../crypto/api";
2222
import { MatrixEvent } from "../models/event";
2323
import { Room } from "../models/room";
@@ -176,20 +176,23 @@ export class RustCrypto implements CryptoBackend {
176176
* @param events - the received to-device messages
177177
* @param oneTimeKeysCounts - the received one time key counts
178178
* @param unusedFallbackKeys - the received unused fallback keys
179+
* @param devices - the received device list updates
179180
* @returns A list of preprocessed to-device messages.
180181
*/
181182
private async receiveSyncChanges({
182183
events,
183184
oneTimeKeysCounts = new Map<string, number>(),
184185
unusedFallbackKeys = new Set<string>(),
186+
devices = new RustSdkCryptoJs.DeviceLists(),
185187
}: {
186188
events?: IToDeviceEvent[];
187189
oneTimeKeysCounts?: Map<string, number>;
188190
unusedFallbackKeys?: Set<string>;
191+
devices?: RustSdkCryptoJs.DeviceLists;
189192
}): Promise<IToDeviceEvent[]> {
190193
const result = await this.olmMachine.receiveSyncChanges(
191194
events ? JSON.stringify(events) : "[]",
192-
new RustSdkCryptoJs.DeviceLists(),
195+
devices,
193196
oneTimeKeysCounts,
194197
unusedFallbackKeys,
195198
);
@@ -229,6 +232,16 @@ export class RustCrypto implements CryptoBackend {
229232
}
230233
}
231234

235+
/** called by the sync loop to process the notification that device lists have
236+
* been changed.
237+
*
238+
* @param deviceLists - device_lists field from /sync
239+
*/
240+
public async processDeviceLists(deviceLists: IDeviceLists): Promise<void> {
241+
const devices = new RustSdkCryptoJs.DeviceLists(deviceLists.changed, deviceLists.left);
242+
await this.receiveSyncChanges({ devices });
243+
}
244+
232245
/** called by the sync loop on m.room.encrypted events
233246
*
234247
* @param room - in which the event was received

src/sliding-sync-sdk.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,8 @@ class ExtensionE2EE implements Extension<ExtensionE2EERequest, ExtensionE2EEResp
8585

8686
public async onResponse(data: ExtensionE2EEResponse): Promise<void> {
8787
// Handle device list updates
88-
if (data["device_lists"]) {
89-
await this.crypto.handleDeviceListChanges(
90-
{
91-
oldSyncToken: "yep", // XXX need to do this so the device list changes get processed :(
92-
},
93-
data["device_lists"],
94-
);
88+
if (data.device_lists) {
89+
await this.crypto.processDeviceLists(data.device_lists);
9590
}
9691

9792
// Handle one_time_keys_count and unused_fallback_key_types

src/sync-accumulator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ interface IToDevice {
132132
events: IToDeviceEvent[];
133133
}
134134

135-
interface IDeviceLists {
135+
export interface IDeviceLists {
136136
changed?: string[];
137137
left?: string[];
138138
}

src/sync.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1515,8 +1515,8 @@ export class SyncApi {
15151515

15161516
// Handle device list updates
15171517
if (data.device_lists) {
1518-
if (this.syncOpts.crypto) {
1519-
await this.syncOpts.crypto.handleDeviceListChanges(syncEventData, data.device_lists);
1518+
if (this.syncOpts.cryptoCallbacks) {
1519+
await this.syncOpts.cryptoCallbacks.processDeviceLists(data.device_lists);
15201520
} else {
15211521
// FIXME if we *don't* have a crypto module, we still need to
15221522
// invalidate the device lists. But that would require a

0 commit comments

Comments
 (0)