From e36bbfefe75c69ba4b9f9068e8ad355cc441f34e Mon Sep 17 00:00:00 2001 From: texuf Date: Mon, 27 May 2024 15:15:15 -0700 Subject: [PATCH] Use the optional flag when adding events for key fulfillments (#75) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently when we repond to KeySolicitations we first post a KeyFulfillment to the channel. Lots of users can post this fulfillment at the same time, but the node will only accept one of them After this change, instead of throwing tons of errors polluting all logs, we now pass “optional: true” and check the error in the calling code --- core/encryption/src/decryptionExtensions.ts | 21 ++++++++++++------- .../src/tests/decryptionExtensions.test.ts | 18 +++++++++++----- core/sdk/src/clientDecryptionExtensions.ts | 13 +++++++++--- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/core/encryption/src/decryptionExtensions.ts b/core/encryption/src/decryptionExtensions.ts index 8d8b4ce8e8..8e6a57eb06 100644 --- a/core/encryption/src/decryptionExtensions.ts +++ b/core/encryption/src/decryptionExtensions.ts @@ -1,6 +1,7 @@ import TypedEmitter from 'typed-emitter' import { Permission } from '@river-build/web3' import { + AddEventResponse_Error, EncryptedData, SessionKeys, UserInboxPayload_GroupEncryptionSessions, @@ -196,7 +197,9 @@ export abstract class BaseDecryptionExtensions { public abstract isUserInboxStreamUpToDate(upToDateStreams: Set): boolean public abstract onDecryptionError(item: EncryptedContentItem, err: DecryptionSessionError): void public abstract sendKeySolicitation(args: KeySolicitationData): Promise - public abstract sendKeyFulfillment(args: KeyFulfilmentData): Promise + public abstract sendKeyFulfillment( + args: KeyFulfilmentData, + ): Promise<{ error?: AddEventResponse_Error }> public abstract encryptAndShareGroupSessions(args: GroupSessionsData): Promise public abstract shouldPauseTicking(): boolean /** @@ -661,7 +664,7 @@ export abstract class BaseDecryptionExtensions { /** * processKeySolicitation - * process incoming key solicitations and send keys and key fulfilments + * process incoming key solicitations and send keys and key fulfillments */ private async processKeySolicitation(item: KeySolicitationItem): Promise { this.log.debug('processing key solicitation', item.streamId, item) @@ -710,18 +713,20 @@ export abstract class BaseDecryptionExtensions { return } - await this.sendKeyFulfillment({ + const { error } = await this.sendKeyFulfillment({ streamId, userAddress: item.fromUserAddress, deviceKey: item.solicitation.deviceKey, sessionIds: item.solicitation.isNewDevice ? [] : sessions.map((x) => x.sessionId), }) - await this.encryptAndShareGroupSessions({ - streamId, - item, - sessions, - }) + if (!error) { + await this.encryptAndShareGroupSessions({ + streamId, + item, + sessions, + }) + } } /** diff --git a/core/encryption/src/tests/decryptionExtensions.test.ts b/core/encryption/src/tests/decryptionExtensions.test.ts index 0a95da1f50..a9ebc96e28 100644 --- a/core/encryption/src/tests/decryptionExtensions.test.ts +++ b/core/encryption/src/tests/decryptionExtensions.test.ts @@ -11,7 +11,11 @@ import { KeySolicitationData, makeSessionKeys, } from '../decryptionExtensions' -import { EncryptedData, UserInboxPayload_GroupEncryptionSessions } from '@river-build/proto' +import { + AddEventResponse_Error, + EncryptedData, + UserInboxPayload_GroupEncryptionSessions, +} from '@river-build/proto' import { GroupEncryptionSession, UserDevice, UserDeviceCollection } from '../olmLib' import { bin_fromHexString, bin_toHexString, dlog } from '@river-build/dlog' @@ -280,9 +284,11 @@ class MockDecryptionExtensions extends BaseDecryptionExtensions { return Promise.resolve() } - public sendKeyFulfillment(args: KeyFulfilmentData): Promise { + public sendKeyFulfillment( + args: KeyFulfilmentData, + ): Promise<{ error?: AddEventResponse_Error }> { log('sendKeyFulfillment', args) - return Promise.resolve() + return Promise.resolve({}) } public encryptAndShareGroupSessions(args: GroupSessionsData): Promise { @@ -405,8 +411,10 @@ class MockGroupEncryptionClient return Promise.resolve() } - public sendKeyFulfillment(_args: KeyFulfilmentData): Promise { - return Promise.resolve() + public sendKeyFulfillment( + _args: KeyFulfilmentData, + ): Promise<{ error?: AddEventResponse_Error }> { + return Promise.resolve({}) } public uploadDeviceKeys(): Promise { diff --git a/core/sdk/src/clientDecryptionExtensions.ts b/core/sdk/src/clientDecryptionExtensions.ts index 1ba2033a56..8636db2007 100644 --- a/core/sdk/src/clientDecryptionExtensions.ts +++ b/core/sdk/src/clientDecryptionExtensions.ts @@ -10,7 +10,11 @@ import { KeySolicitationData, UserDevice, } from '@river-build/encryption' -import { EncryptedData, UserInboxPayload_GroupEncryptionSessions } from '@river-build/proto' +import { + AddEventResponse_Error, + EncryptedData, + UserInboxPayload_GroupEncryptionSessions, +} from '@river-build/proto' import { make_MemberPayload_KeyFulfillment, make_MemberPayload_KeySolicitation } from './types' import { Client } from './client' @@ -231,14 +235,17 @@ export class ClientDecryptionExtensions extends BaseDecryptionExtensions { userAddress, deviceKey, sessionIds, - }: KeyFulfilmentData): Promise { + }: KeyFulfilmentData): Promise<{ error?: AddEventResponse_Error }> { const fulfillment = make_MemberPayload_KeyFulfillment({ userAddress: userAddress, deviceKey: deviceKey, sessionIds: sessionIds, }) - await this.client.makeEventAndAddToStream(streamId, fulfillment) + const { error } = await this.client.makeEventAndAddToStream(streamId, fulfillment, { + optional: true, + }) + return { error } } public async uploadDeviceKeys(): Promise {