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.
parent
89c54ac08f
commit
a049139287
@ -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