UNPKG

js-ecutils

Version:

JavaScript Library for Elliptic Curve Cryptography: key exchanges (Diffie-Hellman, Massey-Omura), ECDSA signatures, and Koblitz encoding. Suitable for crypto education and secure systems.

386 lines (371 loc) 48.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Point = void 0; var _affine = require("./arithmetic/affine.js"); var _jacobian = require("./arithmetic/jacobian.js"); var _curve = require("./curve.js"); var _math = require("../utils/math.js"); function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * The Point class — public-facing representation of a point on an elliptic curve. * * A point on the short Weierstrass curve y² = x³ + ax + b (mod p) belongs * to an abelian group with the following properties: * * - Closure: P + Q is also on the curve. * - Associativity: (P + Q) + R = P + (Q + R). * - Identity: There exists a special "point at infinity" O such that P + O = P. * - Inverse: For every P = (x, y), the inverse is -P = (x, -y mod p), * and P + (-P) = O. * * Usage: * * const curve = new CurveParams({ p: 23n, a: 1n, b: 1n, n: 28n, h: 1n }) * const P = new Point(0n, 1n, curve) * const Q = new Point(6n, 19n, curve) * P.add(Q) // point addition * P.mul(5n) // scalar multiplication * P.neg() // point negation * * To switch coordinate systems, create a new CurveParams with a * different coord field: * * const affineCurve = new CurveParams({ * p: 23n, a: 1n, b: 1n, n: 28n, * coord: CoordinateSystem.AFFINE * }) */ var Point = exports.Point = /*#__PURE__*/function () { /** * Create a point on an elliptic curve. * * Validates that the point lies on the curve at construction time: * * y² ≡ x³ + ax + b (mod p) * * Points produced by internal arithmetic use _trusted = true to skip * re-validation. * * @param {BigInt|null} x - x-coordinate, or null for identity (point at infinity). * @param {BigInt|null} y - y-coordinate, or null for identity. * @param {CurveParams|null} curve - Curve parameters (required for arithmetic). * @param {boolean} _trusted - If true, skip on-curve validation. */ function Point() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var _trusted = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; _classCallCheck(this, Point); this.x = x; this.y = y; this.curve = curve; // Validate: y² ≡ x³ + ax + b (mod p) if (!_trusted) { if (x !== null && y !== null && curve !== null) { var lhs = (0, _math.modPow)(y, 2n, curve.p); var rhs = (0, _math.modulus)((0, _math.modPow)(x, 3n, curve.p) + curve.a * x + curve.b, curve.p); if (lhs !== rhs) { throw new Error("Point(".concat(x, ", ").concat(y, ") is not on the curve ") + "y\xB2 = x\xB3 + ".concat(curve.a, "x + ").concat(curve.b, " (mod ").concat(curve.p, ").")); } } } Object.freeze(this); } /** * True when this point represents the point at infinity (identity element O). */ return _createClass(Point, [{ key: "isIdentity", get: function get() { return this.x === null || this.y === null; } /** * Check whether this point satisfies the curve equation: * * y² ≡ x³ + ax + b (mod p) * * @returns {boolean} */ }, { key: "isOnCurve", value: function isOnCurve() { if (this.isIdentity || this.curve === null) return false; var lhs = (0, _math.modPow)(this.y, 2n, this.curve.p); var rhs = (0, _math.modulus)((0, _math.modPow)(this.x, 3n, this.curve.p) + this.curve.a * this.x + this.curve.b, this.curve.p); return lhs === rhs; } }, { key: "_requireCurve", value: function _requireCurve() { if (this.curve === null) { throw new Error('Cannot perform arithmetic on a Point without curve parameters. ' + "Pass a CurveParams instance via the 'curve' argument."); } return this.curve; } /** * Ensure other carries curve params (borrow ours if needed). */ }, { key: "_coerce", value: function _coerce(other) { if (other.curve === null && this.curve !== null) { return new Point(other.x, other.y, this.curve, true); } return other; } }, { key: "_wrap", value: function _wrap(x, y) { return new Point(x, y, this.curve, true); } // ----- compression ----- /** * Compress this point to its x-coordinate and parity bit. * * The y-coordinate can be recovered from x using the curve equation * and the parity bit selects which of the two square roots to use. * * @returns {[BigInt, BigInt]} [x, parity] where parity = y mod 2. * @throws {Error} If this point is the identity. */ }, { key: "compress", value: function compress() { if (this.isIdentity) { throw new Error('Cannot compress the identity point (point at infinity).'); } return [this.x, this.y % 2n]; } /** * Reconstruct a point from its compressed form. * * Given x and a parity bit, computes: * * rhs = x³ + ax + b (mod p) * y = √rhs (mod p) * * and selects the root matching the parity bit. * * @param {BigInt} x - The x-coordinate. * @param {BigInt} parity - 0n or 1n indicating which y to select. * @param {CurveParams} curve * @returns {Point} * @throws {Error} If x does not correspond to a valid point. */ }, { key: "compressSec1", value: // ----- SEC 1 compression (interoperable) ----- /** * Compress this point to SEC 1 / X9.62 format. * * The output is a single byte prefix (0x02 for even y, 0x03 * for odd y) followed by the x-coordinate as a big-endian unsigned * integer, zero-padded to the field size. * * @returns {Uint8Array} Compressed point bytes. * @throws {Error} If this point is the identity or has no curve params. */ function compressSec1() { if (this.isIdentity) { throw new Error('Cannot compress the identity point (point at infinity).'); } var curve = this._requireCurve(); var byteLen = Number((BigInt(curve.p.toString(2).length) + 7n) / 8n); var prefix = this.y % 2n ? 0x03 : 0x02; var xBytes = bigIntToBytes(this.x, byteLen); var result = new Uint8Array(1 + byteLen); result[0] = prefix; result.set(xBytes, 1); return result; } /** * Serialize this point to SEC 1 / X9.62 uncompressed format. * * The output is 0x04 || x || y, where x and y are big-endian * unsigned integers zero-padded to the field size. * * @returns {Uint8Array} Uncompressed point bytes. * @throws {Error} If this point is the identity or has no curve params. */ }, { key: "toUncompressedSec1", value: function toUncompressedSec1() { if (this.isIdentity) { throw new Error('Cannot serialize the identity point (point at infinity).'); } var curve = this._requireCurve(); var byteLen = Number((BigInt(curve.p.toString(2).length) + 7n) / 8n); var xBytes = bigIntToBytes(this.x, byteLen); var yBytes = bigIntToBytes(this.y, byteLen); var result = new Uint8Array(1 + 2 * byteLen); result[0] = 0x04; result.set(xBytes, 1); result.set(yBytes, 1 + byteLen); return result; } /** * Deserialize a point from SEC 1 / X9.62 format. * * Supports both compressed (0x02/0x03 prefix) and * uncompressed (0x04 prefix) encodings. * * @param {Uint8Array} data - The SEC 1 encoded point bytes. * @param {CurveParams} curve * @returns {Point} * @throws {Error} If the data is malformed or the point is invalid. */ }, { key: "neg", value: // ----- operators ----- /** * Return the additive inverse: -P = (x, -y mod p). * * @returns {Point} */ function neg() { if (this.isIdentity) return this; var curve = this._requireCurve(); return new Point(this.x, (0, _math.modulus)(-this.y, curve.p), curve, true); } /** * Add two points on the same curve using the group law. * * Delegates to affine or Jacobian arithmetic depending on * curve.coord. The chord-and-tangent formulas are: * * Addition (P ≠ Q): * λ = (y₂ - y₁) · (x₂ - x₁)⁻¹ * x₃ = λ² - x₁ - x₂ * y₃ = λ(x₁ - x₃) - y₁ * * Doubling (P = Q): * λ = (3x₁² + a) · (2y₁)⁻¹ * x₃ = λ² - 2x₁ * y₃ = λ(x₁ - x₃) - y₁ * * @param {Point} other * @returns {Point} */ }, { key: "add", value: function add(other) { var curve = this._requireCurve(); other = this._coerce(other); if (curve.coord === _curve.CoordinateSystem.JACOBIAN) { var jp1 = (0, _jacobian.toJacobian)(this); var jp2 = (0, _jacobian.toJacobian)(other); var jp3 = (0, _jacobian.jacAdd)(jp1, jp2, curve); return this._wrap.apply(this, _toConsumableArray((0, _jacobian.toAffine)(jp3, curve))); } return this._wrap.apply(this, _toConsumableArray((0, _affine.affineAdd)(this.x, this.y, other.x, other.y, curve))); } /** * Subtract: P - Q = P + (-Q). * * @param {Point} other * @returns {Point} */ }, { key: "sub", value: function sub(other) { return this.add(other.neg ? other.neg() : new Point(other.x, (0, _math.modulus)(-other.y, this._requireCurve().p), other.curve || this.curve, true)); } /** * Scalar multiplication: k · P via double-and-add in O(log k). * * The scalar k is reduced modulo the group order n before * multiplication, so that n·P = O (the identity). * * @param {BigInt} k - Scalar multiplier. * @returns {Point} */ }, { key: "mul", value: function mul(k) { var curve = this._requireCurve(); k = (0, _math.modulus)(k, curve.n); if (curve.coord === _curve.CoordinateSystem.JACOBIAN) { var jp = (0, _jacobian.toJacobian)(this); var jpResult = (0, _jacobian.jacMul)(k, jp, curve); return this._wrap.apply(this, _toConsumableArray((0, _jacobian.toAffine)(jpResult, curve))); } return this._wrap.apply(this, _toConsumableArray((0, _affine.affineMul)(k, this.x, this.y, curve))); } }, { key: "toString", value: function toString() { if (this.isIdentity) return 'Point(∞)'; return "Point(x=".concat(this.x, ", y=").concat(this.y, ")"); } }], [{ key: "decompress", value: function decompress(x, parity, curve) { var rhs = (0, _math.modulus)((0, _math.modPow)(x, 3n, curve.p) + curve.a * x + curve.b, curve.p); var y = (0, _math.modularSqrt)(rhs, curve.p); if (y === null) { throw new Error("x=".concat(x, " does not correspond to a valid point on the curve ") + "y\xB2 = x\xB3 + ".concat(curve.a, "x + ").concat(curve.b, " (mod ").concat(curve.p, ").")); } if (y % 2n !== parity) { y = curve.p - y; } return new Point(x, y, curve); } }, { key: "fromSec1", value: function fromSec1(data, curve) { if (data.length < 2) { throw new Error('SEC 1 data too short.'); } var byteLen = Number((BigInt(curve.p.toString(2).length) + 7n) / 8n); var prefix = data[0]; if (prefix === 0x02 || prefix === 0x03) { if (data.length !== 1 + byteLen) { throw new Error("Compressed SEC 1 data must be ".concat(1 + byteLen, " bytes, got ").concat(data.length, ".")); } var x = bytesToBigInt(data.slice(1)); var parity = BigInt(prefix - 0x02); // 0 for even, 1 for odd return Point.decompress(x, parity, curve); } if (prefix === 0x04) { if (data.length !== 1 + 2 * byteLen) { throw new Error("Uncompressed SEC 1 data must be ".concat(1 + 2 * byteLen, " bytes, got ").concat(data.length, ".")); } var _x = bytesToBigInt(data.slice(1, 1 + byteLen)); var y = bytesToBigInt(data.slice(1 + byteLen)); return new Point(_x, y, curve); } throw new Error("Unknown SEC 1 prefix: 0x".concat(prefix.toString(16).padStart(2, '0'), ". Expected 0x02, 0x03, or 0x04.")); } }]); }(); // ----- helper functions for byte ↔ BigInt conversion ----- function bigIntToBytes(value, length) { var hex = value.toString(16).padStart(length * 2, '0'); var bytes = new Uint8Array(length); for (var i = 0; i < length; i++) { bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); } return bytes; } function bytesToBigInt(bytes) { var hex = ''; for (var i = 0; i < bytes.length; i++) { hex += bytes[i].toString(16).padStart(2, '0'); } return BigInt('0x' + hex); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfYWZmaW5lIiwicmVxdWlyZSIsIl9qYWNvYmlhbiIsIl9jdXJ2ZSIsIl9tYXRoIiwiX3R5cGVvZiIsIm8iLCJTeW1ib2wiLCJpdGVyYXRvciIsImNvbnN0cnVjdG9yIiwicHJvdG90eXBlIiwiX3RvQ29uc3VtYWJsZUFycmF5IiwiciIsIl9hcnJheVdpdGhvdXRIb2xlcyIsIl9pdGVyYWJsZVRvQXJyYXkiLCJfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkiLCJfbm9uSXRlcmFibGVTcHJlYWQiLCJUeXBlRXJyb3IiLCJhIiwiX2FycmF5TGlrZVRvQXJyYXkiLCJ0IiwidG9TdHJpbmciLCJjYWxsIiwic2xpY2UiLCJuYW1lIiwiQXJyYXkiLCJmcm9tIiwidGVzdCIsImlzQXJyYXkiLCJsZW5ndGgiLCJlIiwibiIsIl9jbGFzc0NhbGxDaGVjayIsIl9kZWZpbmVQcm9wZXJ0aWVzIiwiZW51bWVyYWJsZSIsImNvbmZpZ3VyYWJsZSIsIndyaXRhYmxlIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJfdG9Qcm9wZXJ0eUtleSIsImtleSIsIl9jcmVhdGVDbGFzcyIsImkiLCJfdG9QcmltaXRpdmUiLCJ0b1ByaW1pdGl2ZSIsIlN0cmluZyIsIk51bWJlciIsIlBvaW50IiwiZXhwb3J0cyIsIngiLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJ5IiwiY3VydmUiLCJfdHJ1c3RlZCIsImxocyIsIm1vZFBvdyIsInAiLCJyaHMiLCJtb2R1bHVzIiwiYiIsIkVycm9yIiwiY29uY2F0IiwiZnJlZXplIiwiZ2V0IiwidmFsdWUiLCJpc09uQ3VydmUiLCJpc0lkZW50aXR5IiwiX3JlcXVpcmVDdXJ2ZSIsIl9jb2VyY2UiLCJvdGhlciIsIl93cmFwIiwiY29tcHJlc3MiLCJjb21wcmVzc1NlYzEiLCJieXRlTGVuIiwiQmlnSW50IiwicHJlZml4IiwieEJ5dGVzIiwiYmlnSW50VG9CeXRlcyIsInJlc3VsdCIsIlVpbnQ4QXJyYXkiLCJzZXQiLCJ0b1VuY29tcHJlc3NlZFNlYzEiLCJ5Qnl0ZXMiLCJuZWciLCJhZGQiLCJjb29yZCIsIkNvb3JkaW5hdGVTeXN0ZW0iLCJKQUNPQklBTiIsImpwMSIsInRvSmFjb2JpYW4iLCJqcDIiLCJqcDMiLCJqYWNBZGQiLCJhcHBseSIsInRvQWZmaW5lIiwiYWZmaW5lQWRkIiwic3ViIiwibXVsIiwiayIsImpwIiwianBSZXN1bHQiLCJqYWNNdWwiLCJhZmZpbmVNdWwiLCJkZWNvbXByZXNzIiwicGFyaXR5IiwibW9kdWxhclNxcnQiLCJmcm9tU2VjMSIsImRhdGEiLCJieXRlc1RvQmlnSW50IiwicGFkU3RhcnQiLCJoZXgiLCJieXRlcyIsInBhcnNlSW50Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvcG9pbnQuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgUG9pbnQgY2xhc3Mg4oCUIHB1YmxpYy1mYWNpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBwb2ludCBvbiBhbiBlbGxpcHRpYyBjdXJ2ZS5cbiAqXG4gKiBBIHBvaW50IG9uIHRoZSBzaG9ydCBXZWllcnN0cmFzcyBjdXJ2ZSB5wrIgPSB4wrMgKyBheCArIGIgKG1vZCBwKSBiZWxvbmdzXG4gKiB0byBhbiBhYmVsaWFuIGdyb3VwIHdpdGggdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICpcbiAqIC0gQ2xvc3VyZTogICAgICAgUCArIFEgaXMgYWxzbyBvbiB0aGUgY3VydmUuXG4gKiAtIEFzc29jaWF0aXZpdHk6IChQICsgUSkgKyBSID0gUCArIChRICsgUikuXG4gKiAtIElkZW50aXR5OiAgICAgIFRoZXJlIGV4aXN0cyBhIHNwZWNpYWwgXCJwb2ludCBhdCBpbmZpbml0eVwiIE8gc3VjaCB0aGF0IFAgKyBPID0gUC5cbiAqIC0gSW52ZXJzZTogICAgICAgRm9yIGV2ZXJ5IFAgPSAoeCwgeSksIHRoZSBpbnZlcnNlIGlzIC1QID0gKHgsIC15IG1vZCBwKSxcbiAqICAgICAgICAgICAgICAgICAgYW5kIFAgKyAoLVApID0gTy5cbiAqXG4gKiBVc2FnZTpcbiAqXG4gKiAgICAgY29uc3QgY3VydmUgPSBuZXcgQ3VydmVQYXJhbXMoeyBwOiAyM24sIGE6IDFuLCBiOiAxbiwgbjogMjhuLCBoOiAxbiB9KVxuICogICAgIGNvbnN0IFAgPSBuZXcgUG9pbnQoMG4sIDFuLCBjdXJ2ZSlcbiAqICAgICBjb25zdCBRID0gbmV3IFBvaW50KDZuLCAxOW4sIGN1cnZlKVxuICogICAgIFAuYWRkKFEpICAgICAgICAgIC8vIHBvaW50IGFkZGl0aW9uXG4gKiAgICAgUC5tdWwoNW4pICAgICAgICAgLy8gc2NhbGFyIG11bHRpcGxpY2F0aW9uXG4gKiAgICAgUC5uZWcoKSAgICAgICAgICAgLy8gcG9pbnQgbmVnYXRpb25cbiAqXG4gKiBUbyBzd2l0Y2ggY29vcmRpbmF0ZSBzeXN0ZW1zLCBjcmVhdGUgYSBuZXcgQ3VydmVQYXJhbXMgd2l0aCBhXG4gKiBkaWZmZXJlbnQgY29vcmQgZmllbGQ6XG4gKlxuICogICAgIGNvbnN0IGFmZmluZUN1cnZlID0gbmV3IEN1cnZlUGFyYW1zKHtcbiAqICAgICAgIHA6IDIzbiwgYTogMW4sIGI6IDFuLCBuOiAyOG4sXG4gKiAgICAgICBjb29yZDogQ29vcmRpbmF0ZVN5c3RlbS5BRkZJTkVcbiAqICAgICB9KVxuICovXG5cbmltcG9ydCB7IGFmZmluZUFkZCwgYWZmaW5lTXVsIH0gZnJvbSAnLi9hcml0aG1ldGljL2FmZmluZS5qcydcbmltcG9ydCB7IGphY0FkZCwgamFjTXVsLCB0b0FmZmluZSwgdG9KYWNvYmlhbiB9IGZyb20gJy4vYXJpdGhtZXRpYy9qYWNvYmlhbi5qcydcbmltcG9ydCB7IENvb3JkaW5hdGVTeXN0ZW0gfSBmcm9tICcuL2N1cnZlLmpzJ1xuaW1wb3J0IHsgbW9kdWxhclNxcnQsIG1vZHVsdXMsIG1vZFBvdyB9IGZyb20gJy4uL3V0aWxzL21hdGguanMnXG5cbmV4cG9ydCBjbGFzcyBQb2ludCB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBwb2ludCBvbiBhbiBlbGxpcHRpYyBjdXJ2ZS5cbiAgICpcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIHBvaW50IGxpZXMgb24gdGhlIGN1cnZlIGF0IGNvbnN0cnVjdGlvbiB0aW1lOlxuICAgKlxuICAgKiAgICAgecKyIOKJoSB4wrMgKyBheCArIGIgIChtb2QgcClcbiAgICpcbiAgICogUG9pbnRzIHByb2R1Y2VkIGJ5IGludGVybmFsIGFyaXRobWV0aWMgdXNlIF90cnVzdGVkID0gdHJ1ZSB0byBza2lwXG4gICAqIHJlLXZhbGlkYXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7QmlnSW50fG51bGx9IHggICAgICAgICAgLSB4LWNvb3JkaW5hdGUsIG9yIG51bGwgZm9yIGlkZW50aXR5IChwb2ludCBhdCBpbmZpbml0eSkuXG4gICAqIEBwYXJhbSB7QmlnSW50fG51bGx9IHkgICAgICAgICAgLSB5LWNvb3JkaW5hdGUsIG9yIG51bGwgZm9yIGlkZW50aXR5LlxuICAgKiBAcGFyYW0ge0N1cnZlUGFyYW1zfG51bGx9IGN1cnZlIC0gQ3VydmUgcGFyYW1ldGVycyAocmVxdWlyZWQgZm9yIGFyaXRobWV0aWMpLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IF90cnVzdGVkICAgICAgIC0gSWYgdHJ1ZSwgc2tpcCBvbi1jdXJ2ZSB2YWxpZGF0aW9uLlxuICAgKi9cbiAgY29uc3RydWN0b3IoeCA9IG51bGwsIHkgPSBudWxsLCBjdXJ2ZSA9IG51bGwsIF90cnVzdGVkID0gZmFsc2UpIHtcbiAgICB0aGlzLnggPSB4XG4gICAgdGhpcy55ID0geVxuICAgIHRoaXMuY3VydmUgPSBjdXJ2ZVxuXG4gICAgLy8gVmFsaWRhdGU6IHnCsiDiiaEgeMKzICsgYXggKyBiIChtb2QgcClcbiAgICBpZiAoIV90cnVzdGVkKSB7XG4gICAgICBpZiAoeCAhPT0gbnVsbCAmJiB5ICE9PSBudWxsICYmIGN1cnZlICE9PSBudWxsKSB7XG4gICAgICAgIGNvbnN0IGxocyA9IG1vZFBvdyh5LCAybiwgY3VydmUucClcbiAgICAgICAgY29uc3QgcmhzID0gbW9kdWx1cyhcbiAgICAgICAgICBtb2RQb3coeCwgM24sIGN1cnZlLnApICsgY3VydmUuYSAqIHggKyBjdXJ2ZS5iLFxuICAgICAgICAgIGN1cnZlLnAsXG4gICAgICAgIClcbiAgICAgICAgaWYgKGxocyAhPT0gcmhzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFBvaW50KCR7eH0sICR7eX0pIGlzIG5vdCBvbiB0aGUgY3VydmUgYCArXG4gICAgICAgICAgICAgIGB5wrIgPSB4wrMgKyAke2N1cnZlLmF9eCArICR7Y3VydmUuYn0gKG1vZCAke2N1cnZlLnB9KS5gLFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIE9iamVjdC5mcmVlemUodGhpcylcbiAgfVxuXG4gIC8qKlxuICAgKiBUcnVlIHdoZW4gdGhpcyBwb2ludCByZXByZXNlbnRzIHRoZSBwb2ludCBhdCBpbmZpbml0eSAoaWRlbnRpdHkgZWxlbWVudCBPKS5cbiAgICovXG4gIGdldCBpc0lkZW50aXR5KCkge1xuICAgIHJldHVybiB0aGlzLnggPT09IG51bGwgfHwgdGhpcy55ID09PSBudWxsXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgd2hldGhlciB0aGlzIHBvaW50IHNhdGlzZmllcyB0aGUgY3VydmUgZXF1YXRpb246XG4gICAqXG4gICAqICAgICB5wrIg4omhIHjCsyArIGF4ICsgYiAgKG1vZCBwKVxuICAgKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGlzT25DdXJ2ZSgpIHtcbiAgICBpZiAodGhpcy5pc0lkZW50aXR5IHx8IHRoaXMuY3VydmUgPT09IG51bGwpIHJldHVybiBmYWxzZVxuICAgIGNvbnN0IGxocyA9IG1vZFBvdyh0aGlzLnksIDJuLCB0aGlzLmN1cnZlLnApXG4gICAgY29uc3QgcmhzID0gbW9kdWx1cyhcbiAgICAgIG1vZFBvdyh0aGlzLngsIDNuLCB0aGlzLmN1cnZlLnApICsgdGhpcy5jdXJ2ZS5hICogdGhpcy54ICsgdGhpcy5jdXJ2ZS5iLFxuICAgICAgdGhpcy5jdXJ2ZS5wLFxuICAgIClcbiAgICByZXR1cm4gbGhzID09PSByaHNcbiAgfVxuXG4gIF9yZXF1aXJlQ3VydmUoKSB7XG4gICAgaWYgKHRoaXMuY3VydmUgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0Nhbm5vdCBwZXJmb3JtIGFyaXRobWV0aWMgb24gYSBQb2ludCB3aXRob3V0IGN1cnZlIHBhcmFtZXRlcnMuICcgK1xuICAgICAgICAgIFwiUGFzcyBhIEN1cnZlUGFyYW1zIGluc3RhbmNlIHZpYSB0aGUgJ2N1cnZlJyBhcmd1bWVudC5cIixcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY3VydmVcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgb3RoZXIgY2FycmllcyBjdXJ2ZSBwYXJhbXMgKGJvcnJvdyBvdXJzIGlmIG5lZWRlZCkuXG4gICAqL1xuICBfY29lcmNlKG90aGVyKSB7XG4gICAgaWYgKG90aGVyLmN1cnZlID09PSBudWxsICYmIHRoaXMuY3VydmUgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiBuZXcgUG9pbnQob3RoZXIueCwgb3RoZXIueSwgdGhpcy5jdXJ2ZSwgdHJ1ZSlcbiAgICB9XG4gICAgcmV0dXJuIG90aGVyXG4gIH1cblxuICBfd3JhcCh4LCB5KSB7XG4gICAgcmV0dXJuIG5ldyBQb2ludCh4LCB5LCB0aGlzLmN1cnZlLCB0cnVlKVxuICB9XG5cbiAgLy8gLS0tLS0gY29tcHJlc3Npb24gLS0tLS1cblxuICAvKipcbiAgICogQ29tcHJlc3MgdGhpcyBwb2ludCB0byBpdHMgeC1jb29yZGluYXRlIGFuZCBwYXJpdHkgYml0LlxuICAgKlxuICAgKiBUaGUgeS1jb29yZGluYXRlIGNhbiBiZSByZWNvdmVyZWQgZnJvbSB4IHVzaW5nIHRoZSBjdXJ2ZSBlcXVhdGlvblxuICAgKiBhbmQgdGhlIHBhcml0eSBiaXQgc2VsZWN0cyB3aGljaCBvZiB0aGUgdHdvIHNxdWFyZSByb290cyB0byB1c2UuXG4gICAqXG4gICAqIEByZXR1cm5zIHtbQmlnSW50LCBCaWdJbnRdfSBbeCwgcGFyaXR5XSB3aGVyZSBwYXJpdHkgPSB5IG1vZCAyLlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhpcyBwb2ludCBpcyB0aGUgaWRlbnRpdHkuXG4gICAqL1xuICBjb21wcmVzcygpIHtcbiAgICBpZiAodGhpcy5pc0lkZW50aXR5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb21wcmVzcyB0aGUgaWRlbnRpdHkgcG9pbnQgKHBvaW50IGF0IGluZmluaXR5KS4nKVxuICAgIH1cbiAgICByZXR1cm4gW3RoaXMueCwgdGhpcy55ICUgMm5dXG4gIH1cblxuICAvKipcbiAgICogUmVjb25zdHJ1Y3QgYSBwb2ludCBmcm9tIGl0cyBjb21wcmVzc2VkIGZvcm0uXG4gICAqXG4gICAqIEdpdmVuIHggYW5kIGEgcGFyaXR5IGJpdCwgY29tcHV0ZXM6XG4gICAqXG4gICAqICAgICByaHMgPSB4wrMgKyBheCArIGIgIChtb2QgcClcbiAgICogICAgIHkgICA9IOKImnJocyAgICAgICAgIChtb2QgcClcbiAgICpcbiAgICogYW5kIHNlbGVjdHMgdGhlIHJvb3QgbWF0Y2hpbmcgdGhlIHBhcml0eSBiaXQuXG4gICAqXG4gICAqIEBwYXJhbSB7QmlnSW50fSB4ICAgICAgIC0gVGhlIHgtY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtCaWdJbnR9IHBhcml0eSAgLSAwbiBvciAxbiBpbmRpY2F0aW5nIHdoaWNoIHkgdG8gc2VsZWN0LlxuICAgKiBAcGFyYW0ge0N1cnZlUGFyYW1zfSBjdXJ2ZVxuICAgKiBAcmV0dXJucyB7UG9pbnR9XG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB4IGRvZXMgbm90IGNvcnJlc3BvbmQgdG8gYSB2YWxpZCBwb2ludC5cbiAgICovXG4gIHN0YXRpYyBkZWNvbXByZXNzKHgsIHBhcml0eSwgY3VydmUpIHtcbiAgICBjb25zdCByaHMgPSBtb2R1bHVzKG1vZFBvdyh4LCAzbiwgY3VydmUucCkgKyBjdXJ2ZS5hICogeCArIGN1cnZlLmIsIGN1cnZlLnApXG4gICAgbGV0IHkgPSBtb2R1bGFyU3FydChyaHMsIGN1cnZlLnApXG4gICAgaWYgKHkgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYHg9JHt4fSBkb2VzIG5vdCBjb3JyZXNwb25kIHRvIGEgdmFsaWQgcG9pbnQgb24gdGhlIGN1cnZlIGAgK1xuICAgICAgICAgIGB5wrIgPSB4wrMgKyAke2N1cnZlLmF9eCArICR7Y3VydmUuYn0gKG1vZCAke2N1cnZlLnB9KS5gLFxuICAgICAgKVxuICAgIH1cbiAgICBpZiAoeSAlIDJuICE9PSBwYXJpdHkpIHtcbiAgICAgIHkgPSBjdXJ2ZS5wIC0geVxuICAgIH1cbiAgICByZXR1cm4gbmV3IFBvaW50KHgsIHksIGN1cnZlKVxuICB9XG5cbiAgLy8gLS0tLS0gU0VDIDEgY29tcHJlc3Npb24gKGludGVyb3BlcmFibGUpIC0tLS0tXG5cbiAgLyoqXG4gICAqIENvbXByZXNzIHRoaXMgcG9pbnQgdG8gU0VDIDEgLyBYOS42MiBmb3JtYXQuXG4gICAqXG4gICAqIFRoZSBvdXRwdXQgaXMgYSBzaW5nbGUgYnl0ZSBwcmVmaXggKDB4MDIgZm9yIGV2ZW4geSwgMHgwM1xuICAgKiBmb3Igb2RkIHkpIGZvbGxvd2VkIGJ5IHRoZSB4LWNvb3JkaW5hdGUgYXMgYSBiaWctZW5kaWFuIHVuc2lnbmVkXG4gICAqIGludGVnZXIsIHplcm8tcGFkZGVkIHRvIHRoZSBmaWVsZCBzaXplLlxuICAgKlxuICAgKiBAcmV0dXJucyB7VWludDhBcnJheX0gQ29tcHJlc3NlZCBwb2ludCBieXRlcy5cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoaXMgcG9pbnQgaXMgdGhlIGlkZW50aXR5IG9yIGhhcyBubyBjdXJ2ZSBwYXJhbXMuXG4gICAqL1xuICBjb21wcmVzc1NlYzEoKSB7XG4gICAgaWYgKHRoaXMuaXNJZGVudGl0eSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgY29tcHJlc3MgdGhlIGlkZW50aXR5IHBvaW50IChwb2ludCBhdCBpbmZpbml0eSkuJylcbiAgICB9XG4gICAgY29uc3QgY3VydmUgPSB0aGlzLl9yZXF1aXJlQ3VydmUoKVxuICAgIGNvbnN0IGJ5dGVMZW4gPSBOdW1iZXIoKEJpZ0ludChjdXJ2ZS5wLnRvU3RyaW5nKDIpLmxlbmd0aCkgKyA3bikgLyA4bilcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLnkgJSAybiA/IDB4MDMgOiAweDAyXG4gICAgY29uc3QgeEJ5dGVzID0gYmlnSW50VG9CeXRlcyh0aGlzLngsIGJ5dGVMZW4pXG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoMSArIGJ5dGVMZW4pXG4gICAgcmVzdWx0WzBdID0gcHJlZml4XG4gICAgcmVzdWx0LnNldCh4Qnl0ZXMsIDEpXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLyoqXG4gICAqIFNlcmlhbGl6ZSB0aGlzIHBvaW50IHRvIFNFQyAxIC8gWDkuNjIgdW5jb21wcmVzc2VkIGZvcm1hdC5cbiAgICpcbiAgICogVGhlIG91dHB1dCBpcyAweDA0IHx8IHggfHwgeSwgd2hlcmUgeCBhbmQgeSBhcmUgYmlnLWVuZGlhblxuICAgKiB1bnNpZ25lZCBpbnRlZ2VycyB6ZXJvLXBhZGRlZCB0byB0aGUgZmllbGQgc2l6ZS5cbiAgICpcbiAgICogQHJldHVybnMge1VpbnQ4QXJyYXl9IFVuY29tcHJlc3NlZCBwb2ludCBieXRlcy5cbiAgICogQHRocm93cyB7RXJyb3J9IElmIHRoaXMgcG9pbnQgaXMgdGhlIGlkZW50aXR5IG9yIGhhcyBubyBjdXJ2ZSBwYXJhbXMuXG4gICAqL1xuICB0b1VuY29tcHJlc3NlZFNlYzEoKSB7XG4gICAgaWYgKHRoaXMuaXNJZGVudGl0eSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnQ2Fubm90IHNlcmlhbGl6ZSB0aGUgaWRlbnRpdHkgcG9pbnQgKHBvaW50IGF0IGluZmluaXR5KS4nLFxuICAgICAgKVxuICAgIH1cbiAgICBjb25zdCBjdXJ2ZSA9IHRoaXMuX3JlcXVpcmVDdXJ2ZSgpXG4gICAgY29uc3QgYnl0ZUxlbiA9IE51bWJlcigoQmlnSW50KGN1cnZlLnAudG9TdHJpbmcoMikubGVuZ3RoKSArIDduKSAvIDhuKVxuICAgIGNvbnN0IHhCeXRlcyA9IGJpZ0ludFRvQnl0ZXModGhpcy54LCBieXRlTGVuKVxuICAgIGNvbnN0IHlCeXRlcyA9IGJpZ0ludFRvQnl0ZXModGhpcy55LCBieXRlTGVuKVxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KDEgKyAyICogYnl0ZUxlbilcbiAgICByZXN1bHRbMF0gPSAweDA0XG4gICAgcmVzdWx0LnNldCh4Qnl0ZXMsIDEpXG4gICAgcmVzdWx0LnNldCh5Qnl0ZXMsIDEgKyBieXRlTGVuKVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXNlcmlhbGl6ZSBhIHBvaW50IGZyb20gU0VDIDEgLyBYOS42MiBmb3JtYXQuXG4gICAqXG4gICAqIFN1cHBvcnRzIGJvdGggY29tcHJlc3NlZCAoMHgwMi8weDAzIHByZWZpeCkgYW5kXG4gICAqIHVuY29tcHJlc3NlZCAoMHgwNCBwcmVmaXgpIGVuY29kaW5ncy5cbiAgICpcbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBkYXRhICAtIFRoZSBTRUMgMSBlbmNvZGVkIHBvaW50IGJ5dGVzLlxuICAgKiBAcGFyYW0ge0N1cnZlUGFyYW1zfSBjdXJ2ZVxuICAgKiBAcmV0dXJucyB7UG9pbnR9XG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZGF0YSBpcyBtYWxmb3JtZWQgb3IgdGhlIHBvaW50IGlzIGludmFsaWQuXG4gICAqL1xuICBzdGF0aWMgZnJvbVNlYzEoZGF0YSwgY3VydmUpIHtcbiAgICBpZiAoZGF0YS5sZW5ndGggPCAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NFQyAxIGRhdGEgdG9vIHNob3J0LicpXG4gICAgfVxuICAgIGNvbnN0IGJ5dGVMZW4gPSBOdW1iZXIoKEJpZ0ludChjdXJ2ZS5wLnRvU3RyaW5nKDIpLmxlbmd0aCkgKyA3bikgLyA4bilcbiAgICBjb25zdCBwcmVmaXggPSBkYXRhWzBdXG5cbiAgICBpZiAocHJlZml4ID09PSAweDAyIHx8IHByZWZpeCA9PT0gMHgwMykge1xuICAgICAgaWYgKGRhdGEubGVuZ3RoICE9PSAxICsgYnl0ZUxlbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYENvbXByZXNzZWQgU0VDIDEgZGF0YSBtdXN0IGJlICR7MSArIGJ5dGVMZW59IGJ5dGVzLCBnb3QgJHtkYXRhLmxlbmd0aH0uYCxcbiAgICAgICAgKVxuICAgICAgfVxuICAgICAgY29uc3QgeCA9IGJ5dGVzVG9CaWdJbnQoZGF0YS5zbGljZSgxKSlcbiAgICAgIGNvbnN0IHBhcml0eSA9IEJpZ0ludChwcmVmaXggLSAweDAyKSAvLyAwIGZvciBldmVuLCAxIGZvciBvZGRcbiAgICAgIHJldHVybiBQb2ludC5kZWNvbXByZXNzKHgsIHBhcml0eSwgY3VydmUpXG4gICAgfVxuXG4gICAgaWYgKHByZWZpeCA9PT0gMHgwNCkge1xuICAgICAgaWYgKGRhdGEubGVuZ3RoICE9PSAxICsgMiAqIGJ5dGVMZW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBVbmNvbXByZXNzZWQgU0VDIDEgZGF0YSBtdXN0IGJlICR7MSArIDIgKiBieXRlTGVufSBieXRlcywgZ290ICR7ZGF0YS5sZW5ndGh9LmAsXG4gICAgICAgIClcbiAgICAgIH1cbiAgICAgIGNvbnN0IHggPSBieXRlc1RvQmlnSW50KGRhdGEuc2xpY2UoMSwgMSArIGJ5dGVMZW4pKVxuICAgICAgY29uc3QgeSA9IGJ5dGVzVG9CaWdJbnQoZGF0YS5zbGljZSgxICsgYnl0ZUxlbikpXG4gICAgICByZXR1cm4gbmV3IFBvaW50KHgsIHksIGN1cnZlKVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBVbmtub3duIFNFQyAxIHByZWZpeDogMHgke3ByZWZpeC50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKX0uIEV4cGVjdGVkIDB4MDIsIDB4MDMsIG9yIDB4MDQuYCxcbiAgICApXG4gIH1cblxuICAvLyAtLS0tLSBvcGVyYXRvcnMgLS0tLS1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBhZGRpdGl2ZSBpbnZlcnNlOiAtUCA9ICh4LCAteSBtb2QgcCkuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQb2ludH1cbiAgICovXG4gIG5lZygpIHtcbiAgICBpZiAodGhpcy5pc0lkZW50aXR5KSByZXR1cm4gdGhpc1xuICAgIGNvbnN0IGN1cnZlID0gdGhpcy5fcmVxdWlyZUN1cnZlKClcbiAgICByZXR1cm4gbmV3IFBvaW50KHRoaXMueCwgbW9kdWx1cygtdGhpcy55LCBjdXJ2ZS5wKSwgY3VydmUsIHRydWUpXG4gIH1cblxuICAvKipcbiAgICogQWRkIHR3byBwb2ludHMgb24gdGhlIHNhbWUgY3VydmUgdXNpbmcgdGhlIGdyb3VwIGxhdy5cbiAgICpcbiAgICogRGVsZWdhdGVzIHRvIGFmZmluZSBvciBKYWNvYmlhbiBhcml0aG1ldGljIGRlcGVuZGluZyBvblxuICAgKiBjdXJ2ZS5jb29yZC4gIFRoZSBjaG9yZC1hbmQtdGFuZ2VudCBmb3JtdWxhcyBhcmU6XG4gICAqXG4gICAqIEFkZGl0aW9uIChQIOKJoCBRKTpcbiAgICogICAgIM67ICA9ICh54oKCIC0geeKCgSkgwrcgKHjigoIgLSB44oKBKeKBu8K5XG4gICAqICAgICB44oKDID0gzrvCsiAtIHjigoEgLSB44oKCXG4gICAqICAgICB54oKDID0gzrsoeOKCgSAtIHjigoMpIC0geeKCgVxuICAgKlxuICAgKiBEb3VibGluZyAoUCA9IFEpOlxuICAgKiAgICAgzrsgID0gKDN44oKBwrIgKyBhKSDCtyAoMnnigoEp4oG7wrlcbiAgICogICAgIHjigoMgPSDOu8KyIC0gMnjigoFcbiAgICogICAgIHnigoMgPSDOuyh44oKBIC0geOKCgykgLSB54oKBXG4gICAqXG4gICAqIEBwYXJhbSB7UG9pbnR9IG90aGVyXG4gICAqIEByZXR1cm5zIHtQb2ludH1cbiAgICovXG4gIGFkZChvdGhlcikge1xuICAgIGNvbnN0IGN1cnZlID0gdGhpcy5fcmVxdWlyZUN1cnZlKClcbiAgICBvdGhlciA9IHRoaXMuX2NvZXJjZShvdGhlcilcblxuICAgIGlmIChjdXJ2ZS5jb29yZCA9PT0gQ29vcmRpbmF0ZVN5c3RlbS5KQUNPQklBTikge1xuICAgICAgY29uc3QganAxID0gdG9KYWNvYmlhbih0aGlzKVxuICAgICAgY29uc3QganAyID0gdG9KYWNvYmlhbihvdGhlcilcbiAgICAgIGNvbnN0IGpwMyA9IGphY0FkZChqcDEsIGpwMiwgY3VydmUpXG4gICAgICByZXR1cm4gdGhpcy5fd3JhcCguLi50b0FmZmluZShqcDMsIGN1cnZlKSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fd3JhcCguLi5hZmZpbmVBZGQodGhpcy54LCB0aGlzLnksIG90aGVyLngsIG90aGVyLnksIGN1cnZlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJ0cmFjdDogUCAtIFEgPSBQICsgKC1RKS5cbiAgICpcbiAgICogQHBhcmFtIHtQb2ludH0gb3RoZXJcbiAgICogQHJldHVybnMge1BvaW50fVxuICAgKi9cbiAgc3ViKG90aGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkKFxuICAgICAgb3RoZXIubmVnXG4gICAgICAgID8gb3RoZXIubmVnKClcbiAgICAgICAgOiBuZXcgUG9pbnQoXG4gICAgICAgICAgICBvdGhlci54LFxuICAgICAgICAgICAgbW9kdWx1cygtb3RoZXIueSwgdGhpcy5fcmVxdWlyZUN1cnZlKCkucCksXG4gICAgICAgICAgICBvdGhlci5jdXJ2ZSB8fCB0aGlzLmN1cnZlLFxuICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICApLFxuICAgIClcbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FsYXIgbXVsdGlwbGljYXRpb246IGsgwrcgUCB2aWEgZG91YmxlLWFuZC1hZGQgaW4gTyhsb2cgaykuXG4gICAqXG4gICAqIFRoZSBzY2FsYXIgayBpcyByZWR1Y2VkIG1vZHVsbyB0aGUgZ3JvdXAgb3JkZXIgbiBiZWZvcmVcbiAgICogbXVsdGlwbGljYXRpb24sIHNvIHRoYXQgbsK3UCA9IE8gKHRoZSBpZGVudGl0eSkuXG4gICAqXG4gICAqIEBwYXJhbSB7QmlnSW50fSBrIC0gU2NhbGFyIG11bHRpcGxpZXIuXG4gICAqIEByZXR1cm5zIHtQb2ludH1cbiAgICovXG4gIG11bChrKSB7XG4gICAgY29uc3QgY3VydmUgPSB0aGlzLl9yZXF1aXJlQ3VydmUoKVxuICAgIGsgPSBtb2R1bHVzKGssIGN1cnZlLm4pXG5cbiAgICBpZiAoY3VydmUuY29vcmQgPT09IENvb3JkaW5hdGVTeXN0ZW0uSkFDT0JJQU4pIHtcbiAgICAgIGNvbnN0IGpwID0gdG9KYWNvYmlhbih0aGlzKVxuICAgICAgY29uc3QganBSZXN1bHQgPSBqYWNNdWwoaywganAsIGN1cnZlKVxuICAgICAgcmV0dXJuIHRoaXMuX3dyYXAoLi4udG9BZmZpbmUoanBSZXN1bHQsIGN1cnZlKSlcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fd3JhcCguLi5hZmZpbmVNdWwoaywgdGhpcy54LCB0aGlzLnksIGN1cnZlKSlcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIGlmICh0aGlzLmlzSWRlbnRpdHkpIHJldHVybiAnUG9pbnQo4oieKSdcbiAgICByZXR1cm4gYFBvaW50KHg9JHt0aGlzLnh9LCB5PSR7dGhpcy55fSlgXG4gIH1cbn1cblxuLy8gLS0tLS0gaGVscGVyIGZ1bmN0aW9ucyBmb3IgYnl0ZSDihpQgQmlnSW50IGNvbnZlcnNpb24gLS0tLS1cblxuZnVuY3Rpb24gYmlnSW50VG9CeXRlcyh2YWx1ZSwgbGVuZ3RoKSB7XG4gIGNvbnN0IGhleCA9IHZhbHVlLnRvU3RyaW5nKDE2KS5wYWRTdGFydChsZW5ndGggKiAyLCAnMCcpXG4gIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgYnl0ZXNbaV0gPSBwYXJzZUludChoZXguc2xpY2UoaSAqIDIsIGkgKiAyICsgMiksIDE2KVxuICB9XG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBieXRlc1RvQmlnSW50KGJ5dGVzKSB7XG4gIGxldCBoZXggPSAnJ1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgaGV4ICs9IGJ5dGVzW2ldLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpXG4gIH1cbiAgcmV0dXJuIEJpZ0ludCgnMHgnICsgaGV4KVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUE4QkEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsU0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsTUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsS0FBQSxHQUFBSCxPQUFBO0FBQStELFNBQUFJLFFBQUFDLENBQUEsc0NBQUFELE9BQUEsd0JBQUFFLE1BQUEsdUJBQUFBLE1BQUEsQ0FBQUMsUUFBQSxhQUFBRixDQUFBLGtCQUFBQSxDQUFBLGdCQUFBQSxDQUFBLFdBQUFBLENBQUEseUJBQUFDLE1BQUEsSUFBQUQsQ0FBQSxDQUFBRyxXQUFBLEtBQUFGLE1BQUEsSUFBQUQsQ0FBQSxLQUFBQyxNQUFBLENBQUFHLFNBQUEscUJBQUFKLENBQUEsS0FBQUQsT0FBQSxDQUFBQyxDQUFBO0FBQUEsU0FBQUssbUJBQUFDLENBQUEsV0FBQUMsa0JBQUEsQ0FBQUQsQ0FBQSxLQUFBRSxnQkFBQSxDQUFBRixDQUFBLEtBQUFHLDJCQUFBLENBQUFILENBQUEsS0FBQUksa0JBQUE7QUFBQSxTQUFBQSxtQkFBQSxjQUFBQyxTQUFBO0FBQUEsU0FBQUYsNEJBQUFILENBQUEsRUFBQU0sQ0FBQSxRQUFBTixDQUFBLDJCQUFBQSxDQUFBLFNBQUFPLGlCQUFBLENBQUFQLENBQUEsRUFBQU0sQ0FBQSxPQUFBRSxDQUFBLE1BQUFDLFFBQUEsQ0FBQUMsSUFBQSxDQUFBVixDQUFBLEVBQUFXLEtBQUEsNkJBQUFILENB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