UNPKG

madeline-ton

Version:

Pure JS client-side implementation of the Telegram TON blockchain protocol

239 lines (187 loc) 5.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _leemon = require("leemon"); var _long2 = _interopRequireDefault(require("../lib/bigint/long")); var _random = require("./random"); var _stream = _interopRequireDefault(require("../TL/stream")); /** * Convert P and Q to two big-endian byte arrays * @param {string} PBig P * @param {string} QBig Q * @returns Uint8Array[] */ var toBuffers = function toBuffers(PBig, QBig) { PBig = _stream["default"].switcheroo(PBig); QBig = _stream["default"].switcheroo(QBig); var stream = new _stream["default"](new ArrayBuffer(8)); stream.writeUnsignedInt(PBig).writeUnsignedInt(QBig); stream = stream.getBuffer(); return [new Uint8Array(stream, 0, 4), new Uint8Array(stream, 4, 4)]; }; /** * Factorize using long library from Google Closure. * * Usually the fastest on modern machines. * * @param {number[]} PQ, low and high parts * @returns Uint8Array[] Factors */ var _long = function _long(what) { var g; for (var i = 0; i < 3; i++) { var q = _long2["default"].fromInt(((0, _random.fastRandomInt)(128) & 15) + 17); var x = _long2["default"].fromInt((0, _random.fastRandomInt)(1000000000) + 1); var y = x; var lim = 1 << i + 18; for (var j = 1; j < lim; j++) { var a = x; var b = x; var c = q; while (b.notEquals(_long2["default"].ZERO)) { if (b.and(_long2["default"].ONE).notEquals(_long2["default"].ZERO)) { c = c.add(a); if (c.compare(what) > 0) { c = c.subtract(what); } } a = a.add(a); if (a.compare(what) > 0) { a = a.subtract(what); } b = b.shiftRight(1); } x = c; var z = x.compare(y) < 0 ? y.subtract(x) : x.subtract(y); g = z.gcd(what); if (g.notEquals(_long2["default"].ONE)) { break; } if ((j & j - 1) == 0) { y = x; } } if (g.compare(_long2["default"].ONE) > 0) { break; } } var f = what.div(g), P, Q; if (g.compare(f) > 0) { P = f; Q = g; } else { P = g; Q = f; } if (P.multiply(Q).notEquals(what)) { throw new Error("Failure factorizing (long): ".concat(P, " * ").concat(Q, " != ").concat(what)); } return toBuffers(P.toString(10), Q.toString(10)); }; /** * Factorize using leemon library * * Slowest module, for some reason the most reliable on (very) old hardware * * @param {number} PQ, low and high parts * @returns Uint8Array[] Factors */ var leemon = function leemon(what) { what = (0, _leemon.str2bigInt)(what, 16, Math.ceil(64 / _leemon.bpe) + 1); var minBits = 64; var minLen = Math.ceil(minBits / _leemon.bpe) + 1; var i, q; var j, lim; var g, P; var Q; var a = new Array(minLen); var b = new Array(minLen); var c = new Array(minLen); var g = new Array(minLen); var z = new Array(minLen); var x = new Array(minLen); var y = new Array(minLen); for (i = 0; i < 3; i++) { q = ((0, _random.fastRandomInt)(128) & 15) + 17; (0, _leemon.copyInt_)(x, (0, _random.fastRandomInt)(1000000000) + 1); (0, _leemon.copy_)(y, x); lim = 1 << i + 18; for (j = 1; j < lim; j++) { (0, _leemon.copy_)(a, x); (0, _leemon.copy_)(b, x); (0, _leemon.copyInt_)(c, q); while (!(0, _leemon.isZero)(b)) { if (b[0] & 1) { (0, _leemon.add_)(c, a); if ((0, _leemon.greater)(c, what)) { (0, _leemon.sub_)(c, what); } } (0, _leemon.add_)(a, a); if ((0, _leemon.greater)(a, what)) { (0, _leemon.sub_)(a, what); } (0, _leemon.rightShift_)(b, 1); } (0, _leemon.copy_)(x, c); if ((0, _leemon.greater)(x, y)) { (0, _leemon.copy_)(z, x); (0, _leemon.sub_)(z, y); } else { (0, _leemon.copy_)(z, y); (0, _leemon.sub_)(z, x); } (0, _leemon.eGCD_)(z, what, g, a, b); if (!(0, _leemon.equalsInt)(g, 1)) { break; } if ((j & j - 1) == 0) { (0, _leemon.copy_)(y, x); } } if ((0, _leemon.greater)(g, _leemon.one)) { break; } } (0, _leemon.divide_)(what, g, x, y); if ((0, _leemon.greater)(g, x)) { P = x; Q = g; } else { P = g; Q = x; } if (!(0, _leemon.equals)((0, _leemon.mult)(P, Q), what)) { throw new Error("Failure factorizing (leemon): ".concat((0, _leemon.bigInt2str)(P), " * ").concat((0, _leemon.bigInt2str)(Q), " != ").concat((0, _leemon.bigInt2str)(what))); } return toBuffers((0, _leemon.bigInt2str)(P, 10), (0, _leemon.bigInt2str)(Q, 10)); }; /** * Universal factorization * * @param {Uint8Array} Array of bytes with PQ * @returns Uint8Array[] Factors */ var factorize = function factorize(what) { what = new _stream["default"](what.buffer); var high = _stream["default"].switcheroo(what.readSignedInt()), low = _stream["default"].switcheroo(what.readSignedInt()); what = new _long2["default"](low, high); try { return _long(what); } catch (e) { console.log("Error while factorizing with long: " + e); } try { return leemon(what.toString(16)); } catch (e) { console.log("Error while factorizing with leemon: " + e); } }; var _default = factorize; exports["default"] = _default;