// ds.js —— 无需 fs-extra 的版本(CommonJS) const fs = require('fs').promises; // 用内置 fs.promises class DeepSeekHash { constructor() { this.wasmInstance = null; this.offset = 0; this.cachedUint8Memory = null; this.cachedTextEncoder = new TextEncoder(); this._lastBufferRef = null; // 记录上次的 buffer,内存增长时刷新 } _refreshIfNeeded() { const buf = this.wasmInstance.memory.buffer; if (this._lastBufferRef !== buf) { this.cachedUint8Memory = new Uint8Array(buf); this._lastBufferRef = buf; } } getCachedUint8Memory() { if (!this.wasmInstance || !this.wasmInstance.memory) { throw new Error('WASM instance not initialized'); } this._refreshIfNeeded(); return this.cachedUint8Memory; } encodeString(text, allocate, reallocate) { if (!reallocate) { const encoded = this.cachedTextEncoder.encode(text); const ptr = allocate(encoded.length, 1) >>> 0; const memory = this.getCachedUint8Memory(); memory.subarray(ptr, ptr + encoded.length).set(encoded); this.offset = encoded.length; return ptr; } const strLength = text.length; let ptr = allocate(strLength, 1) >>> 0; const memory = this.getCachedUint8Memory(); let asciiLength = 0; for (; asciiLength < strLength; asciiLength++) { const cc = text.charCodeAt(asciiLength); if (cc > 127) break; memory[ptr + asciiLength] = cc; } if (asciiLength !== strLength) { if (asciiLength > 0) text = text.slice(asciiLength); ptr = reallocate(ptr, strLength, asciiLength + text.length * 3, 1) >>> 0; const view = this.getCachedUint8Memory().subarray( ptr + asciiLength, ptr + asciiLength + text.length * 3 ); const res = this.cachedTextEncoder.encodeInto(text, view); asciiLength += res.written; ptr = reallocate(ptr, asciiLength + text.length * 3, asciiLength, 1) >>> 0; } this.offset = asciiLength; return ptr; } calculateHash(algorithm, challenge, salt, difficulty, expireAt) { if (algorithm !== 'DeepSeekHashV1') { throw new Error('Unsupported algorithm: ' + algorithm); } const prefix = `${salt}_${expireAt}_`; let retptr; try { retptr = this.wasmInstance.__wbindgen_add_to_stack_pointer(-16); const ptr0 = this.encodeString( challenge, this.wasmInstance.__wbindgen_export_0, this.wasmInstance.__wbindgen_export_1 ); const len0 = this.offset; const ptr1 = this.encodeString( prefix, this.wasmInstance.__wbindgen_export_0, this.wasmInstance.__wbindgen_export_1 ); const len1 = this.offset; this.wasmInstance.wasm_solve(retptr, ptr0, len0, ptr1, len1, difficulty); // 读取返回(注意内存可能增长,先刷新) this._refreshIfNeeded(); const dv = new DataView(this.wasmInstance.memory.buffer); const status = dv.getInt32(retptr + 0, true); const value = dv.getFloat64(retptr + 8, true); if (status === 0) return undefined; return value; } finally { if (retptr !== undefined) { this.wasmInstance.__wbindgen_add_to_stack_pointer(16); } } } async init(wasmPath) { const imports = { wbg: {} }; // 若报缺少导入,需改用对应的 glue JS const wasmBuffer = await fs.readFile(wasmPath); const { instance } = await WebAssembly.instantiate(wasmBuffer, imports); this.wasmInstance = instance.exports; this._lastBufferRef = this.wasmInstance.memory.buffer; this.cachedUint8Memory = new Uint8Array(this._lastBufferRef); return this.wasmInstance; } } module.exports = DeepSeekHash;