WASM: PoW

This commit is contained in:
2023-09-24 21:28:39 +01:00
parent 9f731da5be
commit 6e7a28a42b
19 changed files with 1146 additions and 52 deletions

View File

@ -21,7 +21,7 @@ import Note from "Element/Note";
import { ClipboardEventHandler } from "react";
import useLogin from "Hooks/useLogin";
import { System } from "index";
import { System, WasmPowWorker } from "index";
import AsyncButton from "Element/AsyncButton";
import { AsyncIcon } from "Element/AsyncIcon";
import { fetchNip05Pubkey } from "@snort/shared";
@ -30,9 +30,9 @@ import { useNoteCreator } from "State/NoteCreator";
export function NoteCreator() {
const { formatMessage } = useIntl();
const publisher = useEventPublisher();
const uploader = useFileUpload();
const login = useLogin(s => ({ relays: s.relays, publicKey: s.publicKey }));
const login = useLogin(s => ({ relays: s.relays, publicKey: s.publicKey, pow: s.preferences.pow }));
const publisher = login.pow ? useEventPublisher()?.pow(login.pow, new WasmPowWorker()) : useEventPublisher();
const note = useNoteCreator();
const relays = login.relays;

View File

@ -2,13 +2,14 @@ import useLogin from "Hooks/useLogin";
import "./PinPrompt.css";
import { ReactNode, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
import useEventPublisher from "Hooks/useEventPublisher";
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
import { unwrap } from "@snort/shared";
import { EventPublisher, InvalidPinError, PinEncrypted, PinEncryptedPayload } from "@snort/system";
import { DefaultPowWorker } from "index";
import useEventPublisher from "Hooks/useEventPublisher";
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
import Modal from "./Modal";
import AsyncButton from "./AsyncButton";
import { WasmPowWorker } from "index";
export function PinPrompt({
onResult,
@ -91,7 +92,7 @@ export function LoginUnlock() {
const pub = EventPublisher.privateKey(k);
if (login.preferences.pow) {
pub.pow(login.preferences.pow, DefaultPowWorker);
pub.pow(login.preferences.pow, new WasmPowWorker());
}
LoginStore.setPublisher(login.id, pub);
LoginStore.updateSession({
@ -108,7 +109,7 @@ export function LoginUnlock() {
const pub = createPublisher(login, key);
if (pub) {
if (login.preferences.pow) {
pub.pow(login.preferences.pow, DefaultPowWorker);
pub.pow(login.preferences.pow, new WasmPowWorker());
}
LoginStore.setPublisher(login.id, pub);
LoginStore.updateSession({

View File

@ -1,6 +1,5 @@
import useLogin from "Hooks/useLogin";
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
import { DefaultPowWorker } from "index";
export default function useEventPublisher() {
const login = useLogin();
@ -10,12 +9,8 @@ export default function useEventPublisher() {
if (login.publicKey && !existing && !sessionNeedsPin(login)) {
existing = createPublisher(login);
if (existing) {
if (login.preferences.pow) {
existing.pow(login.preferences.pow, DefaultPowWorker);
}
LoginStore.setPublisher(login.id, existing);
}
}
return existing;
}

View File

@ -1,6 +1,6 @@
import { bytesToHex } from "@noble/hashes/utils";
import { DefaultQueryOptimizer, FlatReqFilter, QueryOptimizer, ReqFilter } from "@snort/system";
import { compress, expand_filter, flat_merge, get_diff, default as wasmInit } from "@snort/system-wasm";
import { DefaultQueryOptimizer, EventExt, FlatReqFilter, PowMiner, QueryOptimizer, ReqFilter } from "@snort/system";
import { compress, expand_filter, flat_merge, get_diff, pow, default as wasmInit } from "@snort/system-wasm";
import WasmPath from "@snort/system-wasm/pkg/system_wasm_bg.wasm";
import { Bench } from "tinybench";
@ -90,15 +90,35 @@ const testCompress = (q: QueryOptimizer) => {
const wasmSuite = new Bench({ time: 1_000 });
const suite = new Bench({ time: 1_000 });
const addTests = (s: Bench, q: QueryOptimizer) => {
const addTests = (s: Bench, q: QueryOptimizer, p: PowMiner) => {
s.add("expand", () => testExpand(q));
s.add("get_diff", () => testGetDiff(q));
s.add("flat_merge", () => testFlatMerge(q));
s.add("compress", () => testCompress(q));
s.add("pow", () => {
const ev = {
id: "",
kind: 1,
created_at: 1234567,
pubkey: "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed",
content: "test",
sig: "",
tags: [],
};
p.minePow(ev, 12);
});
};
addTests(suite, DefaultQueryOptimizer);
addTests(wasmSuite, WasmQueryOptimizer);
addTests(suite, DefaultQueryOptimizer, {
minePow(ev, target) {
return Promise.resolve(EventExt.minePow(ev, target));
},
});
addTests(wasmSuite, WasmQueryOptimizer, {
minePow(ev, target) {
return Promise.resolve(pow(ev, target));
},
});
const runAll = async () => {
await wasmInit(WasmPath);
@ -106,9 +126,15 @@ const runAll = async () => {
console.log("DefaultQueryOptimizer");
await suite.run();
console.table(suite.table());
const p0 = document.createElement("pre");
p0.innerText = JSON.stringify(suite.table(), undefined, " ");
document.body.appendChild(p0);
console.log("WasmQueryOptimizer");
await wasmSuite.run();
console.table(wasmSuite.table());
const p1 = document.createElement("pre");
p1.innerText = JSON.stringify(wasmSuite.table(), undefined, " ");
document.body.appendChild(p1);
};
runAll().catch(console.error);

View File

@ -3,7 +3,7 @@ import { EventKind, NostrPrefix, encodeTLVEntries, TLVEntryType, TLVEntry, decod
import { GiftWrapCache } from "Cache/GiftWrapCache";
import { UnwrappedGift } from "Db";
import { Chat, ChatSystem, ChatType, lastReadInChat } from "chat";
import { DefaultPowWorker } from "index";
import { WasmPowWorker } from "index";
export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatSystem {
#cache: GiftWrapCache;
@ -105,7 +105,9 @@ export class Nip24ChatSystem extends ExternalStore<Array<Chat>> implements ChatS
const recvSealedN = pub.giftWrap(await pub.sealRumor(gossip, pt.id), pt.id, powTarget);
messages.push(recvSealedN);
}
messages.push(pub.giftWrap(await pub.sealRumor(gossip, pub.pubKey), pub.pubKey, powTarget, DefaultPowWorker));
messages.push(
pub.giftWrap(await pub.sealRumor(gossip, pub.pubKey), pub.pubKey, powTarget, new WasmPowWorker()),
);
return await Promise.all(messages);
},
sendMessage: (ev, system) => {

View File

@ -2,13 +2,21 @@ import "./index.css";
import "@szhsin/react-menu/dist/index.css";
import "./fonts/inter.css";
import { compress, expand_filter, flat_merge, get_diff, default as wasmInit } from "@snort/system-wasm";
import { compress, expand_filter, flat_merge, get_diff, pow, default as wasmInit } from "@snort/system-wasm";
import WasmPath from "@snort/system-wasm/pkg/system_wasm_bg.wasm";
import { StrictMode } from "react";
import * as ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { NostrSystem, ProfileLoaderService, PowWorker, QueryOptimizer, FlatReqFilter, ReqFilter } from "@snort/system";
import {
NostrSystem,
ProfileLoaderService,
QueryOptimizer,
FlatReqFilter,
ReqFilter,
PowMiner,
NostrEvent,
} from "@snort/system";
import { SnortContext } from "@snort/system-react";
import * as serviceWorkerRegistration from "serviceWorkerRegistration";
@ -53,6 +61,13 @@ const WasmQueryOptimizer = {
},
} as QueryOptimizer;
export class WasmPowWorker implements PowMiner {
minePow(ev: NostrEvent, target: number): Promise<NostrEvent> {
const res = pow(ev, target);
return Promise.resolve(res);
}
}
/**
* Singleton nostr system
*/
@ -75,11 +90,6 @@ export const System = new NostrSystem({
*/
export const ProfileLoader = new ProfileLoaderService(System, UserCache);
/**
* Singleton POW worker
*/
export const DefaultPowWorker = new PowWorker("/pow.js");
serviceWorkerRegistration.register();
async function initSite() {