Page MenuHomePhorge

D9267.1768098585.diff
No OneTemporary

Size
11 KB
Referenced Files
None
Subscribers
None

D9267.1768098585.diff

diff --git a/keyserver/src/shared/state-sync/current-user-state-sync-spec.js b/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/current-user-state-sync-spec.js
@@ -2,10 +2,13 @@
import { currentUserStateSyncSpec as libSpec } from 'lib/shared/state-sync/current-user-state-sync-spec.js';
import type { CurrentUserInfo } from 'lib/types/user-types.js';
+import { currentUserInfoValidator } from 'lib/types/user-types.js';
+import { hash } from 'lib/utils/objects.js';
import type { ServerStateSyncSpec } from './state-sync-spec.js';
import { fetchCurrentUserInfo } from '../../fetchers/user-fetchers.js';
import type { Viewer } from '../../session/viewer.js';
+import { validateOutput } from '../../utils/validation-utils.js';
export const currentUserStateSyncSpec: ServerStateSyncSpec<
CurrentUserInfo,
@@ -13,11 +16,23 @@
CurrentUserInfo,
void,
> = Object.freeze({
- fetch(viewer: Viewer) {
- return fetchCurrentUserInfo(viewer);
- },
+ fetch,
fetchFullSocketSyncPayload(viewer: Viewer) {
return fetchCurrentUserInfo(viewer);
},
+ async fetchServerInfosHash(viewer: Viewer) {
+ const info = await fetch(viewer);
+ return getHash(info);
+ },
+ getServerInfosHash: getHash,
+ getServerInfoHash: getHash,
...libSpec,
});
+
+function fetch(viewer: Viewer) {
+ return fetchCurrentUserInfo(viewer);
+}
+
+function getHash(currentUserInfo: CurrentUserInfo) {
+ return hash(validateOutput(null, currentUserInfoValidator, currentUserInfo));
+}
diff --git a/keyserver/src/shared/state-sync/entries-state-sync-spec.js b/keyserver/src/shared/state-sync/entries-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/entries-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/entries-state-sync-spec.js
@@ -2,12 +2,14 @@
import { serverEntryInfosObject } from 'lib/shared/entry-utils.js';
import { entriesStateSyncSpec as libSpec } from 'lib/shared/state-sync/entries-state-sync-spec.js';
-import type {
- CalendarQuery,
- RawEntryInfo,
- RawEntryInfos,
+import {
+ type CalendarQuery,
+ type RawEntryInfo,
+ type RawEntryInfos,
+ rawEntryInfoValidator,
} from 'lib/types/entry-types.js';
import type { ClientEntryInconsistencyReportCreationRequest } from 'lib/types/report-types.js';
+import { hash, combineUnorderedHashes, values } from 'lib/utils/objects.js';
import type { ServerStateSyncSpec } from './state-sync-spec.js';
import {
@@ -15,6 +17,7 @@
fetchEntryInfosByID,
} from '../../fetchers/entry-fetchers.js';
import type { Viewer } from '../../session/viewer.js';
+import { validateOutput } from '../../utils/validation-utils.js';
export const entriesStateSyncSpec: ServerStateSyncSpec<
RawEntryInfos,
@@ -22,14 +25,7 @@
RawEntryInfo,
$ReadOnlyArray<ClientEntryInconsistencyReportCreationRequest>,
> = Object.freeze({
- async fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
- if (ids) {
- return fetchEntryInfosByID(viewer, ids);
- }
- const query = [viewer.calendarQuery];
- const entriesResult = await fetchEntryInfos(viewer, query);
- return serverEntryInfosObject(entriesResult.rawEntryInfos);
- },
+ fetch,
async fetchFullSocketSyncPayload(
viewer: Viewer,
query: $ReadOnlyArray<CalendarQuery>,
@@ -37,5 +33,28 @@
const result = await fetchEntryInfos(viewer, query);
return result.rawEntryInfos;
},
+ async fetchServerInfosHash(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ const info = await fetch(viewer, ids);
+ return getServerInfosHash(info);
+ },
+ getServerInfosHash,
+ getServerInfoHash,
...libSpec,
});
+
+async function fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ if (ids) {
+ return fetchEntryInfosByID(viewer, ids);
+ }
+ const query = [viewer.calendarQuery];
+ const entriesResult = await fetchEntryInfos(viewer, query);
+ return serverEntryInfosObject(entriesResult.rawEntryInfos);
+}
+
+function getServerInfosHash(infos: RawEntryInfos) {
+ return combineUnorderedHashes(values(infos).map(getServerInfoHash));
+}
+
+function getServerInfoHash(info: RawEntryInfo) {
+ return hash(validateOutput(null, rawEntryInfoValidator, info));
+}
diff --git a/keyserver/src/shared/state-sync/state-sync-spec.js b/keyserver/src/shared/state-sync/state-sync-spec.js
--- a/keyserver/src/shared/state-sync/state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/state-sync-spec.js
@@ -16,5 +16,11 @@
viewer: Viewer,
calendarQuery: $ReadOnlyArray<CalendarQuery>,
) => Promise<FullSocketSyncPayload>,
+ +fetchServerInfosHash: (
+ viewer: Viewer,
+ ids?: $ReadOnlySet<string>,
+ ) => Promise<number>,
+ +getServerInfosHash: (infos: Infos) => number,
+ +getServerInfoHash: (info: Info) => number,
...StateSyncSpec<Infos, Info, Inconsistencies>,
};
diff --git a/keyserver/src/shared/state-sync/threads-state-sync-spec.js b/keyserver/src/shared/state-sync/threads-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/threads-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/threads-state-sync-spec.js
@@ -5,11 +5,14 @@
import {
type RawThreadInfos,
type RawThreadInfo,
+ rawThreadInfoValidator,
} from 'lib/types/thread-types.js';
+import { hash, combineUnorderedHashes, values } from 'lib/utils/objects.js';
import type { ServerStateSyncSpec } from './state-sync-spec.js';
import { fetchThreadInfos } from '../../fetchers/thread-fetchers.js';
import type { Viewer } from '../../session/viewer.js';
+import { validateOutput } from '../../utils/validation-utils.js';
export const threadsStateSyncSpec: ServerStateSyncSpec<
RawThreadInfos,
@@ -17,14 +20,30 @@
RawThreadInfo,
$ReadOnlyArray<ClientThreadInconsistencyReportCreationRequest>,
> = Object.freeze({
- async fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
- const filter = ids ? { threadIDs: ids } : undefined;
- const result = await fetchThreadInfos(viewer, filter);
- return result.threadInfos;
- },
+ fetch,
async fetchFullSocketSyncPayload(viewer: Viewer) {
const result = await fetchThreadInfos(viewer);
return result.threadInfos;
},
+ async fetchServerInfosHash(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ const infos = await fetch(viewer, ids);
+ return getServerInfosHash(infos);
+ },
+ getServerInfosHash,
+ getServerInfoHash,
...libSpec,
});
+
+async function fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ const filter = ids ? { threadIDs: ids } : undefined;
+ const result = await fetchThreadInfos(viewer, filter);
+ return result.threadInfos;
+}
+
+function getServerInfosHash(infos: RawThreadInfos) {
+ return combineUnorderedHashes(values(infos).map(getServerInfoHash));
+}
+
+function getServerInfoHash(info: RawThreadInfo) {
+ return hash(validateOutput(null, rawThreadInfoValidator, info));
+}
diff --git a/keyserver/src/shared/state-sync/users-state-sync-spec.js b/keyserver/src/shared/state-sync/users-state-sync-spec.js
--- a/keyserver/src/shared/state-sync/users-state-sync-spec.js
+++ b/keyserver/src/shared/state-sync/users-state-sync-spec.js
@@ -3,11 +3,13 @@
import { usersStateSyncSpec as libSpec } from 'lib/shared/state-sync/users-state-sync-spec.js';
import type { UserInconsistencyReportCreationRequest } from 'lib/types/report-types.js';
import type { UserInfos, UserInfo } from 'lib/types/user-types.js';
-import { values } from 'lib/utils/objects.js';
+import { userInfoValidator } from 'lib/types/user-types.js';
+import { values, hash, combineUnorderedHashes } from 'lib/utils/objects.js';
import type { ServerStateSyncSpec } from './state-sync-spec.js';
import { fetchKnownUserInfos } from '../../fetchers/user-fetchers.js';
import type { Viewer } from '../../session/viewer.js';
+import { validateOutput } from '../../utils/validation-utils.js';
export const usersStateSyncSpec: ServerStateSyncSpec<
UserInfos,
@@ -15,16 +17,32 @@
UserInfo,
$ReadOnlyArray<UserInconsistencyReportCreationRequest>,
> = Object.freeze({
- fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
- if (ids) {
- return fetchKnownUserInfos(viewer, [...ids]);
- }
-
- return fetchKnownUserInfos(viewer);
- },
+ fetch,
async fetchFullSocketSyncPayload(viewer: Viewer) {
const result = await fetchKnownUserInfos(viewer);
return values(result);
},
+ async fetchServerInfosHash(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ const infos = await fetch(viewer, ids);
+ return getServerInfosHash(infos);
+ },
+ getServerInfosHash,
+ getServerInfoHash,
...libSpec,
});
+
+function fetch(viewer: Viewer, ids?: $ReadOnlySet<string>) {
+ if (ids) {
+ return fetchKnownUserInfos(viewer, [...ids]);
+ }
+
+ return fetchKnownUserInfos(viewer);
+}
+
+function getServerInfosHash(infos: UserInfos) {
+ return combineUnorderedHashes(values(infos).map(getServerInfoHash));
+}
+
+function getServerInfoHash(info: UserInfo) {
+ return hash(validateOutput(null, userInfoValidator, info));
+}
diff --git a/keyserver/src/socket/session-utils.js b/keyserver/src/socket/session-utils.js
--- a/keyserver/src/socket/session-utils.js
+++ b/keyserver/src/socket/session-utils.js
@@ -4,6 +4,10 @@
import t from 'tcomb';
import type { TUnion } from 'tcomb';
+import {
+ NEXT_CODE_VERSION,
+ hasMinCodeVersion,
+} from 'lib/shared/version-utils.js';
import type { UpdateActivityResult } from 'lib/types/activity-types.js';
import type { IdentityKeysBlob } from 'lib/types/crypto-types.js';
import { isDeviceType } from 'lib/types/device-types.js';
@@ -386,8 +390,17 @@
values(serverStateSyncSpecs).map(spec => [
spec.hashKey,
(async () => {
- const data = await spec.fetch(viewer);
- return hash(data);
+ if (
+ !hasMinCodeVersion(viewer.platformDetails, {
+ native: NEXT_CODE_VERSION,
+ web: NEXT_CODE_VERSION,
+ })
+ ) {
+ const data = await spec.fetch(viewer);
+ return hash(data);
+ }
+ const infosHash = await spec.fetchServerInfosHash(viewer);
+ return infosHash;
})(),
]),
);
@@ -452,7 +465,18 @@
// out which infos don't match first
const infos = fetchedData[key];
for (const infoID in infos) {
- hashesToCheck[`${innerHashKey}|${infoID}`] = hash(infos[infoID]);
+ let hashValue;
+ if (
+ hasMinCodeVersion(viewer.platformDetails, {
+ native: NEXT_CODE_VERSION,
+ web: NEXT_CODE_VERSION,
+ })
+ ) {
+ hashValue = spec.getServerInfoHash(infos[infoID]);
+ } else {
+ hashValue = hash(infos[infoID]);
+ }
+ hashesToCheck[`${innerHashKey}|${infoID}`] = hashValue;
}
failUnmentioned[key] = true;
} else if (isTopLevelKey) {
diff --git a/lib/utils/objects.js b/lib/utils/objects.js
--- a/lib/utils/objects.js
+++ b/lib/utils/objects.js
@@ -73,6 +73,14 @@
return stringHash(stableStringify(obj));
}
+// This function doesn't look at the order of the hashes inside of the array
+// e.g `combineUnorderedHashes([1,2,3]) === combineUnorderedHashes([3,1,2])`
+// so it should only be used if the hashes include their ordering in them
+// somehow (e.g. `RawThreadInfo` contains `id`)
+function combineUnorderedHashes(hashes: $ReadOnlyArray<number>): number {
+ return hashes.reduce((a, v) => a ^ v, 0);
+}
+
// returns an object with properties from obj1 not included in obj2
function deepDiff<K, T>(
obj1: NestedObjectMap<K, T>,
@@ -125,6 +133,7 @@
findMaximumDepth,
values,
hash,
+ combineUnorderedHashes,
assertObjectsAreEqual,
deepDiff,
entries,

File Metadata

Mime Type
text/plain
Expires
Sun, Jan 11, 2:29 AM (5 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5917548
Default Alt Text
D9267.1768098585.diff (11 KB)

Event Timeline