From 9b46a13d9af893f019738093e479bace53e56384 Mon Sep 17 00:00:00 2001 From: Phillip Lang Martinez Date: Sat, 24 Dec 2022 17:05:02 -0500 Subject: [PATCH] add publicize transaction in background --- qortal-ui-core/package.json | 3 +- qortal-ui-core/src/components/app-info.js | 106 +++++++++++++++++- .../src/components/computePowWorker.js | 82 ++++++++++++++ qortal-ui-core/tooling/generateBuildConfig.js | 3 + .../tooling/generateES5BuildConfig.js | 2 + .../api/transactions/PublicizeTransaction.js | 7 +- 6 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 qortal-ui-core/src/components/computePowWorker.js diff --git a/qortal-ui-core/package.json b/qortal-ui-core/package.json index b293210f..1e00ccfb 100644 --- a/qortal-ui-core/package.json +++ b/qortal-ui-core/package.json @@ -77,7 +77,8 @@ "rollup-plugin-postcss": "4.0.2", "rollup-plugin-progress": "1.1.2", "rollup-plugin-scss": "3.0.0", - "rollup-plugin-terser": "7.0.2" + "rollup-plugin-terser": "7.0.2", + "rollup-plugin-web-worker-loader": "^1.6.1" }, "engines": { "node": ">=16.15.0" diff --git a/qortal-ui-core/src/components/app-info.js b/qortal-ui-core/src/components/app-info.js index 06bedc8a..59160e10 100644 --- a/qortal-ui-core/src/components/app-info.js +++ b/qortal-ui-core/src/components/app-info.js @@ -3,6 +3,8 @@ import { connect } from 'pwa-helpers' import { store } from '../store.js' import { doPageUrl } from '../redux/app/app-actions.js' import { translate, translateUnsafeHTML } from 'lit-translate' +import WebWorker from 'web-worker:./computePowWorker.js'; +import { routes } from '../plugins/routes.js'; import '@material/mwc-icon' import '@material/mwc-button' @@ -94,6 +96,8 @@ class AppInfo extends connect(store)(LitElement) { this.nodeStatus = {} this.pageUrl = '' this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light' + this.publicKeyisOnChainConfirmation = false + this.interval } render() { @@ -107,10 +111,110 @@ class AppInfo extends connect(store)(LitElement) { ` } + async confirmPublicKeyOnChain(address) { + const _computePow2 = async (chatBytes) => { + const difficulty = 15; + const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full' + const worker = new WebWorker(); + let nonce = null + let chatBytesArray = null + await new Promise((res, rej) => { + worker.postMessage({chatBytes, path, difficulty}); + + worker.onmessage = e => { + worker.terminate() + chatBytesArray = e.data.chatBytesArray + nonce = e.data.nonce + res() + + } + }) + + let _response = await routes.sign_chat({ + data: { + nonce: store.getState().app.selectedAddress.nonce, + chatBytesArray: chatBytesArray, + chatNonce: nonce + }, + + }); + return _response + }; + + + let stop = false + const checkPublicKey = async () => { + if (!stop) { + stop = true; + try { + const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node]; + const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port; + const url = `${nodeUrl}/addresses/publickey/${address}`; + const res = await fetch(url) + let data = '' + try { + data = await res.text(); + } catch (error) { + data = { + error: 'error' + } + } + if(data === 'false'){ + let _reference = new Uint8Array(64); + window.crypto.getRandomValues(_reference); + let reference = window.parent.Base58.encode(_reference); + const chatRes = await routes.chat({ + data: { + type: 19, + nonce: store.getState().app.selectedAddress.nonce, + params: { + lastReference: reference, + proofOfWorkNonce: 0, + fee: 0, + timestamp: Date.now(), + + }, + disableModal: true + }, + disableModal: true, + }); + + try { + const powRes = await _computePow2(chatRes) + if(powRes === true){ + clearInterval(this.interval) + + this.publicKeyisOnChainConfirmation = true + } + } catch (error) { + console.error(error) + } + } + + if (!data.error && data !== 'false' && data) { + clearInterval(this.interval) + + this.publicKeyisOnChainConfirmation = true + } + + } catch (error) { + } + stop = false + } + }; + this.interval = setInterval(checkPublicKey, 5000); + } + firstUpdated() { this.getNodeInfo() this.getCoreInfo() - + try { + this.confirmPublicKeyOnChain(store.getState().app.selectedAddress.address) + } catch (error) { + console.error(error) + } + + setInterval(() => { this.getNodeInfo() this.getCoreInfo() diff --git a/qortal-ui-core/src/components/computePowWorker.js b/qortal-ui-core/src/components/computePowWorker.js new file mode 100644 index 00000000..2ed60a20 --- /dev/null +++ b/qortal-ui-core/src/components/computePowWorker.js @@ -0,0 +1,82 @@ +import { Sha256 } from 'asmcrypto.js' + + +function sbrk(size, heap){ + let brk = 512 * 1024 // stack top + let old = brk + brk += size + + if (brk > heap.length) + throw new Error('heap exhausted') + + return old +} + + + +self.addEventListener('message', async e => { + const response = await computePow(e.data.chatBytes, e.data.path, e.data.difficulty) + postMessage(response) + +}) + + +const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 }) +const heap = new Uint8Array(memory.buffer) + + + +const computePow = async (chatBytes, path, difficulty) => { + + let response = null + + await new Promise((resolve, reject)=> { + + const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; }); + const chatBytesArray = new Uint8Array(_chatBytesArray); + const chatBytesHash = new Sha256().process(chatBytesArray).finish().result; + const hashPtr = sbrk(32, heap); + const hashAry = new Uint8Array(memory.buffer, hashPtr, 32); + hashAry.set(chatBytesHash); + + + const workBufferLength = 8 * 1024 * 1024; + const workBufferPtr = sbrk(workBufferLength, heap); + + + + const importObject = { + env: { + memory: memory + }, + }; + + function loadWebAssembly(filename, imports) { + // Fetch the file and compile it + return fetch(filename) + .then(response => response.arrayBuffer()) + .then(buffer => WebAssembly.compile(buffer)) + .then(module => { + + // Create the instance. + return new WebAssembly.Instance(module, importObject); + }); +} + + +loadWebAssembly(path) + .then(wasmModule => { + response = { + nonce : wasmModule.exports.compute2(hashPtr, workBufferPtr, workBufferLength, difficulty), + chatBytesArray + } + + resolve() + + }); + + + }) + + return response +} \ No newline at end of file diff --git a/qortal-ui-core/tooling/generateBuildConfig.js b/qortal-ui-core/tooling/generateBuildConfig.js index e8beb2b8..6d163ae9 100644 --- a/qortal-ui-core/tooling/generateBuildConfig.js +++ b/qortal-ui-core/tooling/generateBuildConfig.js @@ -7,6 +7,8 @@ const commonjs = require('@rollup/plugin-commonjs') const alias = require('@rollup/plugin-alias') const { terser } = require('rollup-plugin-terser') const scss = require('rollup-plugin-scss') +const webWorkerLoader = require('rollup-plugin-web-worker-loader'); + const generateES5BuildConfig = require('./generateES5BuildConfig') @@ -61,6 +63,7 @@ const generateBuildConfig = ({ elementComponents, functionalComponents, otherOut commonjs(), globals(), progress(), + webWorkerLoader(), scss({ output: options.sassOutputDir }), diff --git a/qortal-ui-core/tooling/generateES5BuildConfig.js b/qortal-ui-core/tooling/generateES5BuildConfig.js index 2b5d15b1..a746a6c1 100644 --- a/qortal-ui-core/tooling/generateES5BuildConfig.js +++ b/qortal-ui-core/tooling/generateES5BuildConfig.js @@ -6,6 +6,7 @@ const progress = require('rollup-plugin-progress'); const { terser } = require("rollup-plugin-terser"); const path = require('path'); const alias = require('@rollup/plugin-alias'); +const webWorkerLoader = require('rollup-plugin-web-worker-loader'); const generateRollupConfig = (file, { outputDir, aliases }) => { @@ -36,6 +37,7 @@ const generateRollupConfig = (file, { outputDir, aliases }) => { }), commonjs(), progress(), + webWorkerLoader(), babel.babel({ babelHelpers: 'bundled', exclude: 'node_modules/**' diff --git a/qortal-ui-crypto/api/transactions/PublicizeTransaction.js b/qortal-ui-crypto/api/transactions/PublicizeTransaction.js index d4982bcb..20dd0ebc 100644 --- a/qortal-ui-crypto/api/transactions/PublicizeTransaction.js +++ b/qortal-ui-crypto/api/transactions/PublicizeTransaction.js @@ -1,5 +1,6 @@ "use strict"; import ChatBase from "./chat/ChatBase.js" +import { QORT_DECIMALS } from "../constants.js" export default class PublicizeTransaction extends ChatBase { constructor() { @@ -11,13 +12,17 @@ export default class PublicizeTransaction extends ChatBase { set proofOfWorkNonce(proofOfWorkNonce) { this._proofOfWorkNonce = this.constructor.utils.int32ToBytes(proofOfWorkNonce) } - + set fee(fee) { + this._fee = fee * QORT_DECIMALS + this._feeBytes = this.constructor.utils.int64ToBytes(this._fee) + } get params() { const params = super.params; params.push( this._proofOfWorkNonce, this._feeBytes ) + console.log({params}) return params; } }