This reverts commit 7b84904d15.
This commit is contained in:
parent
7b84904d15
commit
b1c276db9f
13 changed files with 234 additions and 335 deletions
|
|
@ -1,67 +0,0 @@
|
|||
const determineThreadCount = () => {
|
||||
if (navigator.userAgent.includes("Firefox")) {
|
||||
return Math.min(navigator.hardwareConcurrency, 4);
|
||||
}
|
||||
|
||||
if (!!navigator.hardwareConcurrency) {
|
||||
return navigator.hardwareConcurrency;
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
export default function process(
|
||||
{ basePrefix, version },
|
||||
data,
|
||||
difficulty = 5,
|
||||
signal = null,
|
||||
progressCallback = null,
|
||||
threads = determineThreadCount(),
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let webWorkerURL = `${basePrefix}/.within.website/x/cmd/anubis/static/js/worker/fast.mjs?cacheBuster=${version}`;
|
||||
|
||||
const workers = [];
|
||||
const terminate = () => {
|
||||
workers.forEach((w) => w.terminate());
|
||||
if (signal != null) {
|
||||
// clean up listener to avoid memory leak
|
||||
signal.removeEventListener("abort", terminate);
|
||||
if (signal.aborted) {
|
||||
console.log("PoW aborted");
|
||||
reject(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (signal != null) {
|
||||
signal.addEventListener("abort", terminate, { once: true });
|
||||
}
|
||||
|
||||
for (let i = 0; i < threads; i++) {
|
||||
let worker = new Worker(webWorkerURL);
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
if (typeof event.data === "number") {
|
||||
progressCallback?.(event.data);
|
||||
} else {
|
||||
terminate();
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = (event) => {
|
||||
terminate();
|
||||
reject(event);
|
||||
};
|
||||
|
||||
worker.postMessage({
|
||||
data,
|
||||
difficulty,
|
||||
nonce: i,
|
||||
threads,
|
||||
});
|
||||
|
||||
workers.push(worker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm
|
||||
|
||||
export default function process(
|
||||
{ basePrefix, version },
|
||||
data,
|
||||
difficulty = 5,
|
||||
signal = null,
|
||||
progressCallback = null,
|
||||
_threads = 1,
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let worker = new Worker(`${basePrefix}/.within.website/x/cmd/anubis/static/js/worker/slow.mjs?cacheBuster=${version}`);
|
||||
const terminate = () => {
|
||||
worker.terminate();
|
||||
if (signal != null) {
|
||||
// clean up listener to avoid memory leak
|
||||
signal.removeEventListener("abort", terminate);
|
||||
if (signal.aborted) {
|
||||
console.log("PoW aborted");
|
||||
reject(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (signal != null) {
|
||||
signal.addEventListener("abort", terminate, { once: true });
|
||||
}
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
if (typeof event.data === "number") {
|
||||
progressCallback?.(event.data);
|
||||
} else {
|
||||
terminate();
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = (event) => {
|
||||
terminate();
|
||||
reject(event);
|
||||
};
|
||||
|
||||
worker.postMessage({
|
||||
data,
|
||||
difficulty
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
import processFast from "./algorithms/fast.mjs";
|
||||
import processSlow from "./algorithms/slow.mjs";
|
||||
import processFast from "./proof-of-work.mjs";
|
||||
import processSlow from "./proof-of-work-slow.mjs";
|
||||
|
||||
const defaultDifficulty = 4;
|
||||
const algorithms = {
|
||||
fast: processFast,
|
||||
slow: processSlow,
|
||||
};
|
||||
const basePrefix = "";
|
||||
|
||||
const status = document.getElementById("status");
|
||||
const difficultyInput = document.getElementById("difficulty-input");
|
||||
|
|
@ -43,7 +42,7 @@ const benchmarkTrial = async (stats, difficulty, algorithm, signal) => {
|
|||
.join("");
|
||||
|
||||
const t0 = performance.now();
|
||||
const { hash, nonce } = await process({ basePrefix, version: "devel" }, challenge, Number(difficulty), signal);
|
||||
const { hash, nonce } = await process(challenge, Number(difficulty), signal);
|
||||
const t1 = performance.now();
|
||||
console.log({ hash, nonce });
|
||||
|
||||
|
|
@ -115,7 +114,6 @@ const benchmarkLoop = async (controller) => {
|
|||
} catch (e) {
|
||||
if (e !== false) {
|
||||
status.innerText = e;
|
||||
throw e;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import processFast from "./algorithms/fast.mjs";
|
||||
import processSlow from "./algorithms/slow.mjs";
|
||||
import { testVideo } from "./tests/video.mjs";
|
||||
import processFast from "./proof-of-work.mjs";
|
||||
import processSlow from "./proof-of-work-slow.mjs";
|
||||
import { testVideo } from "./video.mjs";
|
||||
|
||||
const algorithms = {
|
||||
"fast": processFast,
|
||||
|
|
@ -168,7 +168,6 @@ function showContinueBar(hash, nonce, t0, t1) {
|
|||
try {
|
||||
const t0 = Date.now();
|
||||
const { hash, nonce } = await process(
|
||||
basePrefix,
|
||||
challenge,
|
||||
rules.difficulty,
|
||||
null,
|
||||
|
|
|
|||
90
web/js/proof-of-work-slow.mjs
Normal file
90
web/js/proof-of-work-slow.mjs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm
|
||||
|
||||
export default function process(
|
||||
data,
|
||||
difficulty = 5,
|
||||
signal = null,
|
||||
progressCallback = null,
|
||||
_threads = 1,
|
||||
) {
|
||||
console.debug("slow algo");
|
||||
return new Promise((resolve, reject) => {
|
||||
let webWorkerURL = URL.createObjectURL(new Blob([
|
||||
'(', processTask(), ')()'
|
||||
], { type: 'application/javascript' }));
|
||||
|
||||
let worker = new Worker(webWorkerURL);
|
||||
const terminate = () => {
|
||||
worker.terminate();
|
||||
if (signal != null) {
|
||||
// clean up listener to avoid memory leak
|
||||
signal.removeEventListener("abort", terminate);
|
||||
if (signal.aborted) {
|
||||
console.log("PoW aborted");
|
||||
reject(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (signal != null) {
|
||||
signal.addEventListener("abort", terminate, { once: true });
|
||||
}
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
if (typeof event.data === "number") {
|
||||
progressCallback?.(event.data);
|
||||
} else {
|
||||
terminate();
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = (event) => {
|
||||
terminate();
|
||||
reject(event);
|
||||
};
|
||||
|
||||
worker.postMessage({
|
||||
data,
|
||||
difficulty
|
||||
});
|
||||
|
||||
URL.revokeObjectURL(webWorkerURL);
|
||||
});
|
||||
}
|
||||
|
||||
function processTask() {
|
||||
return function () {
|
||||
const sha256 = (text) => {
|
||||
const encoded = new TextEncoder().encode(text);
|
||||
return crypto.subtle.digest("SHA-256", encoded.buffer)
|
||||
.then((result) =>
|
||||
Array.from(new Uint8Array(result))
|
||||
.map((c) => c.toString(16).padStart(2, "0"))
|
||||
.join(""),
|
||||
);
|
||||
};
|
||||
|
||||
addEventListener('message', async (event) => {
|
||||
let data = event.data.data;
|
||||
let difficulty = event.data.difficulty;
|
||||
|
||||
let hash;
|
||||
let nonce = 0;
|
||||
do {
|
||||
if (nonce & 1023 === 0) {
|
||||
postMessage(nonce);
|
||||
}
|
||||
hash = await sha256(data + nonce++);
|
||||
} while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0'));
|
||||
|
||||
nonce -= 1; // last nonce was post-incremented
|
||||
|
||||
postMessage({
|
||||
hash,
|
||||
data,
|
||||
difficulty,
|
||||
nonce,
|
||||
});
|
||||
});
|
||||
}.toString();
|
||||
}
|
||||
132
web/js/proof-of-work.mjs
Normal file
132
web/js/proof-of-work.mjs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
export default function process(
|
||||
data,
|
||||
difficulty = 5,
|
||||
signal = null,
|
||||
progressCallback = null,
|
||||
threads = (navigator.hardwareConcurrency || 1),
|
||||
) {
|
||||
console.debug("fast algo");
|
||||
return new Promise((resolve, reject) => {
|
||||
let webWorkerURL = URL.createObjectURL(new Blob([
|
||||
'(', processTask(), ')()'
|
||||
], { type: 'application/javascript' }));
|
||||
|
||||
const workers = [];
|
||||
const terminate = () => {
|
||||
workers.forEach((w) => w.terminate());
|
||||
if (signal != null) {
|
||||
// clean up listener to avoid memory leak
|
||||
signal.removeEventListener("abort", terminate);
|
||||
if (signal.aborted) {
|
||||
console.log("PoW aborted");
|
||||
reject(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (signal != null) {
|
||||
signal.addEventListener("abort", terminate, { once: true });
|
||||
}
|
||||
|
||||
for (let i = 0; i < threads; i++) {
|
||||
let worker = new Worker(webWorkerURL);
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
if (typeof event.data === "number") {
|
||||
progressCallback?.(event.data);
|
||||
} else {
|
||||
terminate();
|
||||
resolve(event.data);
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = (event) => {
|
||||
terminate();
|
||||
reject(event);
|
||||
};
|
||||
|
||||
worker.postMessage({
|
||||
data,
|
||||
difficulty,
|
||||
nonce: i,
|
||||
threads,
|
||||
});
|
||||
|
||||
workers.push(worker);
|
||||
}
|
||||
|
||||
URL.revokeObjectURL(webWorkerURL);
|
||||
});
|
||||
}
|
||||
|
||||
function processTask() {
|
||||
return function () {
|
||||
const sha256 = (text) => {
|
||||
const encoded = new TextEncoder().encode(text);
|
||||
return crypto.subtle.digest("SHA-256", encoded.buffer);
|
||||
};
|
||||
|
||||
function uint8ArrayToHexString(arr) {
|
||||
return Array.from(arr)
|
||||
.map((c) => c.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
addEventListener('message', async (event) => {
|
||||
let data = event.data.data;
|
||||
let difficulty = event.data.difficulty;
|
||||
let hash;
|
||||
let nonce = event.data.nonce;
|
||||
let threads = event.data.threads;
|
||||
|
||||
const threadId = nonce;
|
||||
|
||||
while (true) {
|
||||
const currentHash = await sha256(data + nonce);
|
||||
const thisHash = new Uint8Array(currentHash);
|
||||
let valid = true;
|
||||
|
||||
for (let j = 0; j < difficulty; j++) {
|
||||
const byteIndex = Math.floor(j / 2); // which byte we are looking at
|
||||
const nibbleIndex = j % 2; // which nibble in the byte we are looking at (0 is high, 1 is low)
|
||||
|
||||
let nibble = (thisHash[byteIndex] >> (nibbleIndex === 0 ? 4 : 0)) & 0x0F; // Get the nibble
|
||||
|
||||
if (nibble !== 0) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
hash = uint8ArrayToHexString(thisHash);
|
||||
console.log(hash);
|
||||
break;
|
||||
}
|
||||
|
||||
const oldNonce = nonce;
|
||||
nonce += threads;
|
||||
|
||||
// send a progress update every 1024 iterations. since each thread checks
|
||||
// separate values, one simple way to do this is by bit masking the
|
||||
// nonce for multiples of 1024. unfortunately, if the number of threads
|
||||
// is not prime, only some of the threads will be sending the status
|
||||
// update and they will get behind the others. this is slightly more
|
||||
// complicated but ensures an even distribution between threads.
|
||||
if (
|
||||
nonce > oldNonce | 1023 && // we've wrapped past 1024
|
||||
(nonce >> 10) % threads === threadId // and it's our turn
|
||||
) {
|
||||
postMessage(nonce);
|
||||
}
|
||||
}
|
||||
|
||||
postMessage({
|
||||
hash,
|
||||
data,
|
||||
difficulty,
|
||||
nonce,
|
||||
});
|
||||
});
|
||||
}.toString();
|
||||
}
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import { Sha256 } from '@aws-crypto/sha256-js';
|
||||
|
||||
const sha256 = (text) => {
|
||||
const hash = new Sha256();
|
||||
hash.update(text);
|
||||
return hash.digest();
|
||||
};
|
||||
|
||||
function uint8ArrayToHexString(arr) {
|
||||
return Array.from(arr)
|
||||
.map((c) => c.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
addEventListener('message', async (event) => {
|
||||
let data = event.data.data;
|
||||
let difficulty = event.data.difficulty;
|
||||
let hash;
|
||||
let nonce = event.data.nonce;
|
||||
let threads = event.data.threads;
|
||||
|
||||
const threadId = nonce;
|
||||
|
||||
while (true) {
|
||||
const currentHash = await sha256(data + nonce);
|
||||
const thisHash = new Uint8Array(currentHash);
|
||||
let valid = true;
|
||||
|
||||
for (let j = 0; j < difficulty; j++) {
|
||||
const byteIndex = Math.floor(j / 2); // which byte we are looking at
|
||||
const nibbleIndex = j % 2; // which nibble in the byte we are looking at (0 is high, 1 is low)
|
||||
|
||||
let nibble = (thisHash[byteIndex] >> (nibbleIndex === 0 ? 4 : 0)) & 0x0F; // Get the nibble
|
||||
|
||||
if (nibble !== 0) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
hash = uint8ArrayToHexString(thisHash);
|
||||
break;
|
||||
}
|
||||
|
||||
const oldNonce = nonce;
|
||||
nonce += threads;
|
||||
|
||||
// send a progress update every 1024 iterations. since each thread checks
|
||||
// separate values, one simple way to do this is by bit masking the
|
||||
// nonce for multiples of 1024. unfortunately, if the number of threads
|
||||
// is not prime, only some of the threads will be sending the status
|
||||
// update and they will get behind the others. this is slightly more
|
||||
// complicated but ensures an even distribution between threads.
|
||||
if (
|
||||
nonce > oldNonce | 1023 && // we've wrapped past 1024
|
||||
(nonce >> 10) % threads === threadId // and it's our turn
|
||||
) {
|
||||
postMessage(nonce);
|
||||
}
|
||||
}
|
||||
|
||||
postMessage({
|
||||
hash,
|
||||
data,
|
||||
difficulty,
|
||||
nonce,
|
||||
});
|
||||
});
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
import { Sha256 } from '@aws-crypto/sha256-js';
|
||||
|
||||
const sha256 = (text) => {
|
||||
const hash = new Sha256();
|
||||
hash.update(text);
|
||||
return hash.digest()
|
||||
.then((result) =>
|
||||
Array.from(new Uint8Array(result))
|
||||
.map((c) => c.toString(16).padStart(2, "0"))
|
||||
.join(""),
|
||||
);
|
||||
};
|
||||
|
||||
addEventListener('message', async (event) => {
|
||||
let data = event.data.data;
|
||||
let difficulty = event.data.difficulty;
|
||||
|
||||
let hash;
|
||||
let nonce = 0;
|
||||
do {
|
||||
if ((nonce & 1023) === 0) {
|
||||
postMessage(nonce);
|
||||
}
|
||||
hash = await sha256(data + nonce++);
|
||||
} while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0'));
|
||||
|
||||
nonce -= 1; // last nonce was post-incremented
|
||||
|
||||
postMessage({
|
||||
hash,
|
||||
data,
|
||||
difficulty,
|
||||
nonce,
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue