Page MenuHomePhabricator

[keyserver] Add new hashing to keyserver state check
ClosedPublic

Authored by michal on Sep 22 2023, 6:01 AM.
Tags
None
Referenced Files
F2319421: D9267.id31852.diff
Mon, Jul 22, 7:38 PM
Unknown Object (File)
Wed, Jul 17, 2:13 AM
Unknown Object (File)
Thu, Jul 11, 11:57 PM
Unknown Object (File)
Mon, Jul 8, 3:56 PM
Unknown Object (File)
Fri, Jul 5, 10:40 PM
Unknown Object (File)
Tue, Jul 2, 3:14 PM
Unknown Object (File)
Tue, Jul 2, 10:41 AM
Unknown Object (File)
Tue, Jul 2, 8:40 AM
Subscribers

Details

Summary

Part of ENG-4959
Depends on D9265
Depends on D9266

Modify the hashing on the keyserver (for new clients) so that:

  • the hashes are generated from data in client-side-schema, so clients don't have to do the conversion
  • the stores aren't hashed by stringifying the whole store but instead we generate a hash for each info and merge them using xor (there's a code comment explaining why that is correct)
Test Plan

Remove the version checks and wait for state check to trigger (with an old client):

  • check that there are no errors
  • check that:
    • currentUserInfo hash still matches because it's not a collection and it doesn't have anything to convert
    • specific userInfos match because they don't contain anything to convert
    • all other contain different hashes than on the client
  • inside of the getClientResponsesSelector additionally select integrityStore and use it's threadHashes for client side hashes -> check that now specific rawThreadInfos hashes match

Diff Detail

Repository
rCOMM Comm
Lint
No Lint Coverage
Unit
No Test Coverage

Event Timeline

michal edited the test plan for this revision. (Show Details)
keyserver/src/socket/session-utils.js
392–394

I tried creating a separate generic function to force flow to consider only one specific case for each iteration ("monomorphize" the generic) flow playground, but couldn't find a solution.

tomek requested changes to this revision.Oct 3 2023, 3:14 AM
tomek added inline comments.
keyserver/src/shared/state-sync/current-user-state-sync-spec.js
30

Why do we use null? Is it a good idea?

keyserver/src/socket/session-utils.js
396–407

What are the errors when you remove both FlowFixMes?

This revision now requires changes to proceed.Oct 3 2023, 3:14 AM
keyserver/src/shared/state-sync/current-user-state-sync-spec.js
30

It means that we skip the version check for conversion. We will be calling this function only for newer clients only (the version check is added in session-utils.js) so this should always succeed

keyserver/src/socket/session-utils.js
396–407

Without the first FlowFixMe:

Cannot call await with spec.fetch(...) bound to p because: [incompatible-call]
 • Either cannot call spec.getServerInfosHash with data bound to infos because Promise [1] is not a subtype of
   UserInfos [2]. Class instances are not subtypes of object types; consider rewriting UserInfos [2] as an interface.

     src/socket/session-utils.js
     393│         // doesn't understand that `data` is of the generic Info type of the
     394│         // spec we are currently iterating on
     395│         (async () => {
     396│           const data = await spec.fetch(viewer);
     397│           if (
     398│             !hasMinCodeVersion(viewer.platformDetails, {
     399│               native: NEXT_CODE_VERSION,

     src/shared/state-sync/state-sync-spec.js
 [1]   9│   +fetch: (viewer: Viewer, ids?: $ReadOnlySet<string>) => Promise<Infos>,

     src/shared/state-sync/users-state-sync-spec.js
 [2]  14│   UserInfos,

Without the second one FlowFixMe there are a lot of errors for different cases because flow types data as (not sure why the Promises are there):

type t =
  | RawEntryInfos
  | RawThreadInfos
  | UserInfos
  | CurrentUserInfo
  | Promise<RawEntryInfos>
  | Promise<RawThreadInfos>
  | Promise<CurrentUserInfo>

and it fails because we are trying to pass a value that can be any of these types to a function getServerInfosHash that takes a specific type. We know that data has this type at runtime but flow doesn't.

michal requested review of this revision.Oct 5 2023, 6:05 AM
tomek added inline comments.
keyserver/src/shared/state-sync/current-user-state-sync-spec.js
30

Will it work correctly if the validator changes in some future code version?

keyserver/src/socket/session-utils.js
396–407

Can we e.g. create a new function in a spec that calls both fetch and getServerInfosHash functions? Could this solve the issue?

This revision is now accepted and ready to land.Oct 5 2023, 6:52 AM

Create a new function in spec that combines fetch and getServerInfosHash so flow doesn't complain

keyserver/src/shared/state-sync/current-user-state-sync-spec.js
30

It will still work, the data from the server, types and validators are always in sync