diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index cbc93446f..4860e1c61 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -1130,7 +1130,6 @@ export class ConversationModel extends Backbone.Model { await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk: this.id, - supplementalKeysSubRequest: [], extraStoreRequests, }); diff --git a/ts/session/apis/snode_api/SNodeAPI.ts b/ts/session/apis/snode_api/SNodeAPI.ts index 81b38464e..10a979541 100644 --- a/ts/session/apis/snode_api/SNodeAPI.ts +++ b/ts/session/apis/snode_api/SNodeAPI.ts @@ -27,7 +27,7 @@ const forceNetworkDeletion = async (): Promise | null> => { const maliciousSnodes = await pRetry( async () => { const snodeToMakeRequestTo = await SnodePool.getNodeFromSwarmOrThrow(usPk); - const builtRequest = await request.buildAndSignParameters(); // we need the timestamp to verify the signature below + const builtRequest = await request.build(); const ret = await BatchRequests.doSnodeBatchRequestNoRetries( [builtRequest], snodeToMakeRequestTo, diff --git a/ts/session/apis/snode_api/SnodeRequestTypes.ts b/ts/session/apis/snode_api/SnodeRequestTypes.ts index 317fe1f55..b4e6aeef6 100644 --- a/ts/session/apis/snode_api/SnodeRequestTypes.ts +++ b/ts/session/apis/snode_api/SnodeRequestTypes.ts @@ -120,7 +120,7 @@ export class RetrieveUserSubRequest extends SnodeAPISubRequest { this.namespace = namespace; } - public async buildAndSignParameters() { + public async build() { const { pubkey, pubkey_ed25519, signature, timestamp } = await SnodeSignature.getSnodeSignatureParamsUs({ method: this.method, @@ -173,7 +173,7 @@ export class RetrieveGroupSubRequest extends SnodeAPISubRequest { this.groupDetailsNeededForSignature = groupDetailsNeededForSignature; } - public async buildAndSignParameters() { + public async build() { /** * This will return the signature details we can use with the admin secretKey if we have it, * or with the subaccount details if we don't. @@ -351,7 +351,7 @@ abstract class AbstractRevokeSubRequest extends SnodeAPISubRequest { export class SubaccountRevokeSubRequest extends AbstractRevokeSubRequest { public method = 'revoke_subaccount' as const; - public async buildAndSignParameters() { + public async build() { const signature = await this.signWithAdminSecretKey(); return { method: this.method, @@ -371,7 +371,7 @@ export class SubaccountUnrevokeSubRequest extends AbstractRevokeSubRequest { /** * For Revoke/unrevoke, this needs an admin signature */ - public async buildAndSignParameters() { + public async build() { const signature = await this.signWithAdminSecretKey(); return { @@ -405,7 +405,7 @@ export class GetExpiriesFromNodeSubRequest extends SnodeAPISubRequest { /** * For Revoke/unrevoke, this needs an admin signature */ - public async buildAndSignParameters() { + public async build() { const timestamp = GetNetworkTime.now(); const ourPubKey = UserUtils.getOurPubKeyStrFromCache(); @@ -445,7 +445,7 @@ export class DeleteAllFromUserNodeSubRequest extends SnodeAPISubRequest { public method = 'delete_all' as const; public readonly namespace = 'all'; // we can only delete_all for all namespaces currently, but the backend allows more - public async buildAndSignParameters() { + public async build() { const signResult = await SnodeSignature.getSnodeSignatureParamsUs({ method: this.method, namespace: this.namespace, @@ -492,7 +492,7 @@ export class DeleteAllFromGroupMsgNodeSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters() { + public async build() { const signDetails = await SnodeGroupSignature.getSnodeGroupSignature({ method: this.method, namespace: this.namespace, @@ -534,7 +534,7 @@ export class DeleteHashesFromUserNodeSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters() { + public async build() { const signResult = await SnodeSignature.getSnodeSignatureByHashesParams({ method: this.method, messagesHashes: this.messageHashes, @@ -588,7 +588,7 @@ export class DeleteHashesFromGroupNodeSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters() { + public async build() { // Note: this request can only be made by an admin and will be denied otherwise, so we make the secretKey mandatory in the constructor. const signResult = await SnodeGroupSignature.getGroupSignatureByHashesParams({ method: this.method, @@ -631,7 +631,7 @@ export class UpdateExpiryOnNodeUserSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters() { + public async build() { const signResult = await SnodeSignature.generateUpdateExpiryOurSignature({ shortenOrExtend: this.shortenOrExtend, messagesHashes: this.messageHashes, @@ -698,7 +698,7 @@ export class UpdateExpiryOnNodeGroupSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters() { + public async build() { const signResult = await SnodeGroupSignature.generateUpdateExpiryGroupSignature({ shortenOrExtend: this.shortenOrExtend, messagesHashes: this.messageHashes, @@ -784,7 +784,7 @@ export class StoreGroupMessageSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters(): Promise<{ + public async build(): Promise<{ method: 'store'; params: StoreOnNodeNormalParams; }> { @@ -855,7 +855,7 @@ abstract class StoreGroupConfigSubRequest< } } - public async buildAndSignParameters(): Promise<{ + public async build(): Promise<{ method: 'store'; params: StoreOnNodeNormalParams; }> { @@ -947,7 +947,7 @@ export class StoreUserConfigSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters(): Promise<{ + public async build(): Promise<{ method: 'store'; params: StoreOnNodeNormalParams; }> { @@ -1027,7 +1027,7 @@ export class StoreUserMessageSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters(): Promise<{ + public async build(): Promise<{ method: 'store'; params: StoreOnNodeNormalParams; }> { @@ -1086,7 +1086,7 @@ export class StoreLegacyGroupMessageSubRequest extends SnodeAPISubRequest { } } - public async buildAndSignParameters(): Promise<{ + public async build(): Promise<{ method: 'store'; params: StoreOnNodeNormalParams; }> { @@ -1181,29 +1181,7 @@ export type RawSnodeSubRequests = | GetExpiriesFromNodeSubRequest | DeleteAllFromGroupMsgNodeSubRequest; -export type BuiltSnodeSubRequests = - | ReturnType - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn - | AwaitedReturn; +export type BuiltSnodeSubRequests = AwaitedReturn; export function builtRequestToLoggingId(request: BuiltSnodeSubRequests): string { const { method, params } = request; @@ -1242,7 +1220,7 @@ export function builtRequestToLoggingId(request: BuiltSnodeSubRequests): string } // eslint-disable-next-line @typescript-eslint/array-type -export type NonEmptyArray = [T, ...T[]]; +type NonEmptyArray = [T, ...T[]]; export type BatchResultEntry = { code: number; diff --git a/ts/session/apis/snode_api/factories/StoreGroupRequestFactory.ts b/ts/session/apis/snode_api/factories/StoreGroupRequestFactory.ts index bcca72ac8..5289490b8 100644 --- a/ts/session/apis/snode_api/factories/StoreGroupRequestFactory.ts +++ b/ts/session/apis/snode_api/factories/StoreGroupRequestFactory.ts @@ -88,11 +88,11 @@ function makeStoreGroupKeysSubRequest({ group, }: { group: Pick; - encryptedSupplementKeys: Array; + encryptedSupplementKeys: Uint8Array | null; }) { const groupPk = group.pubkeyHex; - if (!encryptedSupplementKeys.length) { - return []; + if (!encryptedSupplementKeys?.length) { + return undefined; } // supplementalKeys are already encrypted, but we still need the secretKey to sign the request @@ -106,12 +106,10 @@ function makeStoreGroupKeysSubRequest({ 'pushChangesToGroupSwarmIfNeeded: keysEncryptedmessage not empty but we do not have the secretKey' ); } - return encryptedSupplementKeys.map(encryptedData => { - return new StoreGroupKeysSubRequest({ - encryptedData, - groupPk, - secretKey: group.secretKey, - }); + return new StoreGroupKeysSubRequest({ + encryptedData: encryptedSupplementKeys, + groupPk, + secretKey: group.secretKey, }); } diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index a908490d9..efcb20ab2 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -327,7 +327,6 @@ class ConvoController { await MetaGroupWrapperActions.infoDestroy(groupPk); const lastPushResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], deleteAllMessagesSubRequest, extraStoreRequests: [], }); diff --git a/ts/session/sending/MessageSender.ts b/ts/session/sending/MessageSender.ts index a0c2c5b79..243928c99 100644 --- a/ts/session/sending/MessageSender.ts +++ b/ts/session/sending/MessageSender.ts @@ -6,7 +6,6 @@ import { compact, isArray, isEmpty, isNumber, isString } from 'lodash'; import pRetry from 'p-retry'; import { Data, SeenMessageHashes } from '../../data/data'; import { SignalService } from '../../protobuf'; -import { assertUnreachable } from '../../types/sqlSharedTypes'; import { UserGroupsWrapperActions } from '../../webworker/workers/browser/libsession_worker_interface'; import { OpenGroupRequestCommonType } from '../apis/open_group_api/opengroupV2/ApiUtil'; import { OpenGroupMessageV2 } from '../apis/open_group_api/opengroupV2/OpenGroupMessageV2'; @@ -17,19 +16,11 @@ import { import { BuiltSnodeSubRequests, DeleteAllFromGroupMsgNodeSubRequest, - DeleteAllFromUserNodeSubRequest, DeleteHashesFromGroupNodeSubRequest, DeleteHashesFromUserNodeSubRequest, - GetExpiriesFromNodeSubRequest, - GetServiceNodesSubRequest, MethodBatchType, - NetworkTimeSubRequest, NotEmptyArrayOfBatchResults, - OnsResolveSubRequest, RawSnodeSubRequests, - RetrieveGroupSubRequest, - RetrieveLegacyClosedGroupSubRequest, - RetrieveUserSubRequest, StoreGroupInfoSubRequest, StoreGroupKeysSubRequest, StoreGroupMembersSubRequest, @@ -38,11 +29,6 @@ import { StoreLegacyGroupMessageSubRequest, StoreUserConfigSubRequest, StoreUserMessageSubRequest, - SubaccountRevokeSubRequest, - SubaccountUnrevokeSubRequest, - SwarmForSubRequest, - UpdateExpiryOnNodeGroupSubRequest, - UpdateExpiryOnNodeUserSubRequest, } from '../apis/snode_api/SnodeRequestTypes'; import { BatchRequests } from '../apis/snode_api/batchRequest'; import { GetNetworkTime } from '../apis/snode_api/getNetworkTime'; @@ -369,47 +355,7 @@ async function signSubRequests( ): Promise> { const signedRequests: Array = await Promise.all( params.map(p => { - if ( - p instanceof SubaccountRevokeSubRequest || - p instanceof SubaccountUnrevokeSubRequest || - p instanceof DeleteHashesFromUserNodeSubRequest || - p instanceof DeleteHashesFromGroupNodeSubRequest || - p instanceof DeleteAllFromUserNodeSubRequest || - p instanceof StoreGroupInfoSubRequest || - p instanceof StoreGroupMembersSubRequest || - p instanceof StoreGroupKeysSubRequest || - p instanceof StoreGroupRevokedRetrievableSubRequest || - p instanceof StoreGroupMessageSubRequest || - p instanceof StoreLegacyGroupMessageSubRequest || - p instanceof StoreUserConfigSubRequest || - p instanceof StoreUserMessageSubRequest || - p instanceof RetrieveUserSubRequest || - p instanceof RetrieveGroupSubRequest || - p instanceof UpdateExpiryOnNodeUserSubRequest || - p instanceof UpdateExpiryOnNodeGroupSubRequest || - p instanceof GetExpiriesFromNodeSubRequest || - p instanceof DeleteAllFromGroupMsgNodeSubRequest - ) { - return p.buildAndSignParameters(); - } - - if ( - p instanceof RetrieveLegacyClosedGroupSubRequest || - p instanceof SwarmForSubRequest || - p instanceof OnsResolveSubRequest || - p instanceof GetServiceNodesSubRequest || - p instanceof NetworkTimeSubRequest - ) { - return p.build(); - } - - assertUnreachable( - p, - 'If you see this error, you need to add the handling of the rawRequest above' - ); - throw new Error( - 'If you see this error, you need to add the handling of the rawRequest above' - ); + return p.build(); }) ); diff --git a/ts/session/utils/job_runners/jobs/GroupSyncJob.ts b/ts/session/utils/job_runners/jobs/GroupSyncJob.ts index fe184a7f4..c05e333d5 100644 --- a/ts/session/utils/job_runners/jobs/GroupSyncJob.ts +++ b/ts/session/utils/job_runners/jobs/GroupSyncJob.ts @@ -1,7 +1,7 @@ /* eslint-disable no-await-in-loop */ import { GroupPubkeyType, WithGroupPubkey } from 'libsession_util_nodejs'; import { to_hex } from 'libsodium-wrappers-sumo'; -import { isArray, isEmpty, isNumber } from 'lodash'; +import { compact, isArray, isEmpty, isNumber } from 'lodash'; import { UserUtils } from '../..'; import { assertUnreachable } from '../../../../types/sqlSharedTypes'; import { isSignInByLinking } from '../../../../util/storage'; @@ -85,7 +85,7 @@ async function pushChangesToGroupSwarmIfNeeded({ extraStoreRequests, }: WithGroupPubkey & WithRevokeSubRequest & { - supplementalKeysSubRequest: Array; + supplementalKeysSubRequest?: StoreGroupKeysSubRequest; deleteAllMessagesSubRequest?: DeleteAllFromGroupMsgNodeSubRequest; extraStoreRequests: Array; }): Promise { @@ -136,7 +136,11 @@ async function pushChangesToGroupSwarmIfNeeded({ // Note: this is on purpose that supplementalKeysSubRequest is before pendingConfigRequests // as this is to avoid a race condition where a device is polling right // while we are posting the configs (already encrypted with the new keys) - storeRequests: [...supplementalKeysSubRequest, ...pendingConfigRequests, ...extraStoreRequests], + storeRequests: compact([ + supplementalKeysSubRequest, + ...pendingConfigRequests, + ...extraStoreRequests, + ]), destination: groupPk, deleteHashesSubRequest, revokeSubRequest, @@ -146,8 +150,8 @@ async function pushChangesToGroupSwarmIfNeeded({ const expectedReplyLength = pendingConfigRequests.length + // each of those are sent as a subrequest - supplementalKeysSubRequest.length + // each of those are sent as a subrequest - (allOldHashes.size ? 1 : 0) + // we are sending all hashes changes as a single subrequest + (supplementalKeysSubRequest ? 1 : 0) + // we are sending all the supplemental keys as a single subrequest + (deleteHashesSubRequest ? 1 : 0) + // we are sending all hashes changes as a single subrequest (revokeSubRequest ? 1 : 0) + // we are sending all revoke updates as a single subrequest (unrevokeSubRequest ? 1 : 0) + // we are sending all revoke updates as a single subrequest (deleteAllMessagesSubRequest ? 1 : 0) + // a delete_all sub request is a single subrequest @@ -221,7 +225,6 @@ class GroupSyncJob extends PersistedJob { // return await so we catch exceptions in here return await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk: thisJobDestination, - supplementalKeysSubRequest: [], extraStoreRequests: [], }); diff --git a/ts/state/ducks/metaGroups.ts b/ts/state/ducks/metaGroups.ts index 74a5b9777..92e997806 100644 --- a/ts/state/ducks/metaGroups.ts +++ b/ts/state/ducks/metaGroups.ts @@ -209,7 +209,6 @@ const initNewGroupInWrapper = createAsyncThunk( const result = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests, }); if (result !== RunJobResult.Success) { @@ -499,7 +498,7 @@ async function handleWithHistoryMembers({ } const encryptedSupplementKeys = withHistory.length ? await MetaGroupWrapperActions.generateSupplementKeys(groupPk, withHistory) - : []; + : null; return encryptedSupplementKeys; } @@ -831,7 +830,6 @@ async function handleMemberRemovedFromUI({ // revoked pubkeys, update messages, and libsession groups config in a single batch call const sequenceResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests, }); if (sequenceResult !== RunJobResult.Success) { @@ -910,7 +908,6 @@ async function handleNameChangeFromUI({ const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests, }); @@ -1030,7 +1027,6 @@ const triggerFakeAvatarUpdate = createAsyncThunk( const batchResult = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests, }); if (!batchResult) { diff --git a/ts/test/session/unit/disappearing_messages/ExpireRequest_test.ts b/ts/test/session/unit/disappearing_messages/ExpireRequest_test.ts index f8f036fb2..a6b4b8eac 100644 --- a/ts/test/session/unit/disappearing_messages/ExpireRequest_test.ts +++ b/ts/test/session/unit/disappearing_messages/ExpireRequest_test.ts @@ -55,7 +55,7 @@ describe('ExpireRequest', () => { throw Error('nothing was returned when building the request'); } - const signedReq = await request.buildAndSignParameters(); + const signedReq = await request.build(); expect(signedReq, "method should be 'expire'").to.have.property('method', 'expire'); expect(signedReq.params.pubkey, 'should have a matching pubkey').to.equal(ourNumber); @@ -83,7 +83,7 @@ describe('ExpireRequest', () => { if (!request) { throw Error('nothing was returned when building the request'); } - const signedReq = await request.buildAndSignParameters(); + const signedReq = await request.build(); expect(signedReq, "method should be 'expire'").to.have.property('method', 'expire'); expect(signedReq.params.pubkey, 'should have a matching pubkey').to.equal(ourNumber); @@ -111,7 +111,7 @@ describe('ExpireRequest', () => { if (!request) { throw Error('nothing was returned when building the request'); } - const signedReq = await request.buildAndSignParameters(); + const signedReq = await request.build(); expect(signedReq, "method should be 'expire'").to.have.property('method', 'expire'); expect(signedReq.params.pubkey, 'should have a matching pubkey').to.equal(ourNumber); diff --git a/ts/test/session/unit/disappearing_messages/GetExpiriesRequest_test.ts b/ts/test/session/unit/disappearing_messages/GetExpiriesRequest_test.ts index fc4e131d1..15c5f38b0 100644 --- a/ts/test/session/unit/disappearing_messages/GetExpiriesRequest_test.ts +++ b/ts/test/session/unit/disappearing_messages/GetExpiriesRequest_test.ts @@ -52,7 +52,7 @@ describe('GetExpiriesRequest', () => { it('builds a valid request given the messageHashes and valid timestamp for now', async () => { const unsigned = new GetExpiriesFromNodeSubRequest(props); - const request = await unsigned.buildAndSignParameters(); + const request = await unsigned.build(); expect(request, 'should not return null').to.not.be.null; expect(request, 'should not return undefined').to.not.be.undefined; @@ -77,7 +77,7 @@ describe('GetExpiriesRequest', () => { let errorStr = 'fakeerror'; try { const unsigned = new GetExpiriesFromNodeSubRequest(props); - const request = await unsigned.buildAndSignParameters(); + const request = await unsigned.build(); if (request) { throw new Error('we should not have been able to build a request'); } @@ -93,7 +93,7 @@ describe('GetExpiriesRequest', () => { const unsigned = new GetExpiriesFromNodeSubRequest(props); try { - const request = await unsigned.buildAndSignParameters(); + const request = await unsigned.build(); if (request) { throw new Error('should not be able to build the request'); } diff --git a/ts/test/session/unit/utils/job_runner/group_sync_job/GroupSyncJob_test.ts b/ts/test/session/unit/utils/job_runner/group_sync_job/GroupSyncJob_test.ts index d05a6870e..068fdf452 100644 --- a/ts/test/session/unit/utils/job_runner/group_sync_job/GroupSyncJob_test.ts +++ b/ts/test/session/unit/utils/job_runner/group_sync_job/GroupSyncJob_test.ts @@ -275,7 +275,6 @@ describe('GroupSyncJob pushChangesToGroupSwarmIfNeeded', () => { const result = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests: [], }); expect(result).to.be.eq(RunJobResult.Success); @@ -299,7 +298,6 @@ describe('GroupSyncJob pushChangesToGroupSwarmIfNeeded', () => { }); const result = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests: [], }); @@ -370,7 +368,6 @@ describe('GroupSyncJob pushChangesToGroupSwarmIfNeeded', () => { ]); const result = await GroupSync.pushChangesToGroupSwarmIfNeeded({ groupPk, - supplementalKeysSubRequest: [], extraStoreRequests: [], });