put mempow in webworker and changed wasm import

This commit is contained in:
2024-11-18 01:12:05 +02:00
parent db754eb121
commit 14214ba6f0
9 changed files with 426 additions and 93 deletions

View File

@@ -1032,7 +1032,7 @@ function App() {
.sendMessage("decryptWallet", {
password: authenticatePassword,
wallet: rawWallet,
})
}, 120000)
.then((response) => {
if (response && !response.error) {
setAuthenticatePassword("");

View File

@@ -19,6 +19,7 @@ import {
encryptSingle,
objectToBase64,
} from "./qdn/encryption/group-encryption";
import ChatComputePowWorker from './chatComputePow.worker.js?worker';
import { reusableGet } from "./qdn/publish/pubish";
import { signChat } from "./transactions/signChat";
import { createTransaction } from "./transactions/transactions";
@@ -410,6 +411,30 @@ async function checkWebviewFocus() {
window.addEventListener("message", handleMessage);
});
}
const worker = new ChatComputePowWorker()
export async function performPowTask(chatBytes, difficulty) {
return new Promise((resolve, reject) => {
worker.onmessage = (e) => {
if (e.data.error) {
reject(new Error(e.data.error));
} else {
resolve(e.data);
}
};
worker.onerror = (err) => {
reject(err);
};
// Send the task to the worker
worker.postMessage({
chatBytes,
path: `${import.meta.env.BASE_URL}memory-pow.wasm.full`,
difficulty,
});
});
}
function playNotificationSound() {
// chrome.runtime.sendMessage({ action: "PLAY_NOTIFICATION_SOUND" });
@@ -1399,7 +1424,6 @@ async function sendChatForBuyOrder({ qortAddress, recipientPublicKey, message, a
};
const balance = await getBalanceInfo();
const hasEnoughBalance = +balance < 4 ? false : true;
const difficulty = 8;
const jsonData = {
addresses: message.addresses,
foreignKey: message.foreignKey,
@@ -1460,11 +1484,11 @@ async function sendChatForBuyOrder({ qortAddress, recipientPublicKey, message, a
}
const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes,
path,
difficulty,
});
const chatBytes = tx.chatBytes;
const difficulty = 8;
const { nonce, chatBytesArray } = await performPowTask(chatBytes, difficulty);
let _response = await signChatFunc(
chatBytesArray,
nonce,
@@ -1477,6 +1501,9 @@ async function sendChatForBuyOrder({ qortAddress, recipientPublicKey, message, a
return _response;
}
export async function sendChatGroup({
groupId,
typeMessage,
@@ -1497,7 +1524,7 @@ export async function sendChatGroup({
};
// const balance = await getBalanceInfo();
// const hasEnoughBalance = +balance < 4 ? false : true;
const difficulty = 8;
const txBody = {
timestamp: Date.now(),
@@ -1520,13 +1547,12 @@ export async function sendChatGroup({
// if (!hasEnoughBalance) {
// throw new Error("Must have at least 4 QORT to send a chat message");
// }
const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes,
path,
difficulty,
});
const chatBytes = tx.chatBytes;
const difficulty = 8;
const { nonce, chatBytesArray } = await performPowTask(chatBytes, difficulty);
let _response = await signChatFunc(chatBytesArray, nonce, null, keyPair);
if (_response?.error) {
throw new Error(_response?.message);
@@ -1572,7 +1598,6 @@ export async function sendChatDirect({
// const balance = await getBalanceInfo();
// const hasEnoughBalance = +balance < 4 ? false : true;
const difficulty = 8;
const finalJson = {
message: messageText,
@@ -1600,13 +1625,10 @@ export async function sendChatDirect({
// if (!hasEnoughBalance) {
// throw new Error("Must have at least 4 QORT to send a chat message");
// }
const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes,
path,
difficulty,
});
const chatBytes = tx.chatBytes;
const difficulty = 8;
const { nonce, chatBytesArray } = await performPowTask(chatBytes, difficulty);
let _response = await signChatFunc(chatBytesArray, nonce, null, keyPair);
if (_response?.error) {

View File

@@ -0,0 +1,107 @@
import { Sha256 } from 'asmcrypto.js';
import wasmInit from './memory-pow.wasm?init';
let compute; // Exported compute function from Wasm
let memory; // WebAssembly.Memory instance
let heap; // Uint8Array view of the memory buffer
let brk = 512 * 1024; // Initial brk set to 512 KiB
const allocations = new Map(); // Track allocations by pointer
let workBufferPtr = null; // Reuse work buffer
const workBufferLength = 8 * 1024 * 1024; // 8 MiB
// Load the WebAssembly module
async function loadWasm() {
try {
memory = new WebAssembly.Memory({ initial: 256, maximum: 256 }); // 16 MiB
heap = new Uint8Array(memory.buffer);
const importObject = {
env: {
memory, // Pass memory to Wasm
abort: () => { throw new Error('Wasm abort called'); }, // Handle abort calls from Wasm
},
};
const wasmModule = await wasmInit(importObject);
compute = wasmModule.exports.compute2;
console.log('Wasm loaded successfully:', compute);
} catch (error) {
console.error('Error loading Wasm:', error);
throw error;
}
}
// Memory allocation function
function sbrk(size) {
const old = brk;
// If a previous allocation exists for this size, reuse it
if (allocations.has(size)) {
return allocations.get(size);
}
brk += size;
// Grow memory if needed
if (brk > memory.buffer.byteLength) {
const pagesNeeded = Math.ceil((brk - memory.buffer.byteLength) / (64 * 1024)); // 64 KiB per page
console.log(`Growing memory by ${pagesNeeded} pages`);
try {
memory.grow(pagesNeeded);
heap = new Uint8Array(memory.buffer); // Update heap view
} catch (e) {
console.error('Failed to grow memory:', e);
throw new RangeError('WebAssembly.Memory.grow(): Maximum memory size exceeded');
}
}
allocations.set(size, old); // Track the allocation
return old;
}
// Proof-of-Work computation function
async function computePow(chatBytes, difficulty) {
if (!compute) {
throw new Error('WebAssembly module not initialized. Call loadWasm first.');
}
const chatBytesArray = Uint8Array.from(Object.values(chatBytes));
const chatBytesHash = new Sha256().process(chatBytesArray).finish().result;
// Allocate memory for the hash
const hashPtr = sbrk(32);
const hashAry = new Uint8Array(memory.buffer, hashPtr, 32);
hashAry.set(chatBytesHash);
// Reuse the work buffer if already allocated
if (!workBufferPtr) {
workBufferPtr = sbrk(workBufferLength);
}
console.log('Starting POW computation...');
const nonce = compute(hashPtr, workBufferPtr, workBufferLength, difficulty);
console.log('POW computation finished.');
return { nonce, chatBytesArray };
}
// Worker event listener
self.addEventListener('message', async (e) => {
const { chatBytes, difficulty } = e.data;
try {
// Initialize Wasm if not already done
if (!compute) {
await loadWasm();
}
// Perform the POW computation
const result = await computePow(chatBytes, difficulty);
// Send the result back to the main thread
self.postMessage(result);
} catch (error) {
console.error('Error in worker:', error);
self.postMessage({ error: error.message });
}
});

BIN
src/memory-pow.wasm Normal file

Binary file not shown.

View File

@@ -13,7 +13,8 @@ import {
sendQortFee,
sendCoin as sendCoinFunc,
isUsingLocal,
createBuyOrderTx
createBuyOrderTx,
performPowTask
} from "../background";
import { getNameInfo } from "../backgroundFunctions/encryption";
import { showSaveFilePicker } from "../components/Apps/useQortalMessageListener";
@@ -1066,7 +1067,6 @@ export const sendChatMessage = async (data, isFromExtension) => {
publicKey: uint8PublicKey,
};
const difficulty = 8;
const tx = await createTransaction(18, keyPair, {
timestamp: sendTimestamp,
recipient: recipient,
@@ -1078,15 +1078,13 @@ export const sendChatMessage = async (data, isFromExtension) => {
isEncrypted: 1,
isText: 1,
});
const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes,
path,
difficulty,
});
const chatBytes = tx.chatBytes;
const difficulty = 8;
const { nonce, chatBytesArray } = await performPowTask(chatBytes, difficulty);
let _response = await signChatFunc(chatBytesArray, nonce, null, keyPair);
if (_response?.error) {
throw new Error(_response?.message);
@@ -1106,7 +1104,6 @@ export const sendChatMessage = async (data, isFromExtension) => {
publicKey: uint8PublicKey,
};
const difficulty = 8;
const txBody = {
timestamp: Date.now(),
@@ -1125,14 +1122,11 @@ export const sendChatMessage = async (data, isFromExtension) => {
// if (!hasEnoughBalance) {
// throw new Error("Must have at least 4 QORT to send a chat message");
// }
const path = `${import.meta.env.BASE_URL}memory-pow.wasm.full`;
const { nonce, chatBytesArray } = await computePow({
chatBytes: tx.chatBytes,
path,
difficulty,
});
const chatBytes = tx.chatBytes;
const difficulty = 8;
const { nonce, chatBytesArray } = await performPowTask(chatBytes, difficulty);
let _response = await signChatFunc(chatBytesArray, nonce, null, keyPair);
if (_response?.error) {
throw new Error(_response?.message);

Binary file not shown.