mirror of
https://github.com/tlsnotary/tlsn-extension.git
synced 2026-01-09 13:08:04 -05:00
Compare commits
7 Commits
0.1.0.1000
...
p2p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe56de0b6c | ||
|
|
0a4f152cea | ||
|
|
855ab19b04 | ||
|
|
1021200fca | ||
|
|
00cae21dd9 | ||
|
|
b3e9a56dd9 | ||
|
|
f550001580 |
@@ -6,7 +6,7 @@
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
transition: 200ms opacity;
|
||||
|
||||
transition-delay: 200ms;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
@@ -12,7 +12,11 @@ import {
|
||||
runPlugin,
|
||||
} from '../../utils/rpc';
|
||||
import { usePluginHashes } from '../../reducers/plugins';
|
||||
import { PluginConfig } from '../../utils/misc';
|
||||
import {
|
||||
getPluginConfig,
|
||||
hexToArrayBuffer,
|
||||
PluginConfig,
|
||||
} from '../../utils/misc';
|
||||
import DefaultPluginIcon from '../../assets/img/default-plugin-icon.png';
|
||||
import classNames from 'classnames';
|
||||
import Icon from '../Icon';
|
||||
@@ -25,8 +29,19 @@ import {
|
||||
PluginInfoModalHeader,
|
||||
} from '../PluginInfo';
|
||||
import { getPluginConfigByHash } from '../../entries/Background/db';
|
||||
import { OffscreenActionTypes } from '../../entries/Offscreen/types';
|
||||
import { SidePanelActionTypes } from '../../entries/SidePanel/types';
|
||||
import { openSidePanel } from '../../entries/utils';
|
||||
|
||||
export function PluginList(props: { className?: string }): ReactElement {
|
||||
export function PluginList({
|
||||
className,
|
||||
unremovable,
|
||||
onClick,
|
||||
}: {
|
||||
className?: string;
|
||||
unremovable?: boolean;
|
||||
onClick?: (hash: string) => void;
|
||||
}): ReactElement {
|
||||
const hashes = usePluginHashes();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -34,65 +49,85 @@ export function PluginList(props: { className?: string }): ReactElement {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('flex flex-col flex-nowrap gap-1', props.className)}
|
||||
>
|
||||
<div className={classNames('flex flex-col flex-nowrap gap-1', className)}>
|
||||
{!hashes.length && (
|
||||
<div className="flex flex-col items-center justify-center text-slate-400 cursor-default select-none">
|
||||
<div>No available plugins</div>
|
||||
</div>
|
||||
)}
|
||||
{hashes.map((hash) => (
|
||||
<Plugin key={hash} hash={hash} />
|
||||
<Plugin
|
||||
key={hash}
|
||||
hash={hash}
|
||||
unremovable={unremovable}
|
||||
onClick={onClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Plugin(props: {
|
||||
export function Plugin({
|
||||
hash,
|
||||
hex,
|
||||
unremovable,
|
||||
onClick,
|
||||
className,
|
||||
}: {
|
||||
hash: string;
|
||||
onClick?: () => void;
|
||||
hex?: string;
|
||||
className?: string;
|
||||
onClick?: (hash: string) => void;
|
||||
unremovable?: boolean;
|
||||
}): ReactElement {
|
||||
const [error, showError] = useState('');
|
||||
const [config, setConfig] = useState<PluginConfig | null>(null);
|
||||
const [pluginInfo, showPluginInfo] = useState(false);
|
||||
const [remove, showRemove] = useState(false);
|
||||
|
||||
const onClick = useCallback(async () => {
|
||||
const onRunPlugin = useCallback(async () => {
|
||||
if (!config || remove) return;
|
||||
|
||||
try {
|
||||
await runPlugin(props.hash, 'start');
|
||||
if (onClick) {
|
||||
onClick(hash);
|
||||
return;
|
||||
}
|
||||
|
||||
const [tab] = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
try {
|
||||
await openSidePanel();
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: SidePanelActionTypes.execute_plugin_request,
|
||||
data: {
|
||||
pluginHash: hash,
|
||||
},
|
||||
});
|
||||
|
||||
await browser.storage.local.set({ plugin_hash: props.hash });
|
||||
|
||||
// @ts-ignore
|
||||
if (chrome.sidePanel) await chrome.sidePanel.open({ tabId: tab.id });
|
||||
await runPlugin(hash, 'start');
|
||||
|
||||
window.close();
|
||||
} catch (e: any) {
|
||||
showError(e.message);
|
||||
}
|
||||
}, [props.hash, config, remove]);
|
||||
}, [hash, config, remove, onClick]);
|
||||
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
setConfig(await getPluginConfigByHash(props.hash));
|
||||
if (hex) {
|
||||
setConfig(await getPluginConfig(hexToArrayBuffer(hex)));
|
||||
} else {
|
||||
setConfig(await getPluginConfigByHash(hash));
|
||||
}
|
||||
})();
|
||||
}, [props.hash]);
|
||||
}, [hash, hex]);
|
||||
|
||||
const onRemove: MouseEventHandler = useCallback(
|
||||
(e) => {
|
||||
e.stopPropagation();
|
||||
removePlugin(props.hash);
|
||||
removePlugin(hash);
|
||||
showRemove(false);
|
||||
},
|
||||
[props.hash, remove],
|
||||
[hash, remove],
|
||||
);
|
||||
|
||||
const onConfirmRemove: MouseEventHandler = useCallback(
|
||||
@@ -100,7 +135,7 @@ export function Plugin(props: {
|
||||
e.stopPropagation();
|
||||
showRemove(true);
|
||||
},
|
||||
[props.hash, remove],
|
||||
[hash, remove],
|
||||
);
|
||||
|
||||
const onPluginInfo: MouseEventHandler = useCallback(
|
||||
@@ -108,7 +143,7 @@ export function Plugin(props: {
|
||||
e.stopPropagation();
|
||||
showPluginInfo(true);
|
||||
},
|
||||
[props.hash, pluginInfo],
|
||||
[hash, pluginInfo],
|
||||
);
|
||||
|
||||
if (!config) return <></>;
|
||||
@@ -118,8 +153,9 @@ export function Plugin(props: {
|
||||
className={classNames(
|
||||
'flex flex-row justify-center border rounded border-slate-300 p-2 gap-2 plugin-box',
|
||||
'cursor-pointer hover:bg-slate-100 hover:border-slate-400 active:bg-slate-200',
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
onClick={onRunPlugin}
|
||||
>
|
||||
{!!error && <ErrorModal onClose={() => showError('')} message={error} />}
|
||||
{!remove ? (
|
||||
@@ -134,11 +170,13 @@ export function Plugin(props: {
|
||||
className="flex flex-row items-center justify-center cursor-pointer plugin-box__remove-icon"
|
||||
onClick={onPluginInfo}
|
||||
/>
|
||||
<Icon
|
||||
fa="fa-solid fa-xmark"
|
||||
className="flex flex-row items-center justify-center cursor-pointer text-red-500 bg-red-200 rounded-full plugin-box__remove-icon"
|
||||
onClick={onConfirmRemove}
|
||||
/>
|
||||
{!unremovable && (
|
||||
<Icon
|
||||
fa="fa-solid fa-xmark"
|
||||
className="flex flex-row items-center justify-center cursor-pointer text-red-500 bg-red-200 rounded-full plugin-box__remove-icon"
|
||||
onClick={onConfirmRemove}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>{config.description}</div>
|
||||
|
||||
@@ -41,11 +41,31 @@ import {
|
||||
getMaxSent,
|
||||
getNotaryApi,
|
||||
getProxyApi,
|
||||
getRendezvousApi,
|
||||
} from '../../utils/storage';
|
||||
import { deferredPromise } from '../../utils/promise';
|
||||
import { minimatch } from 'minimatch';
|
||||
import { OffscreenActionTypes } from '../Offscreen/types';
|
||||
import { SidePanelActionTypes } from '../SidePanel/types';
|
||||
import { pushToRedux } from '../utils';
|
||||
import {
|
||||
acceptPairRequest,
|
||||
cancelPairRequest,
|
||||
connectSession,
|
||||
disconnectSession,
|
||||
getP2PState,
|
||||
rejectPairRequest,
|
||||
requestProofByHash,
|
||||
requestProof,
|
||||
sendPairRequest,
|
||||
cancelProofRequest,
|
||||
acceptProofRequest,
|
||||
rejectProofRequest,
|
||||
startProofRequest,
|
||||
startedVerifier,
|
||||
startedProver,
|
||||
endProofRequest,
|
||||
} from './ws';
|
||||
|
||||
const charwise = require('charwise');
|
||||
|
||||
@@ -54,6 +74,7 @@ export enum BackgroundActiontype {
|
||||
clear_requests = 'clear_requests',
|
||||
push_action = 'push_action',
|
||||
execute_plugin_prover = 'execute_plugin_prover',
|
||||
execute_p2p_plugin_prover = 'execute_p2p_plugin_prover',
|
||||
get_prove_requests = 'get_prove_requests',
|
||||
prove_request_start = 'prove_request_start',
|
||||
process_prove_request = 'process_prove_request',
|
||||
@@ -64,12 +85,15 @@ export enum BackgroundActiontype {
|
||||
retry_prove_request = 'retry_prove_request',
|
||||
get_cookies_by_hostname = 'get_cookies_by_hostname',
|
||||
get_headers_by_hostname = 'get_headers_by_hostname',
|
||||
// Plugins
|
||||
add_plugin = 'add_plugin',
|
||||
remove_plugin = 'remove_plugin',
|
||||
get_plugin_by_hash = 'get_plugin_by_hash',
|
||||
read_plugin_config = 'read_plugin_config',
|
||||
get_plugin_config_by_hash = 'get_plugin_config_by_hash',
|
||||
run_plugin = 'run_plugin',
|
||||
get_plugin_hashes = 'get_plugin_hashes',
|
||||
// Content Script
|
||||
open_popup = 'open_popup',
|
||||
change_route = 'change_route',
|
||||
connect_request = 'connect_request',
|
||||
@@ -86,9 +110,27 @@ export enum BackgroundActiontype {
|
||||
get_plugins_response = 'get_plugins_response',
|
||||
run_plugin_request = 'run_plugin_request',
|
||||
run_plugin_response = 'run_plugin_response',
|
||||
// App State
|
||||
get_logging_level = 'get_logging_level',
|
||||
get_app_state = 'get_app_state',
|
||||
set_default_plugins_installed = 'set_default_plugins_installed',
|
||||
// P2P
|
||||
connect_rendezvous = 'connect_rendezvous',
|
||||
disconnect_rendezvous = 'disconnect_rendezvous',
|
||||
send_pair_request = 'send_pair_request',
|
||||
cancel_pair_request = 'cancel_pair_request',
|
||||
accept_pair_request = 'accept_pair_request',
|
||||
reject_pair_request = 'reject_pair_request',
|
||||
cancel_proof_request = 'cancel_proof_request',
|
||||
accept_proof_request = 'accept_proof_request',
|
||||
reject_proof_request = 'reject_proof_request',
|
||||
start_proof_request = 'start_proof_request',
|
||||
proof_request_end = 'proof_request_end',
|
||||
verifier_started = 'verifier_started',
|
||||
prover_started = 'prover_started',
|
||||
get_p2p_state = 'get_p2p_state',
|
||||
request_p2p_proof = 'request_p2p_proof',
|
||||
request_p2p_proof_by_hash = 'request_p2p_proof_by_hash',
|
||||
}
|
||||
|
||||
export type BackgroundAction = {
|
||||
@@ -171,12 +213,17 @@ export const initRPC = () => {
|
||||
return handleGetPluginHashes(request, sendResponse);
|
||||
case BackgroundActiontype.get_plugin_by_hash:
|
||||
return handleGetPluginByHash(request, sendResponse);
|
||||
case BackgroundActiontype.read_plugin_config:
|
||||
getPluginConfig(request.data).then(sendResponse);
|
||||
return true;
|
||||
case BackgroundActiontype.get_plugin_config_by_hash:
|
||||
return handleGetPluginConfigByHash(request, sendResponse);
|
||||
case BackgroundActiontype.run_plugin:
|
||||
return handleRunPlugin(request, sendResponse);
|
||||
case BackgroundActiontype.execute_plugin_prover:
|
||||
return handleExecPluginProver(request);
|
||||
case BackgroundActiontype.execute_p2p_plugin_prover:
|
||||
return handleExecP2PPluginProver(request);
|
||||
case BackgroundActiontype.open_popup:
|
||||
return handleOpenPopup(request);
|
||||
case BackgroundActiontype.connect_request:
|
||||
@@ -202,6 +249,54 @@ export const initRPC = () => {
|
||||
case BackgroundActiontype.set_default_plugins_installed:
|
||||
setDefaultPluginsInstalled(request.data).then(sendResponse);
|
||||
return true;
|
||||
case BackgroundActiontype.connect_rendezvous:
|
||||
connectSession().then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.disconnect_rendezvous:
|
||||
disconnectSession().then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.send_pair_request:
|
||||
sendPairRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.cancel_pair_request:
|
||||
cancelPairRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.accept_pair_request:
|
||||
acceptPairRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.reject_pair_request:
|
||||
rejectPairRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.cancel_proof_request:
|
||||
cancelProofRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.accept_proof_request:
|
||||
acceptProofRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.reject_proof_request:
|
||||
rejectProofRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.start_proof_request:
|
||||
startProofRequest(request.data.pluginHash).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.proof_request_end:
|
||||
endProofRequest(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.verifier_started:
|
||||
startedVerifier(request.data.pluginHash).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.prover_started:
|
||||
startedProver(request.data.pluginHash).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.request_p2p_proof:
|
||||
requestProof(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.request_p2p_proof_by_hash:
|
||||
requestProofByHash(request.data).then(sendResponse);
|
||||
return;
|
||||
case BackgroundActiontype.get_p2p_state:
|
||||
getP2PState();
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -226,13 +321,7 @@ function handleGetProveRequests(
|
||||
): boolean {
|
||||
getNotaryRequests().then(async (reqs) => {
|
||||
for (const req of reqs) {
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(req),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(req));
|
||||
}
|
||||
sendResponse(reqs);
|
||||
});
|
||||
@@ -250,39 +339,21 @@ async function handleFinishProveRequest(
|
||||
const newReq = await addNotaryRequestProofs(id, proof);
|
||||
if (!newReq) return;
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(await getNotaryRequest(id)),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(await getNotaryRequest(id)));
|
||||
}
|
||||
|
||||
if (error) {
|
||||
const newReq = await setNotaryRequestError(id, error);
|
||||
if (!newReq) return;
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(await getNotaryRequest(id)),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(await getNotaryRequest(id)));
|
||||
}
|
||||
|
||||
if (verification) {
|
||||
const newReq = await setNotaryRequestVerification(id, verification);
|
||||
if (!newReq) return;
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(await getNotaryRequest(id)),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(await getNotaryRequest(id)));
|
||||
}
|
||||
|
||||
return sendResponse();
|
||||
@@ -299,13 +370,7 @@ async function handleRetryProveReqest(
|
||||
|
||||
const req = await getNotaryRequest(id);
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(req),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(req));
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.process_prove_request,
|
||||
@@ -353,13 +418,7 @@ async function handleProveRequestStart(
|
||||
|
||||
await setNotaryRequestStatus(id, 'pending');
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(await getNotaryRequest(id)),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(await getNotaryRequest(id)));
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.process_prove_request,
|
||||
@@ -417,13 +476,7 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) {
|
||||
|
||||
await setNotaryRequestStatus(id, 'pending');
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addRequestHistory(await getNotaryRequest(id)),
|
||||
});
|
||||
await pushToRedux(addRequestHistory(await getNotaryRequest(id)));
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.process_prove_request,
|
||||
@@ -444,6 +497,44 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) {
|
||||
});
|
||||
}
|
||||
|
||||
async function runP2PPluginProver(request: BackgroundAction, now = Date.now()) {
|
||||
const {
|
||||
pluginHash,
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
secretHeaders,
|
||||
secretResps,
|
||||
websocketProxyUrl: _websocketProxyUrl,
|
||||
maxSentData: _maxSentData,
|
||||
maxRecvData: _maxRecvData,
|
||||
clientId,
|
||||
} = request.data;
|
||||
const rendezvousApi = await getRendezvousApi();
|
||||
const proverUrl = `${rendezvousApi}?clientId=${clientId}:proof`;
|
||||
const websocketProxyUrl = _websocketProxyUrl || (await getProxyApi());
|
||||
const maxSentData = _maxSentData || (await getMaxSent());
|
||||
const maxRecvData = _maxRecvData || (await getMaxRecv());
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: OffscreenActionTypes.start_p2p_prover,
|
||||
data: {
|
||||
pluginHash,
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
proverUrl,
|
||||
websocketProxyUrl,
|
||||
maxRecvData,
|
||||
maxSentData,
|
||||
secretHeaders,
|
||||
secretResps,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function handleExecPluginProver(request: BackgroundAction) {
|
||||
const now = request.data.now;
|
||||
const id = charwise.encode(now).toString('hex');
|
||||
@@ -451,6 +542,13 @@ export async function handleExecPluginProver(request: BackgroundAction) {
|
||||
return id;
|
||||
}
|
||||
|
||||
export async function handleExecP2PPluginProver(request: BackgroundAction) {
|
||||
const now = request.data.now;
|
||||
const id = charwise.encode(now).toString('hex');
|
||||
runP2PPluginProver(request, now);
|
||||
return id;
|
||||
}
|
||||
|
||||
function handleGetCookiesByHostname(
|
||||
request: BackgroundAction,
|
||||
sendResponse: (data?: any) => void,
|
||||
@@ -486,13 +584,7 @@ async function handleAddPlugin(
|
||||
if (hash) {
|
||||
await addPluginConfig(hash, config);
|
||||
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addOnePlugin(hash),
|
||||
});
|
||||
await pushToRedux(addOnePlugin(hash));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -506,13 +598,7 @@ async function handleRemovePlugin(
|
||||
) {
|
||||
await removePlugin(request.data);
|
||||
await removePluginConfig(request.data);
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: removeOnePlugin(request.data),
|
||||
});
|
||||
await pushToRedux(removeOnePlugin(request.data));
|
||||
|
||||
return sendResponse();
|
||||
}
|
||||
@@ -523,13 +609,7 @@ async function handleGetPluginHashes(
|
||||
) {
|
||||
const hashes = await getPluginHashes();
|
||||
for (const hash of hashes) {
|
||||
await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action: addOnePlugin(hash),
|
||||
});
|
||||
await pushToRedux(addOnePlugin(hash));
|
||||
}
|
||||
return sendResponse();
|
||||
}
|
||||
@@ -557,11 +637,11 @@ function handleRunPlugin(
|
||||
sendResponse: (data?: any) => void,
|
||||
) {
|
||||
(async () => {
|
||||
const { hash, method, params } = request.data;
|
||||
const { hash, method, params, meta } = request.data;
|
||||
const hex = await getPluginByHash(hash);
|
||||
const arrayBuffer = hexToArrayBuffer(hex!);
|
||||
const config = await getPluginConfig(arrayBuffer);
|
||||
const plugin = await makePlugin(arrayBuffer, config);
|
||||
const plugin = await makePlugin(arrayBuffer, config, meta?.p2p);
|
||||
devlog(`plugin::${method}`, params);
|
||||
const out = await plugin.call(method, params);
|
||||
devlog(`plugin response: `, out.string());
|
||||
@@ -1059,7 +1139,6 @@ async function handleRunPluginCSRequest(request: BackgroundAction) {
|
||||
);
|
||||
|
||||
const onPluginRequest = async (req: any) => {
|
||||
console.log(req);
|
||||
if (req.type !== SidePanelActionTypes.execute_plugin_response) return;
|
||||
if (req.data.hash !== hash) return;
|
||||
|
||||
|
||||
584
src/entries/Background/ws.ts
Normal file
584
src/entries/Background/ws.ts
Normal file
@@ -0,0 +1,584 @@
|
||||
import { devlog, safeParseJSON, sha256 } from '../../utils/misc';
|
||||
import {
|
||||
appendIncomingPairingRequests,
|
||||
appendIncomingProofRequests,
|
||||
appendOutgoingPairingRequests,
|
||||
appendOutgoingProofRequest,
|
||||
setClientId,
|
||||
setConnected,
|
||||
setIncomingPairingRequest,
|
||||
setIncomingProofRequest,
|
||||
setOutgoingPairingRequest,
|
||||
setOutgoingProofRequest,
|
||||
setP2PError,
|
||||
setPairing,
|
||||
} from '../../reducers/p2p';
|
||||
import { pushToRedux } from '../utils';
|
||||
import { getPluginByHash } from './db';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { OffscreenActionTypes } from '../Offscreen/types';
|
||||
import { getMaxRecv, getMaxSent, getRendezvousApi } from '../../utils/storage';
|
||||
import { SidePanelActionTypes } from '../SidePanel/types';
|
||||
|
||||
const state: {
|
||||
clientId: string;
|
||||
pairing: string;
|
||||
socket: WebSocket | null;
|
||||
connected: boolean;
|
||||
reqId: number;
|
||||
incomingPairingRequests: string[];
|
||||
outgoingPairingRequests: string[];
|
||||
incomingProofRequests: string[];
|
||||
outgoingProofRequests: string[];
|
||||
} = {
|
||||
clientId: '',
|
||||
pairing: '',
|
||||
socket: null,
|
||||
connected: false,
|
||||
reqId: 0,
|
||||
incomingPairingRequests: [],
|
||||
outgoingPairingRequests: [],
|
||||
incomingProofRequests: [],
|
||||
outgoingProofRequests: [],
|
||||
};
|
||||
|
||||
export const getP2PState = async () => {
|
||||
pushToRedux(setPairing(state.pairing));
|
||||
pushToRedux(setConnected(state.connected));
|
||||
pushToRedux(setClientId(state.clientId));
|
||||
pushToRedux(setIncomingPairingRequest(state.incomingPairingRequests));
|
||||
pushToRedux(setOutgoingPairingRequest(state.outgoingPairingRequests));
|
||||
pushToRedux(setIncomingProofRequest(state.incomingProofRequests));
|
||||
pushToRedux(setOutgoingProofRequest(state.outgoingProofRequests));
|
||||
};
|
||||
|
||||
export const connectSession = async () => {
|
||||
if (state.socket) return;
|
||||
|
||||
const socket = new WebSocket('ws://localhost:3001');
|
||||
|
||||
socket.onopen = () => {
|
||||
devlog('Connected to websocket');
|
||||
state.connected = true;
|
||||
state.socket = socket;
|
||||
pushToRedux(setConnected(true));
|
||||
};
|
||||
|
||||
socket.onmessage = async (event) => {
|
||||
const message: any = safeParseJSON(await event.data.text());
|
||||
|
||||
if (message.error) {
|
||||
pushToRedux(setP2PError(message.error.message));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.method) {
|
||||
case 'client_connect': {
|
||||
const { clientId } = message.params;
|
||||
state.clientId = clientId;
|
||||
pushToRedux(setClientId(clientId));
|
||||
break;
|
||||
}
|
||||
case 'pair_request': {
|
||||
const { from } = message.params;
|
||||
state.incomingPairingRequests = [
|
||||
...new Set(state.incomingPairingRequests.concat(from)),
|
||||
];
|
||||
pushToRedux(appendIncomingPairingRequests(from));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_sent': {
|
||||
const { pairId } = message.params;
|
||||
state.outgoingPairingRequests = [
|
||||
...new Set(state.outgoingPairingRequests.concat(pairId)),
|
||||
];
|
||||
pushToRedux(appendOutgoingPairingRequests(pairId));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_cancel': {
|
||||
const { from } = message.params;
|
||||
state.incomingPairingRequests = state.incomingPairingRequests.filter(
|
||||
(id) => id !== from,
|
||||
);
|
||||
pushToRedux(setIncomingPairingRequest(state.incomingPairingRequests));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_cancelled': {
|
||||
const { pairId } = message.params;
|
||||
state.outgoingPairingRequests = state.outgoingPairingRequests.filter(
|
||||
(id) => id !== pairId,
|
||||
);
|
||||
pushToRedux(setOutgoingPairingRequest(state.outgoingPairingRequests));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_reject': {
|
||||
const { from } = message.params;
|
||||
state.outgoingPairingRequests = state.outgoingPairingRequests.filter(
|
||||
(id) => id !== from,
|
||||
);
|
||||
pushToRedux(setOutgoingPairingRequest(state.outgoingPairingRequests));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_accept': {
|
||||
const { from } = message.params;
|
||||
state.pairing = from;
|
||||
state.outgoingPairingRequests = state.outgoingPairingRequests.filter(
|
||||
(id) => id !== from,
|
||||
);
|
||||
pushToRedux(setOutgoingPairingRequest(state.outgoingPairingRequests));
|
||||
pushToRedux(setPairing(from));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_success': {
|
||||
const { pairId } = message.params;
|
||||
state.pairing = pairId;
|
||||
pushToRedux(setPairing(pairId));
|
||||
state.incomingPairingRequests = state.incomingPairingRequests.filter(
|
||||
(id) => id !== pairId,
|
||||
);
|
||||
pushToRedux(setIncomingPairingRequest(state.incomingPairingRequests));
|
||||
break;
|
||||
}
|
||||
case 'pair_request_rejected': {
|
||||
const { pairId } = message.params;
|
||||
state.incomingPairingRequests = state.incomingPairingRequests.filter(
|
||||
(id) => id !== pairId,
|
||||
);
|
||||
pushToRedux(setIncomingPairingRequest(state.incomingPairingRequests));
|
||||
break;
|
||||
}
|
||||
case 'request_proof': {
|
||||
const { plugin, pluginHash } = message.params;
|
||||
state.incomingProofRequests = [
|
||||
...new Set(state.incomingProofRequests.concat(plugin)),
|
||||
];
|
||||
pushToRedux(appendIncomingProofRequests(plugin));
|
||||
handleProofRequestReceived(pluginHash);
|
||||
break;
|
||||
}
|
||||
case 'request_proof_by_hash': {
|
||||
const { pluginHash } = message.params;
|
||||
const plugin = await getPluginByHash(pluginHash);
|
||||
if (plugin) {
|
||||
state.incomingProofRequests = [
|
||||
...new Set(state.incomingProofRequests.concat(plugin)),
|
||||
];
|
||||
pushToRedux(appendIncomingProofRequests(plugin));
|
||||
handleProofRequestReceived(pluginHash);
|
||||
} else {
|
||||
handleNoPluginHash(pluginHash);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'request_proof_by_hash_failed': {
|
||||
const { pluginHash } = message.params;
|
||||
requestProof(pluginHash);
|
||||
break;
|
||||
}
|
||||
case 'proof_request_received': {
|
||||
const { pluginHash } = message.params;
|
||||
state.outgoingProofRequests = [
|
||||
...new Set(state.outgoingProofRequests.concat(pluginHash)),
|
||||
];
|
||||
pushToRedux(appendOutgoingProofRequest(pluginHash));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'proof_request_cancelled':
|
||||
case 'proof_request_reject':
|
||||
await handleRemoveOutgoingProofRequest(message);
|
||||
break;
|
||||
case 'proof_request_cancel':
|
||||
case 'proof_request_rejected':
|
||||
await handleRemoveIncomingProofRequest(message);
|
||||
break;
|
||||
case 'proof_request_accept': {
|
||||
const { pluginHash, from } = message.params;
|
||||
const maxSentData = await getMaxSent();
|
||||
const maxRecvData = await getMaxRecv();
|
||||
const rendezvousApi = await getRendezvousApi();
|
||||
browser.runtime.sendMessage({
|
||||
type: OffscreenActionTypes.start_p2p_verifier,
|
||||
data: {
|
||||
pluginHash,
|
||||
maxSentData,
|
||||
maxRecvData,
|
||||
verifierUrl:
|
||||
rendezvousApi + '?clientId=' + state.clientId + ':proof',
|
||||
peerId: state.pairing,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'verifier_started': {
|
||||
const { pluginHash } = message.params;
|
||||
browser.runtime.sendMessage({
|
||||
type: SidePanelActionTypes.start_p2p_plugin,
|
||||
data: {
|
||||
pluginHash: pluginHash,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'prover_started': {
|
||||
const { pluginHash } = message.params;
|
||||
browser.runtime.sendMessage({
|
||||
type: OffscreenActionTypes.prover_started,
|
||||
data: {
|
||||
pluginHash: pluginHash,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'proof_request_start': {
|
||||
const { pluginHash, from } = message.params;
|
||||
browser.runtime.sendMessage({
|
||||
type: OffscreenActionTypes.start_p2p_proof_request,
|
||||
data: {
|
||||
pluginHash: pluginHash,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'proof_request_end': {
|
||||
const { pluginHash, proof } = message.params;
|
||||
browser.runtime.sendMessage({
|
||||
type: OffscreenActionTypes.end_p2p_proof_request,
|
||||
data: {
|
||||
pluginHash: pluginHash,
|
||||
proof: proof,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn(`Unknown message type "${message.method}"`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
socket.onerror = () => {
|
||||
console.error('Error connecting to websocket');
|
||||
pushToRedux(setConnected(false));
|
||||
};
|
||||
};
|
||||
|
||||
async function handleRemoveOutgoingProofRequest(message: {
|
||||
params: { pluginHash: string };
|
||||
}) {
|
||||
const { pluginHash } = message.params;
|
||||
state.outgoingProofRequests = state.outgoingProofRequests.filter(
|
||||
(hash) => hash !== pluginHash,
|
||||
);
|
||||
pushToRedux(setOutgoingProofRequest(state.outgoingProofRequests));
|
||||
}
|
||||
|
||||
async function handleRemoveIncomingProofRequest(message: {
|
||||
params: { pluginHash: string };
|
||||
}) {
|
||||
const { pluginHash } = message.params;
|
||||
const plugin = await getPluginByHash(pluginHash);
|
||||
const incomingProofRequest = [];
|
||||
for (const hex of state.incomingProofRequests) {
|
||||
if (plugin) {
|
||||
if (plugin !== hex) incomingProofRequest.push(hex);
|
||||
} else {
|
||||
if ((await sha256(hex)) !== pluginHash) incomingProofRequest.push(hex);
|
||||
}
|
||||
}
|
||||
|
||||
state.incomingProofRequests = incomingProofRequest;
|
||||
pushToRedux(setIncomingProofRequest(state.incomingProofRequests));
|
||||
}
|
||||
|
||||
export const disconnectSession = async () => {
|
||||
if (!state.socket) return;
|
||||
await state.socket.close();
|
||||
state.socket = null;
|
||||
state.clientId = '';
|
||||
state.pairing = '';
|
||||
state.connected = false;
|
||||
state.incomingPairingRequests = [];
|
||||
state.outgoingPairingRequests = [];
|
||||
state.incomingProofRequests = [];
|
||||
state.outgoingProofRequests = [];
|
||||
pushToRedux(setPairing(''));
|
||||
pushToRedux(setConnected(false));
|
||||
pushToRedux(setClientId(''));
|
||||
pushToRedux(setIncomingPairingRequest([]));
|
||||
pushToRedux(setOutgoingPairingRequest([]));
|
||||
pushToRedux(setIncomingProofRequest([]));
|
||||
pushToRedux(setOutgoingProofRequest([]));
|
||||
};
|
||||
|
||||
export const sendPairRequest = async (target: string) => {
|
||||
const { socket, clientId } = state;
|
||||
|
||||
if (clientId === target) return;
|
||||
|
||||
if (socket && clientId) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'pair_request',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: target,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const cancelPairRequest = async (target: string) => {
|
||||
const { socket, clientId } = state;
|
||||
|
||||
if (clientId === target) return;
|
||||
|
||||
if (socket && clientId) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'pair_request_cancel',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: target,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const acceptPairRequest = async (target: string) => {
|
||||
const { socket, clientId } = state;
|
||||
|
||||
if (clientId === target) return;
|
||||
|
||||
if (socket && clientId) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'pair_request_accept',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: target,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const rejectPairRequest = async (target: string) => {
|
||||
const { socket, clientId } = state;
|
||||
|
||||
if (clientId === target) return;
|
||||
|
||||
if (socket && clientId) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'pair_request_reject',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: target,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const requestProof = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
const pluginHex = await getPluginByHash(pluginHash);
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'request_proof',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
plugin: pluginHex,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const requestProofByHash = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'request_proof_by_hash',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const cancelProofRequest = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_cancel',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const acceptProofRequest = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_accept',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const startProofRequest = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_start',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const endProofRequest = async (data: {
|
||||
pluginHash: string;
|
||||
proof: any;
|
||||
}) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_end',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash: data.pluginHash,
|
||||
proof: data.proof,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const rejectProofRequest = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_reject',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const startedVerifier = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'verifier_started',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const startedProver = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'prover_started',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const handleNoPluginHash = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'request_proof_by_hash_failed',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const handleProofRequestReceived = async (pluginHash: string) => {
|
||||
const { socket, clientId, pairing } = state;
|
||||
if (socket && clientId && pairing) {
|
||||
socket.send(
|
||||
bufferify({
|
||||
method: 'proof_request_received',
|
||||
params: {
|
||||
from: clientId,
|
||||
to: pairing,
|
||||
pluginHash,
|
||||
id: state.reqId++,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function bufferify(data: any): Buffer {
|
||||
return Buffer.from(JSON.stringify(data));
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import * as Comlink from 'comlink';
|
||||
import { OffscreenActionTypes } from './types';
|
||||
import {
|
||||
NotaryServer,
|
||||
Prover as _Prover,
|
||||
Verifier as _Verifier,
|
||||
NotarizedSession as _NotarizedSession,
|
||||
TlsProof as _TlsProof,
|
||||
} from 'tlsn-js';
|
||||
@@ -14,16 +15,18 @@ import { BackgroundActiontype } from '../Background/rpc';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { Proof, ProofV1 } from '../../utils/types';
|
||||
import { Method } from 'tlsn-js/wasm/pkg';
|
||||
import { waitForEvent } from '../utils';
|
||||
import type { ParsedTranscriptData } from '../../../../tlsn-js/src/types';
|
||||
|
||||
const { init, Prover, NotarizedSession, TlsProof }: any = Comlink.wrap(
|
||||
new Worker(new URL('./worker.ts', import.meta.url)),
|
||||
);
|
||||
const { init, Prover, NotarizedSession, TlsProof, Verifier }: any =
|
||||
Comlink.wrap(new Worker(new URL('./worker.ts', import.meta.url)));
|
||||
|
||||
const Offscreen = () => {
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const loggingLevel = await browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.get_logging_level,
|
||||
hardwareConcurrency: 1,
|
||||
});
|
||||
await init({ loggingLevel });
|
||||
// @ts-ignore
|
||||
@@ -128,6 +131,150 @@ const Offscreen = () => {
|
||||
})();
|
||||
break;
|
||||
}
|
||||
case OffscreenActionTypes.start_p2p_verifier: {
|
||||
(async () => {
|
||||
const { pluginHash, maxSentData, maxRecvData, verifierUrl } =
|
||||
request.data;
|
||||
|
||||
const verifier: _Verifier = await new Verifier({
|
||||
id: pluginHash,
|
||||
max_sent_data: maxSentData,
|
||||
max_recv_data: maxRecvData,
|
||||
});
|
||||
|
||||
await verifier.connect(verifierUrl);
|
||||
// await new Promise((r) => setTimeout(r, 10000));
|
||||
const proverStarted = waitForEvent(
|
||||
OffscreenActionTypes.prover_started,
|
||||
);
|
||||
|
||||
verifier.verify().then((res) => {
|
||||
console.log(res);
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.proof_request_end,
|
||||
data: {
|
||||
pluginHash,
|
||||
proof: res,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.verifier_started,
|
||||
data: {
|
||||
pluginHash,
|
||||
},
|
||||
});
|
||||
|
||||
await proverStarted;
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.start_proof_request,
|
||||
data: {
|
||||
pluginHash,
|
||||
},
|
||||
});
|
||||
})();
|
||||
break;
|
||||
}
|
||||
case OffscreenActionTypes.start_p2p_prover: {
|
||||
(async () => {
|
||||
const {
|
||||
pluginHash,
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
proverUrl,
|
||||
websocketProxyUrl,
|
||||
maxRecvData,
|
||||
maxSentData,
|
||||
secretHeaders,
|
||||
secretResps,
|
||||
} = request.data;
|
||||
|
||||
const hostname = urlify(url)?.hostname || '';
|
||||
const prover: _Prover = await new Prover({
|
||||
id: pluginHash,
|
||||
serverDns: hostname,
|
||||
maxSentData,
|
||||
maxRecvData,
|
||||
});
|
||||
|
||||
const proofRequestStart = waitForEvent(
|
||||
OffscreenActionTypes.start_p2p_proof_request,
|
||||
);
|
||||
|
||||
const proverSetup = prover.setup(proverUrl);
|
||||
// await new Promise((r) => setTimeout(r, 10000));
|
||||
|
||||
await proverSetup;
|
||||
browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.prover_started,
|
||||
data: {
|
||||
pluginHash,
|
||||
},
|
||||
});
|
||||
await proofRequestStart;
|
||||
|
||||
await prover.sendRequest(
|
||||
websocketProxyUrl + `?token=${hostname}`,
|
||||
{
|
||||
url,
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
},
|
||||
);
|
||||
|
||||
const transcript = await prover.transcript();
|
||||
|
||||
const commit = {
|
||||
sent: subtractRanges(
|
||||
transcript.ranges.sent.all,
|
||||
secretHeaders
|
||||
.map((secret: string) => {
|
||||
const index = transcript.sent.indexOf(secret);
|
||||
return index > -1
|
||||
? {
|
||||
start: index,
|
||||
end: index + secret.length,
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((data: any) => !!data) as {
|
||||
start: number;
|
||||
end: number;
|
||||
}[],
|
||||
),
|
||||
recv: subtractRanges(
|
||||
transcript.ranges.recv.all,
|
||||
secretResps
|
||||
.map((secret: string) => {
|
||||
const index = transcript.recv.indexOf(secret);
|
||||
return index > -1
|
||||
? {
|
||||
start: index,
|
||||
end: index + secret.length,
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((data: any) => !!data) as {
|
||||
start: number;
|
||||
end: number;
|
||||
}[],
|
||||
),
|
||||
};
|
||||
|
||||
const endRequest = waitForEvent(
|
||||
OffscreenActionTypes.end_p2p_proof_request,
|
||||
);
|
||||
await prover.reveal(commit);
|
||||
console.log(await endRequest);
|
||||
})();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -276,6 +423,55 @@ async function createProof(options: {
|
||||
return proof;
|
||||
}
|
||||
|
||||
function getCommitFromTranscript(
|
||||
transcript: {
|
||||
sent: string;
|
||||
recv: string;
|
||||
ranges: { recv: ParsedTranscriptData; sent: ParsedTranscriptData };
|
||||
},
|
||||
secretHeaders: string[],
|
||||
secretResps: string[],
|
||||
) {
|
||||
const commit = {
|
||||
sent: subtractRanges(
|
||||
transcript.ranges.sent.all,
|
||||
secretHeaders
|
||||
.map((secret: string) => {
|
||||
const index = transcript.sent.indexOf(secret);
|
||||
return index > -1
|
||||
? {
|
||||
start: index,
|
||||
end: index + secret.length,
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((data: any) => !!data) as {
|
||||
start: number;
|
||||
end: number;
|
||||
}[],
|
||||
),
|
||||
recv: subtractRanges(
|
||||
transcript.ranges.recv.all,
|
||||
secretResps
|
||||
.map((secret: string) => {
|
||||
const index = transcript.recv.indexOf(secret);
|
||||
return index > -1
|
||||
? {
|
||||
start: index,
|
||||
end: index + secret.length,
|
||||
}
|
||||
: null;
|
||||
})
|
||||
.filter((data: any) => !!data) as {
|
||||
start: number;
|
||||
end: number;
|
||||
}[],
|
||||
),
|
||||
};
|
||||
|
||||
return commit;
|
||||
}
|
||||
|
||||
async function verifyProof(
|
||||
proof: Proof,
|
||||
): Promise<{ sent: string; recv: string }> {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export enum OffscreenActionTypes {
|
||||
notarization_request = 'offscreen/notarization_request',
|
||||
notarization_response = 'offscreen/notarization_response',
|
||||
start_p2p_verifier = 'offscreen/start_p2p_verifier',
|
||||
start_p2p_prover = 'offscreen/start_p2p_prover',
|
||||
prover_started = 'offscreen/prover_started',
|
||||
start_p2p_proof_request = 'offscreen/start_p2p_proof_request',
|
||||
end_p2p_proof_request = 'offscreen/end_p2p_proof_request',
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as Comlink from 'comlink';
|
||||
import init, { Prover, NotarizedSession, TlsProof } from 'tlsn-js';
|
||||
import init, { Prover, NotarizedSession, TlsProof, Verifier } from 'tlsn-js';
|
||||
|
||||
Comlink.expose({
|
||||
init,
|
||||
Prover,
|
||||
Verifier,
|
||||
NotarizedSession,
|
||||
TlsProof,
|
||||
});
|
||||
|
||||
@@ -33,11 +33,17 @@ import Icon from '../../components/Icon';
|
||||
import classNames from 'classnames';
|
||||
import { getConnection } from '../Background/db';
|
||||
import { useIsConnected, setConnection } from '../../reducers/requests';
|
||||
import { P2PHome } from '../../pages/PeerToPeer';
|
||||
import { fetchP2PState } from '../../reducers/p2p';
|
||||
|
||||
const Popup = () => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
fetchP2PState();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const [tab] = await browser.tabs.query({
|
||||
@@ -111,6 +117,7 @@ const Popup = () => {
|
||||
<Route path="/notarize-approval" element={<NotarizeApproval />} />
|
||||
<Route path="/get-plugins-approval" element={<GetPluginsApproval />} />
|
||||
<Route path="/run-plugin-approval" element={<RunPluginApproval />} />
|
||||
<Route path="/p2p" element={<P2PHome />} />
|
||||
<Route
|
||||
path="/install-plugin-approval"
|
||||
element={<InstallPluginApproval />}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react';
|
||||
import './sidePanel.scss';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { fetchPluginConfigByHash, runPlugin } from '../../utils/rpc';
|
||||
import {
|
||||
getPluginConfig,
|
||||
hexToArrayBuffer,
|
||||
makePlugin,
|
||||
PluginConfig,
|
||||
sha256,
|
||||
StepConfig,
|
||||
} from '../../utils/misc';
|
||||
import { PluginList } from '../../components/PluginList';
|
||||
@@ -17,28 +17,62 @@ import Icon from '../../components/Icon';
|
||||
import { useRequestHistory } from '../../reducers/history';
|
||||
import { BackgroundActiontype } from '../Background/rpc';
|
||||
import { getPluginByHash, getPluginConfigByHash } from '../Background/db';
|
||||
import type { Plugin } from '@extism/extism';
|
||||
import { OffscreenActionTypes } from '../Offscreen/types';
|
||||
import { SidePanelActionTypes } from './types';
|
||||
import {
|
||||
fetchP2PState,
|
||||
useClientId,
|
||||
useIncomingProofRequests,
|
||||
} from '../../reducers/p2p';
|
||||
|
||||
export default function SidePanel(): ReactElement {
|
||||
const [config, setConfig] = useState<PluginConfig | null>(null);
|
||||
const [hash, setHash] = useState('');
|
||||
const [hex, setHex] = useState('');
|
||||
const [p2p, setP2P] = useState(false);
|
||||
const [started, setStarted] = useState(false);
|
||||
const clientId = useClientId();
|
||||
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
const result = await browser.storage.local.get('plugin_hash');
|
||||
const { plugin_hash } = result;
|
||||
const config = await getPluginConfigByHash(plugin_hash);
|
||||
setHash(plugin_hash);
|
||||
setConfig(config);
|
||||
// await browser.storage.local.set({ plugin_hash: '' });
|
||||
})();
|
||||
fetchP2PState();
|
||||
browser.runtime.sendMessage({
|
||||
type: SidePanelActionTypes.panel_opened,
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
browser.runtime.onMessage.addListener(async (request) => {
|
||||
const { type, data } = request;
|
||||
|
||||
switch (type) {
|
||||
case SidePanelActionTypes.execute_plugin_request: {
|
||||
setConfig(await getPluginConfigByHash(data.pluginHash));
|
||||
setHash(data.pluginHash);
|
||||
setStarted(true);
|
||||
break;
|
||||
}
|
||||
case SidePanelActionTypes.run_p2p_plugin_request: {
|
||||
const { pluginHash, plugin } = data;
|
||||
const config =
|
||||
(await getPluginConfigByHash(pluginHash)) ||
|
||||
(await getPluginConfig(hexToArrayBuffer(plugin)));
|
||||
|
||||
setHash(pluginHash);
|
||||
setHex(plugin);
|
||||
setP2P(true);
|
||||
setConfig(config);
|
||||
break;
|
||||
}
|
||||
case SidePanelActionTypes.start_p2p_plugin: {
|
||||
setStarted(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col bg-slate-100 w-screen h-screen">
|
||||
<div className="relative flex flex-nowrap flex-shrink-0 flex-row items-center relative gap-2 h-9 p-2 cursor-default justify-center bg-slate-300 w-full">
|
||||
<div className="relative flex flex-nowrap flex-shrink-0 flex-row items-center gap-2 h-9 p-2 cursor-default justify-center bg-slate-300 w-full">
|
||||
<img className="h-5" src={logo} alt="logo" />
|
||||
<button
|
||||
className="button absolute right-2"
|
||||
@@ -47,8 +81,16 @@ export default function SidePanel(): ReactElement {
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
{!config && <PluginList />}
|
||||
{config && <PluginBody hash={hash} config={config} />}
|
||||
{/*{!config && <PluginList />}*/}
|
||||
{started && config && (
|
||||
<PluginBody
|
||||
hash={hash}
|
||||
hex={hex}
|
||||
config={config}
|
||||
p2p={p2p}
|
||||
clientId={clientId}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -56,9 +98,12 @@ export default function SidePanel(): ReactElement {
|
||||
function PluginBody(props: {
|
||||
config: PluginConfig;
|
||||
hash: string;
|
||||
hex?: string;
|
||||
clientId?: string;
|
||||
p2p?: boolean;
|
||||
}): ReactElement {
|
||||
const { hash } = props;
|
||||
const { title, description, icon, steps } = props.config;
|
||||
const { hash, hex, config, p2p, clientId } = props;
|
||||
const { title, description, icon, steps } = config;
|
||||
const [responses, setResponses] = useState<any[]>([]);
|
||||
const [notarizationId, setNotarizationId] = useState('');
|
||||
const notaryRequest = useRequestHistory(notarizationId);
|
||||
@@ -110,10 +155,14 @@ function PluginBody(props: {
|
||||
{steps?.map((step, i) => (
|
||||
<StepContent
|
||||
hash={hash}
|
||||
config={config}
|
||||
hex={hex}
|
||||
index={i}
|
||||
setResponse={setResponse}
|
||||
lastResponse={i > 0 ? responses[i - 1] : undefined}
|
||||
responses={responses}
|
||||
p2p={p2p}
|
||||
clientId={clientId}
|
||||
{...step}
|
||||
/>
|
||||
))}
|
||||
@@ -125,10 +174,14 @@ function PluginBody(props: {
|
||||
function StepContent(
|
||||
props: StepConfig & {
|
||||
hash: string;
|
||||
hex?: string;
|
||||
clientId?: string;
|
||||
index: number;
|
||||
setResponse: (resp: any, i: number) => void;
|
||||
responses: any[];
|
||||
lastResponse?: any;
|
||||
config: PluginConfig;
|
||||
p2p?: boolean;
|
||||
},
|
||||
): ReactElement {
|
||||
const {
|
||||
@@ -141,6 +194,10 @@ function StepContent(
|
||||
lastResponse,
|
||||
prover,
|
||||
hash,
|
||||
hex: _hex,
|
||||
config,
|
||||
p2p = false,
|
||||
clientId = '',
|
||||
} = props;
|
||||
const [completed, setCompleted] = useState(false);
|
||||
const [pending, setPending] = useState(false);
|
||||
@@ -149,11 +206,10 @@ function StepContent(
|
||||
const notaryRequest = useRequestHistory(notarizationId);
|
||||
|
||||
const getPlugin = useCallback(async () => {
|
||||
const hex = await getPluginByHash(hash);
|
||||
const config = await getPluginConfigByHash(hash);
|
||||
const hex = (await getPluginByHash(hash)) || _hex;
|
||||
const arrayBuffer = hexToArrayBuffer(hex!);
|
||||
return makePlugin(arrayBuffer, config!);
|
||||
}, [hash]);
|
||||
return makePlugin(arrayBuffer, config, { p2p, clientId });
|
||||
}, [hash, _hex, config, p2p, clientId]);
|
||||
|
||||
const processStep = useCallback(async () => {
|
||||
const plugin = await getPlugin();
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
export enum SidePanelActionTypes {
|
||||
panel_opened = 'sidePanel/panel_opened',
|
||||
execute_plugin_request = 'sidePanel/execute_plugin_request',
|
||||
execute_plugin_response = 'sidePanel/execute_plugin_response',
|
||||
run_p2p_plugin_request = 'sidePanel/run_p2p_plugin_request',
|
||||
run_p2p_plugin_response = 'sidePanel/run_p2p_plugin_response',
|
||||
start_p2p_plugin = 'sidePanel/start_p2p_plugin',
|
||||
}
|
||||
|
||||
62
src/entries/utils.ts
Normal file
62
src/entries/utils.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import browser from 'webextension-polyfill';
|
||||
import { BackgroundActiontype } from './Background/rpc';
|
||||
import { SidePanelActionTypes } from './SidePanel/types';
|
||||
import { deferredPromise } from '../utils/promise';
|
||||
import { devlog } from '../utils/misc';
|
||||
|
||||
export const pushToRedux = async (action: {
|
||||
type: string;
|
||||
payload?: any;
|
||||
error?: boolean;
|
||||
meta?: any;
|
||||
}) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.push_action,
|
||||
data: {
|
||||
tabId: 'background',
|
||||
},
|
||||
action,
|
||||
});
|
||||
};
|
||||
|
||||
export const openSidePanel = async () => {
|
||||
const { promise, resolve, reject } = deferredPromise();
|
||||
|
||||
try {
|
||||
const [tab] = await browser.tabs.query({
|
||||
active: true,
|
||||
currentWindow: true,
|
||||
});
|
||||
|
||||
const listener = async (request: any) => {
|
||||
if (request.type === SidePanelActionTypes.panel_opened) {
|
||||
browser.runtime.onMessage.removeListener(listener);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(listener);
|
||||
// @ts-ignore
|
||||
if (chrome.sidePanel) await chrome.sidePanel.open({ tabId: tab.id });
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
export const waitForEvent = async (event: string) => {
|
||||
const { promise, resolve } = deferredPromise();
|
||||
|
||||
const listener = async (request: any) => {
|
||||
if (request.type === event) {
|
||||
devlog('received event:', event);
|
||||
browser.runtime.onMessage.removeListener(listener);
|
||||
resolve(request);
|
||||
}
|
||||
};
|
||||
|
||||
browser.runtime.onMessage.addListener(listener);
|
||||
|
||||
return promise;
|
||||
};
|
||||
@@ -11,11 +11,13 @@ import { useRequests } from '../../reducers/requests';
|
||||
import { PluginList } from '../../components/PluginList';
|
||||
import PluginUploadInfo from '../../components/PluginInfo';
|
||||
import { ErrorModal } from '../../components/ErrorModal';
|
||||
import { useClientId } from '../../reducers/p2p';
|
||||
|
||||
export default function Home(): ReactElement {
|
||||
const requests = useRequests();
|
||||
const navigate = useNavigate();
|
||||
const [error, showError] = useState('');
|
||||
const clientId = useClientId();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 py-4 overflow-y-auto">
|
||||
@@ -41,6 +43,17 @@ export default function Home(): ReactElement {
|
||||
<PluginUploadInfo />
|
||||
Add a plugin
|
||||
</NavButton>
|
||||
<NavButton
|
||||
className={'relative'}
|
||||
fa="fa-solid fa-circle"
|
||||
iconSize={0.5}
|
||||
iconClassName={classNames({
|
||||
'!text-green-500': clientId,
|
||||
})}
|
||||
onClick={() => navigate('/p2p')}
|
||||
>
|
||||
P2P
|
||||
</NavButton>
|
||||
<NavButton fa="fa-solid fa-gear" onClick={() => navigate('/options')}>
|
||||
Options
|
||||
</NavButton>
|
||||
@@ -55,12 +68,14 @@ function NavButton(props: {
|
||||
children?: ReactNode;
|
||||
onClick?: MouseEventHandler;
|
||||
className?: string;
|
||||
iconClassName?: string;
|
||||
disabled?: boolean;
|
||||
iconSize?: number;
|
||||
}): ReactElement {
|
||||
return (
|
||||
<button
|
||||
className={classNames(
|
||||
'flex flex-row flex-nowrap items-center justify-center',
|
||||
'flex flex-row flex-nowrap items-center justify-center relative',
|
||||
'text-white rounded px-2 py-1 gap-1',
|
||||
{
|
||||
'bg-primary/[.8] hover:bg-primary/[.7] active:bg-primary':
|
||||
@@ -72,8 +87,15 @@ function NavButton(props: {
|
||||
onClick={props.onClick}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
<Icon className="flex-grow-0 flex-shrink-0" fa={props.fa} size={1} />
|
||||
<span className="flex-grow flex-shrink w-0 flex-grow font-bold">
|
||||
<Icon
|
||||
className={classNames(
|
||||
'absolute w-6 justify-center left-2',
|
||||
props.iconClassName,
|
||||
)}
|
||||
fa={props.fa}
|
||||
size={props.iconSize || 1}
|
||||
/>
|
||||
<span className="flex-grow flex-shrink w-0 font-bold">
|
||||
{props.children}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
getProxyApi,
|
||||
getLoggingFilter,
|
||||
LOGGING_FILTER_KEY,
|
||||
getRendezvousApi,
|
||||
RENDEZVOUS_API_LS_KEY,
|
||||
} from '../../utils/storage';
|
||||
import {
|
||||
EXPLORER_API,
|
||||
@@ -24,6 +26,7 @@ import {
|
||||
NOTARY_PROXY,
|
||||
MAX_RECV,
|
||||
MAX_SENT,
|
||||
RENDEZVOUS_API,
|
||||
} from '../../utils/constants';
|
||||
import Modal, { ModalContent } from '../../components/Modal/Modal';
|
||||
import browser from 'webextension-polyfill';
|
||||
@@ -36,6 +39,7 @@ export default function Options(): ReactElement {
|
||||
const [maxSent, setMaxSent] = useState(MAX_SENT);
|
||||
const [maxReceived, setMaxReceived] = useState(MAX_RECV);
|
||||
const [loggingLevel, setLoggingLevel] = useState<LoggingLevel>('Info');
|
||||
const [rendezvous, setRendezvous] = useState(RENDEZVOUS_API);
|
||||
|
||||
const [dirty, setDirty] = useState(false);
|
||||
const [shouldReload, setShouldReload] = useState(false);
|
||||
@@ -44,11 +48,17 @@ export default function Options(): ReactElement {
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setNotary((await getNotaryApi()) || NOTARY_API);
|
||||
setProxy((await getProxyApi()) || NOTARY_PROXY);
|
||||
setNotary(await getNotaryApi());
|
||||
setProxy(await getProxyApi());
|
||||
})();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setMaxReceived((await getMaxRecv()) || MAX_RECV);
|
||||
setMaxSent((await getMaxSent()) || MAX_SENT);
|
||||
setLoggingLevel((await getLoggingFilter()) || 'Info');
|
||||
setRendezvous((await getRendezvousApi()) || RENDEZVOUS_API);
|
||||
})();
|
||||
}, [advanced]);
|
||||
|
||||
@@ -63,9 +73,18 @@ export default function Options(): ReactElement {
|
||||
await set(MAX_SENT_LS_KEY, maxSent.toString());
|
||||
await set(MAX_RECEIVED_LS_KEY, maxReceived.toString());
|
||||
await set(LOGGING_FILTER_KEY, loggingLevel);
|
||||
await set(RENDEZVOUS_API_LS_KEY, rendezvous);
|
||||
setDirty(false);
|
||||
},
|
||||
[notary, proxy, maxSent, maxReceived, loggingLevel, shouldReload],
|
||||
[
|
||||
notary,
|
||||
proxy,
|
||||
maxSent,
|
||||
maxReceived,
|
||||
loggingLevel,
|
||||
rendezvous,
|
||||
shouldReload,
|
||||
],
|
||||
);
|
||||
|
||||
const onSaveAndReload = useCallback(
|
||||
@@ -81,7 +100,7 @@ export default function Options(): ReactElement {
|
||||
}, [advanced]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-nowrap flex-grow">
|
||||
<div className="flex flex-col flex-nowrap flex-grow overflow-y-auto">
|
||||
{showReloadModal && (
|
||||
<Modal
|
||||
className="flex flex-col items-center text-base cursor-default justify-center !w-auto mx-4 my-[50%] p-4 gap-4"
|
||||
@@ -141,6 +160,8 @@ export default function Options(): ReactElement {
|
||||
loggingLevel={loggingLevel}
|
||||
setLoggingLevel={setLoggingLevel}
|
||||
setShouldReload={setShouldReload}
|
||||
rendezvous={rendezvous}
|
||||
setRendezvous={setRendezvous}
|
||||
/>
|
||||
)}
|
||||
<div className="flex flex-row flex-nowrap justify-end gap-2 p-2">
|
||||
@@ -228,11 +249,13 @@ function AdvancedOptions(props: {
|
||||
maxSent: number;
|
||||
maxReceived: number;
|
||||
loggingLevel: LoggingLevel;
|
||||
rendezvous: string;
|
||||
setShouldReload: (reload: boolean) => void;
|
||||
setMaxSent: (value: number) => void;
|
||||
setMaxReceived: (value: number) => void;
|
||||
setDirty: (value: boolean) => void;
|
||||
setLoggingLevel: (level: LoggingLevel) => void;
|
||||
setRendezvous: (api: string) => void;
|
||||
}) {
|
||||
const {
|
||||
maxSent,
|
||||
@@ -243,6 +266,8 @@ function AdvancedOptions(props: {
|
||||
setLoggingLevel,
|
||||
loggingLevel,
|
||||
setShouldReload,
|
||||
rendezvous,
|
||||
setRendezvous,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@@ -267,6 +292,15 @@ function AdvancedOptions(props: {
|
||||
setDirty(true);
|
||||
}}
|
||||
/>
|
||||
<InputField
|
||||
label="Rendezvous API (for P2P)"
|
||||
value={rendezvous}
|
||||
type="text"
|
||||
onChange={(e) => {
|
||||
setRendezvous(e.target.value);
|
||||
setDirty(true);
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col flex-nowrap py-1 px-2 gap-2">
|
||||
<div className="font-semibold">Logging Level</div>
|
||||
<select
|
||||
|
||||
354
src/pages/PeerToPeer/index.tsx
Normal file
354
src/pages/PeerToPeer/index.tsx
Normal file
@@ -0,0 +1,354 @@
|
||||
import React, {
|
||||
ChangeEvent,
|
||||
ReactElement,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import Icon from '../../components/Icon';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
connectRendezvous,
|
||||
disconnectRendezvous,
|
||||
fetchP2PState,
|
||||
sendPairRequest,
|
||||
useClientId,
|
||||
useIncomingPairingRequests,
|
||||
useOutgoingPairingRequests,
|
||||
cancelPairRequest,
|
||||
useP2PError,
|
||||
setP2PError,
|
||||
acceptPairRequest,
|
||||
rejectPairRequest,
|
||||
usePairId,
|
||||
useIncomingProofRequests,
|
||||
requestProofByHash,
|
||||
useOutgoingProofRequests,
|
||||
acceptProofRequest,
|
||||
rejectProofRequest,
|
||||
cancelProofRequest,
|
||||
} from '../../reducers/p2p';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import Modal, { ModalHeader } from '../../components/Modal/Modal';
|
||||
import { Plugin, PluginList } from '../../components/PluginList';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { sha256 } from '../../utils/misc';
|
||||
import { openSidePanel } from '../../entries/utils';
|
||||
import { SidePanelActionTypes } from '../../entries/SidePanel/types';
|
||||
|
||||
export function P2PHome(): ReactElement {
|
||||
const clientId = useClientId();
|
||||
|
||||
useEffect(() => {
|
||||
fetchP2PState();
|
||||
}, []);
|
||||
|
||||
const toggleConnection = useCallback(async () => {
|
||||
if (!clientId) {
|
||||
connectRendezvous();
|
||||
} else {
|
||||
disconnectRendezvous();
|
||||
}
|
||||
}, [clientId]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full cursor-default gap-2 my-2">
|
||||
<div className="flex flex-row border border-slate-300 rounded mx-2">
|
||||
<div className="bg-slate-200 px-2 py-1 flex-grow-0 border-r border-slate-300">
|
||||
Client ID
|
||||
</div>
|
||||
<input
|
||||
className={classNames(
|
||||
'flex-grow outline-0 px-2 py-1 cursor-default font-semibold',
|
||||
{
|
||||
'text-slate-400 bg-slate-100': !clientId,
|
||||
'text-green-500 cursor-pointer': clientId,
|
||||
},
|
||||
)}
|
||||
onClick={(e) => {
|
||||
// @ts-ignore
|
||||
if (e.target.select && clientId) e.target.select();
|
||||
}}
|
||||
value={clientId ? clientId : '--'}
|
||||
readOnly
|
||||
/>
|
||||
<button
|
||||
className="flex-grow-0 px-2 py-1 button border-l border-slate-300"
|
||||
onClick={toggleConnection}
|
||||
>
|
||||
{clientId ? 'Stop' : 'Start'}
|
||||
</button>
|
||||
</div>
|
||||
<ClientStatus />
|
||||
<div className="flex flex-row mx-2 flex-grow flex-shrink h-0 p-2">
|
||||
<div className="text-slate-400 text-center w-full font-semibold">
|
||||
No proofs history
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ClientStatus() {
|
||||
const clientId = useClientId();
|
||||
const error = useP2PError();
|
||||
const pairId = usePairId();
|
||||
const [incomingPairingRequest] = useIncomingPairingRequests();
|
||||
const [outgoingPairingRequest] = useOutgoingPairingRequests();
|
||||
|
||||
let body = null;
|
||||
|
||||
if (!clientId) {
|
||||
body = <ClientNotStarted />;
|
||||
} else if (pairId) {
|
||||
body = <Paired />;
|
||||
} else if (!incomingPairingRequest && !outgoingPairingRequest) {
|
||||
body = <PendingConnection />;
|
||||
} else if (incomingPairingRequest) {
|
||||
body = <IncomingRequest />;
|
||||
} else if (outgoingPairingRequest) {
|
||||
body = <OutgoingRequest />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'flex flex-col items-center justify-center border border-slate-300',
|
||||
'flex-grow-0 flex-shrink rounded mx-2 bg-slate-100 py-4 gap-4',
|
||||
)}
|
||||
>
|
||||
{body}
|
||||
{error && <span className="text-xs text-red-500">{error}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Paired() {
|
||||
const pairId = usePairId();
|
||||
const clientId = useClientId();
|
||||
const [incomingProofRequest] = useIncomingProofRequests();
|
||||
const [outgoingPluginHash] = useOutgoingProofRequests();
|
||||
const [incomingPluginHash, setIncomingPluginHash] = useState('');
|
||||
const [showingModal, showModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (!incomingProofRequest) {
|
||||
setIncomingPluginHash('');
|
||||
return;
|
||||
}
|
||||
const hash = await sha256(incomingProofRequest);
|
||||
setIncomingPluginHash(hash);
|
||||
})();
|
||||
}, [incomingProofRequest]);
|
||||
|
||||
useEffect(() => {
|
||||
showModal(false);
|
||||
}, [outgoingPluginHash]);
|
||||
|
||||
const accept = useCallback(async () => {
|
||||
if (incomingPluginHash) {
|
||||
await openSidePanel();
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: SidePanelActionTypes.run_p2p_plugin_request,
|
||||
data: {
|
||||
pluginHash: incomingPluginHash,
|
||||
plugin: incomingProofRequest,
|
||||
},
|
||||
});
|
||||
|
||||
acceptProofRequest(incomingPluginHash);
|
||||
|
||||
window.close();
|
||||
}
|
||||
}, [incomingPluginHash, incomingProofRequest, clientId]);
|
||||
|
||||
const reject = useCallback(() => {
|
||||
if (incomingPluginHash) rejectProofRequest(incomingPluginHash);
|
||||
}, [incomingPluginHash]);
|
||||
|
||||
const cancel = useCallback(() => {
|
||||
if (outgoingPluginHash) cancelProofRequest(outgoingPluginHash);
|
||||
}, [outgoingPluginHash]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-2 px-4 w-full">
|
||||
{showingModal && <PluginListModal onClose={() => showModal(false)} />}
|
||||
<div>
|
||||
<span>Paired with </span>
|
||||
<span className="font-semibold text-blue-500">{pairId}</span>
|
||||
</div>
|
||||
{incomingPluginHash ? (
|
||||
<>
|
||||
<div className="font-semibold text-orange-500">
|
||||
Your peer is requesting the following proof:
|
||||
</div>
|
||||
<Plugin
|
||||
className="w-full bg-white !cursor-default hover:!bg-white active:!bg-white hover:!border-slate-300"
|
||||
hash={incomingPluginHash}
|
||||
hex={incomingProofRequest}
|
||||
unremovable
|
||||
/>
|
||||
<div className="flex flex-row gap-2">
|
||||
<button className="button" onClick={reject}>
|
||||
Decline
|
||||
</button>
|
||||
<button className="button button--primary" onClick={accept}>
|
||||
Accept
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
) : outgoingPluginHash ? (
|
||||
<>
|
||||
<div className="font-semibold text-orange-500">
|
||||
Sent request for following proof:
|
||||
</div>
|
||||
<Plugin
|
||||
className="w-full bg-white !cursor-default hover:!bg-white active:!bg-white hover:!border-slate-300"
|
||||
hash={outgoingPluginHash}
|
||||
onClick={() => null}
|
||||
unremovable
|
||||
/>
|
||||
<button className="button" onClick={cancel}>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
className="button button--primary"
|
||||
onClick={() => showModal(true)}
|
||||
>
|
||||
Request Proof
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PluginListModal({ onClose }: { onClose: () => void }) {
|
||||
const onRequestProof = useCallback(async (hash: string) => {
|
||||
requestProofByHash(hash);
|
||||
}, []);
|
||||
return (
|
||||
<Modal className="mx-4" onClose={onClose}>
|
||||
<ModalHeader onClose={onClose}>Choose a plugin to continue</ModalHeader>
|
||||
<PluginList className="m-2" onClick={onRequestProof} unremovable />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
function IncomingRequest() {
|
||||
const [incomingRequest] = useIncomingPairingRequests();
|
||||
|
||||
const accept = useCallback(() => {
|
||||
if (incomingRequest) acceptPairRequest(incomingRequest);
|
||||
}, [incomingRequest]);
|
||||
|
||||
const reject = useCallback(() => {
|
||||
if (incomingRequest) rejectPairRequest(incomingRequest);
|
||||
}, [incomingRequest]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div>
|
||||
<span className="font-semibold text-blue-500">{incomingRequest}</span>
|
||||
<span> wants to pair with you.</span>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2">
|
||||
<button className="button" onClick={reject}>
|
||||
Decline
|
||||
</button>
|
||||
<button className="button button--primary" onClick={accept}>
|
||||
Accept
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OutgoingRequest() {
|
||||
const [outgoingRequest] = useOutgoingPairingRequests();
|
||||
|
||||
const cancel = useCallback(() => {
|
||||
if (outgoingRequest) {
|
||||
cancelPairRequest(outgoingRequest);
|
||||
}
|
||||
}, [outgoingRequest]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<span className="flex flex-row items-center gap-2 mx-2">
|
||||
<Icon
|
||||
className="animate-spin w-fit text-slate-500"
|
||||
fa="fa-solid fa-spinner"
|
||||
size={1}
|
||||
/>
|
||||
<span>
|
||||
<span>Awaiting response from </span>
|
||||
<span className="font-semibold text-blue-500">{outgoingRequest}</span>
|
||||
<span>...</span>
|
||||
</span>
|
||||
</span>
|
||||
<button className="button" onClick={cancel}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ClientNotStarted() {
|
||||
return (
|
||||
<div className="flex flex-col text-slate-500 font-semibold gap-2">
|
||||
Client has not started
|
||||
<button className="button button--primary" onClick={connectRendezvous}>
|
||||
Start Client
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PendingConnection() {
|
||||
const dispatch = useDispatch();
|
||||
const [target, setTarget] = useState('');
|
||||
|
||||
const onSend = useCallback(() => {
|
||||
dispatch(setP2PError(''));
|
||||
sendPairRequest(target);
|
||||
}, [target]);
|
||||
|
||||
const onChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setP2PError(''));
|
||||
setTarget(e.target.value);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-full items-center gap-2">
|
||||
<div className="flex flex-row justify-center gap-2">
|
||||
<Icon
|
||||
className="animate-spin w-fit text-slate-500"
|
||||
fa="fa-solid fa-spinner"
|
||||
size={1}
|
||||
/>
|
||||
<div className="text-slate-500 font-semibold">
|
||||
Waiting for pairing request...
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-slate-500">or</div>
|
||||
<div className="w-full flex flex-row px-2 items-center">
|
||||
<input
|
||||
className="flex-grow flex-shrink w-0 outline-0 px-2 py-1 cursor-default"
|
||||
placeholder="Enter Peer ID to send pairing request"
|
||||
onChange={onChange}
|
||||
value={target}
|
||||
/>
|
||||
<button
|
||||
className="button button--primary w-fit h-full"
|
||||
onClick={onSend}
|
||||
>
|
||||
Send Pairing Request
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2,11 +2,13 @@ import { combineReducers } from 'redux';
|
||||
import requests from './requests';
|
||||
import history from './history';
|
||||
import plugins from './plugins';
|
||||
import p2p from './p2p';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
requests,
|
||||
history,
|
||||
plugins,
|
||||
p2p,
|
||||
});
|
||||
|
||||
export type AppRootState = ReturnType<typeof rootReducer>;
|
||||
|
||||
321
src/reducers/p2p.ts
Normal file
321
src/reducers/p2p.ts
Normal file
@@ -0,0 +1,321 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppRootState } from './index';
|
||||
import deepEqual from 'fast-deep-equal';
|
||||
import { Dispatch } from 'redux';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { BackgroundActiontype } from '../entries/Background/rpc';
|
||||
|
||||
enum ActionType {
|
||||
'/p2p/setConnected' = '/p2p/setConnected',
|
||||
'/p2p/setClientId' = '/p2p/setClientId',
|
||||
'/p2p/setPairing' = '/p2p/setPairing',
|
||||
'/p2p/setError' = '/p2p/setError',
|
||||
'/p2p/appendIncomingPairingRequest' = '/p2p/appendIncomingPairingRequest',
|
||||
'/p2p/appendOutgoingPairingRequest' = '/p2p/appendOutgoingPairingRequest',
|
||||
'/p2p/setIncomingPairingRequest' = '/p2p/setIncomingPairingRequest',
|
||||
'/p2p/setOutgoingPairingRequest' = '/p2p/setOutgoingPairingRequest',
|
||||
'/p2p/appendIncomingProofRequest' = '/p2p/appendIncomingProofRequest',
|
||||
'/p2p/appendOutgoingProofRequest' = '/p2p/appendOutgoingProofRequest',
|
||||
'/p2p/setIncomingProofRequest' = '/p2p/setIncomingProofRequest',
|
||||
'/p2p/setOutgoingProofRequest' = '/p2p/setOutgoingProofRequest',
|
||||
}
|
||||
|
||||
type Action<payload> = {
|
||||
type: ActionType;
|
||||
payload?: payload;
|
||||
error?: boolean;
|
||||
meta?: any;
|
||||
};
|
||||
|
||||
type State = {
|
||||
clientId: string;
|
||||
pairing: string;
|
||||
connected: boolean;
|
||||
error: string;
|
||||
incomingPairingRequests: string[];
|
||||
outgoingPairingRequests: string[];
|
||||
incomingProofRequests: string[];
|
||||
outgoingProofRequests: string[];
|
||||
};
|
||||
|
||||
export type RequestProofMessage = {
|
||||
to: string;
|
||||
from: string;
|
||||
id: number;
|
||||
text?: undefined;
|
||||
};
|
||||
|
||||
const initialState: State = {
|
||||
clientId: '',
|
||||
pairing: '',
|
||||
error: '',
|
||||
connected: false,
|
||||
incomingPairingRequests: [],
|
||||
outgoingPairingRequests: [],
|
||||
incomingProofRequests: [],
|
||||
outgoingProofRequests: [],
|
||||
};
|
||||
|
||||
export const fetchP2PState = async () => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.get_p2p_state,
|
||||
});
|
||||
};
|
||||
|
||||
export const connectRendezvous = () => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.connect_rendezvous,
|
||||
});
|
||||
};
|
||||
|
||||
export const disconnectRendezvous = () => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.disconnect_rendezvous,
|
||||
});
|
||||
};
|
||||
|
||||
export const setConnected = (connected = false) => ({
|
||||
type: ActionType['/p2p/setConnected'],
|
||||
payload: connected,
|
||||
});
|
||||
|
||||
export const setClientId = (clientId: string) => ({
|
||||
type: ActionType['/p2p/setClientId'],
|
||||
payload: clientId,
|
||||
});
|
||||
|
||||
export const setPairing = (clientId: string) => ({
|
||||
type: ActionType['/p2p/setPairing'],
|
||||
payload: clientId,
|
||||
});
|
||||
|
||||
export const appendIncomingPairingRequests = (peerId: string) => ({
|
||||
type: ActionType['/p2p/appendIncomingPairingRequest'],
|
||||
payload: peerId,
|
||||
});
|
||||
|
||||
export const appendIncomingProofRequests = (peerId: string) => ({
|
||||
type: ActionType['/p2p/appendIncomingProofRequest'],
|
||||
payload: peerId,
|
||||
});
|
||||
|
||||
export const appendOutgoingPairingRequests = (peerId: string) => ({
|
||||
type: ActionType['/p2p/appendOutgoingPairingRequest'],
|
||||
payload: peerId,
|
||||
});
|
||||
|
||||
export const appendOutgoingProofRequest = (peerId: string) => ({
|
||||
type: ActionType['/p2p/appendOutgoingProofRequest'],
|
||||
payload: peerId,
|
||||
});
|
||||
|
||||
export const setIncomingPairingRequest = (peerIds: string[]) => ({
|
||||
type: ActionType['/p2p/setIncomingPairingRequest'],
|
||||
payload: peerIds,
|
||||
});
|
||||
|
||||
export const setOutgoingPairingRequest = (peerIds: string[]) => ({
|
||||
type: ActionType['/p2p/setOutgoingPairingRequest'],
|
||||
payload: peerIds,
|
||||
});
|
||||
|
||||
export const setIncomingProofRequest = (peerIds: string[]) => ({
|
||||
type: ActionType['/p2p/setIncomingProofRequest'],
|
||||
payload: peerIds,
|
||||
});
|
||||
|
||||
export const setOutgoingProofRequest = (peerIds: string[]) => ({
|
||||
type: ActionType['/p2p/setOutgoingProofRequest'],
|
||||
payload: peerIds,
|
||||
});
|
||||
|
||||
export const setP2PError = (error: string) => ({
|
||||
type: ActionType['/p2p/setError'],
|
||||
payload: error,
|
||||
});
|
||||
|
||||
export const requestProof = (pluginHash: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.request_p2p_proof,
|
||||
data: pluginHash,
|
||||
});
|
||||
};
|
||||
|
||||
export const requestProofByHash = (pluginHash: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.request_p2p_proof_by_hash,
|
||||
data: pluginHash,
|
||||
});
|
||||
};
|
||||
|
||||
export const sendPairRequest = async (targetId: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.send_pair_request,
|
||||
data: targetId,
|
||||
});
|
||||
};
|
||||
|
||||
export const cancelPairRequest = async (targetId: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.cancel_pair_request,
|
||||
data: targetId,
|
||||
});
|
||||
};
|
||||
|
||||
export const acceptPairRequest = async (targetId: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.accept_pair_request,
|
||||
data: targetId,
|
||||
});
|
||||
};
|
||||
|
||||
export const rejectPairRequest = async (targetId: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.reject_pair_request,
|
||||
data: targetId,
|
||||
});
|
||||
};
|
||||
|
||||
export const cancelProofRequest = async (plughinHash: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.cancel_proof_request,
|
||||
data: plughinHash,
|
||||
});
|
||||
};
|
||||
|
||||
export const acceptProofRequest = async (plughinHash: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.accept_proof_request,
|
||||
data: plughinHash,
|
||||
});
|
||||
};
|
||||
|
||||
export const rejectProofRequest = async (plughinHash: string) => {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.reject_proof_request,
|
||||
data: plughinHash,
|
||||
});
|
||||
};
|
||||
|
||||
export default function p2p(state = initialState, action: Action<any>): State {
|
||||
switch (action.type) {
|
||||
case ActionType['/p2p/setConnected']:
|
||||
return {
|
||||
...state,
|
||||
connected: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/setClientId']:
|
||||
return {
|
||||
...state,
|
||||
clientId: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/setPairing']:
|
||||
return {
|
||||
...state,
|
||||
pairing: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/appendIncomingPairingRequest']:
|
||||
return {
|
||||
...state,
|
||||
incomingPairingRequests: [
|
||||
...new Set(state.incomingPairingRequests.concat(action.payload)),
|
||||
],
|
||||
};
|
||||
case ActionType['/p2p/appendOutgoingPairingRequest']:
|
||||
return {
|
||||
...state,
|
||||
outgoingPairingRequests: [
|
||||
...new Set(state.outgoingPairingRequests.concat(action.payload)),
|
||||
],
|
||||
};
|
||||
case ActionType['/p2p/setIncomingPairingRequest']:
|
||||
return {
|
||||
...state,
|
||||
incomingPairingRequests: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/setOutgoingPairingRequest']:
|
||||
return {
|
||||
...state,
|
||||
outgoingPairingRequests: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/appendIncomingProofRequest']:
|
||||
return {
|
||||
...state,
|
||||
incomingProofRequests: [
|
||||
...new Set(state.incomingProofRequests.concat(action.payload)),
|
||||
],
|
||||
};
|
||||
case ActionType['/p2p/appendOutgoingProofRequest']:
|
||||
return {
|
||||
...state,
|
||||
outgoingProofRequests: [
|
||||
...new Set(state.outgoingProofRequests.concat(action.payload)),
|
||||
],
|
||||
};
|
||||
case ActionType['/p2p/setIncomingProofRequest']:
|
||||
return {
|
||||
...state,
|
||||
incomingProofRequests: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/setOutgoingProofRequest']:
|
||||
return {
|
||||
...state,
|
||||
outgoingProofRequests: action.payload,
|
||||
};
|
||||
case ActionType['/p2p/setError']:
|
||||
return {
|
||||
...state,
|
||||
error: action.payload,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export function useClientId() {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.clientId;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useConnected() {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.connected;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function usePairId(): string {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.pairing;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useIncomingPairingRequests(): string[] {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.incomingPairingRequests;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useOutgoingPairingRequests(): string[] {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.outgoingPairingRequests;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useIncomingProofRequests(): string[] {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.incomingProofRequests;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useOutgoingProofRequests(): string[] {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.outgoingProofRequests;
|
||||
}, deepEqual);
|
||||
}
|
||||
|
||||
export function useP2PError(): string {
|
||||
return useSelector((state: AppRootState) => {
|
||||
return state.p2p.error;
|
||||
}, deepEqual);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export const EXPLORER_API = 'https://explorer.tlsnotary.org';
|
||||
export const NOTARY_API = 'https://notary.pse.dev/v0.1.0-alpha.5';
|
||||
export const RENDEZVOUS_API = 'wss://explorer.tlsnotary.org:3000';
|
||||
export const NOTARY_PROXY = 'wss://notary.pse.dev/proxy';
|
||||
export const MAX_RECV = 16384;
|
||||
export const MAX_SENT = 4096;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
BackgroundActiontype,
|
||||
handleExecP2PPluginProver,
|
||||
handleExecPluginProver,
|
||||
RequestLog,
|
||||
} from '../entries/Background/rpc';
|
||||
@@ -148,6 +149,10 @@ const VALID_HOST_FUNCS: { [name: string]: string } = {
|
||||
export const makePlugin = async (
|
||||
arrayBuffer: ArrayBuffer,
|
||||
config?: PluginConfig,
|
||||
meta?: {
|
||||
p2p: boolean;
|
||||
clientId: string;
|
||||
},
|
||||
) => {
|
||||
const module = await WebAssembly.compile(arrayBuffer);
|
||||
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
|
||||
@@ -219,15 +224,31 @@ export const makePlugin = async (
|
||||
secretResps = JSON.parse(out.string());
|
||||
}
|
||||
|
||||
handleExecPluginProver({
|
||||
type: BackgroundActiontype.execute_plugin_prover,
|
||||
data: {
|
||||
...params,
|
||||
body: reqBody,
|
||||
secretResps,
|
||||
now,
|
||||
},
|
||||
});
|
||||
if (meta?.p2p) {
|
||||
handleExecP2PPluginProver({
|
||||
type: BackgroundActiontype.execute_p2p_plugin_prover,
|
||||
data: {
|
||||
...params,
|
||||
pluginHash: await sha256(
|
||||
Buffer.from(arrayBuffer).toString('hex'),
|
||||
),
|
||||
body: reqBody,
|
||||
secretResps,
|
||||
now,
|
||||
clientId: meta.clientId,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
handleExecPluginProver({
|
||||
type: BackgroundActiontype.execute_plugin_prover,
|
||||
data: {
|
||||
...params,
|
||||
body: reqBody,
|
||||
secretResps,
|
||||
now,
|
||||
},
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
return context.store(`${id}`);
|
||||
|
||||
@@ -13,7 +13,7 @@ export const HostFunctionsDescriptions: {
|
||||
);
|
||||
},
|
||||
notarize: ({ notaryUrls, proxyUrls }) => {
|
||||
const notaries = ['default notary'].concat(notaryUrls || []);
|
||||
const notaries = ['default notary', 'your peer'].concat(notaryUrls || []);
|
||||
const proxies = ['default proxy'].concat(proxyUrls || []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -38,7 +38,12 @@ export async function fetchPluginConfigByHash(
|
||||
});
|
||||
}
|
||||
|
||||
export async function runPlugin(hash: string, method: string, params?: string) {
|
||||
export async function runPlugin(
|
||||
hash: string,
|
||||
method: string,
|
||||
params?: string,
|
||||
meta?: any,
|
||||
) {
|
||||
return browser.runtime.sendMessage({
|
||||
type: BackgroundActiontype.run_plugin,
|
||||
data: {
|
||||
@@ -46,5 +51,6 @@ export async function runPlugin(hash: string, method: string, params?: string) {
|
||||
method,
|
||||
params,
|
||||
},
|
||||
meta,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { LoggingLevel } from 'tlsn-js';
|
||||
import { RENDEZVOUS_API } from './constants';
|
||||
|
||||
export const NOTARY_API_LS_KEY = 'notary-api';
|
||||
export const PROXY_API_LS_KEY = 'proxy-api';
|
||||
export const MAX_SENT_LS_KEY = 'max-sent';
|
||||
export const MAX_RECEIVED_LS_KEY = 'max-received';
|
||||
export const LOGGING_FILTER_KEY = 'logging-filter-2';
|
||||
export const RENDEZVOUS_API_LS_KEY = 'rendezvous-api';
|
||||
|
||||
export async function set(key: string, value: string) {
|
||||
return chrome.storage.sync.set({ [key]: value });
|
||||
@@ -36,3 +38,7 @@ export async function getProxyApi() {
|
||||
export async function getLoggingFilter(): Promise<LoggingLevel> {
|
||||
return await get(LOGGING_FILTER_KEY, 'Info');
|
||||
}
|
||||
|
||||
export async function getRendezvousApi(): Promise<string> {
|
||||
return await get(RENDEZVOUS_API_LS_KEY, RENDEZVOUS_API);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user