Skip to content

Commit da2792e

Browse files
authored
Cache non-encrypted rooms and skip fetching encrypted rooms on startup (#39)
We need this for specific situations where a bot is joined to a LOT of rooms, but the encrypted rooms are in the minority. This should: - Cache rooms that explicitly do not have a encryption state event. - Recheck every time we see an encryption state event. ## Checklist * [ ] Tests written for all new code * [ ] Linter has been satisfied * [ ] Sign-off given on the changes (see CONTRIBUTING.md)
2 parents 669408d + 7e050c7 commit da2792e

File tree

8 files changed

+31
-63
lines changed

8 files changed

+31
-63
lines changed

examples/encryption_bot.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ const worksImage = fs.readFileSync("./examples/static/it-works.png");
3535
const client = new MatrixClient(homeserverUrl, accessToken, storage, crypto);
3636

3737
(async function() {
38-
let encryptedRoomId: string;
38+
let encryptedRoomId: string|undefined = undefined;
3939
const joinedRooms = await client.getJoinedRooms();
40-
await client.crypto.prepare(joinedRooms); // init crypto because we're doing things before the client is started
40+
await client.crypto.prepare(); // init crypto because we're doing things before the client is started
4141
for (const roomId of joinedRooms) {
4242
if (await client.crypto.isRoomEncrypted(roomId)) {
4343
encryptedRoomId = roomId;

src/MatrixClient.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ export class MatrixClient extends EventEmitter {
656656

657657
if (this.crypto) {
658658
LogService.debug("MatrixClientLite", "Preparing end-to-end encryption");
659-
await this.crypto.prepare(this.lastJoinedRoomIds);
659+
await this.crypto.prepare();
660660
LogService.info("MatrixClientLite", "End-to-end encryption enabled");
661661
}
662662

src/appservice/Intent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export class Intent {
168168
}
169169

170170
// Now set up crypto
171-
await this.client.crypto.prepare(await this.getJoinedRooms());
171+
await this.client.crypto.prepare();
172172

173173
this.appservice.on("room.event", (roomId, event) => {
174174
this.client.crypto.onRoomEvent(roomId, event);

src/e2ee/CryptoClient.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ export class CryptoClient {
6868
* Prepares the crypto client for usage.
6969
* @param {string[]} roomIds The room IDs the MatrixClient is joined to.
7070
*/
71-
public async prepare(roomIds: string[]) {
72-
await this.roomTracker.prepare(roomIds);
73-
71+
public async prepare() {
7472
if (this.ready) return; // stop re-preparing here
7573

7674
const storedDeviceId = await this.client.cryptoStore.getDeviceId();

src/e2ee/RoomTracker.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { MatrixClient } from "../MatrixClient";
2+
import { MatrixError } from "../models/MatrixError";
23
import { EncryptionEventContent } from "../models/events/EncryptionEvent";
34
import { ICryptoRoomInformation } from "./ICryptoRoomInformation";
45

@@ -33,16 +34,6 @@ export class RoomTracker {
3334
}
3435
}
3536

36-
/**
37-
* Prepares the room tracker to track the given rooms.
38-
* @param {string[]} roomIds The room IDs to track. This should be the joined rooms set.
39-
*/
40-
public async prepare(roomIds: string[]) {
41-
for (const roomId of roomIds) {
42-
await this.queueRoomCheck(roomId);
43-
}
44-
}
45-
4637
/**
4738
* Queues a room check for the tracker. If the room needs an update to the store, an
4839
* update will be made.
@@ -61,7 +52,11 @@ export class RoomTracker {
6152
encEvent = await this.client.getRoomStateEvent(roomId, "m.room.encryption", "");
6253
encEvent.algorithm = encEvent.algorithm ?? 'UNKNOWN';
6354
} catch (e) {
64-
return; // failure == no encryption
55+
if (e instanceof MatrixError && e.errcode === "M_NOT_FOUND") {
56+
encEvent = {};
57+
} else {
58+
return; // Other failures should not be cached.
59+
}
6560
}
6661

6762
// Pick out the history visibility setting too

test/encryption/CryptoClientTest.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('CryptoClient', () => {
1717

1818
bindNullEngine(http);
1919
await Promise.all([
20-
client.crypto.prepare([]),
20+
client.crypto.prepare(),
2121
http.flushAllExpected(),
2222
]);
2323

@@ -28,24 +28,17 @@ describe('CryptoClient', () => {
2828
describe('prepare', () => {
2929
it('should prepare the room tracker', () => testCryptoStores(async (cryptoStoreType) => {
3030
const userId = "@alice:example.org";
31-
const roomIds = ["!a:example.org", "!b:example.org"];
3231
const { client, http } = createTestClient(null, userId, cryptoStoreType);
3332

3433
client.getWhoAmI = () => Promise.resolve({ user_id: userId, device_id: TEST_DEVICE_ID });
3534

36-
const prepareSpy = simple.stub().callFn((rids: string[]) => {
37-
expect(rids).toBe(roomIds);
38-
return Promise.resolve();
39-
});
40-
41-
(<any>client.crypto).roomTracker.prepare = prepareSpy; // private member access
42-
4335
bindNullEngine(http);
36+
// Prepare first
4437
await Promise.all([
45-
client.crypto.prepare(roomIds),
38+
client.crypto.prepare(),
4639
http.flushAllExpected(),
4740
]);
48-
expect(prepareSpy.callCount).toEqual(1);
41+
expect(client.crypto.isReady).toBe(true);
4942
}));
5043

5144
it('should use a stored device ID', () => testCryptoStores(async (cryptoStoreType) => {
@@ -59,7 +52,7 @@ describe('CryptoClient', () => {
5952

6053
bindNullEngine(http);
6154
await Promise.all([
62-
client.crypto.prepare([]),
55+
client.crypto.prepare(),
6356
http.flushAllExpected(),
6457
]);
6558
expect(whoamiSpy.callCount).toEqual(0);
@@ -118,7 +111,7 @@ describe('CryptoClient', () => {
118111

119112
bindNullEngine(http);
120113
await Promise.all([
121-
client.crypto.prepare([]),
114+
client.crypto.prepare(),
122115
http.flushAllExpected(),
123116
]);
124117

@@ -138,7 +131,7 @@ describe('CryptoClient', () => {
138131
const { client } = createTestClient(null, userId, cryptoStoreType);
139132

140133
await client.cryptoStore.setDeviceId(TEST_DEVICE_ID);
141-
// await client.crypto.prepare([]); // deliberately commented
134+
// await client.crypto.prepare(); // deliberately commented
142135

143136
try {
144137
await client.crypto.isRoomEncrypted("!new:example.org");
@@ -159,7 +152,7 @@ describe('CryptoClient', () => {
159152

160153
bindNullEngine(http);
161154
await Promise.all([
162-
client.crypto.prepare([]),
155+
client.crypto.prepare(),
163156
http.flushAllExpected(),
164157
]);
165158

@@ -176,7 +169,7 @@ describe('CryptoClient', () => {
176169

177170
bindNullEngine(http);
178171
await Promise.all([
179-
client.crypto.prepare([]),
172+
client.crypto.prepare(),
180173
http.flushAllExpected(),
181174
]);
182175

@@ -193,7 +186,7 @@ describe('CryptoClient', () => {
193186

194187
bindNullEngine(http);
195188
await Promise.all([
196-
client.crypto.prepare([]),
189+
client.crypto.prepare(),
197190
http.flushAllExpected(),
198191
]);
199192

@@ -210,7 +203,7 @@ describe('CryptoClient', () => {
210203

211204
bindNullEngine(http);
212205
await Promise.all([
213-
client.crypto.prepare([]),
206+
client.crypto.prepare(),
214207
http.flushAllExpected(),
215208
]);
216209

@@ -248,7 +241,7 @@ describe('CryptoClient', () => {
248241
it('should sign the object while retaining signatures without mutation', async () => {
249242
bindNullEngine(http);
250243
await Promise.all([
251-
client.crypto.prepare([]),
244+
client.crypto.prepare(),
252245
http.flushAllExpected(),
253246
]);
254247

@@ -305,7 +298,7 @@ describe('CryptoClient', () => {
305298
it('should fail in unencrypted rooms', async () => {
306299
bindNullEngine(http);
307300
await Promise.all([
308-
client.crypto.prepare([]),
301+
client.crypto.prepare(),
309302
http.flushAllExpected(),
310303
]);
311304

@@ -381,7 +374,7 @@ describe('CryptoClient', () => {
381374
it('should encrypt media', async () => {
382375
bindNullEngine(http);
383376
await Promise.all([
384-
client.crypto.prepare([]),
377+
client.crypto.prepare(),
385378
http.flushAllExpected(),
386379
]);
387380

@@ -467,7 +460,7 @@ describe('CryptoClient', () => {
467460
it('should be symmetrical', async () => {
468461
bindNullEngine(http);
469462
await Promise.all([
470-
client.crypto.prepare([]),
463+
client.crypto.prepare(),
471464
http.flushAllExpected(),
472465
]);
473466

@@ -492,7 +485,7 @@ describe('CryptoClient', () => {
492485
it('should decrypt', async () => {
493486
bindNullEngine(http);
494487
await Promise.all([
495-
client.crypto.prepare([]),
488+
client.crypto.prepare(),
496489
http.flushAllExpected(),
497490
]);
498491

@@ -522,7 +515,7 @@ describe('CryptoClient', () => {
522515
await client.cryptoStore.setDeviceId(TEST_DEVICE_ID);
523516
bindNullEngine(http);
524517
await Promise.all([
525-
client.crypto.prepare([]),
518+
client.crypto.prepare(),
526519
http.flushAllExpected(),
527520
]);
528521
}));

test/encryption/KeyBackupTest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('KeyBackups', () => {
2121
const prepareCrypto = async () => {
2222
bindNullEngine(http);
2323
await Promise.all([
24-
client.crypto.prepare([]),
24+
client.crypto.prepare(),
2525
http.flushAllExpected(),
2626
]);
2727
};

test/encryption/RoomTrackerTest.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('RoomTracker', () => {
4444
await client.cryptoStore.setDeviceId(TEST_DEVICE_ID);
4545
bindNullEngine(http);
4646
await Promise.all([
47-
client.crypto.prepare([]),
47+
client.crypto.prepare(),
4848
http.flushAllExpected(),
4949
]);
5050
(client.crypto as any).engine.addTrackedUsers = () => Promise.resolve();
@@ -72,7 +72,7 @@ describe('RoomTracker', () => {
7272
await client.cryptoStore.setDeviceId(TEST_DEVICE_ID);
7373
bindNullEngine(http);
7474
await Promise.all([
75-
client.crypto.prepare([]),
75+
client.crypto.prepare(),
7676
http.flushAllExpected(),
7777
]);
7878

@@ -103,24 +103,6 @@ describe('RoomTracker', () => {
103103
expect(queueSpy.callCount).toEqual(1);
104104
}));
105105

106-
describe('prepare', () => {
107-
it('should queue updates for rooms', async () => {
108-
const roomIds = ["!a:example.org", "!b:example.org"];
109-
110-
const { client } = createTestClient();
111-
112-
const queueSpy = simple.stub().callFn((rid: string) => {
113-
expect(rid).toEqual(roomIds[queueSpy.callCount - 1]);
114-
return Promise.resolve();
115-
});
116-
117-
const tracker = new RoomTracker(client);
118-
tracker.queueRoomCheck = queueSpy;
119-
await tracker.prepare(roomIds);
120-
expect(queueSpy.callCount).toEqual(2);
121-
});
122-
});
123-
124106
describe('queueRoomCheck', () => {
125107
it('should store unknown rooms', () => testCryptoStores(async (cryptoStoreType) => {
126108
const roomId = "!b:example.org";

0 commit comments

Comments
 (0)