UNPKG

@dioxide-js/silas

Version:

RPC utility for Silas

110 lines (107 loc) 3.82 kB
import { s as sha256Exports } from '../_virtual/sha256.mjs'; import { s as sha512Exports } from '../_virtual/sha512.mjs'; import { concat } from './buffer.mjs'; class PowDifficulty { constructor({ originTxn, hashSize, ttl, n, debug }) { this.t = []; this.debug = false; this.hashSize = hashSize || 32; this.targetNum = BigInt(0); this.nonZeroBytes = 0; this.originTxn = originTxn; this.ttl = ttl || 30; this.powData = sha512Exports.sha512.arrayBuffer(this.originTxn); this.n = n !== null && n !== void 0 ? n : 3; this.debug = debug; } get nonceLen() { return 4 * this.n; } LeadingZeroBits(x) { let binaryString = x.toString(2); let number = 0; while (binaryString.length < 64) { binaryString = '0' + binaryString; number++; } return number; } Set(denominator) { let num = BigInt('0x8000000000000000') / BigInt(denominator.toFixed(0)); const shift = this.LeadingZeroBits(num); num = BigInt(num) << BigInt(shift); const exp = this.hashSize * 8 - 63 - shift; const bytes = Math.floor(exp / 8); const residue = exp % 8; if (residue) { this.nonZeroBytes = bytes + 1; num >>= BigInt(8) - BigInt(residue); } else { this.nonZeroBytes = bytes; } this.targetNum = num >> BigInt(32); this.nonZeroBytes += 8; if (this.debug) { console.log({ denominator, targetNum: this.targetNum, nonZeroBytes: this.nonZeroBytes }); } } IsFulfilled(sha256Buffer) { const end = this.hashSize; const start = this.nonZeroBytes; if (this.targetNum <= new DataView(sha256Buffer).getUint32(start - 4, true)) { return false; } for (let i = start; i < end; i++) { const target = new DataView(sha256Buffer).getInt8(i); if (target !== 0) { return false; } } return true; } getNonce() { this.Set((80 + (this.originTxn.byteLength + this.nonceLen) * (this.ttl + 1)) / this.n); const nonces = []; let nonce = 0; let start = Date.now(); for (let i = 0; i < this.n; i++) { while (true) { const cloneData = new DataView(this.powData); cloneData.setUint32(60, nonce, true); const powDataWithNonce = sha256Exports.sha256.arrayBuffer(cloneData.buffer); if (this.IsFulfilled(powDataWithNonce)) { nonces[i] = nonce; const end = Date.now(); const time = end - start; this.t.push(time); if (this.debug) { console.log(`computed nonce(${i}) =>`, nonce, time + 'ms'); } start = Date.now(); break; } nonce++; } nonce++; } return nonces; } getHashMixinNonnce() { let finalBytes = new Uint8Array(this.originTxn.byteLength + this.nonceLen); finalBytes.set(new Uint8Array(this.originTxn), 0); if (this.n > 0) { const nonces = this.getNonce(); nonces.forEach((nonce, i) => { finalBytes.set(new Uint8Array(new Uint32Array([nonce]).buffer), this.originTxn.byteLength + i * 4); }); } else { const nonceU8 = new Uint8Array([1, 1, 1, 1]); finalBytes = concat(finalBytes, nonceU8); } return finalBytes.buffer; } } export { PowDifficulty as default }; //# sourceMappingURL=powDifficulty.mjs.map