diff options
Diffstat (limited to 'static/crypto.js')
| -rw-r--r-- | static/crypto.js | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/static/crypto.js b/static/crypto.js index 0455958..04a1400 100644 --- a/static/crypto.js +++ b/static/crypto.js @@ -25,6 +25,14 @@ function leadingZeroBits(bytes) { return count; } +// A loop of only-awaited microtasks (like crypto.subtle.digest) never gives +// the browser a chance to paint — the event loop keeps draining microtasks +// before it's willing to render a frame. A macrotask yield (setTimeout) is +// what actually lets a pending DOM update (e.g. a status message) show up. +function yieldToBrowser() { + return new Promise((resolve) => setTimeout(resolve, 0)); +} + // Self-contained hashcash-style proof of work: no challenge round-trip with // the server. Finds a nonce such that SHA-256("<unix-ts>:<nonce>") has at // least `difficultyBits` leading zero bits. The server only verifies this, @@ -32,12 +40,14 @@ function leadingZeroBits(bytes) { async function computeProofOfWork(difficultyBits) { const encoder = new TextEncoder(); const ts = Math.floor(Date.now() / 1000); + await yieldToBrowser(); // let the "computing proof of work" message paint first for (let nonce = 0; ; nonce++) { const stamp = ts + ":" + nonce; const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(stamp))); if (leadingZeroBits(hash) >= difficultyBits) { return stamp; } + if (nonce % 2000 === 0) await yieldToBrowser(); // keep the tab responsive } } |
