The full testnet4 validation took ~17.4h, and ~95% of that was ECDSA signature verification running on the pure-JS secp256k1 fallback instead of the WASM backend.
Root cause
loadSecpWasm() fetches the .wasm via fetch() on a relative path. That works in the browser but fails in Node (no relative-path fetch), so the verify backend silently falls back to the pure-JS secp256k1 — which is roughly 10–25x slower per verification than the WASM/libsecp path.
Impact (estimated)
- testnet4 has ~31.75M inputs to verify. At pure-JS ~1.8 ms/verify that's ~16h — which is essentially the entire 17.4h run.
- With WASM secp (~50–75 us/verify) the signature work would be ~40 min, dropping a full validation from ~17h to roughly ~1.5h.
- This is the realistic baseline; our 17h number is inflated ~10x by the slow fallback. (It also means most of the apparent "SwiftSync speedup" in our runs was actually "we stopped doing slow JS signature checks", not the accumulator.)
Fix
Make the WASM loader work under Node: read secp256k1.wasm from disk (e.g. readFile / fileURLToPath(new URL('./secp256k1.wasm', import.meta.url))) instead of fetch() when running in Node, and confirm the verify backend selects WASM (not the pure-JS fallback). Add a startup log line stating which backend is active so a silent fallback can't hide again.
Where
Engine WASM loader (wasm/secp-wasm.js in the kernel snapshot; canonical in bitcoin-desktop/schema). Symptom surfaces in node src/validate-sync.mjs.
The full testnet4 validation took ~17.4h, and ~95% of that was ECDSA signature verification running on the pure-JS secp256k1 fallback instead of the WASM backend.
Root cause
loadSecpWasm()fetches the.wasmviafetch()on a relative path. That works in the browser but fails in Node (no relative-path fetch), so the verify backend silently falls back to the pure-JS secp256k1 — which is roughly 10–25x slower per verification than the WASM/libsecp path.Impact (estimated)
Fix
Make the WASM loader work under Node: read
secp256k1.wasmfrom disk (e.g.readFile/fileURLToPath(new URL('./secp256k1.wasm', import.meta.url))) instead offetch()when running in Node, and confirm the verify backend selects WASM (not the pure-JS fallback). Add a startup log line stating which backend is active so a silent fallback can't hide again.Where
Engine WASM loader (
wasm/secp-wasm.jsin the kernel snapshot; canonical inbitcoin-desktop/schema). Symptom surfaces in nodesrc/validate-sync.mjs.