Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32847017
D9267.1768098585.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D9267.1768098585.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D9267: [keyserver] Add new hashing to keyserver state check
Attached
Detach File
Event Timeline
Log In to Comment