@dioxide-js/silas
Version:
RPC utility for Silas
110 lines (107 loc) • 3.82 kB
JavaScript
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