UNPKG

stratum-pool-sha256

Version:

High performance SHA-256 Stratum poolserver in Node.js - zero dependencies, pure JavaScript

217 lines (190 loc) 7.01 kB
/** * @module bignum-compat * @description BigInt compatibility layer to replace the native bignum package. * Provides a bignum-like API using JavaScript's native BigInt for arbitrary precision arithmetic. * This avoids native module compilation issues while maintaining API compatibility. */ /** * BigInt wrapper class that mimics the bignum module API. * Handles arbitrary precision integer arithmetic operations. * * @class BigNumCompat * @param {*} value - Value to initialize the BigNum with * @param {number} [base] - Base for string parsing (e.g., 16 for hex) */ class BigNumCompat { constructor(value, base) { if (value instanceof BigNumCompat) { this.value = value.value; } else if (typeof value === 'string' && base) { // Parse string with specific base (e.g., hex with base 16) this.value = BigInt(base === 16 ? '0x' + value : parseInt(value, base).toString()); } else if (typeof value === 'number' || typeof value === 'string') { this.value = BigInt(value); } else if (typeof value === 'bigint') { this.value = value; } else { throw new Error('Invalid value type for BigNumCompat'); } } /** * Creates a BigNumCompat instance from a buffer. * * @static * @param {Buffer} buffer - Buffer to convert * @param {Object} [options={}] - Conversion options * @param {string} [options.endian='big'] - Byte order ('big' or 'little') * @param {number} [options.size] - Expected buffer size * @returns {BigNumCompat} New BigNumCompat instance */ static fromBuffer(buffer, options = {}) { const { endian = 'big', size } = options; let hex = ''; if (endian === 'little') { // Reverse the buffer for little endian const reversed = Buffer.from(buffer).reverse(); hex = reversed.toString('hex'); } else { hex = buffer.toString('hex'); } // Handle empty or zero buffers if (hex === '' || hex === '00') { return new BigNumCompat(0); } return new BigNumCompat(hex, 16); } /** * Converts the BigNum to a buffer. * * @method toBuffer * @param {Object} [options={}] - Conversion options * @param {string} [options.endian='big'] - Byte order ('big' or 'little') * @param {number} [options.size=32] - Output buffer size * @returns {Buffer} Buffer representation */ toBuffer(options = {}) { const { endian = 'big', size = 32 } = options; let hex = this.value.toString(16); // Pad with zeros if necessary if (hex.length % 2 !== 0) { hex = '0' + hex; } let buffer = Buffer.from(hex, 'hex'); // Pad to requested size if (buffer.length < size) { const padding = Buffer.alloc(size - buffer.length); buffer = Buffer.concat([padding, buffer]); } if (endian === 'little') { buffer = buffer.reverse(); } return buffer; } /** * Converts to JavaScript number. * Note: May lose precision for values > Number.MAX_SAFE_INTEGER. * * @method toNumber * @returns {number} JavaScript number representation */ toNumber() { if (this.value > Number.MAX_SAFE_INTEGER) { // Suppress warning - Bitcoin Cash difficulty naturally exceeds MAX_SAFE_INTEGER // console.warn('BigNumCompat.toNumber(): Value exceeds MAX_SAFE_INTEGER, precision may be lost'); } return Number(this.value); } /** * Multiplies this BigNum by another value. * * @method mul * @param {BigNumCompat|number|string|bigint} other - Value to multiply by * @returns {BigNumCompat} Result of multiplication */ mul(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return new BigNumCompat(this.value * otherValue); } // Power pow(exponent) { const exp = exponent instanceof BigNumCompat ? exponent.value : BigInt(exponent); return new BigNumCompat(this.value ** exp); } /** * Checks if this BigNum is greater than or equal to another value. * * @method ge * @param {BigNumCompat|number|string|bigint} other - Value to compare with * @returns {boolean} True if this >= other */ ge(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return this.value >= otherValue; } // Less than lt(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return this.value < otherValue; } // Greater than gt(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return this.value > otherValue; } // Addition add(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return new BigNumCompat(this.value + otherValue); } // Subtraction sub(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return new BigNumCompat(this.value - otherValue); } // Division div(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return new BigNumCompat(this.value / otherValue); } // Modulo mod(other) { const otherValue = other instanceof BigNumCompat ? other.value : BigInt(other); return new BigNumCompat(this.value % otherValue); } // Bitwise shift left shiftLeft(bits) { const bitCount = bits instanceof BigNumCompat ? bits.value : BigInt(bits); return new BigNumCompat(this.value << bitCount); } // Bitwise shift right shiftRight(bits) { const bitCount = bits instanceof BigNumCompat ? bits.value : BigInt(bits); return new BigNumCompat(this.value >> bitCount); } /** * Converts to string representation. * * @method toString * @param {number} [base=10] - Numeric base for string conversion * @returns {string} String representation */ toString(base = 10) { return this.value.toString(base); } } /** * Factory function to create BigNumCompat instances. * Mimics the original bignum module's API. * * @function bignum * @param {*} value - Value to initialize the BigNum with * @param {number} [base] - Base for string parsing * @returns {BigNumCompat} New BigNumCompat instance */ function bignum(value, base) { return new BigNumCompat(value, base); } // Add static methods to factory function bignum.fromBuffer = BigNumCompat.fromBuffer; // For backward compatibility with require('bignum') module.exports = bignum;