From 7277db35b45b76a2db20d37dc38471d42353e71a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 25 Jul 2024 16:47:57 +1000 Subject: [PATCH 1/4] fix: failing tests making requests to real servers :bad: --- ts/test/test-utils/utils/pubkey.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ts/test/test-utils/utils/pubkey.ts b/ts/test/test-utils/utils/pubkey.ts index 52e522bc8..d90b0af9e 100644 --- a/ts/test/test-utils/utils/pubkey.ts +++ b/ts/test/test-utils/utils/pubkey.ts @@ -45,7 +45,8 @@ export function generateFakePubKeys(amount: number): Array { export function generateFakeSnode(): Snode { return { - ip: `${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}`, + // NOTE: make sure this is random, but not a valid ip (otherwise we will try to hit that ip during testing!) + ip: `${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}`, port: 22116, pubkey_x25519: generateFakePubKeyStr(), pubkey_ed25519: generateFakePubKeyStr(), @@ -59,7 +60,8 @@ function ipv4Section() { export function generateFakeSnodeWithEdKey(ed25519Pubkey: string): Snode { return { - ip: `${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}`, + // NOTE: make sure this is random, but not a valid ip (otherwise we will try to hit that ip during testing!) + ip: `${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}.${ipv4Section()}`, port: 22116, pubkey_x25519: generateFakePubKeyStr(), pubkey_ed25519: ed25519Pubkey, From 26e7a39a61e08e33175cba0658232d97592765e2 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 26 Jul 2024 11:03:28 +1000 Subject: [PATCH 2/4] feat: hit only once every 30mins the fs for release once we've already fetched the latest release --- ts/components/leftpane/ActionsPanel.tsx | 34 +----------- .../useFetchLatestReleaseFromFileServer.ts | 15 +++++ ts/session/fetch_latest_release/index.ts | 55 +++++++++++++++++++ 3 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 ts/hooks/useFetchLatestReleaseFromFileServer.ts create mode 100644 ts/session/fetch_latest_release/index.ts diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx index 319300713..8fbe069ad 100644 --- a/ts/components/leftpane/ActionsPanel.tsx +++ b/ts/components/leftpane/ActionsPanel.tsx @@ -1,7 +1,5 @@ -import { ipcRenderer } from 'electron'; import React, { useEffect, useState } from 'react'; - -import { debounce, isEmpty, isString } from 'lodash'; +import { debounce } from 'lodash'; import { useDispatch, useSelector } from 'react-redux'; import useInterval from 'react-use/lib/useInterval'; import useTimeoutFn from 'react-use/lib/useTimeoutFn'; @@ -37,7 +35,7 @@ import { SessionIconButton } from '../icon/SessionIconButton'; import { LeftPaneSectionContainer } from './LeftPaneSectionContainer'; import { SettingsKey } from '../../data/settings-key'; -import { getLatestReleaseFromFileServer } from '../../session/apis/file_server_api/FileServerApi'; +import { useFetchLatestReleaseFromFileServer } from '../../hooks/useFetchLatestReleaseFromFileServer'; import { forceRefreshRandomSnodePool, getFreshSwarmFor, @@ -144,11 +142,6 @@ const Section = (props: { type: SectionType }) => { const cleanUpMediasInterval = DURATION.MINUTES * 60; -// every 1 minute we fetch from the fileserver to check for a new release -// * if there is none, no request to github are made. -// * if there is a version on the fileserver more recent than our current, we fetch github to get the UpdateInfos and trigger an update as usual (asking user via dialog) -const fetchReleaseFromFileServerInterval = 1000 * 60; // try to fetch the latest release from the fileserver every minute - const setupTheme = async () => { const shouldFollowSystemTheme = window.getSettingValue(SettingsKey.hasFollowSystemThemeEnabled); const theme = window.Events.getThemeSetting(); @@ -232,22 +225,6 @@ const doAppStartUp = async () => { }, 20000); }; -async function fetchReleaseFromFSAndUpdateMain() { - try { - window.log.info('[updater] about to fetchReleaseFromFSAndUpdateMain'); - - const latest = await getLatestReleaseFromFileServer(); - window.log.info('[updater] fetched latest release from fileserver: ', latest); - - if (isString(latest) && !isEmpty(latest)) { - ipcRenderer.send('set-release-from-file-server', latest); - window.readyForUpdates(); - } - } catch (e) { - window.log.warn(e); - } -} - /** * ActionsPanel is the far left banner (not the left pane). * The panel with buttons to switch between the message/contact/settings/theme views @@ -272,12 +249,7 @@ export const ActionsPanel = () => { useInterval(cleanUpOldDecryptedMedias, startCleanUpMedia ? cleanUpMediasInterval : null); - useInterval(() => { - if (!ourPrimaryConversation) { - return; - } - void fetchReleaseFromFSAndUpdateMain(); - }, fetchReleaseFromFileServerInterval); + useFetchLatestReleaseFromFileServer(); useInterval(() => { if (!ourPrimaryConversation) { diff --git a/ts/hooks/useFetchLatestReleaseFromFileServer.ts b/ts/hooks/useFetchLatestReleaseFromFileServer.ts new file mode 100644 index 000000000..4766954e5 --- /dev/null +++ b/ts/hooks/useFetchLatestReleaseFromFileServer.ts @@ -0,0 +1,15 @@ +import { useSelector } from 'react-redux'; +import useInterval from 'react-use/lib/useInterval'; +import { getOurPrimaryConversation } from '../state/selectors/conversations'; +import { fetchLatestRelease } from '../session/fetch_latest_release'; + +export function useFetchLatestReleaseFromFileServer() { + const ourPrimaryConversation = useSelector(getOurPrimaryConversation); + + useInterval(() => { + if (!ourPrimaryConversation) { + return; + } + void fetchLatestRelease.fetchReleaseFromFSAndUpdateMain(); + }, fetchLatestRelease.fetchReleaseFromFileServerInterval); +} diff --git a/ts/session/fetch_latest_release/index.ts b/ts/session/fetch_latest_release/index.ts new file mode 100644 index 000000000..0ecbe7cb8 --- /dev/null +++ b/ts/session/fetch_latest_release/index.ts @@ -0,0 +1,55 @@ +// every 1 minute we fetch from the fileserver to check for a new release +// * if there is none, no request to github are made. +// * if there is a version on the fileserver more recent than our current, we fetch github to get the UpdateInfos and trigger an update as usual (asking user via dialog) + +import { isEmpty, isString } from 'lodash'; +import { ipcRenderer } from 'electron'; +import { DURATION } from '../constants'; +import { getLatestReleaseFromFileServer } from '../apis/file_server_api/FileServerApi'; + +/** + * Try to fetch the latest release from the fileserver every 1 minute. + * If we did fetch a release already in the last 30 minutes, we will skip the call. + */ +const fetchReleaseFromFileServerInterval = DURATION.MINUTES * 1; + +/** + * We don't want to hit the fileserver too often. Only often on start, and then every 30 minutes + */ +const skipIfLessThan = DURATION.MINUTES * 30; + +let lastFetchedTimestamp = Number.MIN_SAFE_INTEGER; + +function resetForTesting() { + lastFetchedTimestamp = Number.MIN_SAFE_INTEGER; +} + +async function fetchReleaseFromFSAndUpdateMain() { + try { + window.log.info('[updater] about to fetchReleaseFromFSAndUpdateMain'); + const diff = Date.now() - lastFetchedTimestamp; + if (diff < skipIfLessThan) { + window.log.info( + `[updater] fetched release from fs ${Math.floor(diff / DURATION.MINUTES)}minutes ago, skipping until that's at least ${Math.floor(skipIfLessThan / DURATION.MINUTES)}` + ); + return; + } + + const justFetched = await getLatestReleaseFromFileServer(); + window.log.info('[updater] fetched latest release from fileserver: ', justFetched); + + if (isString(justFetched) && !isEmpty(justFetched)) { + lastFetchedTimestamp = Date.now(); + ipcRenderer.send('set-release-from-file-server', justFetched); + window.readyForUpdates(); + } + } catch (e) { + window.log.warn(e); + } +} + +export const fetchLatestRelease = { + fetchReleaseFromFileServerInterval, + fetchReleaseFromFSAndUpdateMain, + resetForTesting, +}; From a72e9c9b2fcfd252898586187021f0b369b176cb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 26 Jul 2024 15:47:18 +1000 Subject: [PATCH 3/4] chore: dedup yarn.lock --- yarn.lock | 59 ++++++++++++++++++------------------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/yarn.lock b/yarn.lock index e5f576610..f965aa8ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2019,15 +2019,7 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react@*", "@types/react@17.0.2", "@types/react@^17": - version "17.0.2" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" - integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/react@^17.0.2": +"@types/react@*", "@types/react@^17", "@types/react@^17.0.2": version "17.0.65" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.65.tgz#95f6a2ab61145ffb69129d07982d047f9e0870cd" integrity sha512-oxur785xZYHvnI7TRS61dXbkIhDPnGfsXKv0cNXR/0ml4SipRIFpSMzA7HMEfOywFwJ5AOnPrXYTEiTRUQeGlQ== @@ -2036,6 +2028,14 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@17.0.2": + version "17.0.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.2.tgz#3de24c4efef902dd9795a49c75f760cbe4f7a5a8" + integrity sha512-Xt40xQsrkdvjn1EyWe1Bc0dJLcil/9x2vAuW7ya+PuQip4UYUaXyhzWmAbwRsdMgwOFHpfp7/FFZebDU6Y8VHA== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/redux-logger@3.0.7": version "3.0.7" resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.7.tgz#163f6f6865c69c21d56f9356dc8d741718ec0db0" @@ -3905,7 +3905,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3919,13 +3926,6 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -5128,16 +5128,7 @@ fs-extra@^10.0.0, fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^11.0.0: - version "11.1.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" - integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^11.2.0: +fs-extra@^11.0.0, fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -9588,19 +9579,7 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.1.0, tar@^6.1.11: - version "6.2.0" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" - integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -tar@^6.2.0: +tar@^6.1.0, tar@^6.1.11, tar@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== From 4bb857fa530c5d98111d60a8e001da6f51594e52 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 31 Jul 2024 11:36:43 +1000 Subject: [PATCH 4/4] fix: update fetching desktop release endpoint --- package.json | 2 +- .../useFetchLatestReleaseFromFileServer.ts | 11 +++-- ts/ip2country.d.ts | 1 - .../apis/file_server_api/FileServerApi.ts | 22 +++++++++- ts/session/apis/snode_api/getNetworkTime.ts | 7 ++++ .../crypto/DecryptedAttachmentsManager.ts | 3 +- ts/session/fetch_latest_release/index.ts | 16 ++++---- .../browser/libsession_worker_functions.d.ts | 4 +- .../browser/libsession_worker_interface.ts | 12 ++++++ .../node/libsession/libsession.worker.ts | 40 ++++++++++++++----- yarn.lock | 18 ++++----- 11 files changed, 100 insertions(+), 36 deletions(-) delete mode 100644 ts/ip2country.d.ts diff --git a/package.json b/package.json index d9a439abd..66baf1792 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "fs-extra": "9.0.0", "glob": "7.1.2", "image-type": "^4.1.0", - "libsession_util_nodejs": "https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.19/libsession_util_nodejs-v0.3.19.tar.gz", + "libsession_util_nodejs": "https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.21/libsession_util_nodejs-v0.3.21.tar.gz", "libsodium-wrappers-sumo": "^0.7.9", "linkify-it": "^4.0.1", "lodash": "^4.17.21", diff --git a/ts/hooks/useFetchLatestReleaseFromFileServer.ts b/ts/hooks/useFetchLatestReleaseFromFileServer.ts index 4766954e5..d699db589 100644 --- a/ts/hooks/useFetchLatestReleaseFromFileServer.ts +++ b/ts/hooks/useFetchLatestReleaseFromFileServer.ts @@ -1,15 +1,20 @@ +import { isEmpty } from 'lodash'; import { useSelector } from 'react-redux'; import useInterval from 'react-use/lib/useInterval'; -import { getOurPrimaryConversation } from '../state/selectors/conversations'; import { fetchLatestRelease } from '../session/fetch_latest_release'; +import { UserUtils } from '../session/utils'; +import { getOurPrimaryConversation } from '../state/selectors/conversations'; export function useFetchLatestReleaseFromFileServer() { const ourPrimaryConversation = useSelector(getOurPrimaryConversation); - useInterval(() => { + useInterval(async () => { if (!ourPrimaryConversation) { return; } - void fetchLatestRelease.fetchReleaseFromFSAndUpdateMain(); + const userEd25519SecretKey = (await UserUtils.getUserED25519KeyPairBytes())?.privKeyBytes; + if (userEd25519SecretKey && !isEmpty(userEd25519SecretKey)) { + void fetchLatestRelease.fetchReleaseFromFSAndUpdateMain(userEd25519SecretKey); + } }, fetchLatestRelease.fetchReleaseFromFileServerInterval); } diff --git a/ts/ip2country.d.ts b/ts/ip2country.d.ts deleted file mode 100644 index 6c4567906..000000000 --- a/ts/ip2country.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'ip2country'; diff --git a/ts/session/apis/file_server_api/FileServerApi.ts b/ts/session/apis/file_server_api/FileServerApi.ts index eb47c164d..67b5e079a 100644 --- a/ts/session/apis/file_server_api/FileServerApi.ts +++ b/ts/session/apis/file_server_api/FileServerApi.ts @@ -1,9 +1,12 @@ import AbortController from 'abort-controller'; +import { BlindingActions } from '../../../webworker/workers/browser/libsession_worker_interface'; import { OnionSending, OnionV4JSONSnodeResponse } from '../../onions/onionSend'; import { batchGlobalIsSuccess, parseBatchGlobalStatusCode, } from '../open_group_api/sogsv3/sogsV3BatchPoll'; +import { GetNetworkTime } from '../snode_api/getNetworkTime'; +import { fromUInt8ArrayToBase64 } from '../../utils/String'; export const fileServerHost = 'filev2.getsession.org'; export const fileServerURL = `http://${fileServerHost}`; @@ -123,12 +126,27 @@ const parseStatusCodeFromOnionRequestV4 = ( * Fetch the latest desktop release available on github from the fileserver. * This call is onion routed and so do not expose our ip to github nor the file server. */ -export const getLatestReleaseFromFileServer = async (): Promise => { +export const getLatestReleaseFromFileServer = async ( + userEd25519SecretKey: Uint8Array +): Promise => { + const sigTimestampSeconds = GetNetworkTime.getNowWithNetworkOffsetSeconds(); + const blindedPkHex = await BlindingActions.blindVersionPubkey({ + ed25519SecretKey: userEd25519SecretKey, + }); + const signature = await BlindingActions.blindVersionSign({ + ed25519SecretKey: userEd25519SecretKey, + sigTimestampSeconds, + }); + const body = { + 'X-FS-Pubkey': blindedPkHex, + 'X-FS-Timestamp': `${sigTimestampSeconds}`, + 'X-FS-Signature': fromUInt8ArrayToBase64(signature), + }; const result = await OnionSending.sendJsonViaOnionV4ToFileServer({ abortSignal: new AbortController().signal, endpoint: RELEASE_VERSION_ENDPOINT, method: 'GET', - stringifiedBody: null, + stringifiedBody: JSON.stringify(body), }); if (!batchGlobalIsSuccess(result) || parseStatusCodeFromOnionRequestV4(result) !== 200) { diff --git a/ts/session/apis/snode_api/getNetworkTime.ts b/ts/session/apis/snode_api/getNetworkTime.ts index 086d849b6..8f5786f7b 100644 --- a/ts/session/apis/snode_api/getNetworkTime.ts +++ b/ts/session/apis/snode_api/getNetworkTime.ts @@ -70,9 +70,16 @@ function getNowWithNetworkOffset() { return Date.now() - GetNetworkTime.getLatestTimestampOffset(); } +function getNowWithNetworkOffsetSeconds() { + // make sure to call exports here, as we stub the exported one for testing. + + return Math.floor(GetNetworkTime.getNowWithNetworkOffset() / 1000); +} + export const GetNetworkTime = { getNetworkTime, handleTimestampOffsetFromNetwork, + getNowWithNetworkOffsetSeconds, getLatestTimestampOffset, getNowWithNetworkOffset, }; diff --git a/ts/session/crypto/DecryptedAttachmentsManager.ts b/ts/session/crypto/DecryptedAttachmentsManager.ts index 57b0ad57f..b8567a00e 100644 --- a/ts/session/crypto/DecryptedAttachmentsManager.ts +++ b/ts/session/crypto/DecryptedAttachmentsManager.ts @@ -93,6 +93,8 @@ export const getDecryptedMediaUrl = async ( // we consider the file is encrypted. // if it's not, the hook caller has to fallback to setting the img src as an url to the file instead and load it if (urlToDecryptedBlobMap.has(url)) { + // typescript does not realize that the `has()` above makes sure the `get()` is not undefined + // refresh the last access timestamp so we keep the one being currently in use const existing = urlToDecryptedBlobMap.get(url); const existingObjUrl = existing?.decrypted as string; @@ -102,7 +104,6 @@ export const getDecryptedMediaUrl = async ( lastAccessTimestamp: Date.now(), forceRetain: existing?.forceRetain || false, }); - // typescript does not realize that the has above makes sure the get is not undefined return existingObjUrl; } diff --git a/ts/session/fetch_latest_release/index.ts b/ts/session/fetch_latest_release/index.ts index 0ecbe7cb8..f11c53ea9 100644 --- a/ts/session/fetch_latest_release/index.ts +++ b/ts/session/fetch_latest_release/index.ts @@ -7,12 +7,6 @@ import { ipcRenderer } from 'electron'; import { DURATION } from '../constants'; import { getLatestReleaseFromFileServer } from '../apis/file_server_api/FileServerApi'; -/** - * Try to fetch the latest release from the fileserver every 1 minute. - * If we did fetch a release already in the last 30 minutes, we will skip the call. - */ -const fetchReleaseFromFileServerInterval = DURATION.MINUTES * 1; - /** * We don't want to hit the fileserver too often. Only often on start, and then every 30 minutes */ @@ -24,7 +18,7 @@ function resetForTesting() { lastFetchedTimestamp = Number.MIN_SAFE_INTEGER; } -async function fetchReleaseFromFSAndUpdateMain() { +async function fetchReleaseFromFSAndUpdateMain(userEd25519SecretKey: Uint8Array) { try { window.log.info('[updater] about to fetchReleaseFromFSAndUpdateMain'); const diff = Date.now() - lastFetchedTimestamp; @@ -35,7 +29,7 @@ async function fetchReleaseFromFSAndUpdateMain() { return; } - const justFetched = await getLatestReleaseFromFileServer(); + const justFetched = await getLatestReleaseFromFileServer(userEd25519SecretKey); window.log.info('[updater] fetched latest release from fileserver: ', justFetched); if (isString(justFetched) && !isEmpty(justFetched)) { @@ -49,7 +43,11 @@ async function fetchReleaseFromFSAndUpdateMain() { } export const fetchLatestRelease = { - fetchReleaseFromFileServerInterval, + /** + * Try to fetch the latest release from the fileserver every 1 minute. + * If we did fetch a release already in the last 30 minutes, we will skip the call. + */ + fetchReleaseFromFileServerInterval: DURATION.MINUTES * 1, fetchReleaseFromFSAndUpdateMain, resetForTesting, }; diff --git a/ts/webworker/workers/browser/libsession_worker_functions.d.ts b/ts/webworker/workers/browser/libsession_worker_functions.d.ts index 4cb004816..bdcd0e74b 100644 --- a/ts/webworker/workers/browser/libsession_worker_functions.d.ts +++ b/ts/webworker/workers/browser/libsession_worker_functions.d.ts @@ -30,9 +30,11 @@ type UserGroupsConfigFunctions = type ConvoInfoVolatileConfigFunctions = | [ConvoInfoVolatileConfig, ...BaseConfigActions] | [ConvoInfoVolatileConfig, ...ConvoInfoVolatileConfigActionsType]; +type BlindingFunctions = ['Blinding', ...BlindingFunctions]; export type LibSessionWorkerFunctions = | UserConfigFunctions | ContactsConfigFunctions | UserGroupsConfigFunctions - | ConvoInfoVolatileConfigFunctions; + | ConvoInfoVolatileConfigFunctions + | BlindingFunctions; diff --git a/ts/webworker/workers/browser/libsession_worker_interface.ts b/ts/webworker/workers/browser/libsession_worker_interface.ts index b9476dd4b..4cb078d70 100644 --- a/ts/webworker/workers/browser/libsession_worker_interface.ts +++ b/ts/webworker/workers/browser/libsession_worker_interface.ts @@ -2,6 +2,7 @@ /* eslint-disable import/no-unresolved */ import { BaseWrapperActionsCalls, + BlindingActionsCalls, ContactInfoSet, ContactsWrapperActionsCalls, ConvoInfoVolatileWrapperActionsCalls, @@ -343,6 +344,17 @@ export const ConvoInfoVolatileWrapperActions: ConvoInfoVolatileWrapperActionsCal ]) as Promise>, }; +export const BlindingActions: BlindingActionsCalls = { + blindVersionPubkey: async (opts: { ed25519SecretKey: Uint8Array }) => + callLibSessionWorker(['Blinding', 'blindVersionPubkey', opts]) as Promise< + ReturnType + >, + blindVersionSign: async (opts: { ed25519SecretKey: Uint8Array; sigTimestampSeconds: number }) => + callLibSessionWorker(['Blinding', 'blindVersionSign', opts]) as Promise< + ReturnType + >, +}; + export const callLibSessionWorker = async ( callToMake: LibSessionWorkerFunctions ): Promise => { diff --git a/ts/webworker/workers/node/libsession/libsession.worker.ts b/ts/webworker/workers/node/libsession/libsession.worker.ts index 75100a511..9d3b6146b 100644 --- a/ts/webworker/workers/node/libsession/libsession.worker.ts +++ b/ts/webworker/workers/node/libsession/libsession.worker.ts @@ -3,6 +3,7 @@ import { isEmpty, isNull } from 'lodash'; import { BaseConfigWrapperNode, + BlindingWrapperNode, ContactsConfigWrapperNode, ConvoInfoVolatileWrapperNode, UserConfigWrapperNode, @@ -55,6 +56,7 @@ function getCorrespondingWrapper(wrapperType: ConfigWrapperObjectTypes): BaseCon throw new Error(`${wrapperType} is not init yet`); } return wrapper; + default: assertUnreachable( wrapperType, @@ -119,24 +121,44 @@ function initUserWrapper(options: Array, wrapperType: ConfigWrapperObjectTy } } -onmessage = async (e: { data: [number, ConfigWrapperObjectTypes, string, ...any] }) => { +onmessage = async (e: { + data: [number, ConfigWrapperObjectTypes | 'Blinding', string, ...any]; +}) => { const [jobId, config, action, ...args] = e.data; try { if (action === 'init') { - initUserWrapper(args, config); + if (config === 'Blinding') { + // nothing to do for the blinding wrapper, all functions are static + } else { + initUserWrapper(args, config); + } postMessage([jobId, null, null]); return; } - const wrapper = getCorrespondingWrapper(config); - const fn = (wrapper as any)[action]; - if (!fn) { - throw new Error( - `Worker: job "${jobId}" did not find function "${action}" on config "${config}"` - ); + let result: any; + + if (config === 'Blinding') { + const fn = (BlindingWrapperNode as any)[action]; + + if (!fn) { + throw new Error( + `Worker: job "${jobId}" did not find function "${action}" on wrapper "${config}"` + ); + } + result = await (BlindingWrapperNode as any)[action](...args); + } else { + const wrapper = getCorrespondingWrapper(config); + const fn = (wrapper as any)[action]; + + if (!fn) { + throw new Error( + `Worker: job "${jobId}" did not find function "${action}" on config "${config}"` + ); + } + result = await (wrapper as any)[action](...args); } - const result = await (wrapper as any)[action](...args); postMessage([jobId, null, result]); } catch (error) { const errorForDisplay = prepareErrorForPostMessage(error); diff --git a/yarn.lock b/yarn.lock index f965aa8ae..005709bf0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3906,9 +3906,9 @@ debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: ms "2.0.0" debug@4, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== dependencies: ms "2.1.2" @@ -6533,9 +6533,9 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -"libsession_util_nodejs@https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.19/libsession_util_nodejs-v0.3.19.tar.gz": - version "0.3.19" - resolved "https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.19/libsession_util_nodejs-v0.3.19.tar.gz#221c1fc34fcc18601aea4ce1b733ebfa55af66ea" +"libsession_util_nodejs@https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.21/libsession_util_nodejs-v0.3.21.tar.gz": + version "0.3.21" + resolved "https://github.com/oxen-io/libsession-util-nodejs/releases/download/v0.3.21/libsession_util_nodejs-v0.3.21.tar.gz#64705b1f7c934ca32f929ea8127370cc82bab97a" dependencies: cmake-js "^7.2.1" node-addon-api "^6.1.0" @@ -7401,9 +7401,9 @@ node-addon-api@^6.1.0: integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== node-api-headers@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-1.1.0.tgz#3f9dd7bb10b29e1c3e3db675979605a308b2373c" - integrity sha512-ucQW+SbYCUPfprvmzBsnjT034IGRB2XK8rRc78BgjNKhTdFKgAwAmgW704bKIBmcYW48it0Gkjpkd39Azrwquw== + version "1.2.0" + resolved "https://registry.yarnpkg.com/node-api-headers/-/node-api-headers-1.2.0.tgz#b717cd420aec79031f8dc83a50eb0a8bdf24c70d" + integrity sha512-L9AiEkBfgupC0D/LsudLPOhzy/EdObsp+FHyL1zSK0kKv5FDA9rJMoRz8xd+ojxzlqfg0tTZm2h8ot2nS7bgRA== node-dir@^0.1.17: version "0.1.17"