madeline-ton
Version:
Pure JS client-side implementation of the Telegram TON blockchain protocol
239 lines (187 loc) • 5.5 kB
JavaScript
"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;