nip-13: mine pow async in worker any only invoke noxy with pow
added pow to text notes, reactions and metadata events. pow is mined async in a worker so that the main process does not freeze. noxy profile images, link and image previews are now now only invoked if an event has some valid work proof. noxy can decide if there is enough work and whether or not to serve data for a certain event. target difficulty can be implemented in a later step, this change only check if there is any valid nonce tag with commitment target greater than 0.pull/55/head
parent
7edf1151a6
commit
a1b1f3baee
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* evaluate the difficulty of hex32 according to nip-13.
|
||||
* @param hex32 a string of 64 chars - 32 bytes in hex representation
|
||||
*/
|
||||
export const zeroLeadingBitsCount = (hex32) => {
|
||||
let count = 0;
|
||||
for (let i = 0; i < 64; i += 2) {
|
||||
const hexbyte = hex32.slice(i, i + 2); // grab next byte
|
||||
if (hexbyte == '00') {
|
||||
count += 8;
|
||||
continue;
|
||||
}
|
||||
// reached non-zero byte; count number of 0 bits in hexbyte
|
||||
const bits = parseInt(hexbyte, 16).toString(2).padStart(8, '0');
|
||||
for (let b = 0; b < 8; b++) {
|
||||
if (bits[b] == '1' ) {
|
||||
break; // reached non-zero bit; stop
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
};
|
@ -0,0 +1,47 @@
|
||||
import {getEventHash} from 'nostr-tools';
|
||||
import {zeroLeadingBitsCount} from './cryptoutils.js';
|
||||
|
||||
function mine(event, difficulty, timeout = 5) {
|
||||
const max = 256; // arbitrary
|
||||
if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > max) {
|
||||
throw new Error(`difficulty must be an integer between 0 and ${max}`);
|
||||
}
|
||||
// continue with mining
|
||||
let n = BigInt(0);
|
||||
event.tags.unshift(['nonce', n.toString(), `${difficulty}`]);
|
||||
|
||||
const start = Math.floor(Date.now() * 0.001);
|
||||
console.time('pow');
|
||||
while (true) {
|
||||
const now = Math.floor(Date.now() * 0.001);
|
||||
// if (now > start + 15) {
|
||||
// console.timeEnd('pow');
|
||||
// return false;
|
||||
// }
|
||||
if (now !== event.created_at) {
|
||||
event.created_at = now;
|
||||
// n = BigInt(0); // could reset nonce as we have a new timestamp
|
||||
}
|
||||
event.tags[0][1] = (++n).toString();
|
||||
const id = getEventHash(event);
|
||||
if (zeroLeadingBitsCount(id) === difficulty) {
|
||||
console.log(event.tags[0][1], id);
|
||||
console.timeEnd('pow');
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener('message', async (msg) => {
|
||||
const {
|
||||
difficulty,
|
||||
event,
|
||||
timeout,
|
||||
} = msg.data;
|
||||
try {
|
||||
const minedEvent = mine(event, difficulty, timeout);
|
||||
postMessage({event: minedEvent});
|
||||
} catch (err) {
|
||||
postMessage({error: err});
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue