mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-07-23 04:36:52 +00:00
put mempow in webworker and changed wasm import
This commit is contained in:
@@ -1032,7 +1032,7 @@ function App() {
|
||||
.sendMessage("decryptWallet", {
|
||||
password: authenticatePassword,
|
||||
wallet: rawWallet,
|
||||
})
|
||||
}, 120000)
|
||||
.then((response) => {
|
||||
if (response && !response.error) {
|
||||
setAuthenticatePassword("");
|
||||
|
@@ -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) {
|
||||
|
107
src/chatComputePow.worker.js
Normal file
107
src/chatComputePow.worker.js
Normal 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
BIN
src/memory-pow.wasm
Normal file
Binary file not shown.
@@ -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);
|
||||
|
BIN
src/wasm/memory-pow.wasm.full
Normal file
BIN
src/wasm/memory-pow.wasm.full
Normal file
Binary file not shown.
Reference in New Issue
Block a user