Skip to content

Commit 5812842

Browse files
committed
Add device list to new crypto
1 parent 2daa429 commit 5812842

File tree

6 files changed

+63
-29
lines changed

6 files changed

+63
-29
lines changed

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

+11-7
Original file line numberDiff line numberDiff line change
@@ -662,24 +662,28 @@ 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+
{ oldSyncToken: "yep" },
674+
{ changed: ["@alice:localhost"], left: ["@bob:localhost"] },
675+
);
672676
});
673677

674-
it("can update OTK counts", () => {
678+
it("can update OTK counts", async () => {
675679
client!.crypto!.updateOneTimeKeyCount = jest.fn();
676-
ext.onResponse({
680+
await ext.onResponse({
677681
device_one_time_keys_count: {
678682
signed_curve25519: 42,
679683
},
680684
});
681685
expect(client!.crypto!.updateOneTimeKeyCount).toHaveBeenCalledWith(42);
682-
ext.onResponse({
686+
await ext.onResponse({
683687
device_one_time_keys_count: {
684688
not_signed_curve25519: 42,
685689
// missing field -> default to 0
@@ -688,12 +692,12 @@ describe("SlidingSyncSdk", () => {
688692
expect(client!.crypto!.updateOneTimeKeyCount).toHaveBeenCalledWith(0);
689693
});
690694

691-
it("can update fallback keys", () => {
692-
ext.onResponse({
695+
it("can update fallback keys", async () => {
696+
await ext.onResponse({
693697
device_unused_fallback_key_types: ["signed_curve25519"],
694698
});
695699
expect(client!.crypto!.getNeedsNewFallback()).toEqual(false);
696-
ext.onResponse({
700+
await ext.onResponse({
697701
device_unused_fallback_key_types: ["not_signed_curve25519"],
698702
});
699703
expect(client!.crypto!.getNeedsNewFallback()).toEqual(true);

src/common-crypto/CryptoBackend.ts

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { CryptoApi } from "../crypto-api";
2121
import { DeviceTrustLevel, UserTrustLevel } from "../crypto/CrossSigning";
2222
import { IEncryptedEventInfo } from "../crypto/api";
2323
import { IEventDecryptionResult } from "../@types/crypto";
24+
import { ISyncStateData } from "../sync";
25+
import { ISyncResponse } from "../sync-accumulator";
2426

2527
/**
2628
* Common interface for the crypto implementations
@@ -113,6 +115,16 @@ export interface SyncCryptoCallbacks {
113115
*/
114116
processKeyCounts(oneTimeKeysCounts?: Record<string, number>, unusedFallbackKeys?: string[]): Promise<void>;
115117

118+
/**
119+
* Handle the notification from /sync or /keys/changes that device lists have
120+
* been changed.
121+
*
122+
* @param syncData - Object containing sync tokens associated with this sync
123+
* @param deviceLists - device_lists field from /sync, or response from
124+
* /keys/changes
125+
*/
126+
processDeviceLists(syncData: ISyncStateData, deviceLists?: Required<ISyncResponse>["device_lists"]): Promise<void>;
127+
116128
/**
117129
* Called by the /sync loop whenever an m.room.encryption event is received.
118130
*

src/crypto/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -2922,16 +2922,16 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
29222922
* been changed.
29232923
*
29242924
* @param syncData - Object containing sync tokens associated with this sync
2925-
* @param syncDeviceLists - device_lists field from /sync, or response from
2925+
* @param deviceLists - device_lists field from /sync, or response from
29262926
* /keys/changes
29272927
*/
2928-
public async handleDeviceListChanges(
2928+
public async processDeviceLists(
29292929
syncData: ISyncStateData,
2930-
syncDeviceLists: Required<ISyncResponse>["device_lists"],
2930+
deviceLists?: Required<ISyncResponse>["device_lists"],
29312931
): Promise<void> {
29322932
// Initial syncs don't have device change lists. We'll either get the complete list
29332933
// of changes for the interval or will have invalidated everything in willProcessSync
2934-
if (!syncData.oldSyncToken) return;
2934+
if (!syncData.oldSyncToken || !deviceLists) return;
29352935

29362936
// Here, we're relying on the fact that we only ever save the sync data after
29372937
// sucessfully saving the device list data, so we're guaranteed that the device
@@ -2941,7 +2941,7 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
29412941
// If we didn't make this assumption, we'd have to use the /keys/changes API
29422942
// to get key changes between the sync token in the device list and the 'old'
29432943
// sync token used here to make sure we didn't miss any.
2944-
await this.evalDeviceListChanges(syncDeviceLists);
2944+
await this.evalDeviceListChanges(deviceLists);
29452945
}
29462946

29472947
/**

src/rust-crypto/rust-crypto.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import { DeviceTrustLevel, UserTrustLevel } from "../crypto/CrossSigning";
2929
import { RoomEncryptor } from "./RoomEncryptor";
3030
import { OutgoingRequest, OutgoingRequestProcessor } from "./OutgoingRequestProcessor";
3131
import { KeyClaimManager } from "./KeyClaimManager";
32+
import { ISyncResponse } from "../sync-accumulator";
33+
import { ISyncStateData } from "../sync";
3234
import { MapWithDefault } from "../utils";
3335

3436
/**
@@ -176,20 +178,23 @@ export class RustCrypto implements CryptoBackend {
176178
* @param events - the received to-device messages
177179
* @param oneTimeKeysCounts - the received one time key counts
178180
* @param unusedFallbackKeys - the received unused fallback keys
181+
* @param devices - the received devices
179182
* @returns A list of preprocessed to-device messages.
180183
*/
181184
private async receiveSyncChanges({
182185
events,
183186
oneTimeKeysCounts = new Map<string, number>(),
184187
unusedFallbackKeys = new Set<string>(),
188+
devices = new RustSdkCryptoJs.DeviceLists(),
185189
}: {
186190
events?: IToDeviceEvent[];
187191
oneTimeKeysCounts?: Map<string, number>;
188192
unusedFallbackKeys?: Set<string>;
193+
devices?: RustSdkCryptoJs.DeviceLists;
189194
}): Promise<IToDeviceEvent[]> {
190195
const result = await this.olmMachine.receiveSyncChanges(
191196
events ? JSON.stringify(events) : "[]",
192-
new RustSdkCryptoJs.DeviceLists(),
197+
devices,
193198
oneTimeKeysCounts,
194199
unusedFallbackKeys,
195200
);
@@ -229,6 +234,23 @@ export class RustCrypto implements CryptoBackend {
229234
}
230235
}
231236

237+
/** called by the sync loop to process
238+
*
239+
* @param syncData - Object containing sync tokens associated with this sync
240+
* @param deviceLists - device_lists field from /sync, or response from
241+
*/
242+
public async processDeviceLists(
243+
syncData: ISyncStateData,
244+
deviceLists: Required<ISyncResponse>["device_lists"],
245+
): Promise<void> {
246+
// Initial syncs don't have device change lists. We'll either get the complete list
247+
// of changes for the interval or will have invalidated everything in willProcessSync
248+
if (!syncData.oldSyncToken || !deviceLists) return;
249+
250+
const devices = new RustSdkCryptoJs.DeviceLists(deviceLists.changed, deviceLists.left);
251+
await this.receiveSyncChanges({ devices });
252+
}
253+
232254
/** called by the sync loop on m.room.encrypted events
233255
*
234256
* @param room - in which the event was received

src/sliding-sync-sdk.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,12 @@ 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-
);
95-
}
88+
await this.crypto.processDeviceLists(
89+
{
90+
oldSyncToken: "yep", // XXX need to do this so the device list changes get processed :(
91+
},
92+
data["device_lists"],
93+
);
9694

9795
// Handle one_time_keys_count
9896
if (data["device_one_time_keys_count"]) {

src/sync.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -1514,14 +1514,12 @@ export class SyncApi {
15141514
}
15151515

15161516
// Handle device list updates
1517-
if (data.device_lists) {
1518-
if (this.syncOpts.crypto) {
1519-
await this.syncOpts.crypto.handleDeviceListChanges(syncEventData, data.device_lists);
1520-
} else {
1521-
// FIXME if we *don't* have a crypto module, we still need to
1522-
// invalidate the device lists. But that would require a
1523-
// substantial bit of rework :/.
1524-
}
1517+
if (this.syncOpts.cryptoCallbacks) {
1518+
await this.syncOpts.cryptoCallbacks.processDeviceLists(syncEventData, data.device_lists);
1519+
} else {
1520+
// FIXME if we *don't* have a crypto module, we still need to
1521+
// invalidate the device lists. But that would require a
1522+
// substantial bit of rework :/.
15251523
}
15261524

15271525
// Handle one_time_keys_count and unused fallback keys

0 commit comments

Comments
 (0)